Linux中卸载文件系统由umount系统调用实现,入口函数为sys_umount()。较于文件系统的安装较为简单,下面是具体的实现。
-
-
SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
-
{
-
struct path path;
-
int retval;
-
-
-
retval = user_path(name, &path);
-
if (retval)
-
goto out;
-
retval = -EINVAL;
-
-
if (path.dentry != path.mnt->mnt_root)
-
goto dput_and_out;
-
-
if (!check_mnt(path.mnt))
-
goto dput_and_out;
-
-
retval = -EPERM;
-
-
if (!capable(CAP_SYS_ADMIN))
-
goto dput_and_out;
-
-
retval = do_umount(path.mnt, flags);
-
dput_and_out:
-
-
dput(path.dentry);
-
mntput_no_expire(path.mnt);
-
out:
-
return retval;
-
}
卸载实际工作
-
static int do_umount(struct vfsmount *mnt, int flags)
-
{
-
-
struct super_block *sb = mnt->mnt_sb;
-
int retval;
-
-
-
LIST_HEAD(umount_list);
-
-
retval = security_sb_umount(mnt, flags);
-
if (retval)
-
return retval;
-
-
-
-
-
-
-
-
-
if (flags & MNT_EXPIRE) {
-
-
-
if (mnt == current->fs->root.mnt ||
-
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 (flags & MNT_FORCE && sb->s_op->umount_begin) {
-
sb->s_op->umount_begin(sb);
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
if (mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
-
-
-
-
-
down_write(&sb->s_umount);
-
if (!(sb->s_flags & MS_RDONLY))
-
retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
-
up_write(&sb->s_umount);
-
return retval;
-
}
-
-
down_write(&namespace_sem);
-
-
spin_unlock(&vfsmount_lock);
-
spin_lock(&vfsmount_lock);
-
event++;
-
-
if (!(flags & MNT_DETACH))
-
shrink_submounts(mnt, &umount_list);
-
-
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;
-
}
-
-
if (retval)
-
security_sb_umount_busy(mnt);
-
-
up_write(&namespace_sem);
-
-
-
release_mounts(&umount_list);
-
return retval;
-
}
从内核链表中脱离
-
-
-
-
void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill)
-
{
-
struct vfsmount *p;
-
-
for (p = mnt; p; p = next_mnt(p, mnt))
-
list_move(&p->mnt_hash, kill);
-
-
if (propagate)
-
propagate_umount(kill);
-
-
list_for_each_entry(p, kill, mnt_hash) {
-
list_del_init(&p->mnt_expire);
-
list_del_init(&p->mnt_list);
-
__touch_mnt_namespace(p->mnt_ns);
-
p->mnt_ns = NULL;
-
list_del_init(&p->mnt_child);
-
if (p->mnt_parent != p) {
-
p->mnt_parent->mnt_ghosts++;
-
p->mnt_mountpoint->d_mounted--;
-
}
-
change_mnt_propagation(p, MS_PRIVATE);
-
}
-
}
释放引用计数
-
void release_mounts(struct list_head *head)
-
{
-
struct vfsmount *mnt;
-
while (!list_empty(head)) {
-
mnt = list_first_entry(head, struct vfsmount, mnt_hash);
-
list_del_init(&mnt->mnt_hash);
-
if (mnt->mnt_parent != mnt) {
-
struct dentry *dentry;
-
struct vfsmount *m;
-
spin_lock(&vfsmount_lock);
-
dentry = mnt->mnt_mountpoint;
-
m = mnt->mnt_parent;
-
mnt->mnt_mountpoint = mnt->mnt_root;
-
mnt->mnt_parent = mnt;
-
m->mnt_ghosts--;
-
spin_unlock(&vfsmount_lock);
-
-
dput(dentry);
-
mntput(m);
-
}
-
-
mntput(mnt);
-
}
-
}
阅读(2269) | 评论(0) | 转发(0) |