summaryrefslogtreecommitdiffstats
path: root/ipc/namespace.c
diff options
context:
space:
mode:
authorRik van Riel <riel@surriel.com>2023-01-27 13:46:51 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2023-01-27 19:08:00 -0500
commitda27f796a832122ee533c7685438dad1c4e338dd (patch)
treef65cbf61db048942e78fc877732d60be814eebb0 /ipc/namespace.c
parenta80c4adcb574821e534779c48ae13953b7d1d996 (diff)
downloadlinux-da27f796a832122ee533c7685438dad1c4e338dd.tar.gz
linux-da27f796a832122ee533c7685438dad1c4e338dd.tar.bz2
linux-da27f796a832122ee533c7685438dad1c4e338dd.zip
ipc,namespace: batch free ipc_namespace structures
Instead of waiting for an RCU grace period between each ipc_namespace structure that is being freed, wait an RCU grace period for every batch of ipc_namespace structures. Thanks to Al Viro for the suggestion of the helper function. This speeds up the run time of the test case that allocates ipc_namespaces in a loop from 6 minutes, to a little over 1 second: real 0m1.192s user 0m0.038s sys 0m1.152s Signed-off-by: Rik van Riel <riel@surriel.com> Reported-by: Chris Mason <clm@meta.com> Tested-by: Giuseppe Scrivano <gscrivan@redhat.com> Suggested-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'ipc/namespace.c')
-rw-r--r--ipc/namespace.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/ipc/namespace.c b/ipc/namespace.c
index a26860a41dac..6ecc30effd3e 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -145,10 +145,11 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
static void free_ipc_ns(struct ipc_namespace *ns)
{
- /* mq_put_mnt() waits for a grace period as kern_unmount()
- * uses synchronize_rcu().
+ /*
+ * Caller needs to wait for an RCU grace period to have passed
+ * after making the mount point inaccessible to new accesses.
*/
- mq_put_mnt(ns);
+ mntput(ns->mq_mnt);
sem_exit_ns(ns);
msg_exit_ns(ns);
shm_exit_ns(ns);
@@ -169,6 +170,12 @@ static void free_ipc(struct work_struct *unused)
struct ipc_namespace *n, *t;
llist_for_each_entry_safe(n, t, node, mnt_llist)
+ mnt_make_shortterm(n->mq_mnt);
+
+ /* Wait for any last users to have gone away. */
+ synchronize_rcu();
+
+ llist_for_each_entry_safe(n, t, node, mnt_llist)
free_ipc_ns(n);
}