Linux Hugetlbfs内核源码简析-----(二)Hugetlbfs挂载
本文只讨论执行"mount none /mnt/huge -t hugetlbfs"命令后,mount系统调用的执行过程(基于Linux-3.4.51),不涉及进程相关的细节。
mount系统调用的内核实现:
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; /* 从用户空间copy文件系统类型,文件系统类型字符串长度不能大于PAGE_SIZE,即,不能大与4K。
* kernel_type = "hugetlbfs"
*/
ret = copy_mount_string(type, &kernel_type);
if (ret < )
goto out_type; /* 从用户空间获取挂载点, kerne_dir = "/mnt/huge" */
kernel_dir = getname(dir_name);
if (IS_ERR(kernel_dir)) {
ret = PTR_ERR(kernel_dir);
goto out_dir;
} /*从用户空间获取挂载设备,kernel_dev = "none"*/
ret = copy_mount_string(dev_name, &kernel_dev);
if (ret < )
goto out_dev; /*获取mount命令的其它参数*/
ret = copy_mount_options(data, &data_page);
if (ret < )
goto out_data; /*处理具体的mount细节*/
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;
}
相关参数处理完之后,具体的Mount操作由do_mount()函数实现,do_mount()主要分为两部分来实现,一是找到装载点的dentry项,二是创建hugetlbfs的super_block、vfsmount、已经挂载点dentry等相关数据结构之间的关联。
一、kern_path()查找挂载点
path_init():查找挂载点路径名(即,/mnt/huge)的搜索起点的根目录,保存在数据结构struct nameidata中。
nd->root = current->fs->root;
nd->path = nd->root;
nd->inode = nd->path.dentry->d_inode;
link_path_walk():该函数由一个大循环组成,逐分量处理文件名或路径名。名称在循环内分为各个分量(各分量通过一个或多个“/”分割)。每个分量表示一个目录名,最后一个分量是文件名。在每一个循环周期中,直至指定的文件名或目录名处理完毕并找到匹配的inode。
具体如下:
1、逐字符扫描路径名,斜线“/”会被跳过。
2、may_lookup()判断当前inode是否定义了permission方法,来采用不同的方法判断当前进程是否允许进入该目录。
3、判断当前分量是"."或者“..”,如果是“..”,则设置标志LAST_DOTDOT,最后调用walk_component()--->handle_dots()--->follow_dotdot()处理。如果是".",则设置标志LAST_DOT。
4、如果是普通分量,则调用walk_component()--->do_lookup()处理。do_lookup()处理实际的查找工作,查找分量对应的dentry。首先从上一级目录的dentry中查找inode,并调用d_revalidate()检查该缓存项是否有效(即,是否和实际文件系统的中的数据一致),如果有效,则返回;如果无效,则调用__lookup_hash()继续查找,首先调用lookup_dcache()查找缓存中是否存在,如果不存在,继续调用lookup_real(),调用具体的文件系统的lookup函数查找。
do_lookup()也处理跟踪挂载点的工作,也需要判断下级目录是否也挂载文件系统,__follow_mount_rcu()负责具体处理,在这里不做讨论。
5、nested_symlink()判断分量是否是符号链接。只有用于表示符号链接的inode,其inode_operations中的lookup函数指针才有具体的值,否则为NULL。
complete_walk():该函数做一些相关检查,确认是否需再次调用d_revalidate()判断缓存项是否有效。
二、do_new_mount()装载文件系统
do_new_mount()分为两个部分:do_kern_mount()和do_add_mount()。
do_kern_mount():首先调用get_fs_type()获取对应的已注册的文件系统类型。对于hugetlbfs来说,对应的内核文件系统类型是hugetlbfs_fs_type。获取对应的文件系统类型后,首先调用alloc_vfsmnt()分配并初始化mount数据结构,再调用mount_fs(),进一步调用hugetlbfs_mount(),分配挂载点的super_block、dentry、inode并建立相关映射。最后建立mount、super_block、dentry之间的映射。具体的映射关系如http://www.cnblogs.com/MerlinJ/p/4053689.html文中最后的图表所示。
hugetlbfs_mount()做了如下工作:
1、申请并初始化一个super_block。
2、调用set_anon_super(),获得一个未使用的此设备号dev,然后用主设备号0和次设备号dev设置新超级块的s_dev字段。
3、将该super_block挂到全局super_blocks链表中,同时挂到hugetlbfs_fs_type->fs_supers链表中。
4、调用hugetlbfs_fill_super(),创建dentry、inode,并建立dentry、inode、super_block之间的映射。
do_add_mount():首先判断文件系统是否重复装载,相同文件系统不能挂载到相同挂载点。再调用attach_recursive_mnt(),将挂载点加入到全局目录树,即,将do_kern_mount()创建的mount数据结构,挂到全局mount_hashtable链表中,挂到命名空间的mnt_list链表中,同时挂到父挂载点的mnt_mounts链表中。
只是大体走了一下流程,很多具体细节并没有涉及到,还有待补充。
参考:
http://blog.csdn.net/chenjin_zhong/article/details/8448862
http://blog.csdn.net/dndxhej/article/details/7434521
Linux Hugetlbfs内核源码简析-----(二)Hugetlbfs挂载的更多相关文章
- Flink源码阅读(一)——Flink on Yarn的Per-job模式源码简析
一.前言 个人感觉学习Flink其实最不应该错过的博文是Flink社区的博文系列,里面的文章是不会让人失望的.强烈安利:https://ververica.cn/developers-resource ...
- django-jwt token校验源码简析
一. jwt token校验源码简析 1.1 前言 之前使用jwt签发了token,里面的头部包含了加密的方式.是否有签名等,而载荷中包含用户名.用户主键.过期时间等信息,最后的签名还使用了摘要算法进 ...
- SpringMVC学习(一)——概念、流程图、源码简析
学习资料:开涛的<跟我学SpringMVC.pdf> 众所周知,springMVC是比较常用的web框架,通常整合spring使用.这里抛开spring,单纯的对springMVC做一下总 ...
- centos7编译linux的内核源码
昨天编译了一个linux 内核源码,遇到一些问题, 今天把我遇到的问题和解决方法分享给大家.希望可以帮助到需要的人. 1.检查是否安装了相应的包 我第一次编译的时候只安装的“Development T ...
- linux调度器源码分析 - 初始化(二)
本文为原创,转载请注明:http://www.cnblogs.com/tolimit/ 引言 上期文章linux调度器源码分析 - 概述(一)已经把调度器相关的数据结构介绍了一遍,本篇着重通过代码说明 ...
- AFNetworking源码简析
AFNetworking基本是苹果开发中网络请求库的标配,它是一个轻量级的网络库,专门针对iOS和OS X的网络应用设计,具有模块化的架构和丰富的APIs接口,功能强大并且使用简单,深受苹果应用开发人 ...
- 并发系列(二)——FutureTask类源码简析
背景 本文基于JDK 11,主要介绍FutureTask类中的run().get()和cancel() 方法,没有过多解析相应interface中的注释,但阅读源码时建议先阅读注释,明白方法的主要的功 ...
- 0002 - Spring MVC 拦截器源码简析:拦截器加载与执行
1.概述 Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理.例如通过拦截器可以进行权限验证.记录请求信息的日 ...
- Linux进程调度与源码分析(二)——进程生命周期与task_struct进程结构体
1.进程生命周期 Linux操作系统属于多任务操作系统,系统中的每个进程能够分时复用CPU时间片,通过有效的进程调度策略实现多任务并行执行.而进程在被CPU调度运行,等待CPU资源分配以及等待外部事件 ...
随机推荐
- 华硕X84L无线驱动查找
打开官网:http://www.asus.com.cn/ 点击导航栏的服务与支持 产品型号识别http://www.asus.com.cn/support/Article/565/ 我的是:X84L ...
- 算法库:基础线性代数子程序库(Basic Linear Algebra Subprograms,BLAS)介绍
调试DeepFlow光流算法,由于作者给出的算法是基于Linux系统的,所以要在Windows上运行,不得不做大量的修改工作.移植到Windows平台,除了一些头文件找不到外,还有一些函数也找不到.这 ...
- 山东省第一届ACM省赛
ID PID Title Accepted Submit A 2151 Phone Number 22 74 B 2159 Ivan comes again! 1 17 C 2158 Hello ...
- esriSRProjCS4Type Constants
ArcGIS Developer Help (Geometry) esriSRProjCS4Type Constants See Also esriSRProjCSType Constants ...
- 编码中常用的SQL语法
蓝色标注的都是比较常见的SQL ====================== 开发中常见的SQL: left join , right join 防止丢弃数据 inner join CASE WHNE ...
- ASP.Net软件工程师基础(四)
1.接口 (1)接口是一种规范.协议,定义了一组具有各种功能的方法(属性.索引器本质是方法). (2)接口存在的意义:多态.多态的意义:程序可扩展性. (3)接口解决了类的多继承的问题. (4)接口解 ...
- history.back(-1)和history.go(-1)的区别
history.back(-1):直接返回当前页的上一页,数据全部消息,是个新页面 history.go(-1):也是返回当前页的上一页,不过表单里的数据全部还在 返回到指定连接:document.l ...
- <%%>与<%#%>与<%=%>
在asp.net中经常出现包含这种形式<%%>的html代码,总的来说包含下面这样几种格式: 一. <%%> 这种格式实际上就是和asp的用法一样的,只是asp中里面是vbsc ...
- git克隆项目到一个非空目录
这只是记录: 1. 进入非空目录,假设是 /workdir/proj1 2. git clone --no-checkout https://git.oschina.net/NextApp/platf ...
- 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型
[Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ...