背景

Linux-4.1内核使用overlay挂载文件系统后,在写文件遇突然掉电后重启出现修改文件报错问题;问题原因是写文件过程种会在wrok目录下创建Whiteout文件,文件写成功后会删除Whiteout文件,但在异常掉电时Whiteout文件没有被删除,导致系统重启overlay挂载检查work不为空出现异常;下面来分析overlay启动挂载代码流程。

代码位置

fs/overlayfs/
├── copy_up.c
├── dir.c
├── inode.c
├── Kconfig
├── Makefile
├── overlayfs.h
├── readdir.c
└── super.c

super.c

    ovl_init 初始化函数

register_filesystem(&ovl_fs_type); 注册文件系统到系统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(fs_type, flags, raw_data, ovl_fill_super);   文件系统挂载类型回调函数ovl_fill_super

ovl_fill_super 回调函数

解析挂载参数
ovl_parse_opt((char *) data, &ufs->config);static const match_table_t ovl_tokens = {{OPT_LOWERDIR,          "lowerdir=%s"},{OPT_UPPERDIR,            "upperdir=%s"},{OPT_WORKDIR,         "workdir=%s"},{OPT_ERR,          NULL}};ovl_mount_dir(ufs->config.upperdir, &upperpath);  挂载upper
ovl_mount_dir(ufs->config.workdir, &workpath);       挂载workerkstrdup(ufs->config.lowerdir, GFP_KERNEL);   分配内存
ovl_split_lowerdirs(lowertmp);  判断lower层级不大于500
ovl_lower_dir(lower, &stack[numlower], &ufs->lower_namelen, &sb->s_stack_depth); 挂载各lower层级clone_private_mount(&upperpath);
ovl_workdir_create(ufs->upper_mnt, workpath.dentry); 创建work目录
if (IS_ERR(ufs->workdir)) {创建失败本该挂载为只读文件系统并打印提示,这里被注释了//pr_warn("overlayfs: failed to create directory %s/%s (errno: %i); mounting read-only\n",    //  ufs->config.workdir, OVL_WORKDIR_NAME, -err);//sb->s_flags |= MS_RDONLY;ufs->workdir = NULL; 这里为NULL会导致后面copy-up报空指针错误clone_private_mount(&stack[i]);    克隆lower私有挂载路径,并设置挂载属性为只读
mnt->mnt_flags |= MNT_READONLY; d_make_root(ovl_new_inode(sb, S_IFDIR, oe));    判断是否是根目录挂载  

ovl_workdir_create  创建work目录函数

检查work目录是否存在
#define OVL_WORKDIR_NAME "work"
lookup_one_len(OVL_WORKDIR_NAME, dentry, strlen(OVL_WORKDIR_NAME)); 目录存在就去清除
ovl_cleanup(dir, work); ovl_do_rmdir    vfs_rmdirerror = dir->i_op->rmdir(dir, dentry);fs/ubifs/dir.c +1174const struct inode_operations ubifs_dir_inode_operations = {.rmdir       = ubifs_rmdir,        err = check_dir_empty(c, d_inode(dentry)); 目录不为空会返回-39,删除失败walk directory or extended attribute entries.    遍历目录或扩展属性条目。ubifs_tnc_next_ent(c, &key, &nm);   err = -ENOTEMPTY;#define   ENOTEMPTY   39  /* Directory not empty */       

readdir.c

ovl_workdir_cleanup 补丁文件函数:递归清除文件目录

if (!d_is_dir(dentry) || level > 1) {ovl_cleanup(dir, dentry);    删除文件return;
}err = ovl_do_rmdir(dir, dentry);  删除不为空目录失败就删除目录里面的文件
if (err) {ovl_workdir_cleanup_recurse(&path, level + 1);ovl_dir_read(path, &rdd);  读出目录信息list_for_each_entry(p, &list, l_node) {lookup_one_len(p->name, path->dentry, p->len); ovl_workdir_cleanup(dir, path->mnt, dentry, level); 目录存在就递归删除}
}

递归删除work目录下的文件,目录删空后就能删除目录了

扩展

workdir目录下work下创建文件代码:

snprintf(name, sizeof(name), "#%lx", (unsigned long) dentry);
~ # ls /ubifs/work/work/ -l
c---------    1 root     root        0,   0 Mar  7 15:31 #ffffffc03e44b9d8

Linux-overlay启动挂载代码分析相关推荐

  1. 【鸿蒙OS开发入门】06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 启动init进程

    [鸿蒙OS开发入门]06 - 启动流程代码分析之KernelOS:之启动Linux-4.19 Kernel内核 一.head.S 启动start_kernel() 1.1 start_kernel() ...

  2. 【鸿蒙OS开发入门】13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解

    [鸿蒙OS开发入门]13 - 启动流程代码分析之第一个用户态进程:init 进程 之 init 任务详解 一. /etc/init.cfg 系统默认cfg:启动lo回环网卡 1.1 init.Hi35 ...

  3. linux内核中链表代码分析---list.h头文件分析(二)【转】

    转自:http://blog.chinaunix.net/uid-30254565-id-5637598.html linux内核中链表代码分析---list.h头文件分析(二) 16年2月28日16 ...

  4. Linux配置启动挂载:fstab文件详解

    Linux配置启动挂载:fstab文件详解 [日期:2014-12-23] 来源:Linux社区 作者:aceking10 [字体:大 中 小] fstab文件介绍 fstab文件包含了你的电脑上的存 ...

  5. linux内核中链表代码分析---list.h头文件分析(一)

    linux内核中链表代码分析---list.h头文件分析(一) 16年2月27日17:13:14 在学习数据结构时,有一个重要的知识点就是链表.对于链表的一些基本操作,它的最好学习资料就是内核中的li ...

  6. 【内核】linux内核启动流程详细分析【转】

    转自:http://www.cnblogs.com/lcw/p/3337937.html Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件 ...

  7. 【内核】linux内核启动流程详细分析

    Linux内核启动流程 arch/arm/kernel/head-armv.S 该文件是内核最先执行的一个文件,包括内核入口ENTRY(stext)到start_kernel间的初始化代码, 主要作用 ...

  8. Linux开机启动过程详细分析

    from: http://www.linuxidc.com/Linux/2007-11/8701.htm 由于操作系统正在变得越来越复杂,所以开机引导和关机下电的过程也越来越智能化.从简单的DOS系统 ...

  9. Linux SCSI设备容量打印代码分析

    探寻SCSI设备容量如何获取代码. 分析 8G USB转SD卡启动打印信息: sd 3:0:0:0: [sdb] 15523840 512-byte logical blocks: (7.94 GB/ ...

最新文章

  1. 新建一个spyder窗口
  2. WPS for MacOS如何设置自动拼写检查
  3. 【HDU - 5649】DZY Loves Sorting(线段树,区间更新区间查询,思维,01缩数变换,线段树分割)
  4. 【每日算法Day 84】面试必考题:Trie(字典树/前缀树)的实现
  5. 十大常用算法之马踏棋盘算法
  6. abb机器人伺服电机报闸是什么_什么是抱闸电机
  7. 基于cat12和SPM12进行大脑VBM数据分析笔记2——统计分析
  8. 实验二线性表的链式存储结构
  9. Typora安装教程
  10. JS设置浏览器缩放比例
  11. 亮度键消失、亮度键失灵且电脑亮度为最大 | 小米 | win11 | 解决办法最最最全合集
  12. 什么是甘特图?怎么做甘特图?
  13. 目标检测网络---评价指标
  14. git revert 之后 找回原来的代码
  15. 视频监控开发(1)——萤石云硬盘录像机SDK使用
  16. C语言的for循环转verilog,Verilog for 循环语句
  17. 我只是在猜想 ——站在云端看操作系统以及计算机的未来
  18. neo4j图数据库入门
  19. JavaWeb项目 学生后台管理系统 有源码!!(基于MVC设计模式)
  20. 如何建立有效的绩效管理体系?

热门文章

  1. Macbook Air如何将m4a格式转化为mp3格式?
  2. 世界上第一代电子计算机取名为,计算机应用基础知识计算机应用基础试题及答案...
  3. Niagara_Advanced内容示例 1.3 Communicate with External Render Targets
  4. ESP8266+Blinker+小爱同学舵机控制开关
  5. 解决在高分辨率下运行Photoshop CS6,程序界面字体过小的问题
  6. ubuntu下使用github安装R Packages[已解决]
  7. 霍华德:二呆青年勤修苦练终成一代大侠记
  8. EXCEL清除全表格式
  9. NDK学习笔记:JNI调用Java层方法创建Native的AudioTrack播放PCM(方法签名,CallXXXMethod)
  10. 手机里的照片导入计算机的方法,如何把iphone照片导入电脑 四种方法分享【图文】...