From: Giuseppe Scrivano <gscrivan@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: gscrivan@redhat.com, Andrew Morton <akpm@linux-foundation.org>
Subject: [PATCH v2] ipc, mqueue: lazy call kern_mount_data in new namespaces
Date: Thu, 30 Nov 2017 19:38:16 +0100 [thread overview]
Message-ID: <20171130183816.26916-1-gscrivan@redhat.com> (raw)
kern_mount_data is a relatively expensive operation when creating a
new IPC namespace, so delay the mount until its first usage when not
creating the the global namespace.
This is a net saving for new IPC namespaces that don't use mq_open().
In this case there won't be any kern_mount_data() cost at all.
On my machine, the time for creating 1000 new IPC namespaces dropped
from ~8s to ~2s.
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
---
v1 here: https://lkml.org/lkml/2017/11/27/427
v1 -> v2:
Declare and use a mutex instead of a spinlock.
include/linux/ipc_namespace.h | 2 +-
ipc/mqueue.c | 48 ++++++++++++++++++++++++++++++++++---------
ipc/namespace.c | 2 +-
3 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h
index b5630c8eb2f3..a06617c113f1 100644
--- a/include/linux/ipc_namespace.h
+++ b/include/linux/ipc_namespace.h
@@ -81,7 +81,7 @@ static inline void shm_destroy_orphaned(struct ipc_namespace *ns) {}
#endif /* CONFIG_SYSVIPC */
#ifdef CONFIG_POSIX_MQUEUE
-extern int mq_init_ns(struct ipc_namespace *ns);
+extern int mq_init_ns(struct ipc_namespace *ns, bool mount);
/*
* POSIX Message Queue default values:
*
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index d24025626310..27a82a3fef50 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -87,6 +87,7 @@ struct mqueue_inode_info {
unsigned long qsize; /* size of queue in memory (sum of all msgs) */
};
+static struct file_system_type mqueue_fs_type;
static const struct inode_operations mqueue_dir_inode_operations;
static const struct file_operations mqueue_file_operations;
static const struct super_operations mqueue_super_ops;
@@ -776,9 +777,24 @@ static int do_mq_open(const char __user *u_name, int oflag, umode_t mode,
struct filename *name;
int fd, error;
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
- struct vfsmount *mnt = ipc_ns->mq_mnt;
- struct dentry *root = mnt->mnt_root;
+ struct vfsmount *mnt;
+ struct dentry *root;
int ro;
+ static DEFINE_MUTEX(mnt_lock);
+
+ mutex_lock(&mnt_lock);
+ mnt = ipc_ns->mq_mnt;
+ if (unlikely(!mnt)) {
+ mnt = kern_mount_data(&mqueue_fs_type, ipc_ns);
+ if (IS_ERR(mnt)) {
+ mutex_unlock(&mnt_lock);
+ return PTR_ERR(mnt);
+ }
+ ipc_ns->mq_mnt = mnt;
+ }
+ mutex_unlock(&mnt_lock);
+
+ root = mnt->mnt_root;
audit_mq_open(oflag, mode, attr);
@@ -863,6 +879,9 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
struct vfsmount *mnt = ipc_ns->mq_mnt;
+ if (!mnt)
+ return -ENOENT;
+
name = getname(u_name);
if (IS_ERR(name))
return PTR_ERR(name);
@@ -1581,7 +1600,8 @@ static struct file_system_type mqueue_fs_type = {
.fs_flags = FS_USERNS_MOUNT,
};
-int mq_init_ns(struct ipc_namespace *ns)
+
+int mq_init_ns(struct ipc_namespace *ns, bool mount)
{
ns->mq_queues_count = 0;
ns->mq_queues_max = DFLT_QUEUESMAX;
@@ -1590,23 +1610,31 @@ int mq_init_ns(struct ipc_namespace *ns)
ns->mq_msg_default = DFLT_MSG;
ns->mq_msgsize_default = DFLT_MSGSIZE;
- ns->mq_mnt = kern_mount_data(&mqueue_fs_type, ns);
- if (IS_ERR(ns->mq_mnt)) {
- int err = PTR_ERR(ns->mq_mnt);
+ if (!mount)
ns->mq_mnt = NULL;
- return err;
+ else {
+ int err;
+
+ ns->mq_mnt = kern_mount_data(&mqueue_fs_type, ns);
+ if (IS_ERR(ns->mq_mnt)) {
+ err = PTR_ERR(ns->mq_mnt);
+ ns->mq_mnt = NULL;
+ return err;
+ }
}
return 0;
}
void mq_clear_sbinfo(struct ipc_namespace *ns)
{
- ns->mq_mnt->mnt_sb->s_fs_info = NULL;
+ if (ns->mq_mnt)
+ ns->mq_mnt->mnt_sb->s_fs_info = NULL;
}
void mq_put_mnt(struct ipc_namespace *ns)
{
- kern_unmount(ns->mq_mnt);
+ if (ns->mq_mnt)
+ kern_unmount(ns->mq_mnt);
}
static int __init init_mqueue_fs(void)
@@ -1628,7 +1656,7 @@ static int __init init_mqueue_fs(void)
spin_lock_init(&mq_lock);
- error = mq_init_ns(&init_ipc_ns);
+ error = mq_init_ns(&init_ipc_ns, true);
if (error)
goto out_filesystem;
diff --git a/ipc/namespace.c b/ipc/namespace.c
index f59a89966f92..9d3689577f66 100644
--- a/ipc/namespace.c
+++ b/ipc/namespace.c
@@ -65,7 +65,7 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns,
if (err)
goto fail_destroy_msg;
- err = mq_init_ns(ns);
+ err = mq_init_ns(ns, false);
if (err)
goto fail_destroy_shm;
--
2.14.3
next reply other threads:[~2017-11-30 18:38 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-11-30 18:38 Giuseppe Scrivano [this message]
2017-12-03 18:42 ` kbuild test robot
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=20171130183816.26916-1-gscrivan@redhat.com \
--to=gscrivan@redhat.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.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
all inboxes | Powered by JetHome®