mnt: Improve the umount_tree flags
- 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: "Eric W. Biederman" <ebiederm@xmission.com>
This commit is contained in:
Родитель
a3b3c5627c
Коммит
e819f15210
|
@ -1317,14 +1317,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;
|
||||||
|
@ -1337,7 +1338,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);
|
||||||
|
|
||||||
while (!hlist_empty(&tmp_list)) {
|
while (!hlist_empty(&tmp_list)) {
|
||||||
|
@ -1347,7 +1348,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;
|
||||||
|
|
||||||
pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, &unmounted);
|
pin_insert_group(&p->mnt_umount, &p->mnt_parent->mnt, &unmounted);
|
||||||
|
@ -1445,14 +1446,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1484,7 +1485,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);
|
||||||
|
@ -1646,7 +1647,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;
|
||||||
|
@ -1670,7 +1671,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();
|
||||||
}
|
}
|
||||||
|
@ -1853,7 +1854,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);
|
||||||
|
@ -2033,7 +2034,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:
|
||||||
|
@ -2404,7 +2405,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();
|
||||||
|
@ -2475,7 +2476,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);
|
||||||
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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче