mountってどんな感じで処理してるんだろ〜ということで、sys_mount()を読んでみます。
調べたのは、2.6.33です。
ソースは大概LXRで調べてるんですが、sys_mountで検索しても実体が見つからなくてちょっと苦労しました。
定義が、SYSCALL_DEFINEマクロを使ってたから、sys_mountで検索しても見つからなかっただけですが・・・
実体は、fs/namespace.cにいます。
SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data) {
実際はこんな感じになります。
408asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name, 409 char __user *type, unsigned long flags, 410 void __user *data);
あと、sys_mountはカーネル内からも呼ばれます。
例えば、init/do_mounts.cのrootファイルシステムをマウントするときのdo_mount_root()からとか。
217static int __init do_mount_root(char *name, char *fs, int flags, void *data) 218{ 219 int err = sys_mount(name, "/root", fs, flags, data); 220 if (err)
それで、sys_mount()の実装ですが、実装は結構短めです。
2093SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, 2094 char __user *, type, unsigned long, flags, void __user *, data) 2095{ 2096 int ret; 2097 char *kernel_type; 2098 char *kernel_dir; 2099 char *kernel_dev; 2100 unsigned long data_page; 2101 2102 ret = copy_mount_string(type, &kernel_type); 2103 if (ret < 0) 2104 goto out_type; 2105 2106 kernel_dir = getname(dir_name); 2107 if (IS_ERR(kernel_dir)) { 2108 ret = PTR_ERR(kernel_dir); 2109 goto out_dir; 2110 } 2111 2112 ret = copy_mount_string(dev_name, &kernel_dev); 2113 if (ret < 0) 2114 goto out_dev; 2115 2116 ret = copy_mount_options(data, &data_page); 2117 if (ret < 0) 2118 goto out_data; 2119 2120 ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags, 2121 (void *) data_page); 2122 2123 free_page(data_page); 2124out_data: 2125 kfree(kernel_dev); 2126out_dev: 2127 putname(kernel_dir); 2128out_dir: 2129 kfree(kernel_type); 2130out_type: 2131 return ret; 2132} 2133
sys_mount()で使ってる関数もこれぐらいですし。
copy_mount_string()、getname()、copy_mount_string()、copy_mount_options()、do_mount()、putname()
これらの関数も名前から仕様が想像できるのと、処理もそんなに興味深い訳ではないので、do_mount()だけ見てみます。
do_mount()もfs/namespace.cにいます。
1913long do_mount(char *dev_name, char *dir_name, char *type_page, 1914 unsigned long flags, void *data_page) 1915{ 1916 struct path path; 1917 int retval = 0; 1918 int mnt_flags = 0; 1919 1920 /* Discard magic */ 1921 if ((flags & MS_MGC_MSK) == MS_MGC_VAL) 1922 flags &= ~MS_MGC_MSK; 1923 1924 /* Basic sanity checks */ 1925 1926 if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE)) 1927 return -EINVAL; 1928 1929 if (data_page) 1930 ((char *)data_page)[PAGE_SIZE - 1] = 0;
この辺りは基本的なチェックが入っていて、次にパスをチェックして、
1931 1932 /* ... and get the mountpoint */ 1933 retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); 1934 if (retval) 1935 return retval; 1936
セキュリティ関係のチェックが入ります。
1937 retval = security_sb_mount(dev_name, &path, 1938 type_page, flags, data_page); 1939 if (retval) 1940 goto dput_out; 1941
security_sb_mount()はsecurity/security.cにいて、struct security_operations内の関数ポインタsb_mountにセットされてる関数を読んでます。
これは追うのが大変そうなので、ここまでしか調べてませんorz
296int security_sb_mount(char *dev_name, struct path *path, 297 char *type, unsigned long flags, void *data) 298{ 299 return security_ops->sb_mount(dev_name, path, type, flags, data); 300}
この後は、フラグ関係の処理が続きます。
1942 /* Default to relatime unless overriden */ 1943 if (!(flags & MS_NOATIME)) 1944 mnt_flags |= MNT_RELATIME; 1945 1946 /* Separate the per-mountpoint flags */ 1947 if (flags & MS_NOSUID) 1948 mnt_flags |= MNT_NOSUID; 1949 if (flags & MS_NODEV) 1950 mnt_flags |= MNT_NODEV; 1951 if (flags & MS_NOEXEC) 1952 mnt_flags |= MNT_NOEXEC; 1953 if (flags & MS_NOATIME) 1954 mnt_flags |= MNT_NOATIME; 1955 if (flags & MS_NODIRATIME) 1956 mnt_flags |= MNT_NODIRATIME; 1957 if (flags & MS_STRICTATIME) 1958 mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); 1959 if (flags & MS_RDONLY) 1960 mnt_flags |= MNT_READONLY; 1961 1962 flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | 1963 MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | 1964 MS_STRICTATIME); 1965
ここまできて、最後に、マウントの仕方(再マウント、新規マウントとか)によって、呼ぶ関数を変えるといったことをしてます。
通常のマウントを行う場合は、do_new_mount()が呼ばれます。
1966 if (flags & MS_REMOUNT) 1967 retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, 1968 data_page); 1969 else if (flags & MS_BIND) 1970 retval = do_loopback(&path, dev_name, flags & MS_REC); 1971 else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) 1972 retval = do_change_type(&path, flags); 1973 else if (flags & MS_MOVE) 1974 retval = do_move_mount(&path, dev_name); 1975 else 1976 retval = do_new_mount(&path, type_page, flags, mnt_flags, 1977 dev_name, data_page); 1978dput_out: 1979 path_put(&path); 1980 return retval; 1981} 1982
do_new_mount()もfs/namespace.cにいます。ここでの主要な処理は、do_kern_mount()ですね。
というわけで、do_kern_mount()を調べます。
static int do_new_mount(struct path *path, char *type, int flags, 1645 int mnt_flags, char *name, void *data) 1646{ 1647 struct vfsmount *mnt; 1648 1649 if (!type) 1650 return -EINVAL; 1651 1652 /* we need capabilities... */ 1653 if (!capable(CAP_SYS_ADMIN)) 1654 return -EPERM; 1655 1656 lock_kernel(); 1657 mnt = do_kern_mount(type, flags, name, data); 1658 unlock_kernel(); 1659 if (IS_ERR(mnt)) 1660 return PTR_ERR(mnt); 1661 1662 return do_add_mount(mnt, path, mnt_flags, NULL); 1663}
こいつは、fs/super.cにいます。この中で重要そうなのはvfs_kern_mount()だろ!ということで、vfs_kern_mount()を見ます。
998struct vfsmount * 999do_kern_mount(const char *fstype, int flags, const char *name, void *data) 1000{ 1001 struct file_system_type *type = get_fs_type(fstype); 1002 struct vfsmount *mnt; 1003 if (!type) 1004 return ERR_PTR(-ENODEV); 1005 mnt = vfs_kern_mount(type, flags, name, data); 1006 if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && 1007 !mnt->mnt_sb->s_subtype) 1008 mnt = fs_set_subtype(mnt, fstype); 1009 put_filesystem(type); 1010 return mnt; 1011}
これも同じくfs/super.cにいます。
ここの主要な処理は、type->get_sb()だと思うんですが、これはファイルシステム固有の実装になってるはずなので、そのコードを読む必要があります。
例えば、ramfsの場合は、前に書いた日記これとかこれで調べたのがありますので、参考にしてみてください。
913struct vfsmount * 914vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) 915{ 916 struct vfsmount *mnt; 917 char *secdata = NULL; 918 int error; 919 920 if (!type) 921 return ERR_PTR(-ENODEV); 922 923 error = -ENOMEM; 924 mnt = alloc_vfsmnt(name); 925 if (!mnt) 926 goto out; 927 928 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { 929 secdata = alloc_secdata(); 930 if (!secdata) 931 goto out_mnt; 932 933 error = security_sb_copy_data(data, secdata); 934 if (error) 935 goto out_free_secdata; 936 } 937 938 error = type->get_sb(type, flags, name, data, mnt); 939 if (error < 0) 940 goto out_free_secdata; 941 BUG_ON(!mnt->mnt_sb); 942 943 error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); 944 if (error) 945 goto out_sb; 946 947 /* 948 * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE 949 * but s_maxbytes was an unsigned long long for many releases. Throw 950 * this warning for a little while to try and catch filesystems that 951 * violate this rule. This warning should be either removed or 952 * converted to a BUG() in 2.6.34. 953 */ 954 WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " 955 "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes); 956 957 mnt->mnt_mountpoint = mnt->mnt_root; 958 mnt->mnt_parent = mnt; 959 up_write(&mnt->mnt_sb->s_umount); 960 free_secdata(secdata); 961 return mnt; 962out_sb: 963 dput(mnt->mnt_root); 964 deactivate_locked_super(mnt->mnt_sb); 965out_free_secdata: 966 free_secdata(secdata); 967out_mnt: 968 free_vfsmnt(mnt); 969out: 970 return ERR_PTR(error); 971}
というわけで、思ったよりも長くなったんですが、ここまでがsys_mount()の処理内容でした。