Linux で 4096 バイトセクタ HDD を fdisk

Linux でも 4096 バイトセクタのハードディスクを使うときには注意が必要らしいということを 4096 バイトセクタの HDD と Linux - daily dayflower で書きました。でも fdisk のエキスパートモードってどんなんだろうと思いつつ実際に触っていなかったので、今回はちゃんと触ってみました(でもベンチマークはとってないよ)。

今回のおはなしは(前回と同様)、物理セクタサイズ 4096 バイトの 512 バイトセクタエミュレーションモードのハードディスク、つまり 2010 年現在において 4K セクタとして売られている HDD がターゲット*1です。

CentOS 5.4 で動作確認を行いました。fdisk のバージョンはこんな感じです。

# fdisk -v
fdisk (util-linux 2.13-pre7)

以降の例では 1TB のディスクを3つのパーティションにわけます。

  • 128GB
  • 256GB
  • 残り全部

を、全部基本パーティションとして切ってみました。

方法 1. エキスパートモードを使って開始セクタを微調整する

エキスパートモードと銘打っていますが、後述する方法 2 より簡単です。ただし、複数パーティションを切る場合、(最終パーティション以外の)パーティション末尾のセクタがいくらか無駄になります。

ですが単一パーティションで使う場合は無駄が発生しないので、こちらの方法のほうが楽*2でしょう。

fdisk の起動
# fdisk /dev/sdb 
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that, of course, the previous
content won't be recoverable.


The number of cylinders for this disk is set to 121601.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): 

現在パーティションテーブルが存在しないため、いろいろいわれていますが無視してください。

立ち上げ当初の基本コマンドモードでは以下のコマンドが使えます。

Command action
   a   toggle a bootable flag
   b   edit bsd disklabel
   c   toggle the dos compatibility flag
   d   delete a partition
   l   list known partition types
   m   print this menu
   n   add a new partition
   o   create a new empty DOS partition table
   p   print the partition table
   q   quit without saving changes
   s   create a new empty Sun disklabel
   t   change a partition's system id
   u   change display/entry units
   v   verify the partition table
   w   write table to disk and exit
   x   extra functionality (experts only)

いろいろありますが、今回の例で使うのはおもに下記のコマンドだけです。

   d   delete a partition
   n   add a new partition

   p   print the partition table

   q   quit without saving changes
   w   write table to disk and exit

fdisk の場合、いろいろパーティション情報等をいじっても w で書き込まない限り、q コマンドや Ctrl+C で抜けてしまえばディスクには反映されないので気楽に試すことができます。

ざっくりとパーティションを切っていく

現在のパーティションテーブルを見てみます。

Command (m for help): p

Disk /dev/sdb: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System

空っぽです。

まずは n コマンドで第1パーティションを作成します。

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-121601, default 1): <CR>
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-121601, default 121601): +128G

開始シリンダ(≠セクタ)は、デフォルトにしておきます。エンターを押すだけでデフォルト値の 1 が採用されます。

終了シリンダを絶対値で指定するか、サイズを与えることができます。例示ではメガバイト+sizeM)やキロバイト+sizeK)しかありませんが、ギガバイト+sizeG)でも指定することができます。

同様にして第2、第3パーティションも切っていきます。

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First cylinder (15564-121601, default 15564): <CR>
Using default value 15564
Last cylinder or +size or +sizeM or +sizeK (15564-121601, default 121601): +256G

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 3
First cylinder (46689-121601, default 46689): <CR>
Using default value 46689
Last cylinder or +size or +sizeM or +sizeK (46689-121601, default 121601): <CR>
Using default value 121601

第3パーティションはディスクを最後まで使い切るので、終了シリンダをデフォルト値(末尾シリンダ)のままにしています。

どのようなパーティションテーブルになったのか、p コマンドで見てみます。

Command (m for help): p

Disk /dev/sdb: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1               1       15563   125009766   83  Linux
/dev/sdb2           15564       46688   250011562+  83  Linux
/dev/sdb3           46689      121601   601738672+  83  Linux

ご覧のとおり、単位がシリンダ単位なので、セクタ単位ではどのようになっているかわかりません。

セクタ単位の微調整を行うために、エキスパートモードに入ることにします。

エキスパートモードで開始セクタを調整する

x コマンドをもちいるとエキスパートモードに入ることができます。

Command (m for help): x

Expert command (m for help): 

エキスパートモードのコマンドは下記のとおりです。

Command action
   b   move beginning of data in a partition
   c   change number of cylinders
   d   print the raw data in the partition table
   e   list extended partitions
   f   fix partition order
   g   create an IRIX (SGI) partition table
   h   change number of heads
   m   print this menu
   p   print the partition table
   q   quit without saving changes
   r   return to main menu
   s   change number of sectors/track
   v   verify the partition table
   w   write table to disk and exit

ディスクの CHS(シリンダ/ヘッド/セクタ数)を変更することもできますが、BigDrive の現在ほとんど意味がありません(し危険です)。なので、今回使うコマンドは、

   b   move beginning of data in a partition

   p   print the partition table

だけです。

まずはエキスパートモードでパーティションテーブルを確認してみましょう。

Expert command (m for help): p

Disk /dev/sdb: 255 heads, 63 sectors, 121601 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 00   1   1    0 254  63 1023         63  250019532 83
 2 00 254  63 1023 254  63 1023  250019595  500023125 83
 3 00 254  63 1023 254  63 1023  750042720 1203477345 83
 4 00   0   0    0   0   0    0          0          0 00

ノーマルモードにくらべて、いろいろ複雑な情報がでてきました。

実は DOS パーティションテーブルは、各パーティションの開始位置・終了位置を、CHS と LBA(セクタインデックス)の両者でもっています。テーブル左側にかいてあるのが CHS による開始・終了位置です*3。右側が LBA による位置(とサイズ)情報です。

これを見ると第1・第2パーティションについては残念ながら、開始セクタ番号が 8 の倍数になっていないことがわかります。第3パーティションはラッキーにも 8 の倍数になっています。

さきほどあげた b コマンドを使うと、この開始セクタ番号をいじることができます。

Expert command (m for help): b
Partition number (1-4): 1
New beginning of data (63-500023124, default 63): 64

もともと 63 だったところを 64 にしました。

パーティションテーブルを見てみます。

Expert command (m for help): p

Disk /dev/sdb: 255 heads, 63 sectors, 121601 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 00   1   1    0 254  63 1023         64  250019531 83
 2 00 254  63 1023 254  63 1023  250019595  500023125 83
 3 00 254  63 1023 254  63 1023  750042720 1203477345 83
 4 00   0   0    0   0   0    0          0          0 00

第1パーティションの開始セクタ番号が 8 の倍数である 64 になったこと、(終了セクタ番号をいじれないために)サイズが 1 セクタ分少なくなったことがわかります。


シングルパーティションで使う場合なら、ここまでの作業で OK です。あとは w コマンドで今回編集したパーティションテーブルをディスクに書き込みます。


今回は3つパーティションを切ったので、同様にして第2パーティションの開始セクタについてもいじっていきます。

Expert command (m for help): b
Partition number (1-4): 2
New beginning of data (250019595-750042719, default 250019595): 250019600

8 の倍数にアラインするには、下 3 桁が 8 で割りきれるようにします。

第 3 パーティションについてはもともと 8 の倍数だったのでそのままで大丈夫です。さて、最終的にどのようなパーティションテーブルになったのかを確認します。

Expert command (m for help): p

Disk /dev/sdb: 255 heads, 63 sectors, 121601 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
 1 00   1   1    0 254  63 1023         64  250019531 83
 2 00 254  63 1023 254  63 1023  250019600  500023120 83
 3 00 254  63 1023 254  63 1023  750042720 1203477345 83
 4 00   0   0    0   0   0    0          0          0 00

無事、各パーティションの開始セクタ番号が 8 の倍数になりました。

なおさきほど述べたように、エキスパートモードにおいてすら終了セクタ番号を編集することはできません。ですので、今回の場合、第 1 パーティションの末尾が 5 セクタほど使えない状態になっています。これはこの方法 1 ではどうしようもありません。

方法 2. セクタモードを使って開始セクタ・終了セクタを設定する

一番最初のノーマルモードパーティションを切った際、パーティション開始位置等はシリンダ番号単位で与えていました。だからエキスパートモードにわざわざ入って開始セクタの位置を調整することになりました。

ですが、実は fdisk はパーティションの開始・終了位置を最初からセクタ単位で指定することもできます。そこで、方法 2 ではエキスパートモードを使わず、セクタ単位で一から指定してみます。

セクタ単位モードに切り替える

u コマンドを使うと、単位系をシリンダ単位とセクタ単位の両者で切り替えることができます。

# fdisk /dev/sdb
......

Command (m for help): u
Changing display/entry units to sectors

なにもコマンドラインオプションをつけない場合、デフォルトではシリンダ単位になっています。ですので、u コマンドを一度実行すると、セクタ単位モードになります。

また、起動時に -u オプションをつけて fdisk を実行すると、最初からセクタ単位モードになります。

パーティションをざっくり切る

自力で全パーティション境界を計算してもいいのですが、桁数も多くめんどくさいので、まずはパーティション境界にこだわらずざっくりと切ってみます。

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First sector (63-1953525167, default 63): <CR>
Using default value 63
Last sector or +size or +sizeM or +sizeK (63-1953525167, default 1953525167): +128G

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First sector (250000064-1953525167, default 250000064): <CR>
Using default value 250000064
Last sector or +size or +sizeM or +sizeK (250000064-1953525167, default 1953525167): +256G

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 3
First sector (750000065-1953525167, default 750000065): <CR>
Using default value 750000065
Last sector or +size or +sizeM or +sizeK (750000065-1953525167, default 1953525167): <CR>
Using default value 1953525167

ではパーティションテーブルを確認してみましょう。

Command (m for help): p

Disk /dev/sdb: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders, total 1953525168 sectors
Units = sectors of 1 * 512 = 512 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1              63   250000063   125000000+  83  Linux
/dev/sdb2       250000064   750000064   250000000+  83  Linux
/dev/sdb3       750000065  1953525167   601762551+  83  Linux

残念ながら今回は第1・3パーティションの開始セクタが 8 の倍数ではありません。そもそもなぜか終了セクタが指定した容量 + 1セクタになっているのが不可解です。まあいずれにせよ今回の情報をもとにパーティションを切り直すのであまり深く考えないようにします。

きちんとパーティションを切る

さきほどのパーティションテーブルをもとに、開始セクタを 8 の倍数にしつつ容量もきちんとするなら下記のようになるでしょう。

/dev/sdb1              64   250000063
/dev/sdb2       250000064   750000063
/dev/sdb3       750000064  1953525167

この方針でパーティションを手動できっていきます。

といっても、いままで開始セクタ番号をおまかせで決めさせたり、終了セクタ番号を容量で指定していたところを絶対セクタ番号で指定するように変更するだけです。

まず、o コマンドでパーティションテーブルを初期化します。

Command (m for help): o
Building a new DOS disklabel. Changes will remain in memory only,
until you decide to write them. After that, of course, the previous
content won't be recoverable.


The number of cylinders for this disk is set to 121601.
There is nothing wrong with that, but this is larger than 1024,
and could in certain setups cause problems with:
1) software that runs at boot time (e.g., old versions of LILO)
2) booting and partitioning software from other OSs
   (e.g., DOS FDISK, OS/2 FDISK)
Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

あとはパーティションを切っていきます。

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First sector (63-1953525167, default 63): 64
Last sector or +size or +sizeM or +sizeK (64-1953525167, default 1953525167): 250000063

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 2
First sector (63-1953525167, default 63): 250000064
Last sector or +size or +sizeM or +sizeK (250000064-1953525167, default 1953525167): 750000063

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 3
First sector (63-1953525167, default 63): 750000064
Last sector or +size or +sizeM or +sizeK (750000064-1953525167, default 1953525167): <CR>
Using default value 1953525167

最初の開始セクタを 64 にしたせいで、あとあとのパーティションの開始位置のデフォルト値が 63 になってしまい、いちいち手入力しないといけないのがめんどうですが、メモをもとに作業すればまあ間違わないでしょう。

パーティションテーブルを確認します。

Command (m for help): p

Disk /dev/sdb: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders, total 1953525168 sectors
Units = sectors of 1 * 512 = 512 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1              64   250000063   125000000   83  Linux
/dev/sdb2       250000064   750000063   250000000   83  Linux
/dev/sdb3       750000064  1953525167   601762552   83  Linux

無事開始セクタが 8 の倍数になりました。

雑多な話題

方法 1 と方法 2 でパーティションの開始位置などが異なる

方法 1 の場合は(大枠で)シリンダ境界に沿うようにパーティションが自動的に切られていたのに対して、方法 2 ではシリンダ境界にとらわれることなくパーティションを切ることができるからです。

本来シリンダ境界に沿うようにしたほうが旧来のシステムとの互換性が高いのですが、開始セクタ番号をずらしている(シリンダ境界でなくなっている)時点で互換は保たれていないので方法 2 の切り方でも問題はないでしょう。そもそもさきほどみたように CHS ではとっくにオーバーフローしてますしね。

第 1 パーティションの開始位置は 64 じゃないといけないのか

方法 2 で、さらに c コマンドによって DOS コンパチビリティをオフにすると、開始セクタの位置を 63 より前に設定することができます(セクタ番号 0 は MBR およびパーティションテーブル自体なので、設定できない)。

ですが、古典的に第 1 パーティションは(シリンダ境界から)第 63 セクタから開始することになっていました。で、ブートローダーによってはこの 1〜62 セクタの間にコードや情報をおくことがあります。たとえば GRUB の場合(パーティションに置くのでなければ)、stage 1.5 のローダーはこの部分におかれます。

なので、少なくともシステムディスクの場合、開始セクタは 64 としたほうがよいでしょう。データとしてしか使わないのなら開始セクタを 8 としてもいいかもしれませんが、増やせる容量はたかだか 32K bytes 程度です。

他のパーティションツールではどうすればいいか

面倒なので調べていません。

cfdisk はもう使っている人はいないと思います。

sfdisk でもセクタ単位で設定できそうですが、あれを操れる人は自力でなんとでもできるでしょう。

parted はコマンドを実行した瞬間にパーティションテーブルが変更されそうで怖くてためしていません。マニュアルを読む限りセクタ単位で編集することもできそうですが、今回の方法 2 のように一度(容量や割合で)サイズを指定しておまかせで切ったあとに手動で切り直す必要がありそうです。

gparted もためしていません。基本的に容量単位でパーティションを生成するので細かいセクタ単位の指定はできなさそうです。一応、シリンダ単位にパーティション境界をもってくるかどうかというフラグはあるみたいですが。

*1:旧来の物理セクタサイズ 512 バイトの HDD に対して今回の作業を行ってもパフォーマンスなどの問題はありません。

*2:Western Digital のドライブの場合、単一パーティションならジャンパを使うのが一番楽と思いますが。

*3:ごらんのとおり、BigDrive のためもはや CHS によるパーティション記述はオーバーフローしており意味をなしていないことがわかります。