カーネル2.6.18に向けたmd拡張機能の整理

すでにここで掲載の記事、Linuxカーネルの「オーバーホール」に関するTorvalds氏のコメントにあるように、今まで成長を続けてきた2.6系カーネルの集大成として予定されている2.6.18での安定化に向けた動きがLKML(Linux Kernel Mailing List)を中心に始まっている。今回は、LinuxでソフトウェアRAID機能を提供するmd(Multiple Device)モジュールの機能拡張に関する投稿を紹介する。

Linus Torvalds氏のLinuxカーネルの「オーバーホール」に関する記事は5月10日に掲載されたので、それをまず読んで欲しい。今回からはカーネル2.6の安定化作業と、そこでに目指すべきものを中心に見据えてトピックスを追ってみることにする。

Linux-RAID Mailing Listを中心にmdの開発を行っているNeil Brownから、2006年5月1日に「Introduction - assort md enhancements for 2.6.18」と題した[PATCH 000 of 11]のメッセージに続いて、連続した11個のPatchがLKMLにポストされた。Neil Brownは4月27日にも、「[PATCH 000 of 5] md: Introduction - assorted raid10/raid1 fixes」と題した2.6.17用のPatchを出しているので、ここへ来て今まで拡散しつつあったmdの機能拡張の成果をまとめ始めた様子である。

[PATCH 000 of 11] md: Introduction - assort md enhancements for 2.6.18

これらの11個のPatchは、2.6.18の開始に向けて適合できるに、機能拡張をきれいに整理し直したものである。注目すべき主なものは以下の通りである。

  • #005

    raid5とraid6のコードを単一のモジュールにマージした。多くの共通コードがあるため、それらすべてをまとめることには、利点がある。

  • #008

    追加ドライブを増設するオンライン中に、リニアアレイの拡張を可能にした。

  • #010

    (いつかサポートされるはずの業界標準RAIDメタデータフォーマットである)「DDF」でサポートされているレイアウトの1つを、「raid10」の新フレーバー(訳注:選択肢という意味か?)として追加。 これには、実証されるべき最新のmdadmを必要としている。

以下、このポストされた11個のPatchに書かれたコメントを簡単に追ってみる

[PATCH 001 of 11] md: Reformat code in raid1_end_write_request to avoid goto

md: gotoを回避するためのraid1_end_write_requestコードの再構成。最近の変更ではgotoを不要にしたため、何が起こっているかを明確にするために再構成することにした。

[PATCH 002 of 11] md: Remove arbitrary limit on chunk size.

Chunk Sizeに関する独断的な制限の撤去。コードをまさしく切開せずにサポートすることができる最大のChunk Sizeは、2の30乗バイトである。従ってそれを独断的な4MBという制限の代わりにLimitとする。いずれ「chunksize」は、バイト数の代わりにセクタシフトへと変わるべきである。その結果、Limitは必要無くなるだろう。

[PATCH 003 of 11] md: Remove useless ioctl warning.

不要なioctl警告の削除。この警告は2.2の頃までは少しは有用だったが、今では迷惑以外の何者でもない。それは新ioctls(現在のを取り込みたいし、そしてそれは可能である)を加えることを、面倒にするだけだ。

[PATCH 004 of 11] md: Increase the delay before marking metadata clean, and make it configurable.

メタデータのクリ−ンマークを行う前の遅延時間を増加させることで、それを再構成ができるようにする。mdアレイが20ミリ秒間アイドル(書込みが無い状態)だった場合、「クリーン」としてそれをマークする。この遅延時間は、いくつかの実際の仕事量にとって短すぎることが判明している。従ってそれを200ミリ秒(メタデータを更新する時間はそのうちの僅かとするべき)に増加させて、それをsysfsで設定可能にする。

[PATCH 005 of 11] md: Merge raid5 and raid6 code

raid5とraid6のコードのマージ。raid5.cとraid6main.cの間の多くの共通部分がある。このPatchはraid456と呼ばれる1つのモジュールに、両方をマージする。これは多くのコードをセーブし、そしてオンラインでraid5->raid6へとマイグレーションするための道を開く。重複部はまだある。例えばhandle_stripe5とhandle_stripe6の間といったあたりなど。これについては、たぶん後で一掃することになる。

[PATCH 006 of 11] md: Remove nuisance message at shutdown

シャットダウン時のうるさいメッセージを削除。シャットダウン時には、全てのアレイを読取専用に切り替えるが、それは実際に活動中でないものも含めて、各具現化されたアレイのためのメッセージを作成する。そのため、非活動中のアレイのためのメッセージを削除する。

[PATCH 007 of 11] md: Allow checkpoint of recovery with version-1 superblock.

バージョン1のスーパーブロックで、リカバリ用のチェックポイントを許可する。一時期は、Resync(アレイの再構築)のためのチェックポイント機構を持っていたことがある。バージョン1のスーパーブロックでは、それと同様にリカバリでチェックポイントを使用することを可能にする。このパッチではそれを実装する。recovery_offsetフィールドを使用しているというシグナルに機能フラグを加えるために、我々が必要とする初期の不注意により、そうでなければより古いカーネルは、部分的に回復されたアレイが完全に回復された事実にあることを当然のことと思うだろう。

[PATCH 008 of 11] md: Allow a linear array to have drives added while active.

リニアアレイの活動中にドライブの追加を可能にする。

[PATCH 009 of 11] md: Support stripe/offset mode in raid10

