Skip to content

Commit 9ed4b9e

Browse files
author
Al Viro
committed
dissolve_on_fput(): use anon_ns_root()
that's the condition we are actually trying to check there... Reviewed-by: Christian Brauner <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 05da054 commit 9ed4b9e

File tree

1 file changed

+13
-49
lines changed

1 file changed

+13
-49
lines changed

fs/namespace.c

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,67 +2333,31 @@ void drop_collected_paths(struct path *paths, struct path *prealloc)
23332333
static void free_mnt_ns(struct mnt_namespace *);
23342334
static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *, bool);
23352335

2336-
static inline bool must_dissolve(struct mnt_namespace *mnt_ns)
2337-
{
2338-
/*
2339-
* This mount belonged to an anonymous mount namespace
2340-
* but was moved to a non-anonymous mount namespace and
2341-
* then unmounted.
2342-
*/
2343-
if (unlikely(!mnt_ns))
2344-
return false;
2345-
2346-
/*
2347-
* This mount belongs to a non-anonymous mount namespace
2348-
* and we know that such a mount can never transition to
2349-
* an anonymous mount namespace again.
2350-
*/
2351-
if (!is_anon_ns(mnt_ns)) {
2352-
/*
2353-
* A detached mount either belongs to an anonymous mount
2354-
* namespace or a non-anonymous mount namespace. It
2355-
* should never belong to something purely internal.
2356-
*/
2357-
VFS_WARN_ON_ONCE(mnt_ns == MNT_NS_INTERNAL);
2358-
return false;
2359-
}
2360-
2361-
return true;
2362-
}
2363-
23642336
void dissolve_on_fput(struct vfsmount *mnt)
23652337
{
23662338
struct mnt_namespace *ns;
23672339
struct mount *m = real_mount(mnt);
23682340

2341+
/*
2342+
* m used to be the root of anon namespace; if it still is one,
2343+
* we need to dissolve the mount tree and free that namespace.
2344+
* Let's try to avoid taking namespace_sem if we can determine
2345+
* that there's nothing to do without it - rcu_read_lock() is
2346+
* enough to make anon_ns_root() memory-safe and once m has
2347+
* left its namespace, it's no longer our concern, since it will
2348+
* never become a root of anon ns again.
2349+
*/
2350+
23692351
scoped_guard(rcu) {
2370-
if (!must_dissolve(READ_ONCE(m->mnt_ns)))
2352+
if (!anon_ns_root(m))
23712353
return;
23722354
}
23732355

23742356
scoped_guard(namespace_lock, &namespace_sem) {
2375-
ns = m->mnt_ns;
2376-
if (!must_dissolve(ns))
2377-
return;
2378-
2379-
/*
2380-
* After must_dissolve() we know that this is a detached
2381-
* mount in an anonymous mount namespace.
2382-
*
2383-
* Now when mnt_has_parent() reports that this mount
2384-
* tree has a parent, we know that this anonymous mount
2385-
* tree has been moved to another anonymous mount
2386-
* namespace.
2387-
*
2388-
* So when closing this file we cannot unmount the mount
2389-
* tree. This will be done when the file referring to
2390-
* the root of the anonymous mount namespace will be
2391-
* closed (It could already be closed but it would sync
2392-
* on @namespace_sem and wait for us to finish.).
2393-
*/
2394-
if (mnt_has_parent(m))
2357+
if (!anon_ns_root(m))
23952358
return;
23962359

2360+
ns = m->mnt_ns;
23972361
lock_mount_hash();
23982362
umount_tree(m, UMOUNT_CONNECTED);
23992363
unlock_mount_hash();

0 commit comments

Comments
 (0)