Commit 6b1353cb authored by Eric W. Biederman's avatar Eric W. Biederman Committed by Sasha Levin

mnt: Improve the umount_tree flags

[ Upstream commit e819f152 ]

- Remove the unneeded declaration from pnode.h
- Mark umount_tree static as it has no callers outside of namespace.c
- Define an enumeration of umount_tree's flags.
- Pass umount_tree's flags in by name

This removes the magic numbers 0, 1 and 2 making the code a little
clearer and makes it possible for there to be lazy unmounts that don't
propagate.  Which is what __detach_mounts actually wants for example.

Cc: stable@vger.kernel.org
Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent 01acccfa
...@@ -1322,14 +1322,15 @@ static inline void namespace_lock(void) ...@@ -1322,14 +1322,15 @@ static inline void namespace_lock(void)
down_write(&namespace_sem); down_write(&namespace_sem);
} }
enum umount_tree_flags {
UMOUNT_SYNC = 1,
UMOUNT_PROPAGATE = 2,
};
/* /*
* mount_lock must be held * mount_lock must be held
* namespace_sem must be held for write * namespace_sem must be held for write
* how = 0 => just this tree, don't propagate
* how = 1 => propagate; we know that nobody else has reference to any victims
* how = 2 => lazy umount
*/ */
void umount_tree(struct mount *mnt, int how) static void umount_tree(struct mount *mnt, enum umount_tree_flags how)
{ {
HLIST_HEAD(tmp_list); HLIST_HEAD(tmp_list);
struct mount *p; struct mount *p;
...@@ -1343,7 +1344,7 @@ void umount_tree(struct mount *mnt, int how) ...@@ -1343,7 +1344,7 @@ void umount_tree(struct mount *mnt, int how)
hlist_for_each_entry(p, &tmp_list, mnt_hash) hlist_for_each_entry(p, &tmp_list, mnt_hash)
list_del_init(&p->mnt_child); list_del_init(&p->mnt_child);
if (how) if (how & UMOUNT_PROPAGATE)
propagate_umount(&tmp_list); propagate_umount(&tmp_list);
hlist_for_each_entry(p, &tmp_list, mnt_hash) { hlist_for_each_entry(p, &tmp_list, mnt_hash) {
...@@ -1351,7 +1352,7 @@ void umount_tree(struct mount *mnt, int how) ...@@ -1351,7 +1352,7 @@ void umount_tree(struct mount *mnt, int how)
list_del_init(&p->mnt_list); list_del_init(&p->mnt_list);
__touch_mnt_namespace(p->mnt_ns); __touch_mnt_namespace(p->mnt_ns);
p->mnt_ns = NULL; p->mnt_ns = NULL;
if (how < 2) if (how & UMOUNT_SYNC)
p->mnt.mnt_flags |= MNT_SYNC_UMOUNT; p->mnt.mnt_flags |= MNT_SYNC_UMOUNT;
if (mnt_has_parent(p)) { if (mnt_has_parent(p)) {
hlist_del_init(&p->mnt_mp_list); hlist_del_init(&p->mnt_mp_list);
...@@ -1456,14 +1457,14 @@ static int do_umount(struct mount *mnt, int flags) ...@@ -1456,14 +1457,14 @@ static int do_umount(struct mount *mnt, int flags)
if (flags & MNT_DETACH) { if (flags & MNT_DETACH) {
if (!list_empty(&mnt->mnt_list)) if (!list_empty(&mnt->mnt_list))
umount_tree(mnt, 2); umount_tree(mnt, UMOUNT_PROPAGATE);
retval = 0; retval = 0;
} else { } else {
shrink_submounts(mnt); shrink_submounts(mnt);
retval = -EBUSY; retval = -EBUSY;
if (!propagate_mount_busy(mnt, 2)) { if (!propagate_mount_busy(mnt, 2)) {
if (!list_empty(&mnt->mnt_list)) if (!list_empty(&mnt->mnt_list))
umount_tree(mnt, 1); umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
retval = 0; retval = 0;
} }
} }
...@@ -1495,7 +1496,7 @@ void __detach_mounts(struct dentry *dentry) ...@@ -1495,7 +1496,7 @@ void __detach_mounts(struct dentry *dentry)
lock_mount_hash(); lock_mount_hash();
while (!hlist_empty(&mp->m_list)) { while (!hlist_empty(&mp->m_list)) {
mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list); mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
umount_tree(mnt, 2); umount_tree(mnt, UMOUNT_PROPAGATE);
} }
unlock_mount_hash(); unlock_mount_hash();
put_mountpoint(mp); put_mountpoint(mp);
...@@ -1662,7 +1663,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry, ...@@ -1662,7 +1663,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
out: out:
if (res) { if (res) {
lock_mount_hash(); lock_mount_hash();
umount_tree(res, 0); umount_tree(res, UMOUNT_SYNC);
unlock_mount_hash(); unlock_mount_hash();
} }
return q; return q;
...@@ -1686,7 +1687,7 @@ void drop_collected_mounts(struct vfsmount *mnt) ...@@ -1686,7 +1687,7 @@ void drop_collected_mounts(struct vfsmount *mnt)
{ {
namespace_lock(); namespace_lock();
lock_mount_hash(); lock_mount_hash();
umount_tree(real_mount(mnt), 0); umount_tree(real_mount(mnt), UMOUNT_SYNC);
unlock_mount_hash(); unlock_mount_hash();
namespace_unlock(); namespace_unlock();
} }
...@@ -1869,7 +1870,7 @@ static int attach_recursive_mnt(struct mount *source_mnt, ...@@ -1869,7 +1870,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
out_cleanup_ids: out_cleanup_ids:
while (!hlist_empty(&tree_list)) { while (!hlist_empty(&tree_list)) {
child = hlist_entry(tree_list.first, struct mount, mnt_hash); child = hlist_entry(tree_list.first, struct mount, mnt_hash);
umount_tree(child, 0); umount_tree(child, UMOUNT_SYNC);
} }
unlock_mount_hash(); unlock_mount_hash();
cleanup_group_ids(source_mnt, NULL); cleanup_group_ids(source_mnt, NULL);
...@@ -2046,7 +2047,7 @@ static int do_loopback(struct path *path, const char *old_name, ...@@ -2046,7 +2047,7 @@ static int do_loopback(struct path *path, const char *old_name,
err = graft_tree(mnt, parent, mp); err = graft_tree(mnt, parent, mp);
if (err) { if (err) {
lock_mount_hash(); lock_mount_hash();
umount_tree(mnt, 0); umount_tree(mnt, UMOUNT_SYNC);
unlock_mount_hash(); unlock_mount_hash();
} }
out2: out2:
...@@ -2417,7 +2418,7 @@ void mark_mounts_for_expiry(struct list_head *mounts) ...@@ -2417,7 +2418,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
while (!list_empty(&graveyard)) { while (!list_empty(&graveyard)) {
mnt = list_first_entry(&graveyard, struct mount, mnt_expire); mnt = list_first_entry(&graveyard, struct mount, mnt_expire);
touch_mnt_namespace(mnt->mnt_ns); touch_mnt_namespace(mnt->mnt_ns);
umount_tree(mnt, 1); umount_tree(mnt, UMOUNT_PROPAGATE|UMOUNT_SYNC);
} }
unlock_mount_hash(); unlock_mount_hash();
namespace_unlock(); namespace_unlock();
...@@ -2488,7 +2489,7 @@ static void shrink_submounts(struct mount *mnt) ...@@ -2488,7 +2489,7 @@ static void shrink_submounts(struct mount *mnt)
m = list_first_entry(&graveyard, struct mount, m = list_first_entry(&graveyard, struct mount,
mnt_expire); mnt_expire);
touch_mnt_namespace(m->mnt_ns); touch_mnt_namespace(m->mnt_ns);
umount_tree(m, 1); umount_tree(m, UMOUNT_PROPAGATE|UMOUNT_SYNC);
} }
} }
} }
......
...@@ -47,7 +47,6 @@ int get_dominating_id(struct mount *mnt, const struct path *root); ...@@ -47,7 +47,6 @@ int get_dominating_id(struct mount *mnt, const struct path *root);
unsigned int mnt_get_count(struct mount *mnt); unsigned int mnt_get_count(struct mount *mnt);
void mnt_set_mountpoint(struct mount *, struct mountpoint *, void mnt_set_mountpoint(struct mount *, struct mountpoint *,
struct mount *); struct mount *);
void umount_tree(struct mount *, int);
struct mount *copy_tree(struct mount *, struct dentry *, int); struct mount *copy_tree(struct mount *, struct dentry *, int);
bool is_path_reachable(struct mount *, struct dentry *, bool is_path_reachable(struct mount *, struct dentry *,
const struct path *root); const struct path *root);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment