無料Wikiサービス | デモページ
検索

アクセス数
最近のコメント
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
はじめ - ノース
はじめ - ノース
はじめ - 楽打連動ユーザー
はじめ - 楽打連動ユーザー
Adsense
広告情報が設定されていません。

Filesystemのnone


df コマンドで表示される Filesystem の none とは何でしょうか?とのページを目にしました。proc等の物理的なデバイスに対応されないファイルシステムの場合、noneと表示されるのらしいですが、私の環境(linux 3)では、noneと表示されません。どのような変更がなされたのかと調べてみました。
[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の表示でファイルシスとなっていますが、カーネルしてはバイスファイルが正しいところです。

最終更新 2013/10/14 15:18:11 - north
(2013/10/14 15:02:19 作成)