diff options
author | Davidlohr Bueso <davidlohr@hp.com> | 2014-02-25 18:01:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-02-25 18:25:45 -0500 |
commit | f3713fd9cff733d9df83116422d8e4af6e86b2bb (patch) | |
tree | 58a1a64720424b7a4b32bc6d26ca23000c2ce414 | |
parent | 08088cb9ac0a9c28d4cf3efa4f6848a9b053ccfd (diff) |
ipc,mqueue: remove limits for the amount of system-wide queues
Commit 93e6f119c0ce ("ipc/mqueue: cleanup definition names and
locations") added global hardcoded limits to the amount of message
queues that can be created. While these limits are per-namespace,
reality is that it ends up breaking userspace applications.
Historically users have, at least in theory, been able to create up to
INT_MAX queues, and limiting it to just 1024 is way too low and dramatic
for some workloads and use cases. For instance, Madars reports:
"This update imposes bad limits on our multi-process application. As
our app uses approaches that each process opens its own set of queues
(usually something about 3-5 queues per process). In some scenarios
we might run up to 3000 processes or more (which of-course for linux
is not a problem). Thus we might need up to 9000 queues or more. All
processes run under one user."
Other affected users can be found in launchpad bug #1155695:
https://bugs.launchpad.net/ubuntu/+source/manpages/+bug/1155695
Instead of increasing this limit, revert it entirely and fallback to the
original way of dealing queue limits -- where once a user's resource
limit is reached, and all memory is used, new queues cannot be created.
Signed-off-by: Davidlohr Bueso <davidlohr@hp.com>
Reported-by: Madars Vitolins <m@silodev.com>
Acked-by: Doug Ledford <dledford@redhat.com>
Cc: Manfred Spraul <manfred@colorfullife.com>
Cc: <stable@vger.kernel.org> [3.5+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | include/linux/ipc_namespace.h | 2 | ||||
-rw-r--r-- | ipc/mq_sysctl.c | 18 | ||||
-rw-r--r-- | ipc/mqueue.c | 6 |
3 files changed, 15 insertions, 11 deletions
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index e7831d203737..35e7eca4e33b 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h | |||
@@ -118,9 +118,7 @@ extern int mq_init_ns(struct ipc_namespace *ns); | |||
118 | * the new maximum will handle anyone else. I may have to revisit this | 118 | * the new maximum will handle anyone else. I may have to revisit this |
119 | * in the future. | 119 | * in the future. |
120 | */ | 120 | */ |
121 | #define MIN_QUEUESMAX 1 | ||
122 | #define DFLT_QUEUESMAX 256 | 121 | #define DFLT_QUEUESMAX 256 |
123 | #define HARD_QUEUESMAX 1024 | ||
124 | #define MIN_MSGMAX 1 | 122 | #define MIN_MSGMAX 1 |
125 | #define DFLT_MSG 10U | 123 | #define DFLT_MSG 10U |
126 | #define DFLT_MSGMAX 10 | 124 | #define DFLT_MSGMAX 10 |
diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c index 383d638340b8..5bb8bfe67149 100644 --- a/ipc/mq_sysctl.c +++ b/ipc/mq_sysctl.c | |||
@@ -22,6 +22,16 @@ static void *get_mq(ctl_table *table) | |||
22 | return which; | 22 | return which; |
23 | } | 23 | } |
24 | 24 | ||
25 | static int proc_mq_dointvec(ctl_table *table, int write, | ||
26 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
27 | { | ||
28 | struct ctl_table mq_table; | ||
29 | memcpy(&mq_table, table, sizeof(mq_table)); | ||
30 | mq_table.data = get_mq(table); | ||
31 | |||
32 | return proc_dointvec(&mq_table, write, buffer, lenp, ppos); | ||
33 | } | ||
34 | |||
25 | static int proc_mq_dointvec_minmax(ctl_table *table, int write, | 35 | static int proc_mq_dointvec_minmax(ctl_table *table, int write, |
26 | void __user *buffer, size_t *lenp, loff_t *ppos) | 36 | void __user *buffer, size_t *lenp, loff_t *ppos) |
27 | { | 37 | { |
@@ -33,12 +43,10 @@ static int proc_mq_dointvec_minmax(ctl_table *table, int write, | |||
33 | lenp, ppos); | 43 | lenp, ppos); |
34 | } | 44 | } |
35 | #else | 45 | #else |
46 | #define proc_mq_dointvec NULL | ||
36 | #define proc_mq_dointvec_minmax NULL | 47 | #define proc_mq_dointvec_minmax NULL |
37 | #endif | 48 | #endif |
38 | 49 | ||
39 | static int msg_queues_limit_min = MIN_QUEUESMAX; | ||
40 | static int msg_queues_limit_max = HARD_QUEUESMAX; | ||
41 | |||
42 | static int msg_max_limit_min = MIN_MSGMAX; | 50 | static int msg_max_limit_min = MIN_MSGMAX; |
43 | static int msg_max_limit_max = HARD_MSGMAX; | 51 | static int msg_max_limit_max = HARD_MSGMAX; |
44 | 52 | ||
@@ -51,9 +59,7 @@ static ctl_table mq_sysctls[] = { | |||
51 | .data = &init_ipc_ns.mq_queues_max, | 59 | .data = &init_ipc_ns.mq_queues_max, |
52 | .maxlen = sizeof(int), | 60 | .maxlen = sizeof(int), |
53 | .mode = 0644, | 61 | .mode = 0644, |
54 | .proc_handler = proc_mq_dointvec_minmax, | 62 | .proc_handler = proc_mq_dointvec, |
55 | .extra1 = &msg_queues_limit_min, | ||
56 | .extra2 = &msg_queues_limit_max, | ||
57 | }, | 63 | }, |
58 | { | 64 | { |
59 | .procname = "msg_max", | 65 | .procname = "msg_max", |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index ccf1f9fd263a..c3b31179122c 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -433,9 +433,9 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry, | |||
433 | error = -EACCES; | 433 | error = -EACCES; |
434 | goto out_unlock; | 434 | goto out_unlock; |
435 | } | 435 | } |
436 | if (ipc_ns->mq_queues_count >= HARD_QUEUESMAX || | 436 | |
437 | (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max && | 437 | if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max && |
438 | !capable(CAP_SYS_RESOURCE))) { | 438 | !capable(CAP_SYS_RESOURCE)) { |
439 | error = -ENOSPC; | 439 | error = -ENOSPC; |
440 | goto out_unlock; | 440 | goto out_unlock; |
441 | } | 441 | } |