WD20EARSとVIA6421AとソフトRAID(md)のはまりどころ(2) ビッグセクタドライブとLinux

WD20EARS + Linuxの話のその2です。

Western Digital WD20EARSで問題が出るのはWindows XPだけではありません。Linuxでも出ます。でもfdiskだけで解決できます。

この問題は、新しいディスクでは密度が極めて高いのが根本の原因です。従来の512バイトセクタでエラー訂正能力を保つには大きな容量損が出るため、物理セクタ長を大きくしたいのです。ファイルシステムは4KiB単位で読み書きするので、これに合わせてセクタ長を4KiBにするのは合理的です。しかしながら、特に古めのシステムでは、従来の512バイトセクタを前提としている部分がどこに潜んでいるかわかりません。だからソフトウェア的には512バイトセクタに見えるようにしてあります。これがWestern DigitalのAFTをはじめとする「ビッグセクタ」のドライブの状況です。ビッグセクタを使えば1割程度容量が稼げるので、その分お安くなる、と考えてもよいでしょう。

こうしたドライブは、ソフトウェアから見るとセクタ長が512バイトに見えているので、8の倍数で始まるセクタを単位に8の倍数長(4KiB単位で)読み書きすればパフォーマンスが最大になります。ところが、PCアーキテクチャではHDDをシリンダ、ヘッド、セクタで扱う伝統があり、シリンダ境界とパーティション境界を一致させる必要があります。そして現在のLBAでは1シリンダ=63セクタと定められています。このため、第一パーティションが63セクタ目から始まってしまい、ディスクアクセスが必ずセクタをまたぐ、という現象が生じます。4KiB未満の小さいファイルを多数読み書きするような状況ではディスクアクセスが2倍になるので、パフォーマンスが確実に低下します。この話の詳細については、ぜひ小崎資広氏の「2TBを超えろ! ATAディスクの4Kセクタ問題とは?」をお読み下さい。

Linuxでは、これをfdiskで解決できます。fdiskにはセクタ数を指定するオプション(-S 数字)があるので、これを8の倍数で指定すればいいわけですが、巷ではこのセクタ数を56、ヘッド数を224とする方法がよく出回ってます。ぼくも「雑記/2010-06-03 - DEX Lab」などを見て、やみくもに「fdisk -H 224 -S 56」としました。これでパーティションテーブルを切り直すことで、きっちりと4KiB境界を合わせることができます。

ところで、どうしてfdisk -H 224 -S 56 という数字なのか。このヘッド数はどこからきたの?と思って調べてみたところ、ファイルシステム関係の有名なカーネルハッカー、Theodore Ts'oさんのブログ記事「Aligning filesystems to an SSD’s erase block size | Thoughts by Ted」が見つかりました。

However, with SSD’s (remember SSD’s? This is a blog post about SSD’s…) you need to align partitions on at least 128k boundaries for maximum efficiency. The best way to do this that I’ve found is to use 224 (32*7) heads and 56 (8*7) sectors/track. This results in 12544 (or 256*49) sectors/cylinder, so that each cylinder is 49*128k. You can do this by doing starting fdisk with the following options when first partitioning the SSD:

# fdisk -H 224 -S 56 /dev/sdb

The first partition will only be aligned on a 4k boundary, since in order to be compatible with MS-DOS, the first partition starts on track 1 instead of track 0, but I didn’t worry too much about that since I tend to use the first partition for /boot, which tends not to get modified much. You can go into expert mode with fdisk and force the partition to begin on an 128k alignment, but many Linux partition tools will complain about potential compatibility problems (which are obsolete warnings, since the systems that would have booting systems with these issues haven’t been made in about ten years), but I didn’t needed to do that, so I didn’t worry about it.

要するに、SSDが128k単位なので、これに合わせているということでした。HDDでは必要ありませんけど、害もありません。納得!


さて、このディスクは元々素直にパーティションを切っていたので、第一パーティションが63セクタから始まってます:

heliopora:/home/kmf# fdisk -l -u /dev/sdd

Disk /dev/sdd: 2000.3 GB, 2000398934016 bytes
255 heads, 63 sectors/track, 243201 cylinders, total 3907029168 sectors
Units = セクタ数 of 1 * 512 = 512 bytes

 デバイス Boot      Start         End      Blocks   Id  System
/dev/sdd1              63    16386299     8193118+  83  Linux
/dev/sdd2        16386300    20402549     2008125   82  Linux swap / Solaris
/dev/sdd3        20402550  3907024064  1943310757+  fd  Linux raid 自動検出
heliopora:/home/kmf# 

まずはmdadmでデバイスを切り離します。

