MC68EZ328 DragonOne SBCでuClinuxを動かす(7) ~rootにmountする~

Electronics

前回に続いてinitから呼び出されるprepare_namespace()を探ってみます。

prepare_namespace()

ここから先は慎重にみていきます。 ソースはそんなに長くありません。(不要な部分は削っています)

/*
* Prepare the namespace - decide what/where to mount, load ramdisks, etc.
*/
void prepare_namespace(void)
{
int is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
sys_mkdir("/dev", 0700);
sys_mkdir("/root", 0700);
sys_mknod("/dev/console", S_IFCHR|0600, MKDEV(TTYAUX_MAJOR, 1));
create_dev("/dev/root", ROOT_DEV, NULL);
if (mount_initrd) {
if (initrd_load() && ROOT_DEV != MKDEV(RAMDISK_MAJOR, 0)) {
handle_initrd();
goto out;
}
} else if (is_floppy && rd_doload && rd_load_disk(0))
ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
mount_root();
out:
sys_umount("/dev", 0);
sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot(".");
mount_devfs_fs ();
}

最初に/dev, /rootのディレクトリを作ります。その次は/dev/consoleのデバイスファイルを作ります。TTYAUX_MAJORは5なので、MAJOR=5, MINOR=1のデバイスファイルです。

ここでUbuntuで試しにmountしたromfsの/dev/consoleをみてみると、MAJOR=5, MINOR=1となっていたので一致しています。

mc68ez328_dragonone_sbc_uclinux_part7_dev_console.png

create_dev()

次にcreate_dev()で/dev/rootのデバイスファイルを作ります。この関数はinit/do_mount.cにあります。

static int __init create_dev(char *name, kdev_t dev, char *devfs_name)
{
void *handle;
char path[64];
int n;
sys_unlink(name);
if (!do_devfs)
return sys_mknod(name, S_IFBLK|0600, kdev_t_to_nr(dev));
 :
}

ここでは、DEVFSは使用しない設定になっているので、do_devfsはFALSEです。そのため、sys_mknodで/dev/rootのデバイスファイルを作るだけで、prepare_namespace()にもどります。

prepare_namespace()にもどったあと、mount_initrdの部分やフロッピィディスクの部分は該当しないので素通りして、続いての関数はmount_root()になります。

mount_root()

まさにここでrootディレクトリがmountされるのでしょうか。関数をみてみます。

static void __init mount_root(void)
{
devfs_make_root(root_device_name);
create_dev("/dev/root", ROOT_DEV, root_device_name);
mount_block_root("/dev/root", root_mountflags);
}

たった3行しかありません。しかもdevfsは使わないので、devfs_make_root()はそのままリターンで戻ってきます。次に再びcreate_dev()です。さっきも実行したのですが、今度はroot_device_nameに値が入っています。しかし、devfsは使わないのでこの情報は特に使われず、/dev/rootをunlinkしたあとにsys_mknod()が行われ、再び/dev/rootのデバイスファイルができます。

mount_block_root()

次の関数はmount_block_root()です。この関数をみてみます。

static void __init mount_block_root(char *name, int flags)
{
char *fs_names = __getname();
char *p;
get_fs_names(fs_names);
retry:
for (p = fs_names; *p; p += strlen(p)+1) {
int err = sys_mount(name, "/root", p, flags, root_mount_data);
switch (err) {
case 0:
goto out;
case -EACCES:
flags |= MS_RDONLY;
goto retry;
case -EINVAL:
case -EBUSY:
continue;
}
/*
* Allow the user to distinguish between failed open
* and bad superblock on root device.
*/
printk ("VFS: Cannot open root device \"%s\" or %s\n",
root_device_name, kdevname (ROOT_DEV));
printk ("Please append a correct \"root=\" boot option\n");
panic("VFS: Unable to mount root fs on %s",
kdevname(ROOT_DEV));
}
panic("VFS: Unable to mount root fs on %s", kdevname(ROOT_DEV));
out:
putname(fs_names);
sys_chdir("/root");
ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev;
printk("VFS: Mounted root (%s filesystem)%s.\n",
current->fs->pwdmnt->mnt_sb->s_type->name,
(current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY) ? " readonly" : "");
}

sys_mount()で/dev/rootデバイスを/rootファイルシステムにmountしているように見えます。fs_namesでループしていますが、これはどのファイルシステムを使うかを試しているようです。私が仕込んだデバックログでは以下のように表示されました。

mount_root:mount_block_root(/dev/root) root_mountflags=32769
get_fs_names() fs_names=/dev/root
get_fs_names() errno=0
sys_mount(): name=/dev/root p=ext2 flags=32769 root_mount_data=
sys_mount(): errno=0 err=-22  ※ext2ではなかった
sys_mount(): name=/dev/root p=romfs flags=32769 root_mount_data=
sys_mount(): errno=0 err=0    ※romfsと認識
putname() fs_names=ext2
putname() errno=0
sys_chdir(/root) errno=0
VFS: MAJOR=31, MINOR=0
VFS: Mounted root (romfs filesystem) readonly.
mount_root:mount_block_root(/dev/root) errno=0

putname()でext2を指定していますが、この実体はkmem_cache_free()なので使わないキャッシュを開放しているようです。そのあとにsys_chdir()で/rootにカレントディレクトリを移動しています。

その後rootにマウントが完了したというメッセージが表示されます。

VFS: Mounted root (romfs filesystem) readonly.

最後の仕上げ

mount_root()から戻ってきた後は、最後の仕上げとしてカレントディレクトリを/にします。

まずは、sys_umount(“/dev”, 0);で、/devをumountします。その後カレントディレクトリを/にmountします。

そのあと、sys_chroot(“.”);でカレントディレクトリをルートディレクトリに変更します。これでromfsがルートにmountされます。その後、mount_devfs_fs()がありますが、devfsは使っていないのですぐリターンしてきます。

           :
mount_root();
out:
sys_umount("/dev", 0);
sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot(".");
mount_devfs_fs ();
}

以上で、prepare_namespace()は終わりです。再びinitに戻ります。

おかしなところが見当たらない

ここまでのステップでは私が組み込んだデバックログにエラーはみあたりません。

mc68ez328_dragonone_sbc_uclinux_part7_mount_root_msg2.png

mount_root()が終わった時点でromfsが/rootにmountできているように見え、その後ルートディレクトリにmountされているように見えるのですが。(続く)

タイトルとURLをコピーしました