术语表:
struct mount:挂载点
struct mountpoint:挂载点节点
struct vfsmount:挂载项
源文件系统:用户将要挂载的文件系统
目的文件系统:挂载源文件系统的文件系统
一、目的
本文将介绍linux卸载文件系统的过程,从系统调用umount()函数开始解析,主要分为三个阶段:
1、查找挂载目录下所有已挂载的文件系统;
2、删除这些已挂载文件系统的挂载节点;
3、释放这些已挂载文件系统的挂载点数据结构;
本文以linux3.10版本为基础进行讲解。
二、函数调用关系
umount系统调用的定义在fs/namespace.c文件中,具体的定义为:SYSCALL_DEFINE2(umount,char
__user *, name, int, flags)。
下图描述了主要的函数调用关系,linux卸载文件系统主要分为三个阶段:
1、umount_tree()前半部分代码负责查找挂载目录下所有的文件系统;
2、umount_tree()后半部分代码负责删除这些文件系统的挂载节点;
3、namespace_unlock()负责释放这些已挂载文件系统的挂载点数据结构;
三、已挂载文件系统之间的关系
为了便于描述,我们假设ext2文件系统的tmp目录下挂载了ext3文件系统,ext3文件系统的sys目录下挂载了xfs文件系统,home目录下挂载了brtfs文件系统。我们将使用umount命令卸载ext2文件系统的tmp目录下所有已挂载的文件系统ext3、xfs和brtfs。
这四种文件系统存在以下几种关系:ext3、xfs和btrfs文件系统都存在于挂载点哈希表中;ext3的父文件系统是ext2,ext3是ext2的子文件系统;xfs和btrfs的父文件系统是ext3,exfs和btrfs是ext3的子文件系统。同时,三个挂载节点存在于挂载目录哈希表中,对应的挂载目录分别是tmp、sys和home。
四、查找挂载目录下所有的文件系统
首先do_umount()->umount_tree()前半部分代码的主要作用是把ext2文件系统tmp挂载目录下的所有文件系统通过递归的方式都查找出来,然后把这些文件系统从挂载点哈希表中删除,最后将查找到的所有文件系统都链接到tmp_list链表中。
其中,next_mnt()函数比较重要也很难懂,该函数的主要作用就是递归的把挂载目录下所有子文件系统都查找出来。例如,next_mnt()首先查找出ext2的子文件系统ext3,如果ext3也挂载了子文件系统,那么next_mnt()接着查找出ext3文件系统下所有的子文件系统,如此递归,直到查找出ext2文件系统下所有的已挂载的文件系统。
五、删除所有子文件系统的挂载节点
do_umount()->umount_tree()后半部分代码的主要作用是解除父子文件系统之间的关系,调用put_mountpoint()将挂载节点从挂载目录哈希表中删除并且释放挂载节点数据结构。
从图中可以看到tmp、sys和home三个挂载节点已经从挂载目录哈希表中删除了,并且挂载节点structmountpoint数据结构也被释放了。
六、挂载源文件系统
do_umount()->namespace_unlock()负责将tmp_list记录的所有文件系统依次从链表中删除,并且调用mntput()释放文件系统挂载点structmount数据结构。
从图中可以看到ext3、xfs和btrfs三个文件系统已经被彻底释放了,即被卸载了,系统中只剩下ext2文件系统了。
七、总结
linux卸载文件系统主要分为三个阶段:查找挂载目录下所有子文件系统的集合,并且链接到一个临时链表中;然后释放这些子文件系统的挂载节点数据结构;最后,遍历临时链表,释放所有子文件系统。
版权声明:
原创作品,如非商业性转载,请注明出处;如商业性转载出版,请与作者联系。