heliopora:/home/kmf# mdadm /dev/md1 --fail /dev/sdd3 --remove /dev/sdd3
mdadm: set /dev/sdd3 faulty in /dev/md1
mdadm: hot removed /dev/sdd3
heliopora:/home/kmf# cat /proc/mdstat 
Personalities : [raid6] [raid5] [raid4] 
md1 : active raid5 sdb3[0] sda3[1]
      2909869312 blocks level 5, 64k chunk, algorithm 2 [3/2] [UU_]
      
md0 : active raid5 sdc3[1] hdd3[3] hdc3[2] hda3[0]
      1434427584 blocks level 5, 64k chunk, algorithm 2 [4/4] [UUUU]
      
unused devices: 

ちなみに、切り離し前の /dev/md1 は恐ろしく遅いです:

heliopora:/home/kmf# hdparm -tT /dev/md0

/dev/md0:
 Timing cached reads:   924 MB in  2.00 seconds = 461.88 MB/sec
 Timing buffered disk reads:  300 MB in  3.01 seconds =  99.69 MB/sec
You have mail in /var/mail/kmf
heliopora:/home/kmf# hdparm -tT /dev/md1

/dev/md1:
 Timing cached reads:   940 MB in  2.00 seconds = 468.94 MB/sec
 Timing buffered disk reads:    6 MB in  3.00 seconds =   2.00 MB/sec

切り離し後:

heliopora:/home/kmf# hdparm -t /dev/md1

/dev/md1:
 Timing buffered disk reads:  178 MB in  3.02 seconds =  58.85 MB/sec

続いてパーティションの切り直し:

heliopora:/home/kmf# fdisk -H 224 -S 56 /dev/sdd

このディスクのシリンダ数は 311465 に設定されています。
間違いではないのですが、1024 を超えているため、以下の場合
に問題を生じうる事を確認しましょう:
1) ブート時に実行するソフトウェア (例. バージョンが古い LILO)
2) 別の OS のブートやパーティション作成ソフト
   (例. DOS FDISK, OS/2 FDISK)

コマンド (m でヘルプ): p

Disk /dev/sdd: 2000.3 GB, 2000398934016 bytes
224 heads, 56 sectors/track, 311465 cylinders
Units = シリンダ数 of 12544 * 512 = 6422528 bytes

 デバイス Boot      Start         End      Blocks   Id  System
/dev/sdd1               1        1307     8193118+  83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sdd2            1307        1627     2008125   82  Linux swap / Solaris
Partition 2 does not end on cylinder boundary.
/dev/sdd3            1627      311466  1943310757+  fd  Linux raid 自動検出
Partition 3 does not end on cylinder boundary.

コマンド (m でヘルプ): d
領域番号 (1-4): 1

コマンド (m でヘルプ): d
領域番号 (1-4): 2

コマンド (m でヘルプ): d
Selected partition 3

コマンド (m でヘルプ): p

Disk /dev/sdd: 2000.3 GB, 2000398934016 bytes
224 heads, 56 sectors/track, 311465 cylinders
Units = シリンダ数 of 12544 * 512 = 6422528 bytes

 デバイス Boot      Start         End      Blocks   Id  System

コマンド (m でヘルプ): n
コマンドアクション
   e   拡張
   p   基本領域 (1-4)
p
領域番号 (1-4): 1
最初 シリンダ (1-311465, default 1): 
Using default value 1
終点 シリンダ または +サイズ または +サイズM または +サイズK (1-311465, default 311465): 1020

コマンド (m でヘルプ): n
コマンドアクション
   e   拡張
   p   基本領域 (1-4)
p
領域番号 (1-4): 2
最初 シリンダ (1021-311465, default 1021): 
Using default value 1021
終点 シリンダ または +サイズ または +サイズM または +サイズK (1021-311465, default 311465): 1340

コマンド (m でヘルプ): n
コマンドアクション
   e   拡張
   p   基本領域 (1-4)
p
領域番号 (1-4): 3
最初 シリンダ (1341-311465, default 1341): 
Using default value 1341
終点 シリンダ または +サイズ または +サイズM または +サイズK (1341-311465, default 311465): 
Using default value 311465

コマンド (m でヘルプ): l

 0  空              1e  Hidden W95 FAT1 80  古い Minix      be  Solaris boot   
 1  FAT12           24  NEC DOS         81  Minix / 古い Li bf  Solaris        
 2  XENIX root      39  Plan 9          82  Linux swap / So c1  DRDOS/sec (FAT-
 3  XENIX usr       3c  PartitionMagic  83  Linux           c4  DRDOS/sec (FAT-
 4  FAT16 <32M      40  Venix 80286     84  OS/2 隠し C: ド c6  DRDOS/sec (FAT-
 5  拡張領域        41  PPC PReP Boot   85  Linux 拡張領域  c7  Syrinx         
 6  FAT16           42  SFS             86  NTFS ボリューム da  非 FS データ   
 7  HPFS/NTFS       4d  QNX4.x          87  NTFS ボリューム db  CP/M / CTOS / .
 8  AIX             4e  QNX4.x 2nd part 88  Linux plaintext de  Dell ユーティリ
 9  AIX ブート可能  4f  QNX4.x 3rd part 8e  Linux LVM       df  BootIt         
 a  OS/2 ブートマネ 50  OnTrack DM      93  Amoeba          e1  DOS access     
 b  W95 FAT32       51  OnTrack DM6 Aux 94  Amoeba BBT      e3  DOS R/O        
 c  W95 FAT32 (LBA) 52  CP/M            9f  BSD/OS          e4  SpeedStor      
 e  W95 FAT16 (LBA) 53  OnTrack DM6 Aux a0  IBM Thinkpad ハ eb  BeOS fs        
 f  W95 Ext'd (LBA) 54  OnTrackDM6      a5  FreeBSD         ee  EFI GPT        
10  OPUS            55  EZ-Drive        a6  OpenBSD         ef  EFI (FAT-12/16/
11  隠し FAT12      56  Golden Bow      a7  NeXTSTEP        f0  Linux/PA-RISC  
12  Compaq 診断     5c  Priam Edisk     a8  Darwin UFS      f1  SpeedStor      
14  隠し FAT16 <32M 61  SpeedStor       a9  NetBSD          f4  SpeedStor      
16  隠し FAT16      63  GNU HURD または ab  Darwin boot     f2  DOS セカンダリ 
17  隠し HPFS/NTFS  64  Novell Netware  b7  BSDI fs         fd  Linux raid 自動
18  AST SmartSleep  65  Novell Netware  b8  BSDI スワップ   fe  LANstep        
1b  Hidden W95 FAT3 70  DiskSecure Mult bb  隠し Boot Wizar ff  BBT            
1c  Hidden W95 FAT3 75  PC/IX          

コマンド (m でヘルプ): t
領域番号 (1-4): 2
16進数コード (L コマンドでコードリスト表示): 82
領域のシステムタイプを 2 から 82 (Linux swap / Solaris) に変更しました

コマンド (m でヘルプ): t
領域番号 (1-4): 3
16進数コード (L コマンドでコードリスト表示): fd
領域のシステムタイプを 3 から fd (Linux raid 自動検出) に変更しました

コマンド (m でヘルプ): p

Disk /dev/sdd: 2000.3 GB, 2000398934016 bytes
224 heads, 56 sectors/track, 311465 cylinders
Units = シリンダ数 of 12544 * 512 = 6422528 bytes

 デバイス Boot      Start         End      Blocks   Id  System
/dev/sdd1               1        1020     6397412   83  Linux
/dev/sdd2            1021        1340     2007040   82  Linux swap / Solaris
/dev/sdd3            1341      311465  1945104000   fd  Linux raid 自動検出

確認は fdisk -l -u (-lでパーティションテーブルのリスティング、-uでサイズをセクタ単位にする)でできます:

heliopora:/home/kmf# fdisk -l -u /dev/sdd

Disk /dev/sdd: 2000.3 GB, 2000398934016 bytes
224 heads, 56 sectors/track, 311465 cylinders, total 3907029168 sectors
Units = セクタ数 of 1 * 512 = 512 bytes

 デバイス Boot      Start         End      Blocks   Id  System
/dev/sdd1              56    12794879     6397412   83  Linux
/dev/sdd2        12794880    16808959     2007040   82  Linux swap / Solaris
/dev/sdd3        16808960  3907016959  1945104000   fd  Linux raid 自動検出
heliopora:/home/kmf# 

これでまた mdadm --add すればRAID(md)デバイスにディスクを追加できます。このRAIDバイスは一度growしているので、ディスクが足りない状態です。つまり何もしなくてもsyncが始まります。

heliopora:/home/kmf# mdadm --manage /dev/md1 --add /dev/sdd3
mdadm: added /dev/sdd3
heliopora:/home/kmf# cat /proc/mdstat 
Personalities : [raid6] [raid5] [raid4] 
md1 : active raid5 sdd3[2] sdb3[0] sda3[1]
      1454934656 blocks super 0.91 level 5, 64k chunk, algorithm 2 [3/3] [UUU]
      [>....................]  reshape =  0.9% (13968000/1454934656) finish=3394.5min speed=7072K/sec
      
md0 : active raid5 sdc3[1] hdd3[3] hdc3[2] hda3[0]
      1434427584 blocks level 5, 64k chunk, algorithm 2 [4/4] [UUUU]
      
unused devices: 

これでセクタ境界問題は解決です。次はVIA VT6421チップとの相性問題です。