Hatena::ブログ(Diary)

Emacs ひきこもり生活 このページをアンテナに追加 RSSフィード

2013-10-30

Emacsを高速起動せよ #kansaiemacs

| 14:01 |  Emacsを高速起動せよ #kansaiemacsを含むブックマーク

この前の関西Emacsで発表?した内容を完結させた感じのエントリです。この動画の説明です。

D

みんなEmacsを高速起動したいですよね。ぼくもしたいです。 今回はカーネルの視点からEmacsを高速起動しちゃうよ。

まず実験用に ~/nisehome をHOMEにしてmelpaのパッケージをほぼ全てインストールして、さらにほとんどのパッケージ内のelispをrequireします。すると、めっちゃ起動が遅くなってくれます。具体的に見てみると

$ echo 3 | sudo tee /proc/sys/vm/drop_caches
$ HOME=$HOME/nisehome emacs

で(ファイルキャッシュを全て落としてから)起動してやって (emacs-init-time) を見てやると "348.6 seconds" となってます。だいぶおそいですね。やばい感じです。

このままでは今回の高速起動の対象にはできないので、まず新しいnamespaceに閉じ込めて、VNCの中でEmacsを起動します。

criu のwikiページ VNC - CRIU から newns.c とシェルスクリプトをとってきて起動します。

# ./newns ./newvnc env HOME=/home/naota/nisehome DBUS_SYSTEM_BUS_ADDRESS=unix:/tmp/foo /usr/bin/emacs

ここで DBUS_SYSTEM_BUS_ADDRESS を存在しないダミーのファイルに設定することで、システムのdbus、すなわちnamespaceの外のプロセスとのunix socket接続を防止します。

"vncviewer localhost:5925" するとEmacsが立ち上がっていくのがわかります。

pstreeでnewvncのプロセスIDを確認し、このプロセスツリーをダンプします。 lsすると大量にファイルができているのがわかります。ダンプされたデータです。 さらに pstree|grep vnc してもなにも出てきません。さっきあった VNCEmacsプロセスは全てダンプされて、停止されています。

