Overlayfs 注册与挂载

OverlayFs 注册

OverlayFs在内核中以模块的形式存在,在加载模块时,会涉及到两个关键函数:入口函数和出口函数

module_init(ovl_init);
module_exit(ovl_exit);

当使用命令 overlay 加载 overlayfs 模块时,会调用入口函数 ovl_init()

static int __init ovl_init(void) {return register_filesystem(&ovl_fs_type);
}

当加载 overlay 模块时,模块入口函数 register_fileststem 函数注册 overlayfs:

#include <linux/fs.h>extern int register_filesystem(struct file_system_type *);

注册一个文件系统需要用到 struct file_ststem_type,这个结构定义了文件系统的名称,挂载函数等信息:

struct file_system_type {const char *name;int fs_flags;struct dentry *(*mount) (struct file_system_type *, int,const char *, void *);void (*kill_sb) (struct super_block *);struct module *owner;struct file_system_type * next;struct list_head fs_supers;struct lock_class_key s_lock_key;struct lock_class_key s_umount_key;
};

OverlayFs 挂载

在 overlayfs/super.c 中指明了挂载函数:.mount = ovl_mount

static struct file_system_type ovl_fs_type = {.owner        = THIS_MODULE,.name        = "overlay",.mount       = ovl_mount,.kill_sb   = kill_anon_super,
};
MODULE_ALIAS_FS("overlay");

ovl_mount 是函数 mount_nodev 的封装:

static struct dentry *ovl_mount(struct file_system_type *fs_type, int flags,const char *dev_name, void *raw_data)
{return mount_nodev(fs_type, flags, raw_data, ovl_fill_super);
}struct dentry *mount_nodev(struct file_system_type *fs_type,int flags, void *data,int (*fill_super)(struct super_block *, void *, int))
{...// 1.创建一个 superblock ,它已经链接到全局 superblock 链表中struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL);...// 2. 填充 superblockerror = fill_super(s, data, flags & SB_SILENT ? 1 : 0);...
}
EXPORT_SYMBOL(mount_nodev);

OverlayFs挂载信息

结构体 ovl_fs 以及 ovl_config 是 Overlayfs 的特有信息,它记录了 OverlayFs upper 层和 lower 层的文件系统、文件名以及 work 目录的 dentry 这些挂载信息:

/* private information held for overlayfs's superblock */
struct ovl_fs {struct vfsmount *upper_mnt;unsigned int numlayer;/* Number of unique fs among layers including upper fs */unsigned int numfs;struct ovl_layer *layers;struct ovl_sb *fs;/* workbasedir is the path at workdir= mount option */struct dentry *workbasedir;/* workdir is the 'work' directory under workbasedir */struct dentry *workdir;/* index directory listing overlay inodes by origin file handle */struct dentry *indexdir;long namelen;/* pathnames of lower and upper dirs, for show_options */struct ovl_config config;/* creds of process who forced instantiation of super block */const struct cred *creator_cred;bool tmpfile;bool noxattr;/* Did we take the inuse lock? */bool upperdir_locked;bool workdir_locked;/* Traps in ovl inode cache */struct inode *upperdir_trap;struct inode *workbasedir_trap;struct inode *workdir_trap;struct inode *indexdir_trap;/* -1: disabled, 0: same fs, 1..32: number of unused ino bits */int xino_mode;/* For allocation of non-persistent inode numbers */atomic_long_t last_ino;
};struct ovl_config {char *lowerdir;char *upperdir;char *workdir;bool default_permissions;bool redirect_dir;bool redirect_follow;const char *redirect_mode;bool index;bool nfs_export;int xino;bool metacopy;
};

填充 super_block

填充 super_block 由函数 ovl_file_super 完成,主要包括下列工作:

  1. 分配一个 ovl_fs 结构的 ofs,调用函数 ovl_parse_opt() 对挂载命令进行解析,得到 upper、lower、work 目录的字符串,存入 ofs 的 config 字段:
