2011年11月 4日

[gentoojp-users:02195] Re: mount の動作

青田です。

わたしの手元のGentooおよびUbuntu 11.10でも試してみましたが、どちらでも同
じことになりますね。 mount /sysなどはちゃんとalready mountedになるので不
思議な動作になっていますね…。

まず…前提として /dev にはtmpfsというメモリ上のファイルシステムがmountさ
れていて、/sysにはsysfsというこれもメモリ上のファイルシステムがmountされ
ています。

一見、両方同じメモリ上のファイルシステムに見えますが、tmpfsは普通のファ
イルシステムのように好きにファイルやディレクトリを作りその中身を読み書き
できるのに対して、sysfsの方はあくまでもカーネルの設定変数・定数などをや
りとりするインタフェースであって一般の用途には使えません。

tmpfsとsysfsをそれぞれ複数の場所にmountすることを考えると、当然普通のファ
イルシステムのように使えるtmpfsは中身がそれぞれ違っていた方が嬉しく、一方
システムの情報をやりとりするsysfsは中身がそれぞれ違っていたら大混乱ですの
で、全て中身は同じになります。

これを頭におきつつ本題に入ります…

mount -vvv /sys とすると

mount: fstab path: "/etc/fstab"
mount: mtab path: "/etc/mtab"
mount: lock path: "/etc/mtab~"
mount: temp path: "/etc/mtab.tmp"
mount: UID: 0
mount: eUID: 0
mount: spec: "sysfs"
mount: node: "/sys"
mount: types: "sysfs"
mount: opts: "rw,nosuid,nodev,noexec,relatime"
mount: mount(2) syscall: source: "sysfs", target: "/sys", filesystemtype: "sysfs", mountflags: 2097166, data: (null)
mount: sysfs already mounted or /sys busy
mount: according to mtab, sysfs is already mounted on /sys

となって、どうもbusyエラーを返しているようです。

同様に mount -vvv /dev とすると

mount: fstab path: "/etc/fstab"
mount: mtab path: "/etc/mtab"
mount: lock path: "/etc/mtab~"
mount: temp path: "/etc/mtab.tmp"
mount: UID: 0
mount: eUID: 0
mount: spec: "udev"
mount: node: "/dev"
mount: types: "tmpfs"
mount: opts: "rw,nosuid,relatime,size=10240k,mode=755"
mount: mount(2) syscall: source: "udev", target: "/dev", filesystemtype: "tmpfs", mountflags: 2097154, data: size=10240k,mode=755
udev on /dev type tmpfs (rw,nosuid,relatime,size=10240k,mode=755)

となるように、 どちらにしてもシステムコールを呼んでいて、その差はカーネ
ル内の実装の違いになっています。

ということで、カーネルの処理を見ていくと…

/sysはfs/sysfs/mount.cのsysfs_mount()が、/devはtmpfsですのでmm/shmem.cの
shmem_mount()がmount処理を行なっています。

sysfs_mount()の方では super block構造体の生成時に

sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info);

として、 sysfs_test_super という関数でsuper blockを再利用できるのかチェッ
クしています。 (細かくはネームスペースとかがありますが) もしsuper blockを
すでに一度生成しているなら、必ずそれを使いまわすようになっています。

一方、/devの方はtmpfsのshmem_mount()はその処理をfs/super.cの
mount_nodev()に丸なげしています。この関数は

struct super_block *s = sget(fs_type, NULL, set_anon_super,
NULL);

として super blockを生成しますが、さきほどのsysfs_test_superが入っていた
ところにNULLが入っていることから推察できるとおり、常に新しいsuper block
構造体を生成しています。

この違いは冒頭に書いたtmpfsとsysfsとの違いを考えれば納得ですね。

この2つの違いを頭においたうえで、mount /sysがbusyエラーを返している原因の
部分であろうfs/namespace.c のdo_add_mount()を見てみると、

/* Refuse the same filesystem on the same mount point */
err = -EBUSY;
if (path->mnt->mnt_sb == newmnt->mnt_sb &&
path->mnt->mnt_root == path->dentry)
goto unlock;

このようになっていて、super block構造体が別のものであればなんら問題なく
(busyエラーにならずに) mountできてしまうことがわかります。

こうしてエラーがなくmountされてしまえば、いままでの/devにudevが作っていた
device fileが見えなくなってしまうのは当然ですね。

ということで、まとめると

- mount /devで/devが「見えなくなる」のは仕様です
- それはbusyエラーが出ないからです
- 結局それはtmpfsを使っていることによる仕様です
- tmpfsを使っている以上、これを上手にエラーにするのは難しい気がします

以上、解説してみました。もしわかりにくい場所があればまたご質問ください。

# ちなみに umount -l /dev で2つめの/devだけumountできますね

早間義博 <yossi@xxxxx> writes:

> 早間です。
> 今さら、mount ですが
>
> # mount /dev/
>
> と実行したところ /dev が見えなくなってしまったのです。
> 私のところの mount などがおかしいのでしょうか。
>
> # ls /dev
> initctl
>
> とだけ、表示されます。
>
> 環境は次のとおりです。
> cpu amd64
> kernel sys-kernel/gentoo-sources-3.0.6
> sys-apps/util-linux-2.19.1
>
> なお、tomoyo-2.4 を使用するため、secutity/tomoyo の内容は
> linux-3.1.tar.bz2 のものに入れ替えてあります(さらにパッチがされて
> います)。
> tomoyo の影響をなくすために起動時に security=none を追加して、
> tomoyo-editpolicy が働かないのを確認して
>
> # mount /dev
>
> を実行しても発生したので tomoyo には関係ないと考えています。
> なお、何度でも再現します。
> (ただ、発生後、心配なのですぐ再起動しています)
>
> これは、仕様ですか、いままで、こんな風に mount を実行した覚えは
> 一度もありません。もし、仕様でも全く気がつかないコマンドの使い方です。
>
> -- 早間


投稿者 xml-rpc : 2011年11月 4日 15:57
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/107314
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。