4KiBセクタのHDD

Western Digitalから4KiBセクタのHDDが出ている。

WD20EARS

現在2Tで11000円切るくらいの価格。

容量単価の安さからだろう、現在一番人気のHDDとなっているのだが、こいつがなかなかの曲者のようだ。

WDは4KiBセクタのHDDをadvance format technology採用とかいって売り出している。
AFTとかいってなんか新しい技術ですごそうみたいな感じに見えるが、かなり地雷というかやっかいなところがあるので、理解しないで手を出すと痛い目を見る可能性が高い。
実際価格.comでのレビューをみてると、データの転送が遅すぎてまともに使えないとか文句をいってるものが見える。
ちゃんとパフォーマンスを発揮するようにいじってやればなかなかいいものなんだけども、何も考えずとりあえず接続してパーティション切ってフォーマットして、とかやって使ってみたら、どうしようもない転送速度で涙目になってもおかしくはないくらいの変革なのだ。

HDDの最小記録単位であるセクタであるが、業界慣例というかなんというかでHDDでは512Bっていうのがもう通例となっている。
で、WDの出した4KiBセクタのHDDは、内部的には4KiBセクタなんだけども、外向きには512Bセクタであるかのように振る舞うようになっている。
つまり、物理セクタは4KiBで構成され、論理セクタは512Bのままということだ。
で、最近のOSはLBA(Logical Block Addressing)方式をとっており、ディスクアクセスの際、セクタ単位ではアクセスせず、複数のセクタをひとまとめにしたブロック(クラスタ、アロケーションユニット)単位でアクセスする。
んで、これが通常8論理セクタであり、つまり4KiBなわけである。(まあフォーマットオプションで変更もできるが)
HDDなんてどうせファイルシステム経由でアクセスされるわけで、最小単位を512Bじゃなくて4KiBにしたほうがちょうどで都合がいいじゃない、っていうわけだ。

だけど、なんで論理セクタなんてわざわざ間にかませているかというと、1セクタ512Bの法則はもうかれこれ20年以上もATA/ATAPIの世界で常識になっており、ドライバはおろかチップセットやらBIOSなんかでももう512Bだと仮定しているものが夥しく存在しているからだ。
ここでいきなり「ぼく1セクタ4KiBです^-^」とかいっても絶対とんでもないことが起きることはわかりきっているので、物理セクタと論理セクタを分離したわけだ。
ちなみにここの部分はハードディスクのファームウェアがそういうお仕事をしている。

でもって、ここからが問題をはらむ。
HDDは1トラック63セクタという業界慣例の法則がある。
で、最初の1トラックはMBRとして予約され、第一パーティションは2トラック目から開始する。
そして、通常、1シリンダ255トラックで構成され、CHSアドレッシングの名残を受け継いでいるパーティション(DOSパーティション。WindowsXPまでのWindowsとたいていのLinuxで採用されている)は、その後のパーティション境界はシリンダ境界と一致しなければならないという法則がある。
するってーとなにが起きるかというと、論理8セクタが物理1セクタと等価でなくなるという現象が発生する。

論理8セクタが物理1セクタと等価であるためには、パーティションがLBA 8*xなアドレスで開始していなければならない。
たとえば、パーティションがLBA63から開始しており、その先頭4KiBへのアクセスを考えてみる。

request                       |<--------------------->|
logical  |56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|
phyisical|          7            |            8          |

このように、アクセスが二つの物理アドレスに常にまたがるようになる。
このとき、読み込みでは別に(大きな)問題はないんだけども、書き込みを行う際に、read modify writeという問題が発生する。
一応、読み込みでも読み込みたいブロック数+1を読み込まなければならなくなるので、影響はある。
たとえばこのLBA63-70への書き込みを行うとき、物理アドレスと論理アドレスが異なるため、書き込み命令であるにもかかわらず、論理アドレス56-62および71の情報を保持するため、いったん物理アドレス7,8を読み込み、書き込み内容をその命令にあわせて編集し、物理アドレス7, 8へ書き込む、という手順を踏まなくてはならない。
これは、非常に大きなパフォーマンスダウンを引き起こす。

で、この問題の解決方法の一つに、アラインメントオフセットという方法が用意されている。
これは、論理セクタの開始位置をずらし、物理セクタの最初を7論理セクタにする方法だ。
図で書くとこうなる。