raid10でのストライプ/オフセットモードのサポート。異なるストライプ上でデータを複写する場合、「業界基準」のDDFフォーマットではストライプ/オフセットのレイアウトを可能にしている。

例)
A B C D
D A B C
E F G H
H E F G
(このとき「列」はドライブに、「行」はストライプに、「文字」はChunk中のデータに相当する)

これはraid10の'far'モードに似ているが、全く同じではない。そのためDDFストライプ/オフセットのレイアウトに続く'far/offset'オプションで'far'モードを拡張する。

[PATCH 010 of 11] md: make md_print_devices() static

md_print_devices()をstatic関数にする。Adrian Bunkから貰ったこのPatchは、無意味にグローバルな関数md_print_devices()をstaticにする。

[PATCH 011 of 11] md: Split reshape portion of raid5 sync_request into a separate function.

raid5のsync_requestで作り変えられた部分を、個別のファンクションへ分割。raid5 sync_requestの*方法*は、大きすぎるので...

[PATCH 004 of 11]に対するコメント

「ミリ秒単位にしたらどうだろうか?疑いを払拭するために、safe_mode_delay_msecsとこれを改名しよう。そうするとかなりすっきりする。」

Patchソース中の、以下のようなコードがある[PATCH 004]を見て、2.6カーネル・メンテナのAndrew Mortonが言った。

+ msec = simple_strtoul(buf, &e, 10);
+ if (e == buf || (*e && *e != '\n'))
+ return -EINVAL;
+ msec = (msec * 1000) / scale;
+ if (msec == 0)
+ mddev->safemode_delay = 0;
+ else {
+ mddev->safemode_delay = (msec*HZ)/1000;
+ if (mddev->safemode_delay == 0)
+ mddev->safemode_delay = 1;
+ }
+ return len;

これにNeilBrownが答えた。

それはかなり昔に、私が/proc/net/rpc/nfsdに対してthread-usageの統計情報の表示をミリ秒単位で追加したときにLinusから、それをはるかに「明白な」単位である、「秒」にするように言われたからだ。以下のメールを参照して欲しい。これは私には結構シビアに見える。ライブラリにでもした方がいいのだろうか?

と言ってLinus Torvaldsからのメールを添付した。

Andrew Mortonが言った。

それは出力側についてだからである。出力時に変換する方が簡単だからだ。また私は、多くの人が/procファイルを読むという考えからだとも推測する。しかしそこには書くのは、少数である。
私は大抵の場合、特にa) 「ミリ秒の遅延」がそのような単純なコンセプトで、b) それがユーザスペース中のfloat変数からミリ秒に変換するのが非常に容易な場合、このような想像上の浮動小数点数を受け付けることをカーネルに教えるべきだとは思わない。人間(全く愚かなもの;)がこのファイルへ数を繰り返し出力すると実際に期待しているのだるうか。あるいは、それは主としてmdadmが操作するものになるだろうか。

Linusが言った。

私は通常いくつかの「任意のベース」を持っているインタフェースは嫌いだ。従って「秒」は良いSI(国際単位系)基本単位であるので、「数秒の遅延」は任意のベースとはならない。またそれについて疑問の余地はない。しかし一旦マイクロ秒の上のミリ秒の話しを始めるなら、私は実際の所、むしろ異なるファイルに異なる(マジック)ベースの定数を持たせることで、「偽の浮動小数点数」を持っていたい。どれがミリ秒で、どれがマイクロ秒で、どれがただの秒かをどうやって思い出すか?helper機能を持つのは容易であるし、あるいは「struct timeval」とfloat変数の読み書きを実装する方法もある。

Nick Pigginが提案した。

どちらにしても、名前に単位名を入れれば、曖昧さはすべて解決する。そして、これこそがLinusの最も大きな関心事のように思われるのだが、移植性が明らかに無くなるので jiffiesを使用しないことだ。それが終れば、私は秒かミリ秒を使うかについては、あまり気にしない。
さらに言わせて貰えば、我々の現在の単位の多くはミリ秒である。特にそれらがミリ秒の粒度で、あるいはその桁数近辺で事態を測定している場合には。また私は、整数値で作動しないproc数値はほとんど無いと思っている。

[PATCH 009 of 11]に対するコメント

Al Boldiが聞いた。

推測だがこの図は、--layout=f2のときの場合なのだろうか?もしそうならば、--layout=f4は、4つのミラー/ストライプ・アレイとなるのだろうか?するとこれは4つの物理的に複製された、ミラーになるのだろうか?またそれは、複数のストライプを横断的に使う、staged write-backメカニズムを持つことは可能なのだろうか?というのは、速いバースト書き込みを期待しているのだが。

NeilBrownがこれに答えた。

「f2」とは似たようなレイアウトである。しかしオフセットストライプは、ドライブのはるかに下層にある。それを「o2」あるいは「offset2」と呼ぶことになるだろう。4つのドライブアレイ上のo4は以下のようになる。これは異なるレイアウトで、同じデータをそれぞれが含んでいる4つのデバイスになる。
A B C D
D A B C
C D A B
B C D A
E F G H
staged write-backメカニズムについては、それが何を意図しているのかがわからないが、ファイルシステムへの書込みを確認させる前に、全てのコピーの書き込みが完了するのを待つ必用がある。そうでなければ、クラッシュしてデバイスエラーになった場合に、データ損傷のリスクがあるからだ。従って、隣接したリクエストをまとめるのをサポートする各デバイスのプラグインを導入する以外には、何らかの遅延の挿入で、事態がより速くなるというようなことは無いだろう。