linux-fsdevel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Al Viro <viro@zeniv.linux.org.uk>
To: linux-fsdevel@vger.kernel.org
Cc: brauner@kernel.org, ebiederm@xmission.com, jack@suse.cz,
	torvalds@linux-foundation.org
Subject: [PATCH 25/26] get rid of mountpoint->m_count
Date: Tue, 10 Jun 2025 09:21:47 +0100	[thread overview]
Message-ID: <20250610082148.1127550-25-viro@zeniv.linux.org.uk> (raw)
In-Reply-To: <20250610082148.1127550-1-viro@zeniv.linux.org.uk>

struct mountpoint has an odd kinda-sorta refcount in it.  It's always
either equal to or one above the number of mounts attached to that
mountpoint.

"One above" happens when a function takes a temporary reference to
mountpoint.  Things get simpler if we express that as inserting
a local object into ->m_list and removing it to drop the reference.

New calling conventions:

1) lock_mount(), do_lock_mount(), get_mountpoint() and lookup_mountpoint()
take an extra struct pinned_mountpoint * argument and returns 0/-E...
(or true/false in case of lookup_mountpoint()) instead of returning
struct mountpoint pointers.  In case of success, the struct mountpoint *
we used to get can be found as pinned_mountpoint.mp

2) unlock_mount() (always paired with lock_mount()/do_lock_mount()) takes
an address of struct pinned_mountpoint - the same that had been passed to
lock_mount()/do_lock_mount().

3) put_mountpoint() for a temporary reference (paired with get_mountpoint()
or lookup_mountpoint()) is replaced with unpin_mountpoint(), which takes
the address of pinned_mountpoint we passed to matching {get,lookup}_mountpoint().

4) all instances of pinned_mountpoint are local variables; they always live on
stack.  {} is used for initializer, after successful {get,lookup}_mountpoint()
we must make sure to call unpin_mountpoint() before leaving the scope and
after successful {do_,}lock_mount() we must make sure to call unlock_mount()
before leaving the scope.

5) all manipulations of ->m_count are gone, along with ->m_count itself.
struct mountpoint lives while its ->m_list is non-empty.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 fs/mount.h     |   1 -
 fs/namespace.c | 186 ++++++++++++++++++++++++-------------------------
 2 files changed, 92 insertions(+), 95 deletions(-)

diff --git a/fs/mount.h b/fs/mount.h
index 9b3de2eef68a..684480087da2 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -44,7 +44,6 @@ struct mountpoint {
 	struct hlist_node m_hash;
 	struct dentry *m_dentry;
 	struct hlist_head m_list;
-	int m_count;
 };
 
 struct mount {
diff --git a/fs/namespace.c b/fs/namespace.c
index 777e4c3b2c12..1f1cf1d6a464 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -910,42 +910,48 @@ bool __is_local_mountpoint(const struct dentry *dentry)
 	return is_covered;
 }
 
-static struct mountpoint *lookup_mountpoint(struct dentry *dentry)
+struct pinned_mountpoint {
+	struct hlist_node node;
+	struct mountpoint *mp;
+};
+
+static bool lookup_mountpoint(struct dentry *dentry, struct pinned_mountpoint *m)
 {
 	struct hlist_head *chain = mp_hash(dentry);
 	struct mountpoint *mp;
 
 	hlist_for_each_entry(mp, chain, m_hash) {
 		if (mp->m_dentry == dentry) {
-			mp->m_count++;
-			return mp;
+			hlist_add_head(&m->node, &mp->m_list);
+			m->mp = mp;
+			return true;
 		}
 	}
-	return NULL;
+	return false;
 }
 
-static struct mountpoint *get_mountpoint(struct dentry *dentry)
+static int get_mountpoint(struct dentry *dentry, struct pinned_mountpoint *m)
 {
-	struct mountpoint *mp, *new = NULL;
+	struct mountpoint *mp __free(kfree) = NULL;
+	bool found;
 	int ret;
 
 	if (d_mountpoint(dentry)) {
 		/* might be worth a WARN_ON() */
 		if (d_unlinked(dentry))
-			return ERR_PTR(-ENOENT);
+			return -ENOENT;
 mountpoint:
 		read_seqlock_excl(&mount_lock);
-		mp = lookup_mountpoint(dentry);
+		found = lookup_mountpoint(dentry, m);
 		read_sequnlock_excl(&mount_lock);
-		if (mp)
-			goto done;
+		if (found)
+			return 0;
 	}
 
-	if (!new)
-		new = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
-	if (!new)
-		return ERR_PTR(-ENOMEM);
-
+	if (!mp)
+		mp = kmalloc(sizeof(struct mountpoint), GFP_KERNEL);
+	if (!mp)
+		return -ENOMEM;
 
 	/* Exactly one processes may set d_mounted */
 	ret = d_set_mounted(dentry);
@@ -955,34 +961,28 @@ static struct mountpoint *get_mountpoint(struct dentry *dentry)
 		goto mountpoint;
 
 	/* The dentry is not available as a mountpoint? */
-	mp = ERR_PTR(ret);
 	if (ret)
-		goto done;
+		return ret;
 
 	/* Add the new mountpoint to the hash table */
 	read_seqlock_excl(&mount_lock);
-	new->m_dentry = dget(dentry);
-	new->m_count = 1;
-	hlist_add_head(&new->m_hash, mp_hash(dentry));
-	INIT_HLIST_HEAD(&new->m_list);
+	mp->m_dentry = dget(dentry);
+	hlist_add_head(&mp->m_hash, mp_hash(dentry));
+	INIT_HLIST_HEAD(&mp->m_list);
+	hlist_add_head(&m->node, &mp->m_list);
+	m->mp = no_free_ptr(mp);
 	read_sequnlock_excl(&mount_lock);
-
-	mp = new;
-	new = NULL;
-done:
-	kfree(new);
-	return mp;
+	return 0;
 }
 
 /*
  * vfsmount lock must be held.  Additionally, the caller is responsible
  * for serializing calls for given disposal list.
  */
-static void __put_mountpoint(struct mountpoint *mp, struct list_head *list)
+static void maybe_free_mountpoint(struct mountpoint *mp, struct list_head *list)
 {
-	if (!--mp->m_count) {
+	if (hlist_empty(&mp->m_list)) {
 		struct dentry *dentry = mp->m_dentry;
-		BUG_ON(!hlist_empty(&mp->m_list));
 		spin_lock(&dentry->d_lock);
 		dentry->d_flags &= ~DCACHE_MOUNTED;
 		spin_unlock(&dentry->d_lock);
@@ -992,10 +992,15 @@ static void __put_mountpoint(struct mountpoint *mp, struct list_head *list)
 	}
 }
 
-/* called with namespace_lock and vfsmount lock */
-static void put_mountpoint(struct mountpoint *mp)
+/*
+ * locks: mount_lock [read_seqlock_excl], namespace_sem [excl]
+ */
+static void unpin_mountpoint(struct pinned_mountpoint *m)
 {
-	__put_mountpoint(mp, &ex_mountpoints);
+	if (m->mp) {
+		hlist_del(&m->node);
+		maybe_free_mountpoint(m->mp, &ex_mountpoints);
+	}
 }
 
 static inline int check_mnt(struct mount *mnt)
@@ -1049,7 +1054,7 @@ static void __umount_mnt(struct mount *mnt, struct list_head *shrink_list)
 	hlist_del_init(&mnt->mnt_mp_list);
 	mp = mnt->mnt_mp;
 	mnt->mnt_mp = NULL;
-	__put_mountpoint(mp, shrink_list);
+	maybe_free_mountpoint(mp, shrink_list);
 }
 
 /*
@@ -1067,7 +1072,6 @@ void mnt_set_mountpoint(struct mount *mnt,
 			struct mountpoint *mp,
 			struct mount *child_mnt)
 {
-	mp->m_count++;
 	mnt_add_count(mnt, 1);	/* essentially, that's mntget */
 	child_mnt->mnt_mountpoint = mp->m_dentry;
 	child_mnt->mnt_parent = mnt;
@@ -1116,7 +1120,7 @@ void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp, struct m
 
 	attach_mnt(mnt, parent, mp);
 
-	put_mountpoint(old_mp);
+	maybe_free_mountpoint(old_mp, &ex_mountpoints);
 	mnt_add_count(old_parent, -1);
 }
 
@@ -2024,25 +2028,24 @@ static int do_umount(struct mount *mnt, int flags)
  */
 void __detach_mounts(struct dentry *dentry)
 {
-	struct mountpoint *mp;
+	struct pinned_mountpoint mp = {};
 	struct mount *mnt;
 
 	namespace_lock();
 	lock_mount_hash();
-	mp = lookup_mountpoint(dentry);
-	if (!mp)
+	if (!lookup_mountpoint(dentry, &mp))
 		goto out_unlock;
 
 	event++;
-	while (!hlist_empty(&mp->m_list)) {
-		mnt = hlist_entry(mp->m_list.first, struct mount, mnt_mp_list);
+	while (mp.node.next) {
+		mnt = hlist_entry(mp.node.next, struct mount, mnt_mp_list);
 		if (mnt->mnt.mnt_flags & MNT_UMOUNT) {
 			umount_mnt(mnt);
 			hlist_add_head(&mnt->mnt_umount, &unmounted);
 		}
 		else umount_tree(mnt, UMOUNT_CONNECTED);
 	}
-	put_mountpoint(mp);
+	unpin_mountpoint(&mp);
 out_unlock:
 	unlock_mount_hash();
 	namespace_unlock();
@@ -2618,7 +2621,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
 	HLIST_HEAD(tree_list);
 	struct mnt_namespace *ns = dest_mnt->mnt_ns;
-	struct mountpoint *smp;
+	struct pinned_mountpoint root = {};
 	struct mount *child, *p;
 	struct hlist_node *n;
 	int err = 0;
@@ -2628,9 +2631,9 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	 * Preallocate a mountpoint in case the new mounts need to be
 	 * mounted beneath mounts on the same mountpoint.
 	 */
-	smp = get_mountpoint(source_mnt->mnt.mnt_root);
-	if (IS_ERR(smp))
-		return PTR_ERR(smp);
+	err = get_mountpoint(source_mnt->mnt.mnt_root, &root);
+	if (err)
+		return err;
 
 	/* Is there space to add these mounts to the mount namespace? */
 	if (!moving) {
@@ -2680,13 +2683,13 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 		q = __lookup_mnt(&child->mnt_parent->mnt,
 				 child->mnt_mountpoint);
 		if (q)
-			mnt_change_mountpoint(child, smp, q);
+			mnt_change_mountpoint(child, root.mp, q);
 		/* Notice when we are propagating across user namespaces */
 		if (child->mnt_parent->mnt_ns->user_ns != user_ns)
 			lock_mnt_tree(child);
 		commit_tree(child);
 	}
-	put_mountpoint(smp);
+	unpin_mountpoint(&root);
 	unlock_mount_hash();
 
 	return 0;
@@ -2703,7 +2706,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	ns->pending_mounts = 0;
 
 	read_seqlock_excl(&mount_lock);
-	put_mountpoint(smp);
+	unpin_mountpoint(&root);
 	read_sequnlock_excl(&mount_lock);
 
 	return err;
@@ -2743,12 +2746,12 @@ static int attach_recursive_mnt(struct mount *source_mnt,
  * Return: Either the target mountpoint on the top mount or the top
  *         mount's mountpoint.
  */
-static struct mountpoint *do_lock_mount(struct path *path, bool beneath)
+static int do_lock_mount(struct path *path, struct pinned_mountpoint *pinned, bool beneath)
 {
 	struct vfsmount *mnt = path->mnt;
 	struct dentry *dentry;
-	struct mountpoint *mp = ERR_PTR(-ENOENT);
 	struct path under = {};
+	int err = -ENOENT;
 
 	for (;;) {
 		struct mount *m = real_mount(mnt);
@@ -2786,8 +2789,8 @@ static struct mountpoint *do_lock_mount(struct path *path, bool beneath)
 			path->dentry = dget(mnt->mnt_root);
 			continue;	// got overmounted
 		}
-		mp = get_mountpoint(dentry);
-		if (IS_ERR(mp))
+		err = get_mountpoint(dentry, pinned);
+		if (err)
 			break;
 		if (beneath) {
 			/*
@@ -2798,25 +2801,25 @@ static struct mountpoint *do_lock_mount(struct path *path, bool beneath)
 			 */
 			path_put(&under);
 		}
-		return mp;
+		return 0;
 	}
 	namespace_unlock();
 	inode_unlock(dentry->d_inode);
 	if (beneath)
 		path_put(&under);
-	return mp;
+	return err;
 }
 
-static inline struct mountpoint *lock_mount(struct path *path)
+static inline int lock_mount(struct path *path, struct pinned_mountpoint *m)
 {
-	return do_lock_mount(path, false);
+	return do_lock_mount(path, m, false);
 }
 
-static void unlock_mount(struct mountpoint *where)
+static void unlock_mount(struct pinned_mountpoint *m)
 {
-	inode_unlock(where->m_dentry->d_inode);
+	inode_unlock(m->mp->m_dentry->d_inode);
 	read_seqlock_excl(&mount_lock);
-	put_mountpoint(where);
+	unpin_mountpoint(m);
 	read_sequnlock_excl(&mount_lock);
 	namespace_unlock();
 }
@@ -2981,7 +2984,7 @@ static int do_loopback(struct path *path, const char *old_name,
 {
 	struct path old_path;
 	struct mount *mnt = NULL, *parent;
-	struct mountpoint *mp;
+	struct pinned_mountpoint mp = {};
 	int err;
 	if (!old_name || !*old_name)
 		return -EINVAL;
@@ -2993,11 +2996,9 @@ static int do_loopback(struct path *path, const char *old_name,
 	if (mnt_ns_loop(old_path.dentry))
 		goto out;
 
-	mp = lock_mount(path);
-	if (IS_ERR(mp)) {
-		err = PTR_ERR(mp);
+	err = lock_mount(path, &mp);
+	if (err)
 		goto out;
-	}
 
 	parent = real_mount(path->mnt);
 	if (!check_mnt(parent))
@@ -3009,14 +3010,14 @@ static int do_loopback(struct path *path, const char *old_name,
 		goto out2;
 	}
 
-	err = graft_tree(mnt, parent, mp);
+	err = graft_tree(mnt, parent, mp.mp);
 	if (err) {
 		lock_mount_hash();
 		umount_tree(mnt, UMOUNT_SYNC);
 		unlock_mount_hash();
 	}
 out2:
-	unlock_mount(mp);
+	unlock_mount(&mp);
 out:
 	path_put(&old_path);
 	return err;
@@ -3560,13 +3561,13 @@ static int do_move_mount(struct path *old_path,
 	struct mount *p;
 	struct mount *old;
 	struct mount *parent;
-	struct mountpoint *mp;
+	struct pinned_mountpoint mp;
 	int err;
 	bool beneath = flags & MNT_TREE_BENEATH;
 
-	mp = do_lock_mount(new_path, beneath);
-	if (IS_ERR(mp))
-		return PTR_ERR(mp);
+	err = do_lock_mount(new_path, &mp, beneath);
+	if (err)
+		return err;
 
 	old = real_mount(old_path->mnt);
 	p = real_mount(new_path->mnt);
@@ -3615,7 +3616,7 @@ static int do_move_mount(struct path *old_path,
 		goto out;
 
 	if (beneath) {
-		err = can_move_mount_beneath(old_path, new_path, mp);
+		err = can_move_mount_beneath(old_path, new_path, mp.mp);
 		if (err)
 			goto out;
 
@@ -3635,9 +3636,9 @@ static int do_move_mount(struct path *old_path,
 	if (mount_is_ancestor(old, p))
 		goto out;
 
-	err = attach_recursive_mnt(old, p, mp);
+	err = attach_recursive_mnt(old, p, mp.mp);
 out:
-	unlock_mount(mp);
+	unlock_mount(&mp);
 	if (!err) {
 		if (!is_anon_ns(ns)) {
 			mntput_no_expire(parent);
@@ -3707,7 +3708,7 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
 			   unsigned int mnt_flags)
 {
 	struct vfsmount *mnt;
-	struct mountpoint *mp;
+	struct pinned_mountpoint mp = {};
 	struct super_block *sb = fc->root->d_sb;
 	int error;
 
@@ -3728,13 +3729,12 @@ static int do_new_mount_fc(struct fs_context *fc, struct path *mountpoint,
 
 	mnt_warn_timestamp_expiry(mountpoint, mnt);
 
-	mp = lock_mount(mountpoint);
-	if (IS_ERR(mp)) {
-		mntput(mnt);
-		return PTR_ERR(mp);
+	error = lock_mount(mountpoint, &mp);
+	if (!error) {
+		error = do_add_mount(real_mount(mnt), mp.mp,
+				     mountpoint, mnt_flags);
+		unlock_mount(&mp);
 	}
-	error = do_add_mount(real_mount(mnt), mp, mountpoint, mnt_flags);
-	unlock_mount(mp);
 	if (error < 0)
 		mntput(mnt);
 	return error;
@@ -3802,7 +3802,7 @@ static int do_new_mount(struct path *path, const char *fstype, int sb_flags,
 int finish_automount(struct vfsmount *m, const struct path *path)
 {
 	struct dentry *dentry = path->dentry;
-	struct mountpoint *mp;
+	struct pinned_mountpoint mp = {};
 	struct mount *mnt;
 	int err;
 
@@ -3834,14 +3834,13 @@ int finish_automount(struct vfsmount *m, const struct path *path)
 		err = 0;
 		goto discard_locked;
 	}
-	mp = get_mountpoint(dentry);
-	if (IS_ERR(mp)) {
-		err = PTR_ERR(mp);
+	err = get_mountpoint(dentry, &mp);
+	if (err)
 		goto discard_locked;
-	}
 
-	err = do_add_mount(mnt, mp, path, path->mnt->mnt_flags | MNT_SHRINKABLE);
-	unlock_mount(mp);
+	err = do_add_mount(mnt, mp.mp, path,
+			   path->mnt->mnt_flags | MNT_SHRINKABLE);
+	unlock_mount(&mp);
 	if (unlikely(err))
 		goto discard;
 	return 0;
@@ -4642,7 +4641,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 {
 	struct path new, old, root;
 	struct mount *new_mnt, *root_mnt, *old_mnt, *root_parent, *ex_parent;
-	struct mountpoint *old_mp;
+	struct pinned_mountpoint old_mp = {};
 	int error;
 
 	if (!may_mount())
@@ -4663,9 +4662,8 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 		goto out2;
 
 	get_fs_root(current->fs, &root);
-	old_mp = lock_mount(&old);
-	error = PTR_ERR(old_mp);
-	if (IS_ERR(old_mp))
+	error = lock_mount(&old, &old_mp);
+	if (error)
 		goto out3;
 
 	error = -EINVAL;
@@ -4714,7 +4712,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	umount_mnt(root_mnt);
 	mnt_add_count(root_parent, -1);
 	/* mount old root on put_old */
-	attach_mnt(root_mnt, old_mnt, old_mp);
+	attach_mnt(root_mnt, old_mnt, old_mp.mp);
 	touch_mnt_namespace(current->nsproxy->mnt_ns);
 	/* A moved mount should not expire automatically */
 	list_del_init(&new_mnt->mnt_expire);
@@ -4724,7 +4722,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
 	chroot_fs_refs(&root, &new);
 	error = 0;
 out4:
-	unlock_mount(old_mp);
+	unlock_mount(&old_mp);
 	if (!error)
 		mntput_no_expire(ex_parent);
 out3:
-- 
2.39.5


  parent reply	other threads:[~2025-06-10  8:21 UTC|newest]

Thread overview: 175+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-10  8:17 [PATCHES][RFC][CFR] mount-related stuff Al Viro
2025-06-10  8:21 ` [PATCH 01/26] copy_tree(): don't set ->mnt_mountpoint on the root of copy Al Viro
2025-06-10  8:21   ` [PATCH 02/26] constify mnt_has_parent() Al Viro
2025-06-11 10:26     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 03/26] pnode: lift peers() into pnode.h Al Viro
2025-06-11 10:29     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 04/26] new predicate: mount_is_ancestor() Al Viro
2025-06-11 10:32     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 05/26] constify is_local_mountpoint() Al Viro
2025-06-11 10:32     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 06/26] new predicate: anon_ns_root(mount) Al Viro
2025-06-11 10:39     ` Christian Brauner
2025-06-11 17:57       ` Al Viro
2025-06-10  8:21   ` [PATCH 07/26] dissolve_on_fput(): use anon_ns_root() Al Viro
2025-06-11 10:41     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 08/26] don't set MNT_LOCKED on parentless mounts Al Viro
2025-06-11 10:49     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 09/26] clone_mnt(): simplify the propagation-related logics Al Viro
2025-06-11 10:53     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 10/26] do_umount(): simplify the "is it still mounted" checks Al Viro
2025-06-11 10:54     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 11/26] sanitize handling of long-term internal mounts Al Viro
2025-06-11 10:56     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 12/26] Rewrite of propagate_umount() Al Viro
2025-06-11 10:56     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 13/26] attach_mnt(): expand in attach_recursive_mnt(), then lose the flag argument Al Viro
2025-06-11 10:59     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 14/26] do_move_mount(): take dropping the old mountpoint into attach_recursive_mnt() Al Viro
2025-06-11 10:59     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 15/26] get rid of mnt_set_mountpoint_beneath() Al Viro
2025-06-11 11:01     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 16/26] make commit_tree() usable in same-namespace move case Al Viro
2025-06-11 11:03     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 17/26] attach_recursive_mnt(): unify the mnt_change_mountpoint() logics Al Viro
2025-06-11 11:05     ` Christian Brauner
2025-06-11 18:12       ` Al Viro
2025-06-12 12:08         ` Christian Brauner
2025-06-10  8:21   ` [PATCH 18/26] attach_recursive_mnt(): pass destination mount in all cases Al Viro
2025-06-11 11:07     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 19/26] attach_recursive_mnt(): get rid of flags entirely Al Viro
2025-06-11 11:08     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 20/26] do_move_mount(): get rid of 'attached' flag Al Viro
2025-06-11 11:08     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 21/26] attach_recursive_mnt(): remove from expiry list on move Al Viro
2025-06-11 11:09     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 22/26] take ->mnt_expire handling under mount_lock [read_seqlock_excl] Al Viro
2025-06-11 11:11     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 23/26] pivot_root(): reorder tree surgeries, collapse unhash_mnt() and put_mountpoint() Al Viro
2025-06-11 11:11     ` Christian Brauner
2025-06-10  8:21   ` [PATCH 24/26] combine __put_mountpoint() with unhash_mnt() Al Viro
2025-06-11 11:12     ` Christian Brauner
2025-06-10  8:21   ` Al Viro [this message]
2025-06-11 11:19     ` [PATCH 25/26] get rid of mountpoint->m_count Christian Brauner
2025-06-11 18:47       ` Al Viro
2025-06-16 20:38         ` Al Viro
2025-06-16 21:52           ` Linus Torvalds
2025-06-10  8:21   ` [PATCH 26/26] don't have mounts pin their parents Al Viro
2025-06-11 11:22     ` Christian Brauner
2025-06-16  2:50     ` Ian Kent
2025-06-10 22:30   ` [PATCH 01/26] copy_tree(): don't set ->mnt_mountpoint on the root of copy Eric W. Biederman
2025-06-10 23:14     ` Al Viro
2025-06-11 10:31 ` [PATCHES][RFC][CFR] mount-related stuff Christian Brauner
2025-06-11 17:51   ` Al Viro
2025-06-12 12:09     ` Christian Brauner
2025-06-23  4:49 ` [PATCHES v2][RFC][CFR] " Al Viro
2025-06-23  4:53   ` [PATCH v2 01/35] replace collect_mounts()/drop_collected_mounts() with a safer variant Al Viro
2025-06-23  4:53     ` [PATCH v2 02/35] attach_recursive_mnt(): do not lock the covering tree when sliding something under it Al Viro
2025-06-23  4:53     ` [PATCH v2 03/35] attach_mnt(): expand in attach_recursive_mnt(), then lose the flag argument Al Viro
2025-06-23  4:53     ` [PATCH v2 04/35] get rid of mnt_set_mountpoint_beneath() Al Viro
2025-06-23  4:53     ` [PATCH v2 05/35] prevent mount hash conflicts Al Viro
2025-06-23  4:53     ` [PATCH v2 06/35] copy_tree(): don't set ->mnt_mountpoint on the root of copy Al Viro
2025-06-23  4:54     ` [PATCH v2 07/35] constify mnt_has_parent() Al Viro
2025-06-23  4:54     ` [PATCH v2 08/35] pnode: lift peers() into pnode.h Al Viro
2025-06-23  4:54     ` [PATCH v2 09/35] new predicate: mount_is_ancestor() Al Viro
2025-06-23  4:54     ` [PATCH v2 10/35] constify is_local_mountpoint() Al Viro
2025-06-23  4:54     ` [PATCH v2 11/35] new predicate: anon_ns_root(mount) Al Viro
2025-06-23  4:54     ` [PATCH v2 12/35] dissolve_on_fput(): use anon_ns_root() Al Viro
2025-06-23  4:54     ` [PATCH v2 13/35] __attach_mnt(): lose the second argument Al Viro
2025-06-23  4:54     ` [PATCH v2 14/35] don't set MNT_LOCKED on parentless mounts Al Viro
2025-06-23  4:54     ` [PATCH v2 15/35] clone_mnt(): simplify the propagation-related logics Al Viro
2025-06-23  4:54     ` [PATCH v2 16/35] do_umount(): simplify the "is it still mounted" checks Al Viro
2025-06-23  4:54     ` [PATCH v2 17/35] sanitize handling of long-term internal mounts Al Viro
2025-06-23 16:18       ` Linus Torvalds
2025-06-23 17:03         ` Al Viro
2025-06-23 18:21           ` Linus Torvalds
2025-06-28  7:58           ` [RFC] vfs_parse_fs_string() calling conventions change (was Re: [PATCH v2 17/35] sanitize handling of long-term internal mounts) Al Viro
2025-06-28 16:28             ` Al Viro
2025-06-29 17:47               ` Al Viro
2025-06-28 17:41             ` Linus Torvalds
2025-06-30 15:19           ` David Howells
2025-06-30 16:55             ` Al Viro
2025-06-30 17:04               ` Linus Torvalds
2025-06-23  4:54     ` [PATCH v2 18/35] Rewrite of propagate_umount() Al Viro
2025-06-23  4:54     ` [PATCH v2 19/35] make commit_tree() usable in same-namespace move case Al Viro
2025-06-23  4:54     ` [PATCH v2 20/35] attach_recursive_mnt(): unify the mnt_change_mountpoint() logics Al Viro
2025-06-23  4:54     ` [PATCH v2 21/35] attach_recursive_mnt(): pass destination mount in all cases Al Viro
2025-06-23  4:54     ` [PATCH v2 22/35] attach_recursive_mnt(): get rid of flags entirely Al Viro
2025-06-23  4:54     ` [PATCH v2 23/35] do_move_mount(): take dropping the old mountpoint into attach_recursive_mnt() Al Viro
2025-06-23  4:54     ` [PATCH v2 24/35] do_move_mount(): get rid of 'attached' flag Al Viro
2025-06-23  4:54     ` [PATCH v2 25/35] attach_recursive_mnt(): remove from expiry list on move Al Viro
2025-06-23  4:54     ` [PATCH v2 26/35] take ->mnt_expire handling under mount_lock [read_seqlock_excl] Al Viro
2025-06-23  4:54     ` [PATCH v2 27/35] pivot_root(): reorder tree surgeries, collapse unhash_mnt() and put_mountpoint() Al Viro
2025-06-23  4:54     ` [PATCH v2 28/35] combine __put_mountpoint() with unhash_mnt() Al Viro
2025-06-23  4:54     ` [PATCH v2 29/35] get rid of mountpoint->m_count Al Viro
2025-06-23  4:54     ` [PATCH v2 30/35] don't have mounts pin their parents Al Viro
2025-06-23  4:54     ` [PATCH v2 31/35] copy_tree(): don't link the mounts via mnt_list Al Viro
2025-06-23  4:54     ` [PATCH v2 32/35] mount: separate the flags accessed only under namespace_sem Al Viro
2025-06-23  4:54     ` [PATCH v2 33/35] propagate_one(): get rid of dest_master Al Viro
2025-06-23  4:54     ` [PATCH v2 34/35] propagate_mnt(): get rid of globals Al Viro
2025-06-23  4:54     ` [PATCH v2 35/35] take freeing of emptied mnt_namespace to namespace_unlock() Al Viro
2025-06-23 15:10     ` [PATCH v2 01/35] replace collect_mounts()/drop_collected_mounts() with a safer variant Al Viro
2025-06-23  9:06   ` [PATCHES v2][RFC][CFR] mount-related stuff Ian Kent
2025-06-23 18:55     ` Al Viro
2025-06-24  6:48       ` Ian Kent
2025-06-24  7:05         ` Al Viro
2025-06-24 11:03           ` Ian Kent
2025-06-25  7:57         ` Al Viro
2025-06-25 10:58           ` Ian Kent
2025-06-27  3:03             ` Ian Kent
2025-06-30  2:51   ` [PATCHES v3][RFC][CFR] " Al Viro
2025-06-30  2:52     ` [PATCH v3 01/48] attach_mnt(): expand in attach_recursive_mnt(), then lose the flag argument Al Viro
2025-06-30  2:52       ` [PATCH v3 02/48] get rid of mnt_set_mountpoint_beneath() Al Viro
2025-06-30  2:52       ` [PATCH v3 03/48] prevent mount hash conflicts Al Viro
2025-06-30  2:52       ` [PATCH v3 04/48] copy_tree(): don't set ->mnt_mountpoint on the root of copy Al Viro
2025-06-30  2:52       ` [PATCH v3 05/48] constify mnt_has_parent() Al Viro
2025-06-30  2:52       ` [PATCH v3 06/48] pnode: lift peers() into pnode.h Al Viro
2025-06-30  2:52       ` [PATCH v3 07/48] new predicate: mount_is_ancestor() Al Viro
2025-06-30  2:52       ` [PATCH v3 08/48] constify is_local_mountpoint() Al Viro
2025-06-30  2:52       ` [PATCH v3 09/48] new predicate: anon_ns_root(mount) Al Viro
2025-06-30  2:52       ` [PATCH v3 10/48] dissolve_on_fput(): use anon_ns_root() Al Viro
2025-06-30  2:52       ` [PATCH v3 11/48] __attach_mnt(): lose the second argument Al Viro
2025-06-30  2:52       ` [PATCH v3 12/48] don't set MNT_LOCKED on parentless mounts Al Viro
2025-06-30  2:52       ` [PATCH v3 13/48] clone_mnt(): simplify the propagation-related logics Al Viro
2025-06-30  2:52       ` [PATCH v3 14/48] do_umount(): simplify the "is it still mounted" checks Al Viro
2025-06-30  2:52       ` [PATCH v3 15/48] sanitize handling of long-term internal mounts Al Viro
2025-06-30  2:52       ` [PATCH v3 16/48] Rewrite of propagate_umount() Al Viro
2025-06-30  2:52       ` [PATCH v3 17/48] make commit_tree() usable in same-namespace move case Al Viro
2025-06-30  2:52       ` [PATCH v3 18/48] attach_recursive_mnt(): unify the mnt_change_mountpoint() logics Al Viro
2025-06-30  2:52       ` [PATCH v3 19/48] attach_recursive_mnt(): pass destination mount in all cases Al Viro
2025-06-30  2:52       ` [PATCH v3 20/48] attach_recursive_mnt(): get rid of flags entirely Al Viro
2025-06-30  2:52       ` [PATCH v3 21/48] do_move_mount(): take dropping the old mountpoint into attach_recursive_mnt() Al Viro
2025-06-30  2:52       ` [PATCH v3 22/48] do_move_mount(): get rid of 'attached' flag Al Viro
2025-06-30  2:52       ` [PATCH v3 23/48] attach_recursive_mnt(): remove from expiry list on move Al Viro
2025-06-30  2:52       ` [PATCH v3 24/48] take ->mnt_expire handling under mount_lock [read_seqlock_excl] Al Viro
2025-06-30  2:52       ` [PATCH v3 25/48] pivot_root(): reorder tree surgeries, collapse unhash_mnt() and put_mountpoint() Al Viro
2025-06-30  2:52       ` [PATCH v3 26/48] combine __put_mountpoint() with unhash_mnt() Al Viro
2025-06-30  2:52       ` [PATCH v3 27/48] get rid of mountpoint->m_count Al Viro
2025-06-30  2:52       ` [PATCH v3 28/48] don't have mounts pin their parents Al Viro
2025-06-30  2:52       ` [PATCH v3 29/48] mount: separate the flags accessed only under namespace_sem Al Viro
2025-06-30  2:52       ` [PATCH v3 30/48] propagate_one(): get rid of dest_master Al Viro
2025-06-30  2:52       ` [PATCH v3 31/48] propagate_mnt(): handle all peer groups in the same loop Al Viro
2025-06-30  2:52       ` [PATCH v3 32/48] propagate_one(): separate the "do we need secondary here?" logics Al Viro
2025-06-30  2:52       ` [PATCH v3 33/48] propagate_one(): separate the "what should be the master for this copy" part Al Viro
2025-06-30  2:52       ` [PATCH v3 34/48] propagate_one(): fold into the sole caller Al Viro
2025-06-30  2:52       ` [PATCH v3 35/48] fs/pnode.c: get rid of globals Al Viro
2025-06-30  2:52       ` [PATCH v3 36/48] propagate_mnt(): get rid of last_dest Al Viro
2025-06-30  2:52       ` [PATCH v3 37/48] propagate_mnt(): fix comment and convert to kernel-doc, while we are at it Al Viro
2025-06-30  2:52       ` [PATCH v3 38/48] change_mnt_propagation() cleanups, step 1 Al Viro
2025-06-30  2:52       ` [PATCH v3 39/48] change_mnt_propagation(): do_make_slave() is a no-op unless IS_MNT_SHARED() Al Viro
2025-06-30  2:52       ` [PATCH v3 40/48] do_make_slave(): choose new master sanely Al Viro
2025-06-30  2:52       ` [PATCH v3 41/48] turn do_make_slave() into transfer_propagation() Al Viro
2025-06-30  2:52       ` [PATCH v3 42/48] mnt_slave_list/mnt_slave: turn into hlist_head/hlist_node Al Viro
2025-06-30  2:52       ` [PATCH v3 43/48] change_mnt_propagation(): move ->mnt_master assignment into MS_SLAVE case Al Viro
2025-06-30  2:52       ` [PATCH v3 44/48] copy_tree(): don't link the mounts via mnt_list Al Viro
2025-08-13  6:45         ` Lai, Yi
2025-08-13  7:13           ` Al Viro
2025-08-13  7:32             ` Al Viro
2025-08-14 23:21               ` Al Viro
2025-08-14 23:25                 ` Al Viro
2025-08-15  3:19                 ` Lai, Yi
2025-06-30  2:52       ` [PATCH v3 45/48] take freeing of emptied mnt_namespace to namespace_unlock() Al Viro
2025-06-30  2:52       ` [PATCH v3 46/48] get rid of CL_SHARE_TO_SLAVE Al Viro
2025-06-30  2:52       ` [PATCH v3 47/48] invent_group_ids(): zero ->mnt_group_id always implies !IS_MNT_SHARED() Al Viro
2025-06-30  2:52       ` [PATCH v3 48/48] statmount_mnt_basic(): simplify the logics for group id Al Viro
2025-07-02 19:29     ` [PATCHES v3][RFC][CFR] mount-related stuff Al Viro

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250610082148.1127550-25-viro@zeniv.linux.org.uk \
    --to=viro@zeniv.linux.org.uk \
    --cc=brauner@kernel.org \
    --cc=ebiederm@xmission.com \
    --cc=jack@suse.cz \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).