logical  |  |00|01|02|03|04|05|06|07|08|09|10|11|12|13|14|
phyisical|          1            |            2          |

こうすると、一つ目のパーティションは論理セクタの63から開始するため、ちょうど物理セクタの8の開始と等しくなる。
そのため、read modify write問題は回避できる。
が。
これはあくまでも一つ目のパーティション限定の回避策だ。
しかも、一つ目のパーティションの開始位置が論理セクタ63ってわかってるときに限って有効。
二つ目以降のパーティションの開始論理セクタが物理セクタの開始位置と一致するかどうかは単純に1/8であり、全く使えない。

で、まともな解決方法@Linux。

   physical sector size	: /sys/block/sdX/queue/physical_block_size
   logical sector size	: /sys/block/sdX/queue/logical_block_size
   alignment offset	: /sys/block/sdX/alignment_offset

に定義する。
phyisical_block_sizeは4096, logical_block_sizeは512, alinment_offsetにはずらすオフセット値を入れる。
パーティションの開始論理セクタが(PBS*n+AOFF)/LBSとなるようにする。
一つ目のパーティションの開始位置はLBA63なので、その場合AOFFは3584とする。
(4096*7+3584)/512=63といった具合。

ただ、この方法はこの方法でパーティションごとに計算して指定しないといけなく、なかなか面倒なうえに、ジオメトリパラメータがハードコーディングされているようなものがあるとうまく動作しないこともあり得る。

ということで、一番平和な方法としては、こちらからHDDの物理セクタを意識してパーティションを切ってやることとなる。

で、まず、Windows Vista以降について。
パーティション境界を1MiB境界に設定するようにしているため、実は気にする必要がない。
1MiB境界っていうことは4KiB境界でもあるためだ。
アラインメントオフセットが有効である場合はオフセット値を3584として定義するので、その場合でも問題ない。
が、ほかのディスクにイメージをクローンした場合とかを考えると面倒なので、オフセットは使わないようにするべき。

Windows XPではどうかというと、一つはオフセットを利用する方法。
そして、WDのHDDではユーティリティを使う方法がある
ファイルシステムをフォーマットしたあと、WD Align Utilityを使う。
やっていることは、推測だが、パーティション境界と物理セクタ境界が合わさるようにパーティションの切り直しとデータの移動を行っているんじゃないだろうか。
時間かかるみたいだし。

で、Linux。
fdiskだとパーティションの区切り方がシリンダ境界になってしまい、物理セクタ境界とあわせるのが面倒。
まあ開始シリンダを8の倍数にすればあわせられるけど、ロスが結構でる可能性がある。
単純に7*512*63*255バイト最大でロスする。
なので、GNU Partedを使ってパーティションを切る。
partedでは単位をセクタに指定できるので、それを利用してパーティションを切る。
単純に、開始セクタを8の倍数にすれば、物理セクタ境界とパーティション境界が一致するからだ。
たとえば、200GiBのプライマリパーティションを作成するなら以下のような感じ。

# parted
(parted) mkpart primary 64s 419430463s

開始が64セクタ目なのは、MBRの領域確保のため。
システムブートディスクとして使う予定がないなら8セクタを指定してもいいがそんなにけちらなくてもいいと思う。
また、Windows Vistaや7のように、1MiB境界をパーティション境界に指定してもいいと思う。
その場合は、1024*1024/512で2048セクタを開始位置に指定する。
Ubuntuのインストーラはその方式を採用したみたいだ。
ちなみに、パーティションの容量の計算は、G単位なら、n*2*1024*1024+開始セクタ-1となる。
ほかのパーティションを作成する際にも、開始セクタを8の倍数、終了セクタを8の倍数-1にすれば、物理セクタ境界とパーティション境界が一致しつつ、容量の無駄を出さないですむ。
もちろんpartedで切ったパーティションをWindowsで利用することも可能。
あとまあ、Linuxでならインストール時のパーティション切りの際に、シェルを起動してそこからpartedで切ったり、Live CDなんかからparedで切ってからインストールとかっていうのもできるため、そのあたりの自由度は高く、おのおのの環境に応じて柔軟な対応が可能だろう。
(パーティショニングツールの使い方がわからないとかっていうのは論外だが)


で、そのHDDかったのかって?

あ、はい、ぽちりました。

気を遣ってあげないといけない子とかかわいらしいじゃないですか。
まあ、彼女のマシン用なんだけどね。

「4KiBセクタのHDD」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>