Commit 935c6912b198f60a812b7dada21027b5aac7c461

Authored by David Howells
Committed by Al Viro
1 parent 66f592e2ec

ipc: Convert mqueue fs to fs_context

Convert the mqueue filesystem to use the filesystem context stuff.

Notes:

 (1) The relevant ipc namespace is selected in when the context is
     initialised (and it defaults to the current task's ipc namespace).
     The caller can override this before calling vfs_get_tree().

 (2) Rather than simply calling kern_mount_data(), mq_init_ns() and
     mq_internal_mount() create a context, adjust it and then do the rest
     of the mount procedure.

 (3) The lazy mqueue mounting on creation of a new namespace is retained
     from a previous patch, but the avoidance of sget() if no superblock
     yet exists is reverted and the superblock is again keyed on the
     namespace pointer.

     Yes, there was a performance gain in not searching the superblock
     hash, but it's only paid once per ipc namespace - and only if someone
     uses mqueue within that namespace, so I'm not sure it's worth it,
     especially as calling sget() allows avoidance of recursion.

Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 2 changed files with 73 additions and 23 deletions Side-by-side Diff

... ... @@ -18,6 +18,7 @@
18 18 #include <linux/pagemap.h>
19 19 #include <linux/file.h>
20 20 #include <linux/mount.h>
  21 +#include <linux/fs_context.h>
21 22 #include <linux/namei.h>
22 23 #include <linux/sysctl.h>
23 24 #include <linux/poll.h>
... ... @@ -42,6 +43,10 @@
42 43 #include <net/sock.h>
43 44 #include "util.h"
44 45  
  46 +struct mqueue_fs_context {
  47 + struct ipc_namespace *ipc_ns;
  48 +};
  49 +
45 50 #define MQUEUE_MAGIC 0x19800202
46 51 #define DIRENT_SIZE 20
47 52 #define FILENT_SIZE 80
48 53  
... ... @@ -87,9 +92,11 @@
87 92 unsigned long qsize; /* size of queue in memory (sum of all msgs) */
88 93 };
89 94  
  95 +static struct file_system_type mqueue_fs_type;
90 96 static const struct inode_operations mqueue_dir_inode_operations;
91 97 static const struct file_operations mqueue_file_operations;
92 98 static const struct super_operations mqueue_super_ops;
  99 +static const struct fs_context_operations mqueue_fs_context_ops;
93 100 static void remove_notification(struct mqueue_inode_info *info);
94 101  
95 102 static struct kmem_cache *mqueue_inode_cachep;
... ... @@ -322,7 +329,7 @@
322 329 return ERR_PTR(ret);
323 330 }
324 331  
325   -static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
  332 +static int mqueue_fill_super(struct super_block *sb, struct fs_context *fc)
326 333 {
327 334 struct inode *inode;
328 335 struct ipc_namespace *ns = sb->s_fs_info;
329 336  
330 337  
... ... @@ -343,20 +350,58 @@
343 350 return 0;
344 351 }
345 352  
346   -static struct dentry *mqueue_mount(struct file_system_type *fs_type,
347   - int flags, const char *dev_name,
348   - void *data)
  353 +static int mqueue_get_tree(struct fs_context *fc)