struct ovl_fs *ofs;  //存储 overlayfs 挂载信息
...
ofs = kzalloc(sizeof(struct ovl_fs), GFP_KERNEL);
...
err = ovl_parse_opt((char *)data, &ofs->config);
...
  1. 对 upper 目录和 worker 目录的字符串进行解析。
if (ofs->config.upperdir) {...err = ovl_get_upper(sb, ofs, &upperpath);...err = ovl_get_workdir(sb, ofs, &upperpath);...
}

内核通过 ovl_get_upper() 以及 ovl_get_workdir() 来获得 upper 层和 work 目录的路径,最终都会调用 kern_path() 执行路径解析,得到目录,在解析完路径之后,函数内部会对其进行有效性检查,要求 upper 目录与 work 目录必须处在相同文件系统下,同时要求两个目录不能在同一子树中

  1. 函数 ovl_get_lowerstack() 对记录 lower 层的字符串进行解析,分析出 lower 层数,循环调用函数 ovl_lower_dir() 对 lower 层进行解析,该函数最终也会调用到 kern_path() 执行路径解析,得到每个 lower 目录的路径,保存在路径栈 stack 中:
// func ovl_get_lowerstack()
...
// 复制 lower 层的字符串
lowertmp = kstrdup(ofs->config.lowerdir, GFP_KERNEL);
...
// 得到 lower 层数目
stacklen = ovl_split_lowerdirs(lowertmp);
...
// 为路径栈分配空间
stack = kcalloc(stacklen, sizeof(struct path), GFP_KERNEL);
...
// 循环获取每个 lower 层的路径
for (numlower = 0; numlower < stacklen; numlower++) {err = ovl_lower_dir(lower, &stack[numlower], ofs,&sb->s_stack_depth, &remote);...
}
...
  1. 填充 struct ovl_entry 类型的变量 oe 分配空间(这个变量记录 OverlayFS 根目录的层次信息,由根目录指向)。为 OverlayFS 根目录分配 inode,创建根目录的 dentry。通过前面得到的 upper 层和 lower 层的路径填充 oe,然后设置根目录 dentry 的 d_fsdata 字段指向 oe。

  2. 填充 super_block 的 s_d_op 字段,这个字段是一个 struct dentry_operations 类型的指针,它描述了 OverlayFS 的 dentry 操作,每当在 OverlayFS 中分配一个 dentry 时,会使用 s_d_op 字段赋值 dentry 的 d_op 字段

    // func ovl_get_lowerstack()
    ...
    // 填充 oe
    for (i = 0; i < numlower; i++) {oe->lowerstack[i].dentry = dget(stack[i].dentry);oe->lowerstack[i].layer = &ofs->layers[i+1];
    }
    // 填充 sb->s_d_op
    if (remote)sb->s_d_op = &ovl_reval_dentry_operations;
    elsesb->s_d_op = &ovl_dentry_operations;
    ...// func ovl_get_root()
    ...
    // 为根目录分配inode,创建dentry
    root = d_make_root(ovl_new_inode(sb, S_IFDIR, 0));
    ...
  3. 填充 super_block 的剩余字段

