存储学徒的小作坊

文件系统挂载过程浅析(2)

上一篇 / 下一篇  2007-05-28 13:01:07 / 天气: 舒适 / 个人分类:学习笔记

查看( 118 ) / 评论( 2 )

完成了文件系统的加载,自然就免不了对其中的文件目录进行一番大刀阔斧的修修剪剪,然后再温柔的过河拆桥,卸载文件系统。

5、卸载文件系统

5.1 sys_oldumount

为了和旧版的兼容,给出了sys_oldumount的接口,在实际的实现里它是不带flag参数得sys_umount。src/fs/namespace.c中是这样实现的:

asmlinkage long sys_oldumount(char __user * name)
{
 return sys_umount(name, 0);
}

5.2 sys_mount
sys_umount可以处理挂载点,也可以处理快设备。这在非命名块设备的文件系统种尤为重要。其源码如下:


/*
 * Now umount can handle mount points as well as block devices.
 * This is important for filesystems which use unnamed block devices.
 *
 * We now support a flag for forced unmount like the other 'big iron'
 * unixes. Our API is identical to OSF/1 to avoid making a mess of AMD
 */

asmlinkage long sys_umount(char __user * name, int flags)
{
 struct nameidata nd;
 int retval;
-------ietf add start-------
根据name即,挂载点的路径参数,获得该挂在点的inode和dentry信息,将结果存入nd中。如果name参数是绝对路径,将按路径从根目录开始查找,否则从当前目录查找。具体请参见src/fs/namei.c的do_path_lookup函数(line 1103)。
-------ietf add end  -------
 retval = __user_walk(name, LOOKUP_FOLLOW, &nd);
 if (retval)
  goto out;
 retval = -EINVAL;
-------ietf add start-------
如果给定的路径不是一个挂载点,则返回
-------ietf add end  -------
 if (nd.dentry != nd.mnt->mnt_root)
  goto dput_and_out;
 if (!check_mnt(nd.mnt))
  goto dput_and_out;

 retval = -EPERM;
 if (!capable(CAP_SYS_ADMIN))
  goto dput_and_out;
-------ietf add start-------
根据flags,对挂载点执行卸载操作,详见5.3
-------ietf add end  -------
 retval = do_umount(nd.mnt, flags);
dput_and_out:
-------ietf add start-------
将原先挂载点在dentry中的数据全部清除,给dentry瘦身;释放设备superblock,文件系统模块引用释放。
-------ietf add end  -------
 path_release_on_umount(&nd);
out:
 return retval;
}


5.3 do_umount

static int do_umount(struct vfsmount *mnt, int flags)
{
 struct super_block *sb = mnt->mnt_sb;
 int retval;
 LIST_HEAD(umount_list);
-------ietf add start-------
安全框架的卸载操作
-------ietf add end  -------
 retval = security_sb_umount(mnt, flags);
 if (retval)
  return retval;

 /*
  * Allow userspace to request a mountpoint be expired rather than
  * unmounting unconditionally. Unmount only happens if:
  *  (1) the mark is already set (the mark is cleared by mntput())
  *  (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount]
  */
 if (flags & MNT_EXPIRE) {
  if (mnt == current->fs->rootmnt ||
      flags & (MNT_FORCE | MNT_DETACH))
   return -EINVAL;

  if (atomic_read(&mnt->mnt_count) != 2)
   return -EBUSY;

  if (!xchg(&mnt->mnt_expiry_mark, 1))
   return -EAGAIN;
 }

 /*
  * If we may have to abort operations to get out of this
  * mount, and they will themselves hold resources we must
  * allow the fs to do things. In the Unix tradition of
  * 'Gee thats tricky lets do it in userspace' the umount_begin
  * might fail to complete on the first run through as other tasks
  * must return, and the like. Thats for the mount program to worry
  * about for the moment.
  */
-------ietf add start-------
调用对应文件系统superblock的卸载程序
-------ietf add end  -------
 lock_kernel();
 if (sb->s_op->umount_begin)
  sb->s_op->umount_begin(mnt, flags);
 unlock_kernel();

 /*
  * No sense to grab the lock for this test, but test itself looks
  * somewhat bogus. Suggestions for better replacement?
  * Ho-hum... In principle, we might treat that as umount + switch
  * to rootfs. GC would eventually take care of the old vfsmount.
  * Actually it makes sense, especially if rootfs would contain a
  * /reboot - static binary that would close all descriptors and
  * call reboot(9). Then init(8) could umount root and exec /reboot.
  */
-------ietf add start-------
对于系统根文件系统的保护操作
-------ietf add end  -------
 if (mnt == current->fs->rootmnt && !(flags & MNT_DETACH)) {
  /*
   * Special case for "unmounting" root ...
   * we just try to remount it readonly.
   */
  down_write(&sb->s_umount);
  if (!(sb->s_flags & MS_RDONLY)) {
   lock_kernel();
   DQUOT_OFF(sb);
   retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
   unlock_kernel();
  }
  up_write(&sb->s_umount);
  return retval;
 }

 down_write(&namespace_sem);
 spin_lock(&vfsmount_lock);
 event++;
-------ietf add start-------
遍历umout链表,卸载其中的项。在umount_tree中,对于当前挂载点有bind,slave关系的挂载关系进行重新处理。
-------ietf add end  -------
 retval = -EBUSY;
 if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
  if (!list_empty(&mnt->mnt_list))
   umount_tree(mnt, 1, &umount_list);
  retval = 0;
 }
 spin_unlock(&vfsmount_lock);
 if (retval)
  security_sb_umount_busy(mnt);
 up_write(&namespace_sem);
 release_mounts(&umount_list);
 return retval;
}


TAG: Linux linux 文件系统 umount

jingkewang888发布于2007-05-30 16:01:15
京客网
jingkewang888  博客首页   这就是我    Google排名第一品牌服务商    My Blog    欢迎来到爱车空间   jingkewang888

关于免费空间   jingkewang888   ?oioj’s Blog   大学生's Bolg  博客首页   这就是我  jingkewang888

搜索引擎优化SEO  部落窝  电话录音    免费空间
正常情况发布于2007-07-07 22:07:12
太多了,不过还是慢慢学习学习吧
我来说两句

(可选)

日历

« 2008-10-14  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 3221
  • 日志数: 15
  • 建立时间: 2006-12-30
  • 更新时间: 2007-06-28

RSS订阅

Open Toolbar