免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 727 | 回复: 2

[内核入门] Linux内核源码分析-卸载文件系统-sys_umount [复制链接]

论坛徽章:
0
发表于 2016-10-20 11:12 |显示全部楼层
Linux内核源码分析-卸载文件系统-sys_umount
本文主要参考《深入理解Linux内核》,结合2.6.11.1版的内核代码,分析内核文件子系统中的卸载文件系统函数。
注意:
1、不描述内核同步、错误处理、参数合法性验证相关的内容
2、源码摘自Linux内核2.6.11.1版
3、阅读本文请结合《深入理解Linux内核》第三版相关章节
4、本文会不定时更新
1sys_umount
函数源码:
  1. /*
  2. * Now umount can handle mount points as well as block devices.
  3. * This is important for filesystems which use unnamed block devices.
  4. *
  5. * We now support a flag for forced unmount like the other 'big iron'
  6. * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
  7. */

  8. asmlinkage long sys_umount(char __user * name, int flags)
  9. {
  10.         struct nameidata nd;
  11.         int retval;

  12.         retval = __user_walk(name, LOOKUP_FOLLOW, &nd);
  13.         if (retval)
  14.                 goto out;
  15.         retval = -EINVAL;
  16.         if (nd.dentry != nd.mnt->mnt_root)
  17.                 goto dput_and_out;
  18.         if (!check_mnt(nd.mnt))
  19.                 goto dput_and_out;

  20.         retval = -EPERM;
  21.         if (!capable(CAP_SYS_ADMIN))
  22.                 goto dput_and_out;

  23.         retval = do_umount(nd.mnt, flags);
  24. dput_and_out:
  25.         path_release_on_umount(&nd);
  26. out:
  27.         return retval;
  28. }
复制代码
函数处理流程:
1、把mnt对象的mnt_sb存入类型为super_block*的局部变量sb中
2、调用安全验证函数security_sb_umount验证安全性
3、如果以参数MNT_EXPIRE卸载文件系统:
(1) 如果是卸载当前进程的根文件系统、卸载参数中包MNT_FORCE或 MNT_DETACH标志,则返回EINVAL
(2) 如果mnt->mnt_count 不等于2,即除了父mnt和该函数外,有其他引用,标志mnt非空闲,返回EBUSY
(3) 调用函数xchg,如果mnt->mnt_expiry_mark为0,即非过期,设置为过期并返回EAGAIN;已过期则执行下一步
4、如果是强制卸载且sb->s_op->umount_begin非空,这调用该函数,用于网络文件系统
5、卸载根文件系统,且卸载标志不含MNT_DETACH(即非懒卸载),如果超级块不是以只读方式安装,以只读方式重新安装
6、如果超级块的引用计数器为1,处理acct相关的信息
7、如果文件系统已为空闲或是懒卸载,调用函数umount_tree卸载以该文件系统根的文件系统树
3umount_tree
函数源码:
  1. void umount_tree(struct vfsmount *mnt)
  2. {
  3.         struct vfsmount *p;
  4.         LIST_HEAD(kill);

  5.         for (p = mnt; p; p = next_mnt(p, mnt)) {
  6.                 list_del(&p->mnt_list);
  7.                 list_add(&p->mnt_list, &kill);
  8.         }

  9.         while (!list_empty(&kill)) {
  10.                 mnt = list_entry(kill.next, struct vfsmount, mnt_list);
  11.                 list_del_init(&mnt->mnt_list);
  12.                 list_del_init(&mnt->mnt_fslink);
  13.                 if (mnt->mnt_parent == mnt) {
  14.                         spin_unlock(&vfsmount_lock);
  15.                 } else {
  16.                         struct nameidata old_nd;
  17.                         detach_mnt(mnt, &old_nd);
  18.                         spin_unlock(&vfsmount_lock);
  19.                         path_release(&old_nd);
  20.                 }
  21.                 mntput(mnt);
  22.                 spin_lock(&vfsmount_lock);
  23.         }
  24. }
复制代码