# pstree -p|grep Xvnc
        |-newvnc(15079)-+-Xvnc(15080)-+-{Xvnc}(15083)
        |               |             |-{Xvnc}(15084)
        |               |             |-{Xvnc}(15085)
        |               |             `-{Xvnc}(15086)
# mkdir emacs-dump; cd emacs-dump
# criu dump -t 15079 --tcp-established
# ls
core-1.img    core-7.img         fdinfo-12.img      filelocks-49.img  ids-2.img        itimers-2.img      packetsk.img     pages-7.img           rlimit-103.img   sigacts-49.img    signal-p-5.img    tunfile.img
core-103.img  core-9.img         fdinfo-2.img       filelocks-9.img   ids-20.img       itimers-20.img     pagemap-1.img    pages-8.img           rlimit-106.img   sigacts-9.img     signal-p-6.img    unixsk.img
core-104.img  creds-1.img        fdinfo-3.img       fs-1.img          ids-23.img       itimers-23.img     pagemap-103.img  pages-9.img           rlimit-13.img    signal-p-1.img    signal-p-7.img    utsns-1.img
core-106.img  creds-103.img      fdinfo-4.img       fs-103.img        ids-49.img       itimers-49.img     pagemap-106.img  pipes-data.img        rlimit-14.img    signal-p-103.img  signal-p-9.img    vmas-1.img
core-107.img  creds-106.img      fdinfo-5.img       fs-106.img        ids-9.img        itimers-9.img      pagemap-13.img   pipes.img             rlimit-16.img    signal-p-104.img  signal-s-1.img    vmas-103.img
core-109.img  creds-13.img       fdinfo-6.img       fs-13.img         ifaddr-1.img     mm-1.img           pagemap-14.img   posix-timers-1.img    rlimit-2.img     signal-p-106.img  signal-s-103.img  vmas-106.img
core-13.img   creds-14.img       fdinfo-7.img       fs-14.img         inetsk.img       mm-103.img         pagemap-16.img   posix-timers-103.img  rlimit-20.img    signal-p-107.img  signal-s-106.img  vmas-13.img
core-14.img   creds-16.img       fdinfo-8.img       fs-16.img         inotify-wd.img   mm-106.img         pagemap-2.img    posix-timers-106.img  rlimit-23.img    signal-p-109.img  signal-s-13.img   vmas-14.img
core-16.img   creds-2.img        fdinfo-9.img       fs-2.img          inotify.img      mm-13.img          pagemap-20.img   posix-timers-13.img   rlimit-49.img    signal-p-13.img   signal-s-14.img   vmas-16.img
core-17.img   creds-20.img       fifo-data.img      fs-20.img         inventory.img    mm-14.img          pagemap-23.img   posix-timers-14.img   rlimit-9.img     signal-p-14.img   signal-s-16.img   vmas-2.img
core-19.img   creds-23.img       fifo.img           fs-23.img         ipcns-msg-1.img  mm-16.img          pagemap-49.img   posix-timers-16.img   route-1.img      signal-p-16.img   signal-s-2.img    vmas-20.img
core-2.img    creds-49.img       filelocks-1.img    fs-49.img         ipcns-sem-1.img  mm-2.img           pagemap-9.img    posix-timers-2.img    sigacts-1.img    signal-p-17.img   signal-s-20.img   vmas-23.img
core-20.img   creds-9.img        filelocks-103.img  fs-9.img          ipcns-shm-1.img  mm-20.img          pages-1.img      posix-timers-20.img   sigacts-103.img  signal-p-19.img   signal-s-23.img   vmas-49.img
core-21.img   eventfd.img        filelocks-106.img  ghost-file-1.img  ipcns-var-1.img  mm-23.img          pages-10.img     posix-timers-23.img   sigacts-106.img  signal-p-2.img    signal-s-49.img   vmas-9.img
core-23.img   eventpoll-tfd.img  filelocks-13.img   ids-1.img         itimers-1.img    mm-49.img          pages-11.img     posix-timers-49.img   sigacts-13.img   signal-p-20.img   signal-s-9.img
core-24.img   eventpoll.img      filelocks-14.img   ids-103.img       itimers-103.img  mm-9.img           pages-2.img      posix-timers-9.img    sigacts-14.img   signal-p-21.img   signalfd.img
core-4.img    fanotify-mark.img  filelocks-16.img   ids-106.img       itimers-106.img  mountpoints-1.img  pages-3.img      pstree.img            sigacts-16.img   signal-p-23.img   sk-queues.img
core-49.img   fanotify.img       filelocks-2.img    ids-13.img        itimers-13.img   netdev-1.img       pages-4.img      reg-files.img         sigacts-2.img    signal-p-24.img   stats-dump
core-5.img    fdinfo-10.img      filelocks-20.img   ids-14.img        itimers-14.img   netlinksk.img      pages-5.img      remap-fpath.img       sigacts-20.img   signal-p-4.img    tty-info.img
core-6.img    fdinfo-11.img      filelocks-23.img   ids-16.img        itimers-16.img   ns-files.img       pages-6.img      rlimit-1.img          sigacts-23.img   signal-p-49.img   tty.img
# pstree -p|grep vnc

では、復活させてみましょう。 キャッシュを落としてから復活させても 1秒で復活しています。 これが終わればふたたび "vncviewer localhost:5925" でつなげば Emacsの画面が出てきます。 elispを全て読み終わった状態でdumpしているので、elispの解析やら実行やらが全てスキップされて高速化しているわけですね。

# echo 3 > /proc/sys/vm/drop_caches
# time criu restore --tcp-established -d
(00.071714)    107: Error (image.c:213): Unable to open vmas-107.img: No such file or directory

real    0m1.240s
user    0m0.000s
sys     0m0.010s

ここで、つないだ VNC で C-x C-c します。当然 EmacsVNCが終了します。 ではもう一度 restore して vncviewer でつないでみましょう。

# time criu restore --tcp-established -d
(00.065680)    107: Error (image.c:213): Unable to open vmas-107.img: No such file or directory

real    0m0.422s
user    0m0.000s
sys     0m0.010s

ふたたび EmacsVNCで動いているのが見てとれるかと思います。サイコーですね。 Emacsは死なぬ! 何度でもよみがえるさ! ってやつです。



最後に背景について見ていきましょう。 今回使ったのは CRIU (checkpoint/restore in userspace)というものです。 これはプロセスの状態をディスクにダンプし、そのダンプデータからプロセスを再開するものです。

通常はXへの描画などをしていると Xと Emacs間の通信が切れてしまうのでX上で動く Emacsをダンプすることはできません。しかし、EmacsVNC上で起動し、さらに1つの独立した namespace上でVNC(とEmacs)を起動します。 これでVNC下のプロセスをまとめてダンプできるようになります。

criuコマンドを使うにはカーネル3.11以上が必要です。さらに、いくつかカーネルの設定が必要です。 以下のものを有効にしておいてください。

  • CHECKPOINT_RESTORE
  • FHANDLE
  • EVENTFD
  • EPOLL
  • INOTIFY_USER
  • IA32_EMULATION
  • UNIX_DIAG
  • INET_DIAG
  • INET_UDP_DIAG
  • PACKET_DIAG
  • NETLINK_DIAG

criuコマンドは気のきいたディストリビューションならパッケージがあるかと思います。 Gentooにはありますし、emerge時に以上のカーネル設定もチェックしてくれるので間違いがありません。 お使いのディストリビューションの気がきいていなければ、 Gentoo をいれてみるのもいいでしょう。これから寒くもなりますし。

criuコマンドが入ったら"criu check"もしておきましょう。基本的なチェックが走ります。あとはおまけですが iptablesとか tunとかもいれとくといいです。 TCP接続を保ったままダンプできたりしてクールです。

2013-09-24

Gentooビルドクラスタを作りたいということ 多分次のGenTwooに向けて

| 02:34 |  Gentooビルドクラスタを作りたいということ 多分次のGenTwooに向けてを含むブックマーク

https://github.com/naota/portage-daemon

最近こんなのを作ってた。

linux.yaml

master:
  address: localhost
builder:
  command: sudo emerge -1 %s 2>&1 || true
  target: linux.amd64

fbsd.yaml

master:
  address: localhost
builder:
  command: ssh root@<IP> emerge -1 %s 2>&1 || true
  target: fbsd.x86

manager.yaml

master:
  address: localhost
manager:
  builder: Builder
  command: Command
  state-file: manager-state.dump

とかして、RabbitMQを起動してから "./builder linux.yaml", "./builder fbsd.yaml", "./manager manager.yaml"を起動する。

そして "./control manager.yaml build linux.amd64 newt"とかするとローカルで"emerge -1 newt"が走るし、"./control manager.yaml build fbsd.x86 freebsd-lib"とすると、どこかのIPのホストでsshこしに"emerge -1 freebsd-lib"が走る。今回はbuilderを"linux.amd64"と"fbsd.x86"を1つずつしか立ちあげてないけれど、別のyaml書いて、たとえば"linux.amd64"をうけつけてsshでどっかのGentoo Linux上でemerge -1するように書くとそっちにも適当に(たしかラウンドロビンに?)分散される。

emergeの結果はこのように確認できる。

% ./control manager.yaml jobs                  
86d3c69a-d35d-400e-b5fe-43131eb4bd94 New      linux.amd64       newt
e00c060f-7baf-4846-8100-fb7ab605d4e6 Done     linux.amd64       newt

左端がジョブのUUIDになっているので、これを使って結果を取得する。

% ./control manager.yaml result e00c060f-7baf-4846-8100-fb7ab605d4e6
Calculating dependencies  .. ... .. .. ... done!

>>> Verifying ebuild manifests

>>> Emerging (1 of 1) dev-libs/newt-0.52.15
 * newt-0.52.15.tar.gz SHA256 SHA512 WHIRLPOOL size ;-) ...              [ ok ]
...
ecompressdir: bzip2 -9 /usr/share/man
ecompressdir: bzip2 -9 /usr/share/doc

>>> Installing (1 of 1) dev-libs/newt-0.52.15
>>> Auto-cleaning packages...

>>> No outdated packages were found on your system.

 * GNU info directory index is up-to-date.

と、こんな感じでemergeの出力が全部とれる。

まあ、わかりにくいので図にしておくとこんな感じ

f:id:meech:20130925023302p:image




で、なんでこんなのを作った(作っている)のかというと、1つはGentooのbugzillaにバグレポがいっぱい来て自分の手元で再現実験したり、patch書いてそれが直ってるか確認したりするんだけど、いくつも平行でやってるとどれがどういう状況だったのか忘れてしまったり、emergeが多くなりすぎて重くなったりして困ることである。これを使えば1つのマシンで走るemergeは高々1つになるし、出力もちゃんと(一応)永続的に確認できる。

もう1つは「次の世代のGenTwoo」を実現するため。GenTwooはもともともっとバグレポなどのコラボレーションの敷居というのを下げたいという目的で作っている。最終的にはとりあえず起動しているだけでなにかしらの貢献ができる、という形にしたいのだ。たとえば、新しく入ったebuildが本当にビルドできるのかどうかチェックしたり、ビルドしてエラーが出たらその出力を開発者のところに送りかえしたり、うまくビルドできたという情報・エラーが出ているという情報を集めて統計をとってどのぐらいebuildが安定しているのかの指標にしたり、その指標に従って自動アップデートがかかるかどうかの参考にしたり、バイナリパッケージを提供したりする。そのようなつながりを持ったdistroを実現したいのだ。

その第一歩として、とりあえずビルド命令を受け付けるプロセスは全てローカルで動く(だからsshでemergeの走るマシンにつなぐ)・標準出力がそのまんま結果としてとれる・実行の指定はシェルコマンドそのまんまという大変に原始的な形だが一応クラスタにできそーなものを作ってみた。

これから

  • emerge出力の解析によるエラー判定
    • それを使ったUSEフラグの調整など
  • リモートでビルド命令を受け付けできる
  • ebuildにこのpatchをあてた状態でemergeとかUSEをこうしてなど、編集を加えたemergeの実現
  • バイナリパッケージをキャッシュクラスタ上のマシンに提供するプログラム
  • 隔離された環境(kvmlxrなど)でのemergeを実現する
  • SQLiteとかDBを使う
  • ほんとにHaskellで書いてていいのか(

などとやりたいことは多いし、実際にインターネット越しに展開しようとするとセキュリティ面で考慮することはもっと多いだろう。

まあ、でもこんなことをやりたいしやれたらおもしれーんじゃないかな、と思っている。

2013-09-17

おれがsudoできないのはどう考えてもmetalogが悪い話

| 21:10 |  おれがsudoできないのはどう考えてもmetalogが悪い話を含むブックマーク

最近、"sudo emerge" などしようとするとその時点で動きが止まってしまうことが多々あってまーたbtrfsか?と思っていました。でも、psを見てもSTATEは"D"になってないし、btrfsぽくはない。そんなある日metalogを強制終了してやると、止まっていたsudoが動きだすことに気がついたのです。さて、いったいmetalogがなにがどーしてsudoを止めているのかな?

こういう状況の時

  • metalogの下にconsolelog.shがゾンビになってたくさんぶらさがっている
  • metalogのmasterプロセスをstraceするとwriteの途中で止まっている
  • gdbでmetalogのmasterプロセスをbacktraceするとmetalog.cのsignal_doLog_queue()で止まっている

ことがわかります

signal_doLog_queue() はこうなっていて、ここのwriteで停止しています。

static void signal_doLog_queue(const char *fmt, const unsigned int pid, const int status)
{
    ssize_t ret;
    unsigned int fmt_len = (unsigned int)strlen(fmt);
    char buf[sizeof(pid) + sizeof(status) + sizeof(fmt_len)];
    memcpy(buf, &pid, sizeof(pid));
    memcpy(buf+sizeof(pid), &status, sizeof(status));
    memcpy(buf+sizeof(pid)+sizeof(status), &fmt_len, sizeof(fmt_len));
    ret = write(dolog_queue[1], buf, sizeof(buf));
    assert(ret == sizeof(buf));
    ret = write(dolog_queue[1], fmt, fmt_len);
    assert(ret == fmt_len);
}

ここでwriteされているdolog_queueは、このようにsocketかpipeになっています。

    /* setup the signal handler pipe */
    if (socketpair(AF_LOCAL, SOCK_STREAM, 0, dolog_queue) < 0) {
        if (pipe(dolog_queue) < 0) {
            warnp("Unable to create a pipe");
            return -4;
        }
    }

すると読みだしは誰なんだ?というのが気になるところで、読みだしているのは、このmetalogのメイン関数であるprocess()になっています

static int process(const int sockets[])
{
...
    siglog = syslog = klog = NULL;
    nfds = 0;

    siglog = &fds[nfds];
    fds[nfds].fd = dolog_queue[0];
    fds[nfds].events = POLLIN | POLLERR | POLLHUP | POLLNVAL;
    fds[nfds].revents = 0;
...
    for (;;) {
        while (poll(fds, nfds, -1) < 0 && errno == EINTR)
            ;

        /* Signal queue */
        if (siglog && siglog->revents) {
            event = siglog->revents;
            siglog->revents = 0;
            if (event != POLLIN) {
                warn("Signal queue socket error - aborting");
                close(siglog->fd);
                return -1;
            }

            signal_doLog_dequeue();
        }

こんな感じでpollで読めるfdを見つけて読むという単純なやつですね。 問題になるのが、socketなりpipeなりを自分で読んで自分で書いてます。だから、socketなりのバッファがいっぱいになると相手が読み出してくれるまで待つのだけれど、その読む相手というのがwriteで待っている自分なわけで完全にmetalogが停止してしまう、というわけですよ。(具体的にsocketのバッファサイズを調べたりしたかったがうまくいかず)

さて、じゃあなんでそんなにいっぱいになるほどwriteされてるのか?という問題に入ります。

signal_doLog_queue()はもともと、 SIGCHLDのシグナルハンドラである sigchld(int sig)から、子プロセスが0以外の終了ステータスとなった時に呼ばれている関数です。つまり、最初に書いていた consolelog.shが0以外の返り値で死んだ場合にログが書かれています。

consolelog.shはたったこれだけでエラーになりそうなのは evalの書きこみのところだけですね。

#!/bin/sh
# consolelog.sh
# For metalog -- log to a console

set -f

. /etc/conf.d/metalog
if [ -z "${CONSOLE}" ] ; then
	CONSOLE="/dev/console"
fi

if [ -z "${FORMAT}" ] ; then
	FORMAT='$1 [$2] $3'
fi

for d in ${CONSOLE} ; do
	eval echo ${FORMAT} > ${d}
done

exit 0

"while : ;do echo foo > /dev/tty10;done"などと書いたスクリプトを大量に実行してみるとIOエラーがすぐに出てエラーで死んでくることがわかるかと思います。

結局のところまとめると

  • btrfsが大量にWARNを発生
  • metalogがそれをconsolelog.shを使って書こうとする
  • 同時に書こうとするのでコンソールがIOエラー
  • 多くのconsolelog.shが0以外のステータスで終了
  • シグナルハンドラでsocketに書こうとするがバッファがいっぱいで読みだされるまで止まる
  • writeで止まっているから読みだし側の処理が行なわれない

こんなことがmetalogで起こっている。 大量のログ書きこみ自体は手元でloggerでやろうとしてもうまくいかないので、なかなか再現できない。

sudoできなくなるのはとてもつらいので、別のloggerに乗り換えようかな。

トラックバック - http://d.hatena.ne.jp/meech/20130917

2013-07-16

最近のbtrfsの話(linus head) cleaner の lock とか

| 21:30 |  最近のbtrfsの話(linus head) cleaner の lock とかを含むブックマーク

最近、うちのbtrfsはよくこういうエラーで死んでいて

% cd /sys/fs/pstore
% cat dmesg-efi-3 dmesg-efi-2 dmesg-efi-1                                                                                                                                                                                                                   
Oops#1 Part3
<3>[16662.858996] [drm:ring_stuck] *ERROR* Kicking stuck wait on render ring
<7>[17728.729197] BTRFS debug (device sde1): unlinked 3 orphans
<7>[17912.803995] BTRFS debug (device sde1): unlinked 8 orphans
<4>[21166.871256] general protection fault: 0000 [#1] SMP 
<4>[21166.871287] Modules linked in: macvtap macvlan ebtables xt_CHECKSUM iptable_mangle hwmon_vid nfsd auth_rpcgss oid_registry nfs_acl lockd sunrpc i915 snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_intel i2c_algo_bit intel_agp intel_gtt drm_kms_helper snd_hda_codec drm agpgart i2c_i801 pata_via
<4>[21166.871414] CPU: 7 PID: 258 Comm: btrfs-cleaner Tainted: G        W    3.11.0-rc1+ #271
<4>[21166.871439] Hardware name: System manufacturer System Product Name/P8H67-M PRO, BIOS 3806 08/20/2012
<4>[21166.871469] task: ffff8805fb0c0000 ti: ffff8805faff0000 task.ti: ffff8805faff0000
<4>[21166.871493] RIP: 0010:[<ffffffff812e70c9>]  [<ffffffff812e70c9>] btrfs_clean_one_deleted_snapshot+0x49/0x150
Oops#1 Part2
<4>[21166.871527] RSP: 0018:ffff8805faff1e70  EFLAGS: 00010283
<4>[21166.871546] RAX: dead000000200200 RBX: ffff880323212458 RCX: 0000000000003b79
<4>[21166.871569] RDX: dead000000100100 RSI: 0000000000000246 RDI: ffff8805fb52c798
<4>[21166.871591] RBP: ffff8805faff1e88 R08: 0000000000000000 R09: 0000000000000001
<4>[21166.871612] R10: 0000000000000000 R11: 0000000000000000 R12: ffff8805fb52c000
<4>[21166.871633] R13: ffff880323212000 R14: ffff8805fb0c0000 R15: 0000000000000000
<4>[21166.871655] FS:  0000000000000000(0000) GS:ffff88061f3c0000(0000) knlGS:0000000000000000
<4>[21166.871680] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
<4>[21166.871698] CR2: 000012db7ef1c008 CR3: 000000000ec0c000 CR4: 00000000000427e0
<4>[21166.871719] Stack:
<4>[21166.871730]  ffff8805fb48a800 ffff8805fb0c0000 ffff8805fb0c0000 ffff8805faff1ec8
<4>[21166.871759]  ffffffff812df5d0 0000000000000000 ffff8805fb817a48 ffff8805fb48a800
Oops#1 Part1
<4>[21166.871786]  ffffffff812df4b0 0000000000000000 0000000000000000 ffff8805faff1f48
<4>[21166.871815] Call Trace:
<4>[21166.871829]  [<ffffffff812df5d0>] cleaner_kthread+0x120/0x180
<4>[21166.871847]  [<ffffffff812df4b0>] ? check_leaf.isra.41+0x310/0x310
<4>[21166.871869]  [<ffffffff810aa4d0>] kthread+0xc0/0xd0
<4>[21166.871886]  [<ffffffff810aa410>] ? kthread_create_on_node+0x120/0x120
<4>[21166.871910]  [<ffffffff81703f1c>] ret_from_fork+0x7c/0xb0
<4>[21166.871930]  [<ffffffff810aa410>] ? kthread_create_on_node+0x120/0x120
<4>[21166.871951] Code: 3e 47 41 00 49 8b 9c 24 d8 07 00 00 49 8d 84 24 d8 07 00 00 48 39 c3 0f 84 c5 00 00 00 48 8b 43 08 4c 8d ab a8 fb ff ff 48 8b 13 <48> 89 42 08 48 89 10 48 b8 00 01 10 00 00 00 ad de 48 89 03 48 
<1>[21166.872091] RIP  [<ffffffff812e70c9>] btrfs_clean_one_deleted_snapshot+0x49/0x150
<4>[21166.872117]  RSP <ffff8805faff1e70>
<4>[21166.876524] ---[ end trace fa76c497d23a7946 ]---

まあ、cronでsnapshotをdeleteしているタイミングで(確率的に)死んでるからそのcron jobとめればいいんだけど、それも気持ちわるいので放置してn時間に1回再起動している。

死んでる当該部分は fs/btrfs/transaction.c の

int btrfs_clean_one_deleted_snapshot(struct btrfs_root *root)
{
	int ret;
	struct btrfs_fs_info *fs_info = root->fs_info;

	spin_lock(&fs_info->trans_lock);
	if (list_empty(&fs_info->dead_roots)) {
		spin_unlock(&fs_info->trans_lock);
		return 0;
	}
	root = list_first_entry(&fs_info->dead_roots,
			struct btrfs_root, root_list);
	list_del(&root->root_list);
	spin_unlock(&fs_info->trans_lock);

この list_del のところ。 で、 list_delで dumpのRAXとRDXに "dead000000200200" と "dead000000100100" って出ているのでわかる人にはわかるかと思うのだけど、 &root->root_list が list に入ってないのに del_list してることになってる(正確にはlistにいれて消したのにまた消そうとしているはず)

このコードの部分は trans_lockで spinlock されてるし 他の部分も

inode.c

			spin_lock(&fs_info->trans_lock);
			list_for_each_entry(dead_root, &fs_info->dead_roots,
					    root_list) {
				if (dead_root->root_key.objectid ==
				    found_key.objectid) {
					is_dead_root = 1;
					break;
				}
			}
			spin_unlock(&fs_info->trans_lock);

transaction.c

int btrfs_add_dead_root(struct btrfs_root *root)
{
	spin_lock(&root->fs_info->trans_lock);
	list_add_tail(&root->root_list, &root->fs_info->dead_roots);
	spin_unlock(&root->fs_info->trans_lock);

ちゃんと trans_lock で lockされてるし、あやしげな

disk-io.c

static void del_fs_roots(struct btrfs_fs_info *fs_info)
{
	int ret;
	struct btrfs_root *gang[8];
	int i;

	while (!list_empty(&fs_info->dead_roots)) {
		gang[0] = list_entry(fs_info->dead_roots.next,
				     struct btrfs_root, root_list);
		list_del(&gang[0]->root_list);

		if (gang[0]->in_radix) {
			btrfs_drop_and_free_fs_root(fs_info, gang[0]);
		} else {
			free_extent_buffer(gang[0]->node);
			free_extent_buffer(gang[0]->commit_root);
			btrfs_put_fs_root(gang[0]);
		}
	}

これも、 open_ctreeとclose_ctreeからだけ呼ばれてこのタイミングでは cleaner スレッドは止まっているはずなので、こことぶつかってることはありえない…(と思う)



そーすると、一体どこがどうなって btrfs_clean_one_deleted_snapshot があんな死に方をしてしまうのかまったくもって謎めいている。なにがどうなってるのやら

トラックバック - http://d.hatena.ne.jp/meech/20130716

2013-07-01

PulseAudio使ってるならカーネルのSND_HDA_PREALLOC_SIZEは2048にしとけよ?って話

| 02:11 |  PulseAudio使ってるならカーネルのSND_HDA_PREALLOC_SIZEは2048にしとけよ?って話を含むブックマーク

ここに書いてあるのそんまんまなんだけど

https://bugs.gentoo.org/show_bug.cgi?id=409625

PulseAudio使ってて、しかもサウンドがHDA IntelだったらSND_HDA_PREALLOC_SIZEってのをdefaultが64なのを2048にした方がいいらしい。

当該kernel configの説明にもそのように書いてあるのでGentoo使ってて、HDA Intelで、PulseAudio使っている人はいますぐ設定書きかえてカーネルビルドしよう。 3.10も出たしちょうどいいタイミングだよね。