[English Page][Japanese Page]

tmpfs の謎


SunOS 4.1.4 の tmpfs には、カーネルが panic する3つのバグがあります。そのうち2つは patch が一応存在しますが、最後の一つ、シンボリックリンクのバグについては、未だに patch が存在しません。ここでは、SunOS 4.1.4 の tmpfs のバグ3種類に対する解決方法を紹介します。
■まず、tmpfs を使っているかどうかの確認

Solaris 2.x/7 では、tmpfs はデフォルトで使用されますが、SunOS 4.1.4 では、tmpfs を使うための設定が、/etc/rc.local の中で、デフォルトではコメントアウトされています。

そこでまず、本当に tmpfs を使っているかどうか確認する必要があります。 以下のようなコマンドの出力が得られれば、tmpfs が使われています。

  $ mount -p | grep swap
  swap      /tmp tmp rw           0 0
  $ df | grep swap
  swap                   90196      32    90164      0%   /tmp

もし、tmpfs が使われていなかった場合は、/etc/rc.local の中に書かれている
# mount /tmp
のコメントを外し、ついでに安全のため、
mount -v /tmp; chmod +t /tmp
と書き換え、さらに /etc/fstab の中に、
swap /tmp tmp rw 0 0
という行を追加します。これでリブートすれば(または直接 mount /tmp を実行すれば) tmpfs が使われるようになります。


■3種類の tmpfs のバグ

●FIFO ハードリンクのバグ

How to repeat:
  $ cd /tmp
  $ mknod aaa p
  $ ln aaa bbb    # must be hard-link (not symbolic-link)
  $ ls -l

BAD TRAP:

解決方法:

SunOS 4.1.4用の patch は何故か出ていません。そこで、SunOS 4.1.3用、または SunOS 4.1.3_U1用の patch を敢えて当てます。

100507-06 (SunOS 4.1.3用) または、
102396-01 (SunOS 4.1.3_U1用) の中の、
tmp_vnodeops.o のみを使います。

patch の中には、他にも tmp_*.o が入っていますが、これらは、すでに SunOS 4.1.4 には統合済みだったり(リリースノートによると100507-05 までは統合済み)、別の patch で更に置き換わるため、 必要ありません。


●削除ディレクトリ書き込みのバグ

How to repeat:
  $ mkdir /tmp/aaa
  $ cd /tmp/aaa
  $ rmdir /tmp/aaa
  $ touch bbb
  $ cd /

assertion failed: tp->tn_dir == NULL

解決方法:

こちらは、SunOS 4.1.4用の patch が出ています。
103314-01 を当てます。
tmp_dir.o が置き換わります。

・ここまでの tmpfsカーネルpatch のまとめ
tmp_dir.o       --  103314-01 の tmp_dir.o で置き換え
tmp_subr.o      --  SunOS 4.1.4 オリジナルのまま
tmp_tnode.o     --  SunOS 4.1.4 オリジナルのまま
tmp_vfsops.o    --  SunOS 4.1.4 オリジナルのまま
tmp_vnodeops.o  --  100507-06 または 102396-01 の tmp_vnodeops.o で置き換え


●書き込み不可シンボリックリンクのバグ

How to repeat:
  $ cd /tmp
  $ mkdir aaa
  $ chmod -w aaa
  $ cd aaa
  $ ln -s bbb ccc    # must be symbolic-link (not hard-link)

panic: kmem_free: block already free

解決方法:

このバグの patch は、今現在もまだ出ていません。

以前は、workaround のためのプログラムを、カーネルに modload して解決したりもしました。

今ここに、adb で、カーネルの問題の部分を修正する方法を紹介します。

vmunixadb で見て、以下の部分に注目して下さい。

tmp_symlink+164?i
_tmp_symlink+0x164:             call    _tmp_memfree

書き込み不可のディレクトリに、シンボリックリンクを作ろうとすると、 この部分を通ります。しかし、この時点で tmp_memfree() を呼ぶ必要はなく(すでに kmem_free されている)、この call 命令がバグの原因と判断しました。

これを nop で置き換えればバグが解決することを確認しています。

実際には、vmunix のバイナリ自体は修正せず、SunOS のブート時に以下のようなスクリプトを /etc/rc.local などから起動して、ロードされたカーネルを書き換えるという方法が 安全だと思います。

tmp_symlink-fix (ブート時に adb を実行するスクリプト)
#!/bin/sh

set - `echo 'tmp_symlink+164/i' | adb -k /vmunix /dev/mem | tail -1`

if [ "$1" = '_tmp_symlink+0x164:' -a "$2" = 'call' -a "$3" = '_tmp_memfree' ]
then
  echo \
'tmp_symlink+164/i
/W1000000
/i' | adb -k -w /vmunix /dev/mem
else
  echo "$@" '-- not call _tmp_memfree'
fi
■さいごに

これら tmpfs のバグについて、正式な patch が出ることを望みたいものです。 また、いつか将来、SunOS 4.1.4 のソースが公開された場合には、自分で再度、上記バグの原因を検証したいとも 思っています。


To 謎の処理系 SunOS 4.1.4 Home
yamamori