OverlayFS 注册与挂载相关推荐

  1. Docker Overlayfs文件系统联合挂载原理

    我们经常会听到什么联合挂载,Overlayfs,它们到底是什么关系,这一篇将给大家解释. 联合挂载技术实现-Overlayfs overlayFS则是联合挂载技术的一种实现.除了overlayFS以外 ...

  2. overlayfs源代码解析

    overlayfs源代码解析 mount挂载 注册文件系统 挂载文件系统 读写目录 openat系统调用打开目录 getdents系统调用,搜索目录 创建/删除文件 创建文件 删除文件 读写文件 读/ ...

  3. 容器三把斧之 | OverlayFS原理与实现

    Docker 底层有三驾马车,Namespace.CGroup 和 UnionFS(联合文件系统),UnionFS 是 Docker 镜像的基础.前面我们介绍过 Namespace 和 CGroup, ...

  4. 深入理解overlayfs(二):使用与原理分析

    版权声明:本文为CSDN博主「luckyapple1028」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明. 原文链接:https://blog.csdn.net/l ...

  5. Docker实现原理之 - OverlayFS实现原理

    感谢平台分享-http://bjbsair.com/2020-04-10/tech-info/53289.html Docker 底层有三驾马车, Namespace . CGroup 和 Union ...

  6. Android 动态分区详解(七) overlayfs 与 adb remount 操作

    0. 导读 最开始学习 Android 动态分区源码的时候,比较代码发现 system/core/fs_mgr 目录下多了一个名为 fs_mgr_overlayfs.cpp 的文件,一直不知道什么时候 ...

  7. 使用Squashfs和Overlayfs提高嵌入式Linux文件系统可靠性

    在使用嵌入式 Linux 系统的时,会出现由于设备意外断电引起文件系统损坏而最终使该设备无法启动的现象.为了应对这种情况,通常会从硬件设计如采用备用电源,无论是锂电池还是超级电容等,或者从系统软件设上 ...

  8. Docker技术原理

    一.Docker架构 Docker包括三个基本概念: 镜像(Image): Docker 镜像(Image),就相当于是一个 root 文件系统.比如官方镜像 ubuntu:16.04 就包含了完整的 ...

  9. 微前端在美团外卖的实践

    来自:美团技术团队 微前端是微服务理念在前端的应用.之前美美给大家介绍过微前端在美团HR系统和美团闪购的实践文章. 今天的文章来自美团外卖广告团队,他们参考业界优秀方案,同时也深度结合了广告端实际业务 ...

最新文章

  1. 《用Python进行自然语言处理》第 1 章 语言处理与 Python
  2. SAP 电商云 Spartacus SSR Optimization Engine 几处 timeout 的执行顺序
  3. mysql 触发器计算总价,mysql’插入’触发器根据其他字段计算字段
  4. qt中继承pushbutton自定义控件设置按钮样式
  5. MySQL:查询条件
  6. 【OpenCV 例程200篇】53. Scipy 实现图像二维卷积
  7. linux 启动ftp服务,sftp服务
  8. 3d胆码计算机方法,3D百十个位定胆技巧准确率95
  9. 开头的单词_为什么以“S”开头的单词最多?| 英汉比较教学法·语音思维No.16...
  10. NOI2022游记,未曾设想的道路
  11. 美团外卖饿了么百度外卖竞品分析报告
  12. 浅谈C中的malloc和free “来自bccn C语言论坛”
  13. 理解 LDA 主题模型
  14. python 直方图均衡化
  15. Windows命令行tree命令打印目录树
  16. 一句话获取spring下所有注解
  17. Unity LOD-Level of Detail(多层次细节)使用心得2—— LOD Bias设置
  18. 基于TI C55x架构的定点TMS320VC5509A音频专用DSP处理器开发板规格书
  19. java课程设计:基于SSM实现个人健康管理系统
  20. vue+elementUI实现调用PC摄像头拍照上传图片(谷歌火狐测试可用,其他自测)

热门文章

  1. lumen 配置数据库结果自动转数组_Laravel Lumen 数组操作
  2. 超级删除PowerTools
  3. OpenHarmony 3.1Release 电话功能演示—基于润和DAYU200开发套件
  4. 学渣的刷题之旅 leetcode刷题 20.有效的括号
  5. 阿里P8熬了一个月肝出这份32W字Java面试手册,在Github标星31K+
  6. FPGA几大厂商介绍,你知道的有哪些呢?
  7. 电赛公开课整理(一),电路基础,截图+模电知识【15000字】【原创】
  8. 自动化失败的6种原因
  9. 使用section.key的形式读取ini配置项
  10. Dynamics CRM 系统自定义部分的语言翻译