All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hao Lee <haolee.swjtu@gmail.com>
To: viro@zeniv.linux.org.uk
Cc: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org,
	haolee.swjtu@gmail.com
Subject: [PATCH] fs/namespace: eliminate unnecessary mount counting
Date: Sun, 23 Jan 2022 10:04:48 +0000	[thread overview]
Message-ID: <20220123100448.GA1468@haolee.io> (raw)

propagate_one() counts the number of propagated mounts in each
propagation. We can count them in advance and use the number in
subsequent propagation.

Signed-off-by: Hao Lee <haolee.swjtu@gmail.com>
---
 fs/namespace.c | 27 +++++++++++++++++++--------
 fs/pnode.c     | 12 +++++++-----
 fs/pnode.h     |  5 +++--
 3 files changed, 29 insertions(+), 15 deletions(-)

diff --git a/fs/namespace.c b/fs/namespace.c
index c6feb92209a6..5d05392854ca 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2082,18 +2082,15 @@ static int invent_group_ids(struct mount *mnt, bool recurse)
 	return 0;
 }
 
-int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
+int update_pending_mounts(struct mnt_namespace *ns, unsigned int mounts)
 {
 	unsigned int max = READ_ONCE(sysctl_mount_max);
-	unsigned int mounts = 0, old, pending, sum;
-	struct mount *p;
-
-	for (p = mnt; p; p = next_mnt(p, mnt))
-		mounts++;
+	unsigned int old, pending, sum;
 
 	old = ns->mounts;
 	pending = ns->pending_mounts;
 	sum = old + pending;
+
 	if ((old > sum) ||
 	    (pending > sum) ||
 	    (max < sum) ||
@@ -2104,6 +2101,17 @@ int count_mounts(struct mnt_namespace *ns, struct mount *mnt)
 	return 0;
 }
 
+unsigned int count_mounts(struct mount *mnt)
+{
+	unsigned int mounts = 0;
+	struct mount *p;
+
+	for (p = mnt; p; p = next_mnt(p, mnt))
+		mounts++;
+
+	return mounts;
+}
+
 /*
  *  @source_mnt : mount tree to be attached
  *  @nd         : place the mount tree @source_mnt is attached
@@ -2178,6 +2186,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	struct mountpoint *smp;
 	struct mount *child, *p;
 	struct hlist_node *n;
+	unsigned int nr_mounts;
 	int err;
 
 	/* Preallocate a mountpoint in case the new mounts need
@@ -2187,9 +2196,10 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 	if (IS_ERR(smp))
 		return PTR_ERR(smp);
 
+	nr_mounts = count_mounts(source_mnt);
 	/* Is there space to add these mounts to the mount namespace? */
 	if (!moving) {
-		err = count_mounts(ns, source_mnt);
+		err = update_pending_mounts(ns, nr_mounts);
 		if (err)
 			goto out;
 	}
@@ -2198,7 +2208,8 @@ static int attach_recursive_mnt(struct mount *source_mnt,
 		err = invent_group_ids(source_mnt, true);
 		if (err)
 			goto out;
-		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, &tree_list);
+		err = propagate_mnt(dest_mnt, dest_mp, source_mnt, nr_mounts,
+				    &tree_list);
 		lock_mount_hash();
 		if (err)
 			goto out_cleanup_ids;
diff --git a/fs/pnode.c b/fs/pnode.c
index 1106137c747a..877de718fc35 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -222,7 +222,7 @@ static inline bool peers(struct mount *m1, struct mount *m2)
 	return m1->mnt_group_id == m2->mnt_group_id && m1->mnt_group_id;
 }
 
-static int propagate_one(struct mount *m)
+static int propagate_one(struct mount *m, unsigned int nr_mounts)
 {
 	struct mount *child;
 	int type;
@@ -269,7 +269,7 @@ static int propagate_one(struct mount *m)
 	last_dest = m;
 	last_source = child;
 	hlist_add_head(&child->mnt_hash, list);
-	return count_mounts(m->mnt_ns, child);
+	return update_pending_mounts(m->mnt_ns, nr_mounts);
 }
 
 /*
@@ -284,9 +284,11 @@ static int propagate_one(struct mount *m)
  * @dest_dentry: destination dentry.
  * @source_mnt: source mount.
  * @tree_list : list of heads of trees to be attached.
+ * @nr_mounts : the number of mounts in source_mnt
  */
 int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
-		    struct mount *source_mnt, struct hlist_head *tree_list)
+		    struct mount *source_mnt, unsigned int nr_mounts,
+		    struct hlist_head *tree_list)
 {
 	struct mount *m, *n;
 	int ret = 0;
@@ -305,7 +307,7 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
 
 	/* all peers of dest_mnt, except dest_mnt itself */
 	for (n = next_peer(dest_mnt); n != dest_mnt; n = next_peer(n)) {
-		ret = propagate_one(n);
+		ret = propagate_one(n, nr_mounts);
 		if (ret)
 			goto out;
 	}
@@ -316,7 +318,7 @@ int propagate_mnt(struct mount *dest_mnt, struct mountpoint *dest_mp,
 		/* everything in that slave group */
 		n = m;
 		do {
-			ret = propagate_one(n);
+			ret = propagate_one(n, nr_mounts);
 			if (ret)
 				goto out;
 			n = next_peer(n);
diff --git a/fs/pnode.h b/fs/pnode.h
index 988f1aa9b02a..005355c0dd49 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -38,7 +38,7 @@ static inline void set_mnt_shared(struct mount *mnt)
 
 void change_mnt_propagation(struct mount *, int);
 int propagate_mnt(struct mount *, struct mountpoint *, struct mount *,
-		struct hlist_head *);
+		  unsigned int, struct hlist_head *);
 int propagate_umount(struct list_head *);
 int propagate_mount_busy(struct mount *, int);
 void propagate_mount_unlock(struct mount *);
@@ -52,5 +52,6 @@ void mnt_change_mountpoint(struct mount *parent, struct mountpoint *mp,
 struct mount *copy_tree(struct mount *, struct dentry *, int);
 bool is_path_reachable(struct mount *, struct dentry *,
 			 const struct path *root);
-int count_mounts(struct mnt_namespace *ns, struct mount *mnt);
+int update_pending_mounts(struct mnt_namespace *ns, unsigned int mounts);
+unsigned int count_mounts(struct mount *mnt);
 #endif /* _LINUX_PNODE_H */
-- 
2.34.1


             reply	other threads:[~2022-01-23 10:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-01-23 10:04 Hao Lee [this message]
2022-02-14  3:04 ` [PATCH] fs/namespace: eliminate unnecessary mount counting Al Viro
2022-02-14  3:42   ` [PATCH] clean overflow checks in count_mounts() a bit Al Viro
2022-02-14  8:29   ` [PATCH] fs/namespace: eliminate unnecessary mount counting Hao Lee

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=20220123100448.GA1468@haolee.io \
    --to=haolee.swjtu@gmail.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --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.