@naota344の今週のLKML

今週は

  • [PATCH RFC] fadvise: move active pages to inactive list with POSIX_FADV_DONTNEED
  • [PATCH v2 0/3] support for broken memory modules (BadRAM)
  • [PATCH] Enable 'make CONFIG_FOO=y oldconfig'

[PATCH RFC] fadvise: move active pages to inactive list with POSIX_FADV_DONTNEED

http://permalink.gmane.org/gmane.linux.kernel.mm/65374

ディスクというのはメモリに比べて遅いものです。ファイルを読みこもうとするたびに、いちいちディスクにアクセスするのでは時間がかかってしょうがありません。そこで「最近アクセスされたデータはまた近いうちにアクセスされる」という考えのもとに、アクセスしたデータをメモリにキャッシュしておきます。こうしておけば二回目以降はメモリ上のデータを読めばいいのでアクセスが速くなりますね。

さて、一般にディスク上の全てのデータをメモリに乗せておけるほどにはメモリは大きくはありません。つまり、全てをキャッシュしておくことはできないのでキャッシュしたデータを捨てなくてはいけません。では、どのデータを捨てればいいでしょうか? LinuxではLRU(Least Recently Used)といって「最近一番使われてないもの」が捨てられます。これを疑似的に実装するために FILO なリストが使われています。リストの先頭から順にキャッシュを捨てていって、新しいキャッシュはリストの末尾に追加されます。

実装はこれだけで十分でしょうか? ひとつ例を考えてみましょう。

「大きなファイルをたった一度だけ読みこんだ場合はどうなる?」

この場合リストが一つだけだと定期的に読みこむデータのキャッシュであろうと、一度だけ読みこむファイルのデータなんぞに追い出されてしまいますね…。

そこでLinuxでは "active" と "inactive" との2つのリストを用意しています。

  • キャッシュの破棄は inactive からだけ行なわれる
  • inactive に入っているデータが再度アクセスされると active に移される
  • active が inactive よりもある程度以上に大きくなれば、active の末尾から inactive の末尾に移される

と、いうことで一度だけ読むようなデータは inactive に入ったままなので、定期的に読みこむデータの邪魔をしなくなります。

さて、ここでまたひとつ例を考えてみましょう。

rsync を使うようなバックアッププロセスではどうなるでしょうか」

これはファイルを読みこみ、また別のところに書きこみをするのでこのデータのキャッシュは active リストに入っていきます。さっきと同じ問題になりますね…。しかし、またリストを増やすようなのはあまり好ましくありません。

ここで突然ですが posix_fadvise のご紹介。以前にこちらで紹介してましたね。 http://d.hatena.ne.jp/meech/20110502/1304353559 この POSIX_FADV_DONTNEED を使えば、指定したデータをキャッシュから削除することができます。つまり、バックアップではこれを使えばいいはず…なんです…が、

Linuxではこの fadvise は実行時に処理され、実行時にキャッシュを捨てようとして、後は fadvise していたことを覚えないようになっていました。このバックアップのようなケースでは、書きこみによってページには dirty flag がついていて、ディスクと内容が同期していないので(普通にコピーしてるだけでは)キャッシュをこの時点では捨てることはできません。これを確実に動くようにするには fadvise する前にデータをディスクに書きこんで(ページがcleanになったことを保証するために) fdatasync しておかなくてはいけません。すると、毎回ディスクに書きこみにいくわけでかなりパフォーマンスが劣化してしまいます。

参考: http://insights.oetiker.ch/linux/fadvise.html

https://lkml.org/lkml/2011/2/20/57

というわけで、ここのpatchで fadvise された時点で active で dirty な page を inactive の先頭に移し、書きこみが終わった時点で fadvise された page を inactive の先頭に移してすぐ回収されるようにして、この fadvise がうまくきかない状況に対応しています。

さあ、やっと冒頭のURLのpatchの前提ができました…。また、ひとつ例を考えます。

rsyncと同時に別のプロセスが同じデータを使ってたらどうなんの?」

他のプロセスが使っている時に、 rsync がこれもう一回しか使わないよー、と言ってきた時に上のpatchのような処理が行なわれてしまうと、使っていたデータがキャッシュが追い出されてしまいますね…。

と、いうことで active に入っているものについては inactive に移すだけで回収はされないようにしておきましょう、というのがこの patch です。これで rsync なんかのバックアップが fadvise しても他のプロセスが使っているデータにはそんなに影響が出なくなりますね。

[PATCH v2 0/3] support for broken memory modules (BadRAM)

http://permalink.gmane.org/gmane.linux.kernel.mm/65317

bootparameter に badram= という引数を追加して、アクセスしてはいけないメモリ領域を指定できるようにしようという壊れたメモリに対処しようという patch です。

とはいえ、そんな pattern なんてどうやって調べるんだ?と思っていると…

Memtest86 has an option to generate these patterns since v2.3 so the only thing
for the user to do should be:
- run Memtest86
- note down the pattern
- add badram=<pattern> to the kernel command line

とありました。 memtest86 にそんな機能があるんですね…。

[PATCH] Enable 'make CONFIG_FOO=y oldconfig'

http://permalink.gmane.org/gmane.linux.kbuild.devel/6821

oldconfig のさいに CONFIG_FOO=y などとして環境変数から .config を設定できるようにするような patch が来ていました。 スクリプトであれこれやるのには楽になりそうな変更ですね。