Filesystemのnone
df コマンドで表示される Filesystem の none とは何でしょうか?とのページを目にしました。proc等の物理的なデバイスに対応されないファイルシステムの場合、noneと表示されるのらしいですが、私の環境(linux 3)では、noneと表示されません。どのような変更がなされたのかと調べてみました。
procのマウントは、start_kernel(void)から、proc_root_init()がコールされ、まずprocファイルシステムを登録後、pid_ns_prepare_proc()からkern_mount_data()とコールします。
[root@localhost kitamura]# df -a ファイルシス 1K-ブロック 使用 使用可 使用% マウント位置 rootfs 6182228 5318216 802108 87% / proc 0 0 0 - /proc sysfs 0 0 0 - /sys devtmpfs 299400 0 299400 0% /dev devpts 0 0 0 - /dev/pts tmpfs 305088 0 305088 0% /de :物理デバイスを有するファイルシステムも、そうでないファイルシステムのマウントも行き着く所は同じです。マウントにおいて物理デバイスの役割はスーパブロックの取得で、スーパブロックさえ取得すればこの引数は用無しです。
procのマウントは、start_kernel(void)から、proc_root_init()がコールされ、まずprocファイルシステムを登録後、pid_ns_prepare_proc()からkern_mount_data()とコールします。
void __init proc_root_init(void)
{
int err;
proc_init_inodecache();
err = register_filesystem(&proc_fs_type);
if (err)
return;
err = pid_ns_prepare_proc(&init_pid_ns);
if (err) {
unregister_filesystem(&proc_fs_type);
return;
}
proc_symlink("mounts", NULL, "self/mounts");
proc_net_init();
#ifdef CONFIG_SYSVIPC
proc_mkdir("sysvipc", NULL);
#endif
proc_mkdir("fs", NULL);
proc_mkdir("driver", NULL);
proc_mkdir("fs/nfsd", NULL); /* somewhere for the nfsd filesystem to be mounted */
#if defined(CONFIG_SUN_OPENPROMFS) || defined(CONFIG_SUN_OPENPROMFS_MODULE)
/* just give it a mountpoint */
proc_mkdir("openprom", NULL);
#endif
proc_tty_init();
#ifdef CONFIG_PROC_DEVICETREE
proc_device_tree_init();
#endif
proc_mkdir("bus", NULL);
proc_sys_init();
}
int pid_ns_prepare_proc(struct pid_namespace *ns)
{
struct vfsmount *mnt;
mnt = kern_mount_data(&proc_fs_type, ns);
if (IS_ERR(mnt))
return PTR_ERR(mnt);
ns->proc_mnt = mnt;
return 0;
}
kern_mount_data()でvfs_kern_mount()をコールする事で、実際のマウント処理を行います。この時第三引数がtype->nameとなっています。すなわちファイルシステム名をデバイスファイルとしているのです。たぶん昔はNULLとしていた物と思われます。
struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
{
struct vfsmount *mnt;
mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
if (!IS_ERR(mnt)) {
mnt_make_longterm(mnt);
}
return mnt;
}
vfs_kern_mount()でvfsmountを取得します。alloc_vfsmnt()でmountを取得した後、mount_fs()でデバイス毎のスーパブロック取得のコールバック関数がコールされ、その情報がmountに設定されます。procfsのような物理デバイスを有していないファイルシステムでは、このコールバック関数はpusedoのコールバック関数が定義されています。
struct vfsmount *vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
{
struct mount *mnt;
struct dentry *root;
if (!type)
return ERR_PTR(-ENODEV);
mnt = alloc_vfsmnt(name);
if (!mnt)
return ERR_PTR(-ENOMEM);
if (flags & MS_KERNMOUNT)
mnt->mnt.mnt_flags = MNT_INTERNAL;
root = mount_fs(type, flags, name, data);
if (IS_ERR(root)) {
free_vfsmnt(mnt);
return ERR_CAST(root);
}
mnt->mnt.mnt_root = root;
mnt->mnt.mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt;
br_write_lock(vfsmount_lock);
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
br_write_unlock(vfsmount_lock);
return &mnt->mnt;
}
alloc_vfsmnt()でmount構造他を取得し、この時引数nameのデバイス名をmnt->mnt_devnameに設定することで、/proc/mountsの参照となります。
static struct mount *alloc_vfsmnt(const char *name)
{
struct mount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
if (mnt) {
int err;
err = mnt_alloc_id(mnt);
if (err)
goto out_free_cache;
if (name) {
mnt->mnt_devname = kstrdup(name, GFP_KERNEL);
if (!mnt->mnt_devname)
goto out_free_id;
}
mnt->mnt_count = 1;
mnt->mnt_writers = 0;
INIT_LIST_HEAD(&mnt->mnt_hash);
INIT_LIST_HEAD(&mnt->mnt_child);
INIT_LIST_HEAD(&mnt->mnt_mounts);
INIT_LIST_HEAD(&mnt->mnt_list);
INIT_LIST_HEAD(&mnt->mnt_expire);
INIT_LIST_HEAD(&mnt->mnt_share);
INIT_LIST_HEAD(&mnt->mnt_slave_list);
INIT_LIST_HEAD(&mnt->mnt_slave);
#ifdef CONFIG_FSNOTIFY
INIT_HLIST_HEAD(&mnt->mnt_fsnotify_marks);
#endif
}
return mnt;
:
}
dfコマンドは/etc/mtabを参照しています。/etc/mtabは/proc/mountsにリンクされています。show_vfsmnt()は/proc/mountsの表示での編集処理です。スーパブロックのshow_devname()が定義されていればそれがコールされます。procfsでは定義されていません。したがってr->mnt_devnameが設定されていないならnoneを表示します。現行バージョンではファイルシステムが設定されているため、noneと表示されなくなりました。
static int show_vfsmnt(struct seq_file *m, struct vfsmount *mnt)
{
struct mount *r = real_mount(mnt);
int err = 0;
struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
struct super_block *sb = mnt_path.dentry->d_sb;
if (sb->s_op->show_devname) {
err = sb->s_op->show_devname(m, mnt_path.dentry);
if (err)
goto out;
} else {
mangle(m, r->mnt_devname ? r->mnt_devname : "none");
}
seq_putc(m, ' ');
seq_path(m, &mnt_path, " \t\n\\");
seq_putc(m, ' ');
show_type(m, sb);
seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
err = show_sb_opts(m, sb);
if (err)
goto out;
show_mnt_opts(m, mnt);
if (sb->s_op->show_options)
err = sb->s_op->show_options(m, mnt_path.dentry);
seq_puts(m, " 0 0\n");
out:
return err;
}
なお、dfの表示でファイルシスとなっていますが、カーネルしてはバイスファイルが正しいところです。




