@naota344の今週のLKML
今週は
- [PATCH 1/1] Staging: hv: mousevsc: Move the mouse driver out of staging
- [RFC] Metadata Replication for Ext4
- lsusd - The Linux SUSpend Daemon
[PATCH 1/1] Staging: hv: mousevsc: Move the mouse driver out of staging
MicrosoftのHyper-V用のマウスドライバをstagingから本ドライバツリーに移そうとしているようです。 Hyper-Vのドライバはまだ全てstagingですが、これをスタートにこれから本ツリーにどんどん移していくのでしょうか。
[RFC] Metadata Replication for Ext4
http://permalink.gmane.org/gmane.comp.file-systems.ext4/28596
Ext4でメタデータのコピーを持つようにしようというRFCです。簡単にRFCの中身をまとめます。
motivationは
他の対応策との比較について…
- メタデータ破損時に安全側に倒して、後のfsckまで実際の復旧を遅らせることはできるがfsckで時間をとられるのはproduction systemではあまり望ましいことではない
- 最近メタデータ checksumのpatchが出たが、破損を検知することはできても復旧させることはできない…
ちなみに「安全側に倒して、後のfsckまで実際の復旧を遅らせる」というのは、たとえば inode allocation bitmap部分が読めなくなった時に全て allocされていると見なしておいて、fsckの時にdiskをscanし実際にallocされているものでbitmapを作りなおす…などといった作業になります。
Metadata replicationについて
- read errorやchecksum errorを検出して、実行時にそのまま(fsck使わずに)修復ができる
という利点をあげています。
さらにデザインについても書いているので、続けてまとめてみましょう。
メタデータは大きく「static metadata」と「dynamic metadata」の二つに分けられます
static metadataは、mkfs時に確保されディスク上で常に一定のサイズを持つものです。これはたとえば block, inodeのaloocation bitmapやinode tableになります。
dynamic metadataは、ファイルシステムを使用するにつれて作成されたり削除されたりするもので、そのファイルシステムの使用状況によってサイズが異なります。これはたとえば directory blockやextent blockになります。
そしてこの replica のRFCでは、 dynamic metadata のうちでは directory block のみを対象にしています。これは
- directory block の破損は多くのファイルの読みこみ失敗につながること
- extent tree blockをreplicaするとパフォーマンス・容量の両方の面でコストがかかること
が理由にあげられています。
さて、実際のレプリカデータについてです。
まず、レプリカ機能がONになると新しい「予約済みのinode」が一つ増えます。このinode(レプリカinode)がstatic metdataとdynamic metadataのレプリカブロックを保存するために使われます。具体的には
- 最初のブロックに「レプリカinodeのsuper block」
- static metdataのレプリカ
- dynamic metadataへのindex (元のblock番号からレプリカのblock番号へのマッピング)
- dynamic metadataのレプリカ
のように保存されます。
super blockは
struct ext4_replica_sb { __le32 r_wtime; /* 書きこみ時間 */ __le32 r_static_offset; /* static metadataの先頭のブロック番号 */ __le32 r_index_offset; /* dynamic metadataのindexの先頭のブロック番号 */ __le16 r_magic; /* マジックナンバー */ __u8 r_log_groups_per_index; /* Number of block-groups * represented by each index block. */ __u8 r_reserved_pad; /* padding */ };
このようなデータになっています。
この super blockの後には static metadataのレプリカが置かれます。 static metadataは固定長で最初にグループ0のstatic metadata、次にグループ1のstatic metadataというようにグループ番号順にstatic metadataのみがまず配置されます。 長さが固定されている static metadataをdynamic metadataと別の場所に置くことで任意のグループの static metadata の位置を探しだしやすくなります。
…と、この後 dyncamic metadataの保存方法やoverheadに関する考察もなされていますが、まだRFCの段階ですし、詳細は元のメールを追ってください。
http://permalink.gmane.org/gmane.comp.file-systems.ext4/28613
これに対していま metadata readに対してラベルをつけて(そしてpriorityを少し上げているように)いるように、metadata書きこみにもラベルをつけてdmと組みあわせてファイルシステムを限定しない metadata replica を実現できないか? との意見が来ています。
しかし、 metadata破損を検出して dmに対してreplicaを要求するAPIが必要になってしまう、といった反論やパーティションをまた別個に作らなくてはいけない(めんどいですよね。ZFSのいいとこの一つはこのめんどさがないからですよね)といった点が指摘されています。
もうひとつ興味深かったのは…
http://permalink.gmane.org/gmane.comp.file-systems.ext4/28651
In fact some popular consumer SSDs do some fairly efficient data
de-duplication which completly runs any metadata redundancy on a single
of these devices void.
SSDだとde-dupしちゃってreplica が意味なくなるのでは?という指摘ですね。 btrfsはどうしているんだろう…。
長く紹介しましたが、まだRFCでdynamic の方は動くコードがまだないです……がext4がスケールしていく上で大事な機能ではないかな、と思います。どのような形で実装されるのか(はたまた流れてしまうのか)楽しみですね。
lsusd - The Linux SUSpend Daemon
http://permalink.gmane.org/gmane.linux.kernel/1206042
Linux用のsuspend管理デーモンの実装を書いてみた人があらわれました!!
……とだけ言っても…なんのことやら?なので前提から解説します。
Opportunistic suspend はAndroidにあってLinuxにない機能のひとつです。Androidは携帯電話などの電力が限られたデバイスで多く使われていますから、特になにもすることがないような時には積極的に機会をとらえてマシン全体をサスペンドさせるようにしています。しかしこの「特になにもすることがない」というのが曲者です。数多くのプロセスが動いている中で「特になにもすることがない」ことをどうやって判定したらいいでしょうか。
Androidには PowerManager.WakeLock http://developer.android.com/reference/android/os/PowerManager.WakeLock.html というクラスがあって、このロックを取得することで、CPUのサスペンドや画面のオフを防ぐことができます。
wakelockでは以下のようなパターンが使われています。これはたとえばユーザが携帯のスイッチをおした時になんかしらの定期作業(メールチェックとか)を行なうものプログラムだと思ってください。
select(); //kernel will grab a wakelock when event occurs wake_lock(); read(); //kernel will drop wakelock when data is read do_stuff() wake_unlock();
このプログラムはまず select() を使ってなにかしら event が来るまで sleep します。ここで他にサスペンドを阻害するものがなければ、携帯全体がサスペンドします。
さて、そこでユーザが携帯のスイッチを押してサスペンドから起こします。まずカーネルが起きる処理を行ないますね。その後、サスペンドから復帰したことをその event を読もうとしてる各プロセスに通知していきます。
すると、上記のプログラムは select() をぬけて 「read() でイベントを受け取る 前に wake_lock()を使ってロックをとります」 その後、 read() で eventを受け取って お仕事して、 wakelockを解除しています。
kernel側のlockはeventを発行してから全てのプロセスがeventをreadするまでで、userland側のlockはwake_lock()からwake_unlock()までになっています。つまり、このコードのようにするとlockされている期間がkernel側とuserland側とでoverlapしますね。こうすることで「カーネルからのeventを受け取って」から「userland側がwakelockを取得する」までの間にサスペンドに入ってしまうことを防止しています。
さて…Linuxでもそのようなものを実装しようとして 「[RFC] Proposal for optimistic suspend idea. http://lwn.net/Articles/460560/ 」というRFCがありました。この提案の中では「サスペンドできない時は、重要なプロセスが動作している」という点に注目して、新たなスケジューラクラス SCHED_STAYAWAKE を追加しています。ここに所属しているプロセスがある間はサスペンドをしないようにしよう、というpatchになっています。 さきほど解説したoverlapの部分もうまく対処されていますが、それは元のメールを読んでください。
ところが、このpatchはスケジューラに手を入れるものだったので反対が多く、そもそもユーザランド側でそういう「ロックをとりまとめるデーモン」を作るべきだ、というような話になりました。
そのデーモンはこんな仕様になります。
- これからsuspendしようとしていることを登録しておいたプロセスに通知すること
- 通知されたプロセスが「OK」または「だめ!」を返答するのを待機すること
- 別個にいまはsuspendしてはいけないことを登録しておけること
- suspend要求を受け付けること
- 次にsuspendから復帰した時に登録しておいたプロセスに通知すること
そうするとsuspend/resumeは全体として
- 「suspendしてはいけない」という登録がないこと・suspendから復帰中でないことを確認
- suspendすることを知りたいプロセスに通知
- 返答を待って全て「OK」かどうか確認
- この返答待ちの間に、suspendを通知されたいプロセスが増えていないかどうかを確認 (増えていたら再度通知)
- 実際のsuspend処理を開始……
- …………………………
- suspendから復帰
- suspendから復帰したことをプロセスに通知
- 全てのプロセスから処理完了したことが通知されるまでは新たなsuspendを防止する
というような流れになります。
と、ここで最初に戻ると…この daemon の実装として、ファイルシステムの排他ロック・共有ロックなどを利用した 「lsusd - The Linux SUSpend Daemon」という実装が出てきた、という話になります。
http://permalink.gmane.org/gmane.linux.kernel/1206042
Linuxはkernelとuserlandとの実装が別個に進められていて、BSDと比べてこういった境界部分をどっちで実装していくのか、そして本当に実装するのか、kernelではないなら誰が実装していくのかが不透明でちょっと困りものです。 しかし suspend 機能はこれからどんどん重要度が増していくでしょうから、うまく実装が進んで各distroに採用されていってほしいものですね。