对于前面的根目录文件系统的安装中涉及到了mount系统调用的调用,这里我们考虑一个文件系统将被安装在一个已经安装文件系统之上的情形,即调用mount系统调用实现。mount系统调用被用来安装一个普通文件系统,他的服务例程为sys_mount()。

[cpp] view plain copy  print?
  1. /*sys_mount系统调用*/
  2. /*dev_name为待安装设备的路径名;
  3. dir_name为安装点的路径名;
  4. type是表示文件系统类型的字符串;
  5. */
  6. SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
  7. char __user *, type, unsigned long, flags, void __user *, data)
  8. {
  9. int ret;
  10. char *kernel_type;
  11. char *kernel_dir;
  12. char *kernel_dev;
  13. unsigned long data_page;
  14. /*从用户空间复制到系统空间*/
  15. ret = copy_mount_string(type, &kernel_type);
  16. if (ret < 0)
  17. goto out_type;
  18. kernel_dir = getname(dir_name);
  19. if (IS_ERR(kernel_dir)) {
  20. ret = PTR_ERR(kernel_dir);
  21. goto out_dir;
  22. }
  23. ret = copy_mount_string(dev_name, &kernel_dev);
  24. if (ret < 0)
  25. goto out_dev;
  26. /*用户空间复制到系统空间,拷贝整个页面*/
  27. ret = copy_mount_options(data, &data_page);
  28. if (ret < 0)
  29. goto out_data;
  30. /*操作主体*/
  31. ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
  32. (void *) data_page);
  33. free_page(data_page);
  34. out_data:
  35. kfree(kernel_dev);
  36. out_dev:
  37. putname(kernel_dir);
  38. out_dir:
  39. kfree(kernel_type);
  40. out_type:
  41. return ret;
  42. }

下面是主体实现

[cpp] view plain copy  print?
  1. long do_mount(char *dev_name, char *dir_name, char *type_page,
  2. unsigned long flags, void *data_page)
  3. {
  4. struct path path;
  5. int retval = 0;
  6. int mnt_flags = 0;
  7. /* Discard magic */
  8. if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
  9. flags &= ~MS_MGC_MSK;
  10. /* Basic sanity checks */
  11. if (!dir_name || !*dir_name || !memchr(dir_name, 0, PAGE_SIZE))
  12. return -EINVAL;
  13. if (data_page)
  14. ((char *)data_page)[PAGE_SIZE - 1] = 0;
  15. /* Default to relatime unless overriden */
  16. if (!(flags & MS_NOATIME))
  17. mnt_flags |= MNT_RELATIME;
  18. /* Separate the per-mountpoint flags */
  19. if (flags & MS_NOSUID)
  20. mnt_flags |= MNT_NOSUID;
  21. if (flags & MS_NODEV)
  22. mnt_flags |= MNT_NODEV;
  23. if (flags & MS_NOEXEC)
  24. mnt_flags |= MNT_NOEXEC;
  25. if (flags & MS_NOATIME)
  26. mnt_flags |= MNT_NOATIME;
  27. if (flags & MS_NODIRATIME)
  28. mnt_flags |= MNT_NODIRATIME;
  29. if (flags & MS_STRICTATIME)
  30. mnt_flags &= ~(MNT_RELATIME | MNT_NOATIME);
  31. if (flags & MS_RDONLY)
  32. mnt_flags |= MNT_READONLY;
  33. flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
  34. MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
  35. MS_STRICTATIME);
  36. /* ... and get the mountpoint */
  37. /*获得安装点path结构*/
  38. retval = kern_path(dir_name, LOOKUP_FOLLOW, &path);
  39. if (retval)
  40. return retval;
  41. retval = security_sb_mount(dev_name, &path,
  42. type_page, flags, data_page);
  43. if (retval)
  44. goto dput_out;
  45. if (flags & MS_REMOUNT)
  46. /*修改已经存在的文件系统参数,即改变超级块对象s_flags
  47. 字段的安装标志*/
  48. retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags,
  49. data_page);
  50. else if (flags & MS_BIND)
  51. /*要求在系统目录树的另一个安装点上得文件或目录能够可见*/
  52. retval = do_loopback(&path, dev_name, flags & MS_REC);
  53. else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE))
  54. /*is responsible for handling shared, slave, and unbindable mounts by changing
  55. the mount flags or building up the required data structure connections
  56. between the vfsmount
  57. instances involved.*/
  58. retval = do_change_type(&path, flags);
  59. else if (flags & MS_MOVE)
  60. /*改变已安装文件的安装点*/
  61. /*used to move a mounted filesystem*/
  62. retval = do_move_mount(&path, dev_name);
  63. else
  64. /*handles normal mount operations. This is the default situation, so no special
  65. flags
  66. are required*/
  67. /*当用户要求安装一个特殊文件系统或存放在磁盘分区
  68. 中的普通文件系统时,调用*/
  69. retval = do_new_mount(&path, type_page, flags, mnt_flags,
  70. dev_name, data_page);
  71. dput_out:
  72. path_put(&path);
  73. return retval;
  74. }
[cpp] view plain copy  print?
  1. /*
  2. * create a new mount for userspace and request it to be added into the
  3. * namespace's tree
  4. */
  5. static int do_new_mount(struct path *path, char *type, int flags,
  6. int mnt_flags, char *name, void *data)
  7. {
  8. struct vfsmount *mnt;
  9. if (!type)
  10. return -EINVAL;
  11. /* we need capabilities... */
  12. if (!capable(CAP_SYS_ADMIN))
  13. return -EPERM;
  14. lock_kernel();
  15. /*处理实际的安装操作并返回一个新的安装文件系统
  16. 描述符地址,使用get_fs_type扫描已经注册文件系统链表
  17. 找到匹配的file_system_type实例。然后分配或获取sb结构
  18. 并与mnt关联,初始化mnt并返回*/
  19. */
  20. mnt = do_kern_mount(type, flags, name, data);
  21. unlock_kernel();
  22. if (IS_ERR(mnt))
  23. return PTR_ERR(mnt);
  24. /*处理必要的锁定操作,确保一个文件系统不会重复装载到
  25. 同一个位置,将文件系统整合到系统中*/
  26. return do_add_mount(mnt, path, mnt_flags, NULL);
  27. }

do_kern_mount函数在前面初始化中介绍过了,下面看do_add_mount函数用于将文件系统整合到系统中。

[cpp] view plain copy  print?
  1. /*
  2. * add a mount into a namespace's mount tree
  3. * - provide the option of adding the new mount to an expiration list
  4. */
  5. int do_add_mount(struct vfsmount *newmnt, struct path *path,
  6. int mnt_flags, struct list_head *fslist)
  7. {
  8. int err;
  9. down_write(&namespace_sem);
  10. /* Something was mounted here while we slept */
  11. while (d_mountpoint(path->dentry) &&
  12. follow_down(path))
  13. ;
  14. err = -EINVAL;
  15. /*验证再改安装点上最近安装的文件系统是否任然指向
  16. 当前命名空间*/
  17. if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
  18. goto unlock;
  19. /* Refuse the same filesystem on the same mount point */
  20. err = -EBUSY;
  21. /*如果要安装的文件系统已经被安装在由系统调用的参数
  22. 所指定的安装点上*/
  23. if (path->mnt->mnt_sb == newmnt->mnt_sb &&
  24. path->mnt->mnt_root == path->dentry)
  25. goto unlock;
  26. err = -EINVAL;
  27. /*该安装点是一个符号链接*/
  28. if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
  29. goto unlock;
  30. newmnt->mnt_flags = mnt_flags;
  31. /*把新安装的文件系统对象插入到namespace链表、
  32. 散列表以及父文件系统的子链表中*/
  33. if ((err = graft_tree(newmnt, path)))
  34. goto unlock;
  35. if (fslist) /* add to the specified expiration list */
  36. list_add_tail(&newmnt->mnt_expire, fslist);
  37. up_write(&namespace_sem);
  38. return 0;
  39. unlock:
  40. up_write(&namespace_sem);
  41. mntput(newmnt);
  42. return err;
  43. }

新安装的文件系统对象链入系统树。

[cpp] view plain copy  print?
  1. static int graft_tree(struct vfsmount *mnt, struct path *path)
  2. {
  3. int err;
  4. if (mnt->mnt_sb->s_flags & MS_NOUSER)
  5. return -EINVAL;
  6. if (S_ISDIR(path->dentry->d_inode->i_mode) !=
  7. S_ISDIR(mnt->mnt_root->d_inode->i_mode))
  8. return -ENOTDIR;
  9. err = -ENOENT;
  10. mutex_lock(&path->dentry->d_inode->i_mutex);
  11. if (IS_DEADDIR(path->dentry->d_inode))
  12. goto out_unlock;
  13. err = security_sb_check_sb(mnt, path);
  14. if (err)
  15. goto out_unlock;
  16. err = -ENOENT;
  17. if (!d_unlinked(path->dentry))/*加入树*/
  18. err = attach_recursive_mnt(mnt, path, NULL);
  19. out_unlock:
  20. mutex_unlock(&path->dentry->d_inode->i_mutex);
  21. if (!err)
  22. security_sb_post_addmount(mnt, path);
  23. return err;
  24. }
[cpp] view plain copy  print?
  1. /*将文件系统添加到父文件系统的命名空间中*/
  2. static int attach_recursive_mnt(struct vfsmount *source_mnt,
  3. struct path *path, struct path *parent_path)
  4. {
  5. LIST_HEAD(tree_list);
  6. struct vfsmount *dest_mnt = path->mnt;
  7. struct dentry *dest_dentry = path->dentry;
  8. struct vfsmount *child, *p;
  9. int err;
  10. if (IS_MNT_SHARED(dest_mnt)) {
  11. err = invent_group_ids(source_mnt, true);
  12. if (err)
  13. goto out;
  14. }
  15. err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
  16. if (err)
  17. goto out_cleanup_ids;
  18. if (IS_MNT_SHARED(dest_mnt)) {
  19. for (p = source_mnt; p; p = next_mnt(p, source_mnt))
  20. set_mnt_shared(p);
  21. }
  22. spin_lock(&vfsmount_lock);
  23. if (parent_path) {
  24. detach_mnt(source_mnt, parent_path);
  25. attach_mnt(source_mnt, path);
  26. touch_mnt_namespace(parent_path->mnt->mnt_ns);
  27. } else {
  28. /*确保新的vfsmount实例的mnt_parent成员指向父文件系统
  29. 的vfsmount实例,而mnt_mountpoint成员指向装载点在父文件
  30. 系统中的dentry实例*/
  31. mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
  32. commit_tree(source_mnt);
  33. }
  34. list_for_each_entry_safe(child, p, &tree_list, mnt_hash) {
  35. list_del_init(&child->mnt_hash);
  36. /*将新的mnt添加到全局散列表以及父文件系统mnt实例中
  37. 的子文件系统链表*/
  38. commit_tree(child);
  39. }
  40. spin_unlock(&vfsmount_lock);
  41. return 0;
  42. out_cleanup_ids:
  43. if (IS_MNT_SHARED(dest_mnt))
  44. cleanup_group_ids(source_mnt, NULL);
  45. out:
  46. return err;
  47. }

