All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ian Kent <raven@themaw.net>
To: Al Viro <viro@ZenIV.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>,
	David Howells <dhowells@redhat.com>,
	Miklos Szeredi <miklos@szeredi.hu>,
	linux-fsdevel <linux-fsdevel@vger.kernel.org>,
	Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [PATCH 3/3] vfs: make may_umount_tree() mount namespace aware
Date: Mon, 11 Jul 2022 11:37:52 +0800	[thread overview]
Message-ID: <165751067234.210556.2619133379044425664.stgit@donald.themaw.net> (raw)
In-Reply-To: <165751053430.210556.5634228273667507299.stgit@donald.themaw.net>

Change may_umount_tree() (and the associated autofs code) to use the
propagate_mount_tree_busy() helper so it also checks if propagated
mounts are busy.

This avoids unnecessary umount requests being sent to the automount
daemon when a mount in another mount namespace is in use when the
expire check is done.

Signed-off-by: Ian Kent <raven@themaw.net>
---
 fs/autofs/expire.c    |   14 ++++++++++++--
 fs/namespace.c        |   32 ++++++++++++++++++++------------
 fs/pnode.h            |    2 --
 include/linux/mount.h |    5 ++++-
 4 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/fs/autofs/expire.c b/fs/autofs/expire.c
index 038b3d2d9f57..1352c454cf1d 100644
--- a/fs/autofs/expire.c
+++ b/fs/autofs/expire.c
@@ -31,10 +31,13 @@ static int autofs_mount_busy(struct vfsmount *mnt,
 {
 	struct dentry *top = dentry;
 	struct path path = {.mnt = mnt, .dentry = dentry};
+	unsigned int flags;
 	int status = 1;
 
 	pr_debug("dentry %p %pd\n", dentry, dentry);
 
+	/* A reference to the mount is held. */
+	flags = TREE_BUSY_REFERENCED;
 	path_get(&path);
 
 	if (!follow_down_one(&path))
@@ -55,7 +58,7 @@ static int autofs_mount_busy(struct vfsmount *mnt,
 	}
 
 	/* Update the expiry counter if fs is busy */
-	if (!may_umount_tree(path.mnt)) {
+	if (!may_umount_tree(path.mnt, flags)) {
 		struct autofs_info *ino;
 
 		ino = autofs_dentry_ino(top);
@@ -152,14 +155,21 @@ static int autofs_direct_busy(struct vfsmount *mnt,
 			      unsigned long timeout,
 			      unsigned int how)
 {
+	unsigned int flags;
+
 	pr_debug("top %p %pd\n", top, top);
 
 	/* Forced expire, user space handles busy mounts */
 	if (how & AUTOFS_EXP_FORCED)
 		return 0;
 
+	/* A mounted direct mount will have an open file handle
+	 * associated with it so we need TREE_BUSY_REFERENCED.
+	 */
+	flags = TREE_BUSY_REFERENCED;
+
 	/* If it's busy update the expiry counters */
-	if (!may_umount_tree(mnt)) {
+	if (!may_umount_tree(mnt, flags)) {
 		struct autofs_info *ino;
 
 		ino = autofs_dentry_ino(top);
diff --git a/fs/namespace.c b/fs/namespace.c
index 3c1ee5b5bb69..bdcb55e821f4 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1431,28 +1431,36 @@ void mnt_cursor_del(struct mnt_namespace *ns, struct mount *cursor)
  * open files, pwds, chroots or sub mounts that are
  * busy.
  */
-int may_umount_tree(struct vfsmount *m)
+int may_umount_tree(struct vfsmount *m, unsigned int flags)
 {
 	struct mount *mnt = real_mount(m);
-	int actual_refs = 0;
-	int minimum_refs = 0;
 	struct mount *p;
+	int ret = 1;
+
 	BUG_ON(!m);
 
-	/* write lock needed for mnt_get_count */
+	down_read(&namespace_sem);
 	lock_mount_hash();
-	for (p = mnt; p; p = next_mnt(p, mnt)) {
-		actual_refs += mnt_get_count(p);
-		minimum_refs += 2;
+	if (propagate_mount_tree_busy(mnt, flags)) {
+		ret = 0;
+		goto out;
 	}
+	/* Only the passed in mount will have a reference held by
+	 * the caller.
+	 */
+	flags &= ~TREE_BUSY_REFERENCED;
+	for (p = next_mnt(mnt, mnt); p; p = next_mnt(p, mnt)) {
+		if (propagate_mount_tree_busy(p, flags)) {
+			ret = 0;
+			break;
+		}
+	}
+out:
 	unlock_mount_hash();
+	up_read(&namespace_sem);
 
-	if (actual_refs > minimum_refs)
-		return 0;
-
-	return 1;
+	return ret;
 }
-
 EXPORT_SYMBOL(may_umount_tree);
 
 /**
diff --git a/fs/pnode.h b/fs/pnode.h
index d7b9dddb257b..12c3ab5962a0 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -30,8 +30,6 @@
 
 #define CL_COPY_ALL		(CL_COPY_UNBINDABLE | CL_COPY_MNT_NS_FILE)
 
-#define TREE_BUSY_REFERENCED	0x01
-
 static inline void set_mnt_shared(struct mount *mnt)
 {
 	mnt->mnt.mnt_flags &= ~MNT_SHARED_MASK;
diff --git a/include/linux/mount.h b/include/linux/mount.h
index 55a4abaf6715..c21d74ea3d85 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -112,7 +112,10 @@ extern bool our_mnt(struct vfsmount *mnt);
 
 extern struct vfsmount *kern_mount(struct file_system_type *);
 extern void kern_unmount(struct vfsmount *mnt);
-extern int may_umount_tree(struct vfsmount *);
+
+#define TREE_BUSY_REFERENCED	0x01
+
+extern int may_umount_tree(struct vfsmount *m, unsigned int flags);
 extern int may_umount(struct vfsmount *);
 extern long do_mount(const char *, const char __user *,
 		     const char *, unsigned long, void *);



      parent reply	other threads:[~2022-07-11  3:38 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-11  3:37 [PATCH 0/3] autofs: fix may_umount_tree() Ian Kent
2022-07-11  3:37 ` [PATCH 1/3] vfs: track count of child mounts Ian Kent
2022-07-20  1:50   ` Al Viro
2022-07-20  2:17     ` Ian Kent
2022-07-20  7:26       ` Ian Kent
2022-07-26  5:11       ` Ian Kent
2022-07-26  7:10         ` Ian Kent
2022-07-11  3:37 ` [PATCH 2/3] vfs: add propagate_mount_tree_busy() helper Ian Kent
2022-07-20  1:54   ` Al Viro
2022-07-20  2:31     ` Ian Kent
2022-07-20  2:39       ` Al Viro
2022-07-11  3:37 ` Ian Kent [this message]

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=165751067234.210556.2619133379044425664.stgit@donald.themaw.net \
    --to=raven@themaw.net \
    --cc=akpm@linux-foundation.org \
    --cc=dhowells@redhat.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=miklos@szeredi.hu \
    --cc=viro@ZenIV.linux.org.uk \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.