vfs: spread struct mount - do_umount/propagate_mount_busy
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
44d964d609
commit
1ab5973862
3 changed files with 23 additions and 23 deletions
|
@ -1180,7 +1180,7 @@ int may_umount(struct vfsmount *mnt)
|
||||||
int ret = 1;
|
int ret = 1;
|
||||||
down_read(&namespace_sem);
|
down_read(&namespace_sem);
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
if (propagate_mount_busy(mnt, 2))
|
if (propagate_mount_busy(real_mount(mnt), 2))
|
||||||
ret = 0;
|
ret = 0;
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
up_read(&namespace_sem);
|
up_read(&namespace_sem);
|
||||||
|
@ -1246,13 +1246,13 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
|
||||||
|
|
||||||
static void shrink_submounts(struct mount *mnt, struct list_head *umounts);
|
static void shrink_submounts(struct mount *mnt, struct list_head *umounts);
|
||||||
|
|
||||||
static int do_umount(struct vfsmount *mnt, int flags)
|
static int do_umount(struct mount *mnt, int flags)
|
||||||
{
|
{
|
||||||
struct super_block *sb = mnt->mnt_sb;
|
struct super_block *sb = mnt->mnt.mnt_sb;
|
||||||
int retval;
|
int retval;
|
||||||
LIST_HEAD(umount_list);
|
LIST_HEAD(umount_list);
|
||||||
|
|
||||||
retval = security_sb_umount(mnt, flags);
|
retval = security_sb_umount(&mnt->mnt, flags);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
|
@ -1263,7 +1263,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
|
||||||
* (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount]
|
* (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount]
|
||||||
*/
|
*/
|
||||||
if (flags & MNT_EXPIRE) {
|
if (flags & MNT_EXPIRE) {
|
||||||
if (mnt == current->fs->root.mnt ||
|
if (&mnt->mnt == current->fs->root.mnt ||
|
||||||
flags & (MNT_FORCE | MNT_DETACH))
|
flags & (MNT_FORCE | MNT_DETACH))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -1272,13 +1272,13 @@ static int do_umount(struct vfsmount *mnt, int flags)
|
||||||
* all race cases, but it's a slowpath.
|
* all race cases, but it's a slowpath.
|
||||||
*/
|
*/
|
||||||
br_write_lock(vfsmount_lock);
|
br_write_lock(vfsmount_lock);
|
||||||
if (mnt_get_count(mnt) != 2) {
|
if (mnt_get_count(&mnt->mnt) != 2) {
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
|
|
||||||
if (!xchg(&mnt->mnt_expiry_mark, 1))
|
if (!xchg(&mnt->mnt.mnt_expiry_mark, 1))
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1305,7 +1305,7 @@ static int do_umount(struct vfsmount *mnt, int flags)
|
||||||
* /reboot - static binary that would close all descriptors and
|
* /reboot - static binary that would close all descriptors and
|
||||||
* call reboot(9). Then init(8) could umount root and exec /reboot.
|
* call reboot(9). Then init(8) could umount root and exec /reboot.
|
||||||
*/
|
*/
|
||||||
if (mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
|
if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
|
||||||
/*
|
/*
|
||||||
* Special case for "unmounting" root ...
|
* Special case for "unmounting" root ...
|
||||||
* we just try to remount it readonly.
|
* we just try to remount it readonly.
|
||||||
|
@ -1322,12 +1322,12 @@ static int do_umount(struct vfsmount *mnt, int flags)
|
||||||
event++;
|
event++;
|
||||||
|
|
||||||
if (!(flags & MNT_DETACH))
|
if (!(flags & MNT_DETACH))
|
||||||
shrink_submounts(real_mount(mnt), &umount_list);
|
shrink_submounts(mnt, &umount_list);
|
||||||
|
|
||||||
retval = -EBUSY;
|
retval = -EBUSY;
|
||||||
if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
|
if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
|
||||||
if (!list_empty(&mnt->mnt_list))
|
if (!list_empty(&mnt->mnt.mnt_list))
|
||||||
umount_tree(real_mount(mnt), 1, &umount_list);
|
umount_tree(mnt, 1, &umount_list);
|
||||||
retval = 0;
|
retval = 0;
|
||||||
}
|
}
|
||||||
br_write_unlock(vfsmount_lock);
|
br_write_unlock(vfsmount_lock);
|
||||||
|
@ -1369,7 +1369,7 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
|
||||||
if (!capable(CAP_SYS_ADMIN))
|
if (!capable(CAP_SYS_ADMIN))
|
||||||
goto dput_and_out;
|
goto dput_and_out;
|
||||||
|
|
||||||
retval = do_umount(path.mnt, flags);
|
retval = do_umount(real_mount(path.mnt), flags);
|
||||||
dput_and_out:
|
dput_and_out:
|
||||||
/* we mustn't call path_put() as that would clear mnt_expiry_mark */
|
/* we mustn't call path_put() as that would clear mnt_expiry_mark */
|
||||||
dput(path.dentry);
|
dput(path.dentry);
|
||||||
|
@ -2101,7 +2101,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
|
||||||
*/
|
*/
|
||||||
list_for_each_entry_safe(mnt, next, mounts, mnt.mnt_expire) {
|
list_for_each_entry_safe(mnt, next, mounts, mnt.mnt_expire) {
|
||||||
if (!xchg(&mnt->mnt.mnt_expiry_mark, 1) ||
|
if (!xchg(&mnt->mnt.mnt_expiry_mark, 1) ||
|
||||||
propagate_mount_busy(&mnt->mnt, 1))
|
propagate_mount_busy(mnt, 1))
|
||||||
continue;
|
continue;
|
||||||
list_move(&mnt->mnt.mnt_expire, &graveyard);
|
list_move(&mnt->mnt.mnt_expire, &graveyard);
|
||||||
}
|
}
|
||||||
|
@ -2148,7 +2148,7 @@ static int select_submounts(struct mount *parent, struct list_head *graveyard)
|
||||||
goto repeat;
|
goto repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!propagate_mount_busy(&mnt->mnt, 1)) {
|
if (!propagate_mount_busy(mnt, 1)) {
|
||||||
list_move_tail(&mnt->mnt.mnt_expire, graveyard);
|
list_move_tail(&mnt->mnt.mnt_expire, graveyard);
|
||||||
found++;
|
found++;
|
||||||
}
|
}
|
||||||
|
|
16
fs/pnode.c
16
fs/pnode.c
|
@ -272,9 +272,9 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
|
||||||
/*
|
/*
|
||||||
* return true if the refcount is greater than count
|
* return true if the refcount is greater than count
|
||||||
*/
|
*/
|
||||||
static inline int do_refcount_check(struct vfsmount *mnt, int count)
|
static inline int do_refcount_check(struct mount *mnt, int count)
|
||||||
{
|
{
|
||||||
int mycount = mnt_get_count(mnt) - mnt->mnt_ghosts;
|
int mycount = mnt_get_count(&mnt->mnt) - mnt->mnt.mnt_ghosts;
|
||||||
return (mycount > count);
|
return (mycount > count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,14 +288,14 @@ static inline int do_refcount_check(struct vfsmount *mnt, int count)
|
||||||
*
|
*
|
||||||
* vfsmount lock must be held for write
|
* vfsmount lock must be held for write
|
||||||
*/
|
*/
|
||||||
int propagate_mount_busy(struct vfsmount *mnt, int refcnt)
|
int propagate_mount_busy(struct mount *mnt, int refcnt)
|
||||||
{
|
{
|
||||||
struct vfsmount *m;
|
struct vfsmount *m;
|
||||||
struct mount *child;
|
struct mount *child;
|
||||||
struct vfsmount *parent = mnt->mnt_parent;
|
struct vfsmount *parent = mnt->mnt.mnt_parent;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (mnt == parent)
|
if (&mnt->mnt == parent)
|
||||||
return do_refcount_check(mnt, refcnt);
|
return do_refcount_check(mnt, refcnt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -303,14 +303,14 @@ int propagate_mount_busy(struct vfsmount *mnt, int refcnt)
|
||||||
* If not, we don't have to go checking for all other
|
* If not, we don't have to go checking for all other
|
||||||
* mounts
|
* mounts
|
||||||
*/
|
*/
|
||||||
if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt))
|
if (!list_empty(&mnt->mnt.mnt_mounts) || do_refcount_check(mnt, refcnt))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
for (m = propagation_next(parent, parent); m;
|
for (m = propagation_next(parent, parent); m;
|
||||||
m = propagation_next(m, parent)) {
|
m = propagation_next(m, parent)) {
|
||||||
child = __lookup_mnt(m, mnt->mnt_mountpoint, 0);
|
child = __lookup_mnt(m, mnt->mnt.mnt_mountpoint, 0);
|
||||||
if (child && list_empty(&child->mnt.mnt_mounts) &&
|
if (child && list_empty(&child->mnt.mnt_mounts) &&
|
||||||
(ret = do_refcount_check(&child->mnt, 1)))
|
(ret = do_refcount_check(child, 1)))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -33,7 +33,7 @@ void change_mnt_propagation(struct mount *, int);
|
||||||
int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
|
int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *,
|
||||||
struct list_head *);
|
struct list_head *);
|
||||||
int propagate_umount(struct list_head *);
|
int propagate_umount(struct list_head *);
|
||||||
int propagate_mount_busy(struct vfsmount *, int);
|
int propagate_mount_busy(struct mount *, int);
|
||||||
void mnt_release_group_id(struct mount *);
|
void mnt_release_group_id(struct mount *);
|
||||||
int get_dominating_id(struct vfsmount *mnt, const struct path *root);
|
int get_dominating_id(struct vfsmount *mnt, const struct path *root);
|
||||||
unsigned int mnt_get_count(struct vfsmount *mnt);
|
unsigned int mnt_get_count(struct vfsmount *mnt);
|
||||||
|
|
Loading…
Reference in a new issue