Linux虚拟文件系统之文件系统安装(sys_mount())相关推荐

  1. 网络与IO知识扫盲(一):Linux虚拟文件系统,文件描述符,IO重定向

    系统IO原理 在 Linux 中: VFS(Virtual Filesystem Switch):虚拟文件系统,是一个目录树.树上不同的节点可以映射到物理的文件地址,可以挂载. 相当于一个解耦层,在具 ...

  2. Linux虚拟文件系统、文件描述符、管道

    在Linux中,所有内容都是以文件的形式保存和管理的,即一切皆文件,普通文件是文件,目录(Windows下称为文件夹)是文件,硬件设备(键盘.监视器.硬盘.打印机等)都是文件,就连套接字(socket ...

  3. linux 目录防篡改,一种基于Linux虚拟文件系统的防篡改方法及系统的制作方法

    一种基于Linux虚拟文件系统的防篡改方法及系统的制作方法 [技术领域] [0001]本发明涉及文件防护技术领域,特别涉及一种基于Linux虚拟文件系统的防篡改方法及系统. [背景技术] [0002] ...

  4. Linux虚拟文件系统:数据结构与文件系统注册、文件打开读写

    数据结构 超级块 - super_block 索引节点 - inode 目录项 - dentry 文件结构 - file 虚拟文件系统实现 注册文件系统 - register_filesystem 打 ...

  5. Linux虚拟文件系统

    从文件 I/O 看 Linux 的虚拟文件系统 1 引言 Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等.通过使用同一套文件 I/O 系统 调用即可对 Linux ...

  6. Linux 虚拟文件系统四大对象:超级块、inode、dentry、file之间关系

    一:文件系统 1. 什么是文件系统? 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统. 通常文件系统是用于存储和组织文件的一种机制,便于对文件进行方便的查找与访问. 文件系统 ...

  7. linux虚拟文件系统浅析

    linux虚拟文件系统浅析 虚拟文件系统(VFS) 在我看来, "虚拟"二字主要有两层含义: 1, 在同一个目录结构中, 可以挂载着若干种不同的文件系统. VFS隐藏了它们的实现细 ...

  8. linux 文件系统 vfs,linux虚拟文件系统vfs

    <操作系统>课程设计报告课程设计题目:操作系统课程设计 设计时间:2016/1/10一. 课程设计目的与要求需要完成的内容:(1) 安装虚拟机:Vmware.Vmware palyer ( ...

  9. Linux 虚拟文件系统(一)概述

    Linux 虚拟文件系统(一)概述 tags: Linux源码 Linux 虚拟文件系统一概述 文章梗概 正文 文件系统 虚拟文件系统架构 虚拟文件系统如何知道可用的文件系统有哪些的 不太喜欢的环节 ...

  10. linux 创建 虚拟文件系统设备 文件节点 使用 proc_create 实例 简介

    proc虚拟文件系统也可以创建虚拟文件节点,实现用户空间与内核空间的交互.在驱动中创建节点,可以实现对硬件的控制.proc_create函数原型(在kernel-3.10/include/linux/ ...

最新文章

  1. MVP在Android平台上的应用
  2. jeecg uedit 自定义图片上传路径
  3. Ubuntu 下 使用 adb logcat 显示 Android 日志
  4. mysql 5.7.15 union order by 子查询排序不生效
  5. 使用ImageView引起Missing contentDescription attribute on image的问题
  6. 【EOS】EOS环境基础
  7. FlowNet到FlowNet2.0:基于卷积神经网络的光流预测算法
  8. iPhone使用教程
  9. 经典6位半HP34401A电路图
  10. 自动驾驶领域中常见英文缩写、相关含义以及常用专业英文
  11. 2020年Web前端面试题及答案----CSS篇
  12. 论文阅读笔记《Optimal Image-Based Guidance of Mobile Manipulators Using Direct Visual Servoing》
  13. 树莓派使用create_ap创建局域网
  14. Freemarker语法2
  15. H2.64和H2.65编码区别
  16. 【笔记】学习CSS布局17——column
  17. 武汉公交车司机的技术真NB
  18. #单利,复利。Daphne,Cleo。
  19. 愿与你同行作一个终身学习者
  20. 000视频基础知识入门--科普向

热门文章

  1. bzero函数_Linux(基础) | 系统IO函数的使用
  2. ZooKeeper 安装与部署
  3. 代替Reflection(反射)的一些方法(转)
  4. 为什么开发移动端web不使用jQuery
  5. (转载)使用Maven构建多模块项目
  6. 动态修改php的配置项
  7. [Andriod官方API指南]连接之蓝牙
  8. 【hdu - 2568】ACM程序设计期末考试081230
  9. C#笔记(一):类型,泛型,集合
  10. Silverlight 5 RC新特性探索系列:15.Silverlight 5 RC 对OpenType字体属性的支持