posix mqueue namespace (v13)
cover posix mqueue namespace (v13)
IPC namespaces are completely disjoint id->object mappings. A task can pass CLONE_NEWIPC to unshare and clone to get a new, empty, IPC namespace. Until now this has supported SYSV IPC.
Most Posix IPC is done in userspace. The posix mqueue support, however, is implemented on top of the mqueue fs.
This patchset implements multiple mqueue fs instances, one per IPC namespace to be precise.
To create a new ipc namespace with posix mq support, you should now:
unshare(CLONE_NEWIPC|CLONE_NEWNS); umount /dev/mqueue mount -t mqueue mqueue /dev/mqueue
It's perfectly valid to do vfs operations on files in another ipc_namespace's /dev/mqueue, but any use of mq_open(3) and friends will act in your own ipc_ns. After the ipc namespace has exited, you can still unlink but no longer create files in that fs (since accounting is carried.
Changelog:
v13:
1. addressed comments by Dave and Suka
2. ported Cedric's patch to make posix mq sysctls per-namespace
When convenient, it would be great to see this tested in -mm.
thanks,
-serge
PATCH 1/3 mqueue ns: move mqueue_mnt into struct ipc_namespace
Move mqueue vfsmount plus a few tunables into the ipc_namespace struct. The CONFIG_IPC_NS boolean and the ipc_namespace struct will serve both the posix message queue namespaces and the SYSV ipc namespaces.
Changelog:
Dec 18: fix dummy fn #defines
--- include/linux/ipc_namespace.h | 32 ++++++++++-- init/Kconfig | 4 +- ipc/mqueue.c | 116 ++++++++++++++++++++++------------------- ipc/msgutil.c | 21 +++++++ ipc/namespace.c | 2 + ipc/util.c | 9 --- ipc/util.h | 15 +++++ 7 files changed, 131 insertions(+), 68 deletions(-)
include/linux/ipc_namespace.h +28 -4
@@ -44,24 +44,48 @@ struct ipc_namespace {int shm_tot;struct notifier_block ipcns_nb; + +struct vfsmount *mq_mnt; +unsigned int mq_queues_count; +unsigned int mq_queues_max; +unsigned int mq_msg_max; +unsigned int mq_msgsize_max; + };extern struct ipc_namespace init_ipc_ns;extern atomic_t nr_ipc_ns; -#ifdef CONFIG_SYSVIPC +#if defined(CONFIG_POSIX_MQUEUE ) || defined(CONFIG_SYSVIPC )#define INIT_IPC_NS (ns) .ns = &init_ipc_ns, +#else +#define INIT_IPC_NS (ns) +#endif +#ifdef CONFIG_SYSVIPC extern int register_ipcns_notifier (struct ipc_namespace *);extern int cond_register_ipcns_notifier (struct ipc_namespace *);extern void unregister_ipcns_notifier (struct ipc_namespace *);extern int ipcns_notify (unsigned long ); -#else /* CONFIG_SYSVIPC */ -#define INIT_IPC_NS (ns) +#define register_ipcns_notifier (ns) (0) +#define cond_register_ipcns_notifier (ns) (0) +#define unregister_ipcns_notifier (ns) ((void) 0) +#define ipcns_notify (l) (0)#endif /* CONFIG_SYSVIPC */ -#if defined(CONFIG_SYSVIPC ) && defined(CONFIG_IPC_NS ) +#ifdef CONFIG_POSIX_MQUEUE +extern void mq_init_ns (struct ipc_namespace *ns); +/* default values */ +#define DFLT_QUEUESMAX 256/* max number of message queues */ +#define DFLT_MSGMAX 10/* max number of messages in each queue */ +#define HARD_MSGMAX (131072/sizeof(void *)) +#define DFLT_MSGSIZEMAX 8192/* max message size */ +#else +#define mq_init_ns (ns) ((void) 0) +#endif + +#if defined(CONFIG_IPC_NS )extern void free_ipc_ns (struct kref *kref);extern struct ipc_namespace *copy_ipcs (unsigned long flags,struct ipc_namespace *ns);
init/Kconfig +2 -2
@@ -489,10 +489,10 @@ config UTS_NS config IPC_NS bool "IPC namespace" - depends on NAMESPACES && SYSVIPC + depends on NAMESPACES && (SYSVIPC || POSIX_MQUEUE) help In this namespace tasks work with IPC ids which correspond to - different IPC objects in different namespaces + different IPC objects in different namespaces. config USER_NS bool "User namespace (EXPERIMENTAL)"
ipc/mqueue.c +63 -53
336 lines not on this page · raw message
ipc/msgutil.c +21 -0
@@ -13,10 +13,31 @@#include <linux/security.h> #include <linux/slab.h> #include <linux/ipc.h> +#include <linux/ipc_namespace.h> #include <asm/uaccess.h> #include "util.h" +/* +* The next 2 defines are here bc this is the only file +* compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE +* and not CONFIG_IPC_NS. +*/ +struct ipc_namespace init_ipc_ns = { + .kref = { + .refcount =ATOMIC_INIT (2 ), + }, +#ifdef CONFIG_POSIX_MQUEUE + .mq_mnt =NULL , + .mq_queues_count =0 , + .mq_queues_max =DFLT_QUEUESMAX , + .mq_msg_max =DFLT_MSGMAX , + .mq_msgsize_max =DFLT_MSGSIZEMAX , +#endif +}; + +atomic_t nr_ipc_ns =ATOMIC_INIT (1 ); +struct msg_msgseg {struct msg_msgseg * next;/* the next part of the message follows immediately */
ipc/namespace.c +2 -0
@@ -25,6 +25,7 @@ static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)sem_init_ns (ns);msg_init_ns (ns);shm_init_ns (ns); +mq_init_ns (ns);/* * msgmni has already been computed for the new ipc ns.
@@ -101,6 +102,7 @@ void free_ipc_ns(struct kref *kref)sem_exit_ns (ns);msg_exit_ns (ns);shm_exit_ns (ns); +mq_exit_ns (ns);kfree (ns);atomic_dec (&nr_ipc_ns);
ipc/util.c +0 -9
@@ -47,15 +47,6 @@ struct ipc_proc_iface {int (*show)(struct seq_file *,void *); }; -struct ipc_namespace init_ipc_ns = { - .kref = { - .refcount =ATOMIC_INIT (2 ), - }, -}; - -atomic_t nr_ipc_ns =ATOMIC_INIT (1 ); - -#ifdef CONFIG_MEMORY_HOTPLUG static void ipc_memory_notifier (struct work_struct *work)
ipc/util.h +15 -0
@@ -20,6 +20,13 @@ void shm_init (void);struct ipc_namespace ; +#ifdef CONFIG_POSIX_MQUEUE +void mq_exit_ns (struct ipc_namespace *ns); +#else +#define mq_exit_ns (ns) ((void) 0) +#endif + +#ifdef CONFIG_SYSVIPC void sem_init_ns (struct ipc_namespace *ns);void msg_init_ns (struct ipc_namespace *ns);void shm_init_ns (struct ipc_namespace *ns);
@@ -27,6 +34,14 @@ void shm_init_ns(struct ipc_namespace *ns);void sem_exit_ns (struct ipc_namespace *ns);void msg_exit_ns (struct ipc_namespace *ns);void shm_exit_ns (struct ipc_namespace *ns); +#else +#define sem_init_ns (ns) ((void) 0) +#define msg_init_ns (ns) ((void) 0) +#define shm_init_ns (ns) ((void) 0) +#define sem_exit_ns (ns) ((void) 0) +#define msg_exit_ns (ns) ((void) 0) +#define shm_exit_ns (ns) ((void) 0) +#endif /* * Structure that holds the parameters needed by the ipc operations
Signature · 1 line
1.5.4.3
PATCH 2/3 ipc namespaces: implement support for posix msqueues
In reply to Serge E. HallynImplement multiple mounts of the mqueue file system, and link it to usage of CLONE_NEWIPC.
Each ipc ns has a corresponding mqueuefs superblock. When a user does clone(CLONE_NEWIPC) or unshare(CLONE_NEWIPC), the unshare will cause an internal mount of a new mqueuefs sb linked to the new ipc ns.
When a user does 'mount -t mqueue mqueue /dev/mqueue', he mounts the mqueuefs superblock.
Posix message queues can be worked with both through the mq_* system calls (see mq_overview(7)), and through the VFS through the mqueue mount. Any usage of mq_open() and friends will work with the acting task's ipc namespace. Any actions through the VFS will work with the mqueuefs in which the file was created. So if a user doesn't remount mqueuefs after unshare(CLONE_NEWIPC), mq_open("/ab") will not be reflected in "ls /dev/mqueue".
If task a mounts mqueue for ipc_ns:1, then clones task b with a new ipcns, ipcns:2, and then task a is the last task in ipc_ns:1 to exit, then (1) ipc_ns:1 will be freed, (2) it's superblock will live on until task b umounts the corresponding mqueuefs, and vfs actions will continue to succeed, but (3) sb->s_fs_info will be NULL for the sb corresponding to the deceased ipc_ns:1.
To make this happen, we must protect the ipc reference count when
a. a task exits and drops its ipcns->count, since
it might be dropping it to 0 and freeing the ipcns
b. a task accesses the ipcns through its mqueuefs
interface, since it bumps the ipcns refcount and might race with the last task in the ipcns exiting.
So the kref is changed to an atomic_t so we can use atomic_dec_and_lock(&ns->count,mq_lock), and every access to the ipcns through ns = mqueuefs_sb->s_fs_info is protected by the same lock.
Changelog:
Dec 19: Commented put_ipc_ns (As per Dave Hansen comment)
Addressed nits (per Sukadev Bhattiprolu comment)
Dec 17: removed unused static fn (get_ipcns_from_sb)
--- include/linux/ipc_namespace.h | 16 ++--- ipc/mqueue.c | 140 ++++++++++++++++++++++++++++++++--------- ipc/msgutil.c | 8 +-- ipc/namespace.c | 41 ++++++++++-- ipc/util.h | 6 +- 5 files changed, 160 insertions(+), 51 deletions(-)
include/linux/ipc_namespace.h +7 -9
@@ -25,7 +25,7 @@ struct ipc_ids { };struct ipc_namespace { -struct kref kref; +atomic_t count;struct ipc_ids ids[3 ];int sem_ctls[4 ];
@@ -56,6 +56,7 @@ struct ipc_namespace {extern struct ipc_namespace init_ipc_ns;extern atomic_t nr_ipc_ns; +extern spinlock_t mq_lock;#if defined(CONFIG_POSIX_MQUEUE ) || defined(CONFIG_SYSVIPC )#define INIT_IPC_NS (ns) .ns = &init_ipc_ns,#else
@@ -75,18 +76,18 @@ extern int ipcns_notify(unsigned long);#endif /* CONFIG_SYSVIPC */ #ifdef CONFIG_POSIX_MQUEUE -extern void mq_init_ns (struct ipc_namespace *ns); +extern int mq_init_ns (struct ipc_namespace *ns);/* default values */ #define DFLT_QUEUESMAX 256/* max number of message queues */ #define DFLT_MSGMAX 10/* max number of messages in each queue */ #define HARD_MSGMAX (131072/sizeof(void *))#define DFLT_MSGSIZEMAX 8192/* max message size */ #else -#define mq_init_ns (ns) ((void) 0) +#define mq_init_ns (ns) (0)#endif #if defined(CONFIG_IPC_NS ) -extern void free_ipc_ns (struct kref *kref); +extern void free_ipc_ns (struct ipc_namespace *ns);extern struct ipc_namespace *copy_ipcs (unsigned long flags,struct ipc_namespace *ns); extern void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
@@ -96,14 +97,11 @@ extern void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,static inline struct ipc_namespace *get_ipc_ns (struct ipc_namespace *ns) {if (ns) -kref_get (&ns->kref); +atomic_inc (&ns->count);return ns; } -static inline void put_ipc_ns (struct ipc_namespace *ns) -{ -kref_put (&ns->kref, free_ipc_ns); -} +extern void put_ipc_ns (struct ipc_namespace *ns);#else static inline struct ipc_namespace *copy_ipcs (unsigned long flags,struct ipc_namespace *ns)
ipc/mqueue.c +111 -29
258 lines not on this page · raw message
ipc/msgutil.c +3 -5
@@ -18,18 +18,16 @@#include "util.h" +spinlock_t mq_lock; +/* * The next 2 defines are here bc this is the only file * compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE * and not CONFIG_IPC_NS. */ struct ipc_namespace init_ipc_ns = { - .kref = { - .refcount =ATOMIC_INIT (2 ), - }, + .count =ATOMIC_INIT (2 ), #ifdef CONFIG_POSIX_MQUEUE - .mq_mnt =NULL , - .mq_queues_count =0 , .mq_queues_max =DFLT_QUEUESMAX , .mq_msg_max =DFLT_MSGMAX , .mq_msgsize_max = DFLT_MSGSIZEMAX,
ipc/namespace.c +35 -6
83 lines not on this page · raw message
ipc/util.h +4 -2
@@ -21,9 +21,11 @@ void shm_init (void);struct ipc_namespace ;#ifdef CONFIG_POSIX_MQUEUE -void mq_exit_ns (struct ipc_namespace *ns); +extern void mq_clear_sbinfo (struct ipc_namespace *ns); +extern void mq_put_mnt (struct ipc_namespace *ns);#else -#define mq_exit_ns (ns) ((void) 0) +#define mq_clear_sbinfo (ns) ((void) 0) +#define mq_put_mnt (ns) ((void) 0)#endif #ifdef CONFIG_SYSVIPC
Signature · 1 line
1.5.4.3
PATCH 3/3 mqueue namespace: adapt sysctl
In reply to a message not in the archiveFrom: Nadia Derbey <Nadia.Derbey-6ktuUTfB/[email protected]>
Largely inspired from ipc/ipc_sysctl.c. This patch isolates the mqueue sysctl stuff in its own file.
--- include/linux/ipc_namespace.h | 14 +++++ init/Kconfig | 6 ++ ipc/Makefile | 1 + ipc/mq_sysctl.c | 125 +++++++++++++++++++++++++++++++++++++++++ ipc/mqueue.c | 65 +--------------------- 5 files changed, 147 insertions(+), 64 deletions(-) create mode 100644 ipc/mq_sysctl.c
include/linux/ipc_namespace.h +14 -0
@@ -121,4 +121,18 @@ static inline void put_ipc_ns(struct ipc_namespace *ns) { }#endif + +#ifdef CONFIG_POSIX_MQUEUE_SYSCTL + +struct ctl_table_header ; +extern struct ctl_table_header *mq_register_sysctl_table (void ); + +#else /* CONFIG_POSIX_MQUEUE_SYSCTL */ + +static inline struct ctl_table_header *mq_register_sysctl_table (void ) +{ +return NULL ; +} + +#endif /* CONFIG_POSIX_MQUEUE_SYSCTL */ #endif
init/Kconfig +6 -0
@@ -148,6 +148,12 @@ config POSIX_MQUEUE If unsure, say Y. +config POSIX_MQUEUE_SYSCTL + bool + depends on POSIX_MQUEUE + depends on SYSCTL + default y + config BSD_PROCESS_ACCT bool "BSD Process Accounting" help
ipc/Makefile +1 -0
@@ -8,4 +8,5 @@ obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o obj_mq-$(CONFIG_COMPAT) += compat_mq.o obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) obj-$(CONFIG_IPC_NS) += namespace.o +obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
ipc/mq_sysctl.c new file +125 -0
125 lines not on this page · raw message
ipc/mqueue.c +1 -64
83 lines not on this page · raw message
Signature · 1 line
1.5.4.3
PATCH 3/3 mqueue namespace: adapt sysctl
In reply to Serge E. Hallyn(resending since lkml appears to have disappeared from the earlier headers)
From: Nadia Derbey <[email protected]>
Largely inspired from ipc/ipc_sysctl.c. This patch isolates the mqueue sysctl stuff in its own file.
--- include/linux/ipc_namespace.h | 14 +++++ init/Kconfig | 6 ++ ipc/Makefile | 1 + ipc/mq_sysctl.c | 125 +++++++++++++++++++++++++++++++++++++++++ ipc/mqueue.c | 65 +--------------------- 5 files changed, 147 insertions(+), 64 deletions(-) create mode 100644 ipc/mq_sysctl.c
include/linux/ipc_namespace.h +14 -0
@@ -121,4 +121,18 @@ static inline void put_ipc_ns(struct ipc_namespace *ns) { }#endif + +#ifdef CONFIG_POSIX_MQUEUE_SYSCTL + +struct ctl_table_header ; +extern struct ctl_table_header *mq_register_sysctl_table (void ); + +#else /* CONFIG_POSIX_MQUEUE_SYSCTL */ + +static inline struct ctl_table_header *mq_register_sysctl_table (void ) +{ +return NULL ; +} + +#endif /* CONFIG_POSIX_MQUEUE_SYSCTL */ #endif
init/Kconfig +6 -0
@@ -148,6 +148,12 @@ config POSIX_MQUEUE If unsure, say Y. +config POSIX_MQUEUE_SYSCTL + bool + depends on POSIX_MQUEUE + depends on SYSCTL + default y + config BSD_PROCESS_ACCT bool "BSD Process Accounting" help
ipc/Makefile +1 -0
@@ -8,4 +8,5 @@ obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o obj_mq-$(CONFIG_COMPAT) += compat_mq.o obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) obj-$(CONFIG_IPC_NS) += namespace.o +obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
ipc/mq_sysctl.c new file +125 -0
125 lines not on this page · raw message
ipc/mqueue.c +1 -64
83 lines not on this page · raw message
Signature · 1 line
1.5.4.3