@naota344の今週のLKML

今週は

  • [PATCH] per-cgroup tcp buffer limitation
  • [RFC PATCH 0/2] block: Allow extending partition size online
  • [PATCH RFC] epoll: limit paths

[PATCH] per-cgroup tcp buffer limitation

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

TCPのコネクションが使用するカーネルのメモリ量をcgroupで制限できるようにするパッチです。もともと /proc/sys/net/ipv4/tcp_mem を使えば制限はできるのですが、さらにcgroupごとに制限をかけていきます。

http://permalink.gmane.org/gmane.linux.kernel.containers/21295

もともとのRFCがこのcontainersで行なわれていたことから分かるとおり、もとはコンテナごとの制限をめざしていたようです。

それにしても、どんどんcgroupに機能が投入されていきますね…。しかし、こういうサポートが進んでいけばLinuxコンテナを使用したお手軽な仮想サーバ作りが便利になるでしょうね。

[RFC PATCH 0/2] block: Allow extending partition size online

http://permalink.gmane.org/gmane.linux.kernel/1187135

マシンの起動中にパーティションのサイズを大きくできるようにするためのpatchです。とは言えパーティションテーブルをいじるコードが入っているわけではありません。まず、fdiskなどでパーティションテーブルを編集し、新しく追加されたコマンドextedpartでカーネルパーティションサイズの認識を変更する、という手段をとります。

http://permalink.gmane.org/gmane.linux.kernel/1187133

ということが、マシンを再起動することなくできるようになるようです。

[PATCH RFC] epoll: limit paths

http://permalink.gmane.org/gmane.linux.kernel/1187571

このようなプログラムを書きます

#include <unistd.h>
#include <sys/epoll.h>

int main(void) {
    int e1, e2, p[2];
    struct epoll_event evt = {
        .events = EPOLLIN
    };

    e1 = epoll_create(1);
    e2 = epoll_create(2);
    pipe(p);

    epoll_ctl(e2, EPOLL_CTL_ADD, e1, &evt);
    epoll_ctl(e1, EPOLL_CTL_ADD, p[0], &evt);
    write(p[1], p, sizeof p);
    epoll_ctl(e1, EPOLL_CTL_ADD, e2, &evt);

    return 0;
}

epollは基本的には複数のファイルデスクリプタを登録して、その中のどれかが(読みこみ可能|書きこみ可能|シャットダウン)などなど状態の変化あるいはイベントなどを検出できるような機能ですね。epoll_create()で作って、epoll_ctl(epoll_fd,EPOLL_CTL_ADD, fd, &evt)という形でepoll_fdにfdがevtで指定したeventが起きた時に検出するように登録します。

このコードだと下の図のようになっています

見事に循環してますね…。こうしてしまうとまあ予想通りにdeadlockが発生します。p[1]への書きこみでp[0]が読みこみ可能になり、それがe1に伝えられ、e1が読みこみ可能になり、e2に伝えられ…というわけです。

これに対処するためにcommit 22bacca48a1755f79b7e0f192ddb9fbb7fc6e64e というのが二月にあてられているのですがこれは総当たりしてループがないかどうか、をチェックするようになっていて https://lkml.org/lkml/2011/2/25/297 のコードのように大きなepollのグラフではかなりの時間をかけてチェックすることになってしまいます。これに対応するために前述の https://lkml.org/lkml/2011/2/25/297 ではvisitしたepollfdを覚えておくといった対応がとられているのですが、いずれにせよこのような大きなツリーでは、ループがなくともどこかに(たとえば)書きこみがあってwakeupが連鎖する時にこのループを行なわざるをえなくなっています。……ということで一端これは忘れられたようです……。

今回のpatchはあるepollfdから到達できるfdの数を制限しています。 patchでは

int path_limits[PATH_ARR_SIZE] = { 1000, 500, 100, 50, 10 };

となっていて、直接つながっているのは1000まで、2-popでつながっているのは500まで…というふうになっています。