mount の根本的な問題2007年02月01日 11時11分16秒

さて、/sbin/mount をデバッグする。mount を -g を付けて作り直す。

# cd /usr/src/sbin/mount
# make clean
rm -f mount mount.o mount_fs.o getmntopts.o vfslist.o mount.8.gz mount.8.cat.gz
# make CFLAGS+=-g
cc -g -c /usr/src/sbin/mount/mount.c
cc -g -c /usr/src/sbin/mount/mount_fs.c
cc -g -c /usr/src/sbin/mount/getmntopts.c
cc -g -c /usr/src/sbin/mount/vfslist.c
cc -g  -o mount mount.o mount_fs.o getmntopts.o vfslist.o
gzip -cn /usr/src/sbin/mount/mount.8 > mount.8.gz
# make install
install -s -o root -g wheel -m 555   mount /sbin
install -o root -g wheel -m 444 mount.8.gz  /usr/share/man/man8

インストールし、gdb から起動する。


% gdb mount
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...(no debugging symbols found)...
(gdb) break main
Function "main" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y

Breakpoint 1 (main) pending.
(gdb) run -d /usr/ports
Starting program: /sbin/mount -d /usr/ports
(no debugging symbols found)...
(no debugging symbols found)...
mount -t md -o ro -P -F/usr/uzip/ports-20060830.uzip /dev/md.uzip /usr/ports

Program exited normally.
(gdb)

なぜだか、解らないが install をした後のバイナリは gdb でデバッグが出来ない。そこで、インストールする前の物を実行する。

何回か、走らせて見た後に mount_fs に問題があるみたいに見えた。


(gdb) run -d /usr/ports
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...
(gdb) break main
Breakpoint 1 at 0x804923c: file 

...

/usr/src/sbin/mount/mount.c, line 218.
(gdb) list
539                             (void)printf(" %s", argv[i]);
540                     (void)printf("\n");
541                     return (0);
542             }
543
544             if (use_mountprog(vfstype)) {
545                     ret = exec_mountprog(name, execname, argv);
546             } else {
547                     ret = mount_fs(vfstype, argc, argv);
548             }

(gdb) p vfstype
$4 = 0x881655d9 "md"
(gdb) p argc
$5 = 7
(gdb) p argv[0]
$6 = 0xbfbfdfc0 "mount_md"
(gdb) p argv[1]
$7 = 0x8051030 "-o"
(gdb) p argv[2]
$8 = 0x8050000 "ro"
(gdb) p argv[3]
$9 = 0x8050003 "-P"
(gdb) p argv[4]
$10 = 0x8050006 "-F/usr/uzip/ports-20060830.uzip"
(gdb) p argv[5]
$11 = 0x8051040 "/dev/md.uzip"
(gdb) p argv[6]
$12 = 0x8051050 "/usr/ports"
(gdb) p argv[7]
$13 = 0x0

mount_fs にて、渡されるオプションが検査され、-P は有効なオプションではないので、失敗する。

しかし、本当の原因は少し違うところにあった。mount_md は外部プログラムなので、mount_fs ではなく exec_mountprog が呼ばれるべきなのだ。つまり、外部コマンドが呼ばれていないのが問題だ。use_mountprog が正しく、判定できていないのが原因だ。この関数が保持する表の中に、"md" が無いために、mount は mount_md を呼ばずに失敗する。


% cvs diff -u6
Index: mount.c
===================================================================
RCS file: /home/ncvs/src/sbin/mount/mount.c,v
retrieving revision 1.92
diff -u -u -6 -r1.92 mount.c
--- mount.c     14 Nov 2006 01:07:42 -0000      1.92
+++ mount.c     28 Jan 2007 05:53:58 -0000
@@ -133,12 +133,13 @@
         */
        unsigned int i;
        const char *fs[] = {
        "cd9660", "mfs", "msdosfs", "nfs", "nfs4", "ntfs",
        "nwfs", "nullfs", "portalfs", "smbfs", "udf", "umapfs",
        "unionfs",
+       "md",
        NULL
        };
 
        for (i = 0; fs[i] != NULL; ++i) {
                if (strcmp(vfstype, fs[i]) == 0)
                        return (1);


ここに "md" を追加することで、動作するようになった。

確かに、"md" を入れたら動くようになった。しかし、この根本的な問題はデザインにある。このデザインは、「mount プログラムが知っている外部プログラムを管理し、そのファイルタイプが無い場合は内部で処理する。」となっている。つまり、mount プログラムが全ての外部プログラムを把握しているのを前提で、作られているわけだ。

そんなことは、絶対に不可能だ。すでに、mount_md が失敗するので十分に証明されている。mount プログラムは、自分で扱えるファイルタイプを保持し、それに適合したときのみに、内部処理するべきだ。

この実装では、実験してはいないが、FUSE fs 等の ports から入るマウントコマンドも動かないような気がする。 前回次回

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://uyota.asablo.jp/blog/2007/02/01/1156945/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。