349 354 {
350   - struct ipc_namespace *ns;
351   - if (flags & SB_KERNMOUNT) {
352   - ns = data;
353   - data = NULL;
354   - } else {
355   - ns = current->nsproxy->ipc_ns;
356   - }
357   - return mount_ns(fs_type, flags, data, ns, ns->user_ns, mqueue_fill_super);
  355 + struct mqueue_fs_context *ctx = fc->fs_private;
  356 +
  357 + put_user_ns(fc->user_ns);
  358 + fc->user_ns = get_user_ns(ctx->ipc_ns->user_ns);
  359 + fc->s_fs_info = ctx->ipc_ns;
  360 + return vfs_get_super(fc, vfs_get_keyed_super, mqueue_fill_super);
358 361 }
359 362  
  363 +static void mqueue_fs_context_free(struct fs_context *fc)
  364 +{
  365 + struct mqueue_fs_context *ctx = fc->fs_private;
  366 +
  367 + if (ctx->ipc_ns)
  368 + put_ipc_ns(ctx->ipc_ns);
  369 + kfree(ctx);
  370 +}
  371 +
  372 +static int mqueue_init_fs_context(struct fs_context *fc)
  373 +{
  374 + struct mqueue_fs_context *ctx;
  375 +
  376 + ctx = kzalloc(sizeof(struct mqueue_fs_context), GFP_KERNEL);
  377 + if (!ctx)
  378 + return -ENOMEM;
  379 +
  380 + ctx->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
  381 + fc->fs_private = ctx;
  382 + fc->ops = &mqueue_fs_context_ops;
  383 + return 0;
  384 +}
  385 +
  386 +static struct vfsmount *mq_create_mount(struct ipc_namespace *ns)
  387 +{
  388 + struct mqueue_fs_context *ctx;
  389 + struct fs_context *fc;
  390 + struct vfsmount *mnt;
  391 +
  392 + fc = fs_context_for_mount(&mqueue_fs_type, SB_KERNMOUNT);
  393 + if (IS_ERR(fc))
  394 + return ERR_CAST(fc);
  395 +
  396 + ctx = fc->fs_private;
  397 + put_ipc_ns(ctx->ipc_ns);
  398 + ctx->ipc_ns = get_ipc_ns(ns);
  399 +
  400 + mnt = fc_mount(fc);
  401 + put_fs_context(fc);
  402 + return mnt;
  403 +}
  404 +
360 405 static void init_once(void *foo)
361 406 {
362 407 struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
363 408  
364 409  
... ... @@ -1522,15 +1567,22 @@
1522 1567 .statfs = simple_statfs,
1523 1568 };
1524 1569  
  1570 +static const struct fs_context_operations mqueue_fs_context_ops = {
  1571 + .free = mqueue_fs_context_free,
  1572 + .get_tree = mqueue_get_tree,
  1573 +};
  1574 +
1525 1575 static struct file_system_type mqueue_fs_type = {
1526   - .name = "mqueue",
1527   - .mount = mqueue_mount,
1528   - .kill_sb = kill_litter_super,
1529   - .fs_flags = FS_USERNS_MOUNT,
  1576 + .name = "mqueue",
  1577 + .init_fs_context = mqueue_init_fs_context,
  1578 + .kill_sb = kill_litter_super,
  1579 + .fs_flags = FS_USERNS_MOUNT,
1530 1580 };
1531 1581  
1532 1582 int mq_init_ns(struct ipc_namespace *ns)
1533 1583 {
  1584 + struct vfsmount *m;
  1585 +
1534 1586 ns->mq_queues_count = 0;
1535 1587 ns->mq_queues_max = DFLT_QUEUESMAX;
1536 1588 ns->mq_msg_max = DFLT_MSGMAX;
... ... @@ -1538,12 +1590,10 @@
1538 1590 ns->mq_msg_default = DFLT_MSG;
1539 1591 ns->mq_msgsize_default = DFLT_MSGSIZE;
1540 1592  
1541   - ns->mq_mnt = kern_mount_data(&mqueue_fs_type, ns);
1542   - if (IS_ERR(ns->mq_mnt)) {
1543   - int err = PTR_ERR(ns->mq_mnt);
1544   - ns->mq_mnt = NULL;
1545   - return err;
1546   - }
  1593 + m = mq_create_mount(ns);
  1594 + if (IS_ERR(m))
  1595 + return PTR_ERR(m);
  1596 + ns->mq_mnt = m;
1547 1597 return 0;
1548 1598 }
1549 1599  
... ... @@ -42,7 +42,7 @@
42 42 goto fail;
43 43  
44 44 err = -ENOMEM;
45   - ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
  45 + ns = kzalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
46 46 if (ns == NULL)
47 47 goto fail_dec;
48 48