Linux虚拟文件系统之文件系统安装(sys_mount())
- /*sys_mount系统调用*/
- /*dev_name为待安装设备的路径名;
- dir_name为安装点的路径名;
- type是表示文件系统类型的字符串;
- */
- SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
- char __user *, type, unsigned long, flags, void __user *, data)
- {
- int ret;
- char *kernel_type;
- char *kernel_dir;
- char *kernel_dev;
- unsigned long data_page;
- /*从用户空间复制到系统空间*/
- ret = copy_mount_string(type, &kernel_type);
- if (ret < 0)
- goto out_type;
- kernel_dir = getname(dir_name);
- if (IS_ERR(kernel_dir)) {
- ret = PTR_ERR(kernel_dir);
- goto out_dir;
- }
- ret = copy_mount_string(dev_name, &kernel_dev);
- if (ret < 0)
- goto out_dev;
- /*用户空间复制到系统空间,拷贝整个页面*/
- ret = copy_mount_options(data, &data_page);
- if (ret < 0)
- goto out_data;
- /*操作主体*/
- ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
- (void *) data_page);
- free_page(data_page);
- out_data:
- kfree(kernel_dev);
- out_dev:
- putname(kernel_dir);
- out_dir:
- kfree(kernel_type);
- out_type:
- return ret;
- }
下面是主体实现
- long do_mount(char *dev_name, char *dir_name, 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;
- /* 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;
- flags &= ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_ACTIVE |
- MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT |
- MS_STRICTATIME);
- /* ... and get the mountpoint */
- /*获得安装点path结构*/
- 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)
- goto dput_out;
- if (flags & MS_REMOUNT)
- /*修改已经存在的文件系统参数,即改变超级块对象s_flags
- 字段的安装标志*/
- 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))
- /*is responsible for handling shared, slave, and unbindable mounts by changing
- the mount flags or building up the required data structure connections
- between the vfsmount
- instances involved.*/
- retval = do_change_type(&path, flags);
- else if (flags & MS_MOVE)
- /*改变已安装文件的安装点*/
- /*used to move a mounted filesystem*/
- retval = do_move_mount(&path, dev_name);
- else
- /*handles normal mount operations. This is the default situation, so no special
- flags
- are required*/
- /*当用户要求安装一个特殊文件系统或存放在磁盘分区
- 中的普通文件系统时,调用*/
- retval = do_new_mount(&path, type_page, flags, mnt_flags,
- dev_name, data_page);
- dput_out:
- path_put(&path);
- return retval;
- }
- /*
- * create a new mount for userspace and request it to be added into the
- * namespace's tree
- */
- static int do_new_mount(struct path *path, char *type, int flags,
- int mnt_flags, char *name, void *data)
- {
- struct vfsmount *mnt;
- if (!type)
- return -EINVAL;
- /* we need capabilities... */
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- lock_kernel();
- /*处理实际的安装操作并返回一个新的安装文件系统
- 描述符地址,使用get_fs_type扫描已经注册文件系统链表
- 找到匹配的file_system_type实例。然后分配或获取sb结构
- 并与mnt关联,初始化mnt并返回*/
- */
- mnt = do_kern_mount(type, flags, name, data);
- unlock_kernel();
- if (IS_ERR(mnt))
- return PTR_ERR(mnt);
- /*处理必要的锁定操作,确保一个文件系统不会重复装载到
- 同一个位置,将文件系统整合到系统中*/
- return do_add_mount(mnt, path, mnt_flags, NULL);
- }
do_kern_mount函数在前面初始化中介绍过了,下面看do_add_mount函数用于将文件系统整合到系统中。
- /*
- * add a mount into a namespace's mount tree
- * - provide the option of adding the new mount to an expiration list
- */
- int do_add_mount(struct vfsmount *newmnt, struct path *path,
- int mnt_flags, struct list_head *fslist)
- {
- int err;
- down_write(&namespace_sem);
- /* Something was mounted here while we slept */
- while (d_mountpoint(path->dentry) &&
- follow_down(path))
- ;
- err = -EINVAL;
- /*验证再改安装点上最近安装的文件系统是否任然指向
- 当前命名空间*/
- if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt))
- goto unlock;
- /* Refuse the same filesystem on the same mount point */
- err = -EBUSY;
- /*如果要安装的文件系统已经被安装在由系统调用的参数
- 所指定的安装点上*/
- if (path->mnt->mnt_sb == newmnt->mnt_sb &&
- path->mnt->mnt_root == path->dentry)
- goto unlock;
- err = -EINVAL;
- /*该安装点是一个符号链接*/
- if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode))
- goto unlock;
- newmnt->mnt_flags = mnt_flags;
- /*把新安装的文件系统对象插入到namespace链表、
- 散列表以及父文件系统的子链表中*/
- if ((err = graft_tree(newmnt, path)))
- goto unlock;
- if (fslist) /* add to the specified expiration list */
- list_add_tail(&newmnt->mnt_expire, fslist);
- up_write(&namespace_sem);
- return 0;
- unlock:
- up_write(&namespace_sem);
- mntput(newmnt);
- return err;
- }
新安装的文件系统对象链入系统树。
- static int graft_tree(struct vfsmount *mnt, struct path *path)
- {
- int err;
- if (mnt->mnt_sb->s_flags & MS_NOUSER)
- return -EINVAL;
- if (S_ISDIR(path->dentry->d_inode->i_mode) !=
- S_ISDIR(mnt->mnt_root->d_inode->i_mode))
- return -ENOTDIR;
- err = -ENOENT;
- mutex_lock(&path->dentry->d_inode->i_mutex);
- if (IS_DEADDIR(path->dentry->d_inode))
- goto out_unlock;
- err = security_sb_check_sb(mnt, path);
- if (err)
- goto out_unlock;
- err = -ENOENT;
- if (!d_unlinked(path->dentry))/*加入树*/
- err = attach_recursive_mnt(mnt, path, NULL);
- out_unlock:
- mutex_unlock(&path->dentry->d_inode->i_mutex);
- if (!err)
- security_sb_post_addmount(mnt, path);
- return err;
- }
- /*将文件系统添加到父文件系统的命名空间中*/
- static int attach_recursive_mnt(struct vfsmount *source_mnt,
- struct path *path, struct path *parent_path)
- {
- LIST_HEAD(tree_list);
- struct vfsmount *dest_mnt = path->mnt;
- struct dentry *dest_dentry = path->dentry;
- struct vfsmount *child, *p;
- int err;
- if (IS_MNT_SHARED(dest_mnt)) {
- err = invent_group_ids(source_mnt, true);
- if (err)
- goto out;
- }
- err = propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list);
- if (err)
- goto out_cleanup_ids;
- if (IS_MNT_SHARED(dest_mnt)) {
- for (p = source_mnt; p; p = next_mnt(p, source_mnt))
- set_mnt_shared(p);
- }
- spin_lock(&vfsmount_lock);
- if (parent_path) {
- detach_mnt(source_mnt, parent_path);
- attach_mnt(source_mnt, path);
- touch_mnt_namespace(parent_path->mnt->mnt_ns);
- } else {
- /*确保新的vfsmount实例的mnt_parent成员指向父文件系统
- 的vfsmount实例,而mnt_mountpoint成员指向装载点在父文件
- 系统中的dentry实例*/
- mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt);
- commit_tree(source_mnt);
- }
- list_for_each_entry_safe(child, p, &tree_list, mnt_hash) {
- list_del_init(&child->mnt_hash);
- /*将新的mnt添加到全局散列表以及父文件系统mnt实例中
- 的子文件系统链表*/
- commit_tree(child);
- }
- spin_unlock(&vfsmount_lock);
- return 0;
- out_cleanup_ids:
- if (IS_MNT_SHARED(dest_mnt))
- cleanup_group_ids(source_mnt, NULL);
- out:
- return err;
- }
Linux虚拟文件系统之文件系统安装(sys_mount())相关推荐
- 网络与IO知识扫盲(一):Linux虚拟文件系统,文件描述符,IO重定向
系统IO原理 在 Linux 中: VFS(Virtual Filesystem Switch):虚拟文件系统,是一个目录树.树上不同的节点可以映射到物理的文件地址,可以挂载. 相当于一个解耦层,在具 ...
- Linux虚拟文件系统、文件描述符、管道
在Linux中,所有内容都是以文件的形式保存和管理的,即一切皆文件,普通文件是文件,目录(Windows下称为文件夹)是文件,硬件设备(键盘.监视器.硬盘.打印机等)都是文件,就连套接字(socket ...
- linux 目录防篡改,一种基于Linux虚拟文件系统的防篡改方法及系统的制作方法
一种基于Linux虚拟文件系统的防篡改方法及系统的制作方法 [技术领域] [0001]本发明涉及文件防护技术领域,特别涉及一种基于Linux虚拟文件系统的防篡改方法及系统. [背景技术] [0002] ...
- Linux虚拟文件系统:数据结构与文件系统注册、文件打开读写
数据结构 超级块 - super_block 索引节点 - inode 目录项 - dentry 文件结构 - file 虚拟文件系统实现 注册文件系统 - register_filesystem 打 ...
- Linux虚拟文件系统
从文件 I/O 看 Linux 的虚拟文件系统 1 引言 Linux 中允许众多不同的文件系统共存,如 ext2, ext3, vfat 等.通过使用同一套文件 I/O 系统 调用即可对 Linux ...
- Linux 虚拟文件系统四大对象:超级块、inode、dentry、file之间关系
一:文件系统 1. 什么是文件系统? 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统. 通常文件系统是用于存储和组织文件的一种机制,便于对文件进行方便的查找与访问. 文件系统 ...
- linux虚拟文件系统浅析
linux虚拟文件系统浅析 虚拟文件系统(VFS) 在我看来, "虚拟"二字主要有两层含义: 1, 在同一个目录结构中, 可以挂载着若干种不同的文件系统. VFS隐藏了它们的实现细 ...
- linux 文件系统 vfs,linux虚拟文件系统vfs
<操作系统>课程设计报告课程设计题目:操作系统课程设计 设计时间:2016/1/10一. 课程设计目的与要求需要完成的内容:(1) 安装虚拟机:Vmware.Vmware palyer ( ...
- Linux 虚拟文件系统(一)概述
Linux 虚拟文件系统(一)概述 tags: Linux源码 Linux 虚拟文件系统一概述 文章梗概 正文 文件系统 虚拟文件系统架构 虚拟文件系统如何知道可用的文件系统有哪些的 不太喜欢的环节 ...
- linux 创建 虚拟文件系统设备 文件节点 使用 proc_create 实例 简介
proc虚拟文件系统也可以创建虚拟文件节点,实现用户空间与内核空间的交互.在驱动中创建节点,可以实现对硬件的控制.proc_create函数原型(在kernel-3.10/include/linux/ ...
最新文章
- MVP在Android平台上的应用
- jeecg uedit 自定义图片上传路径
- Ubuntu 下 使用 adb logcat 显示 Android 日志
- mysql 5.7.15 union order by 子查询排序不生效
- 使用ImageView引起Missing contentDescription attribute on image的问题
- 【EOS】EOS环境基础
- FlowNet到FlowNet2.0:基于卷积神经网络的光流预测算法
- iPhone使用教程
- 经典6位半HP34401A电路图
- 自动驾驶领域中常见英文缩写、相关含义以及常用专业英文
- 2020年Web前端面试题及答案----CSS篇
- 论文阅读笔记《Optimal Image-Based Guidance of Mobile Manipulators Using Direct Visual Servoing》
- 树莓派使用create_ap创建局域网
- Freemarker语法2
- H2.64和H2.65编码区别
- 【笔记】学习CSS布局17——column
- 武汉公交车司机的技术真NB
- #单利,复利。Daphne,Cleo。
- 愿与你同行作一个终身学习者
- 000视频基础知识入门--科普向
热门文章
- bzero函数_Linux(基础) | 系统IO函数的使用
- ZooKeeper 安装与部署
- 代替Reflection(反射)的一些方法(转)
- 为什么开发移动端web不使用jQuery
- (转载)使用Maven构建多模块项目
- 动态修改php的配置项
- [Andriod官方API指南]连接之蓝牙
- 【hdu - 2568】ACM程序设计期末考试081230
- C#笔记(一):类型,泛型,集合
- Silverlight 5 RC新特性探索系列:15.Silverlight 5 RC 对OpenType字体属性的支持