mount过程分析之三(do_mount -> do_new_mount)
来源:互联网 发布:mariadb mysql 对比 编辑:程序博客网 时间:2024/06/05 19:45
sys_mount - > do_mount
do_mount函数也在namespace.c里可以找到,如下:
long do_mount(const char *dev_name, const char *dir_name, const char *type_page, unsigned long flags, void *data_page){ struct path path; int retval = 0; int mnt_flags = 0; /* Discard magic */ if ((flags & MS_MGC_MSK) == MS_MGC_VAL) flags &= ~MS_MGC_MSK; /* Basic sanity checks */ if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE)) return -EINVAL; if (data_page) ((char *)data_page)[PAGE_SIZE - 1] = 0; // 把mountpoint解释成path内核结构,这里是路径名解析的过程 // 调用do_path_lookup。关于路径名解析我们后面再说 /* ... and get the mountpoint */ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); if (retval) return retval; retval = security_sb_mount(dev_name, &path, type_page, flags, data_page); if (!retval && !may_mount()) retval = -EPERM; if (retval) goto dput_out; // 从这里开始就是一系列的对flags的解析,把通用option提出来 // 并且找出我们要mount做哪种操作,如bind, remount, newmount等 /* Default to relatime unless overriden */ if (!(flags & MS_NOATIME)) mnt_flags |= MNT_RELATIME; /* Separate the per-mountpoint flags */ if (flags & MS_NOSUID) mnt_flags |= MNT_NOSUID; if (flags & MS_NODEV) mnt_flags |= MNT_NODEV; if (flags & MS_NOEXEC) mnt_flags |= MNT_NOEXEC; if (flags & MS_NOATIME) mnt_flags |= MNT_NOATIME; if (flags & MS_NODIRATIME) mnt_flags |= MNT_NODIRATIME; if (flags & MS_STRICTATIME) mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME); if (flags & MS_RDONLY) mnt_flags |= MNT_READONLY; /* The default atime for remount is preservation */ if ((flags & MS_REMOUNT) && ((flags & (MS_NOATIME | MS_NODIRATIME | MS_RELATIME | MS_STRICTATIME)) == 0)) { mnt_flags &= ~MNT_ATIME_MASK; mnt_flags |= path.mnt->mnt_flags & MNT_ATIME_MASK; } flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE | MS_BORN | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | MS_STRICTATIME); // 根据flags的指示,决定做哪种mount操作 if (flags & MS_REMOUNT) retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, data_page); else if (flags & MS_BIND) retval = do_loopback(&path, dev_name, flags & MS_REC); else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) retval = do_change_type(&path, flags); else if (flags & MS_MOVE) retval = do_move_mount(&path, dev_name); else // 我们这里以new mount为入手点,继续向下分析 retval = do_new_mount(&path, type_page, flags, mnt_flags, dev_name, data_page);dput_out: path_put(&path); return retval;}
综上所述,我们得出do_mount主要干这么几个事:
1. 解析mountpoint路径名,把字符串路径名变成内核dentry或者说path结构
2. 解析flags,把通用option分出来。
3. 根据flags中指明mount操作的标志,决定做哪一种mount操作。
4. 执行remount/bind/shared/move/new mount操作。
到此mount就可能做5种mount操作(remount, bind, chang type, move和new mount)之一。我们以do_new_mount为例继续分析,do_new_mount属于最常见的情况,挂载一个新的文件系统。
sys_mount - > do_mount -> do_new_mount
do_new_mount函数也在namespace.c里可以找到,它主要做三件事:
1.根据fstype从全局文件系统类型(file_system_type)链表中找到对应的文件系统类型结构
2. 用上一步得到的特定文件系统类型结构中的mount回调函数执行下面的挂载操作,最终构建一个mount结构体,其中包含vfsmount信息。
3.将得到的mount结构体加入全局文件系统树中
来看一下详细代码:
static int do_new_mount(struct path *path, const char *fstype, int flags, int mnt_flags, const char *name, void *data){ struct file_system_type *type; struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns; struct vfsmount *mnt; int err; if (!fstype) return -EINVAL; // 根据fs类型名(如xfs)在全局文件系统类型链表上找到其对应的file_system_type结构 type = get_fs_type(fstype); if (!type) return -ENODEV; if (user_ns != &init_user_ns) { if (!(type->fs_flags & FS_USERNS_MOUNT)) { put_filesystem(type); return -EPERM; } /* Only in special cases allow devices from mounts * created outside the initial user namespace. */ if (!(type->fs_flags & FS_USERNS_DEV_MOUNT)) { flags |= MS_NODEV; mnt_flags |= MNT_NODEV | MNT_LOCK_NODEV; } } // 调用此函数准备进入每个文件系统的个别处理函数,构建一个vfsmnt结构 // 注意这里以文件系统类型、挂载标记、设备名和挂载选项信息为参数,并没有mountpoint参数。这里只是想用type中的mount回调函数读取设备的superblock信息,填充mnt结构,然后把flag和data解析后填充到mnt结构中。 mnt = vfs_kern_mount(type, flags, name, data); if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && !mnt->mnt_sb->s_subtype) mnt = fs_set_subtype(mnt, fstype); put_filesystem(type); if (IS_ERR(mnt)) return PTR_ERR(mnt); // 准备将得到的mnt结构加入全局文件系统树 // 注意path变量,也就是mountpoint在这里 err = do_add_mount(real_mount(mnt), path, mnt_flags); if (err) mntput(mnt); return err;}
vfs_kern_mount和do_add_mount是接下来重要的两个步骤,vfs_kern_mount继续解析superblock并填充mnt结构,do_add_mount将创建好的mnt加入到全局文件系统树中。所以下面将分别按两条线对这两个函数的过程进行详述。
http://blog.csdn.net/zr_lang/article/details/40325241 (mount 七)
http://blog.csdn.net/zr_lang/article/details/40343899 (mount 六)
http://blog.csdn.net/zr_lang/article/details/40115013 (mount 五)
http://blog.csdn.net/zr_lang/article/details/40080979 (mount 四)
http://blog.csdn.net/zr_lang/article/details/40049305 (mount 三)
http://blog.csdn.net/zr_lang/article/details/40002285 (mount 二)
http://blog.csdn.net/zr_lang/article/details/39963253 (mount 一)- mount过程分析之三(do_mount -> do_new_mount)
- mount过程分析之二——mount系统调用
- mount过程分析之五(mount_bdev->fill_super)
- mount过程分析之七(do_add_mount)
- mount过程分析之四(vfs_kern_mount->mount_fs->xfs_fs_mount)
- VFS之mount函数分析
- 文件系统注册及mount过程分析
- mount 挂载原理及过程分析
- mount过程分析之六——挂载关系(图解)
- linux文件系统之mount流程分析
- Linux之Mount内核代码分析
- linux文件系统之mount流程分析
- linux文件系统之mount流程分析
- mount过程分析之一(基于3.16.3内核)
- Spring MVC framework深入分析之三(上)--执行过程
- Spring MVC framework深入分析之三(下)--执行过程
- Spring MVC framework深入分析之三(上)--执行过程
- Spring MVC framework深入分析之三(下)--执行过程
- c++函数参数类型-引用
- Qt-4.8 WebKit + QtWebKit-2.3.x上CSS3 Web Fonts支持的一些记录
- c单链表逆置
- 【构造】 Codeforces 476D Dreamoon and Sets
- 《算法竞赛入门经典(第2版)》代码 Chapter 2
- mount过程分析之三(do_mount -> do_new_mount)
- 静态库的生成
- 关于sda与hda
- HTML中实现两个列,每个列都固定宽度高度占满整个屏幕。如果内容多就出现滚动条!
- 热烈祝贺Polymer中文组织网站上线
- NYOJ正三角形外接圆面积
- 基于数据挖掘技术的客户关系管理系统设计与实现
- [Android]异步任务AsyncTask使用解析
- 什么是保护消息边界和流?