函数处理流程:
1、循环调用函数next_mnt,对以mnt为根的文件系统对象树进行深度优先搜索,每次返回一个文件系统对象,把该对象从文件系统对象链表中删除,然后加入kill链表中、
2、对kill链表中的每个文件系统对象,把该对象从kill链表和文件系统到期链表中删除;如果文件系统不是命名空间的根文件系统,调用函数detach_mnt释放该文件对象相关的数据结构,返回文件系统的安装点信息,调用函数path_release释放安装点目录
4next_mnt
函数源码:
  1. static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root)
  2. {
  3.         struct list_head *next = p->mnt_mounts.next;
  4.         if (next == &p->mnt_mounts) {
  5.                 while (1) {
  6.                         if (p == root)
  7.                                 return NULL;
  8.                         next = p->mnt_child.next;
  9.                         if (next != &p->mnt_parent->mnt_mounts)
  10.                                 break;
  11.                         p = p->mnt_parent;
  12.                 }
  13.         }
  14.         return list_entry(next, struct vfsmount, mnt_child);
  15. }
复制代码
函数处理流程:
1、取出当前文件系统对象的子链表的第一个元素存入局部变量next中
2、如果当前文件系统的子文件系统链表为空,循环执行下列步骤
(1) 如果当前文件系统是根,返回NULL
(2) 否则,把当前文件系统对象的兄弟链表中下一个元素存入next
(3) 如果next不是当前文件系统对象的父文件系统对象的子链表的头,即父文件系统子链表未处理完成,退出循环
(4) 如果当前文件系统的父文件系统的子文件系统链表已处理完,把当前文件系统设置为当前文件系统的父文件系统
3、返回包含next的文件系统对象
5detach_mnt
函数源码:
  1. static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd)
  2. {
  3.         old_nd->dentry = mnt->mnt_mountpoint; //安装点目录项对象
  4.         old_nd->mnt = mnt->mnt_parent;  //父文件对象
  5.         mnt->mnt_parent = mnt;  //把文件对象从文件对象树中移除
  6.         mnt->mnt_mountpoint = mnt->mnt_root; //安装点目录项对象
  7.         list_del_init(&mnt->mnt_child);  //把文件对象从兄弟链表中删除
  8.         list_del_init(&mnt->mnt_hash);//把文件对象从文件对象hash表中删除
  9.         old_nd->dentry->d_mounted--; //减少原安装点的安装文件系统数
  10. }
复制代码



论坛徽章:
140
2015年亚洲杯之日本
日期:2015-04-28 13:32:012015年亚洲杯之朝鲜
日期:2015-05-06 10:16:442015年亚洲杯之日本
日期:2015-05-06 10:21:342015年亚洲杯纪念徽章
日期:2015-05-13 17:16:442015亚冠之北京国安
日期:2015-05-13 17:18:292015亚冠之鹿岛鹿角
日期:2015-05-13 17:19:062015亚冠之德黑兰石油
日期:2015-05-27 16:47:402015亚冠之塔什干棉农
日期:2015-05-28 15:24:122015亚冠之卡尔希纳萨夫
日期:2015-06-01 13:52:392015亚冠之柏斯波利斯
日期:2015-06-04 17:37:292015亚冠之阿尔纳斯尔
日期:2015-06-16 11:31:202015亚冠之塔什干火车头
日期:2015-06-23 10:12:33
发表于 2016-10-20 11:19 |显示全部楼层
打赏一下,多谢分享

论坛徽章:
0
发表于 2016-10-20 12:13 |显示全部楼层
回复 2# 王楠w_n

这个系列我已经写了10来篇了,正等博客审核了,谢谢,继续努力!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

DTCC2020中国数据库技术大会

【架构革新 高效可控】2020年12月21日-23日第十一届中国数据库技术大会将在北京隆重召开。

大会设置2大主会场,20+技术专场,将邀请超百位行业专家,重点围绕数据架构、AI与大数据、传统企业数据库实践和国产开源数据库等内容展开分享和探讨,为广大数据领域从业人士提供一场年度盛会和交流平台。

http://dtcc.it168.com


大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP