summaryrefslogtreecommitdiffstats
path: root/ipc/mqueue.c
diff options
context:
space:
mode:
authorDoug Ledford <dledford@redhat.com>2012-06-01 01:26:30 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 02:49:30 +0200
commit5b5c4d1a1440e94994c73dddbad7be0676cd8b9a (patch)
treefe00ef0f888fbfc40b7542fd8a66cf3368d3d2c7 /ipc/mqueue.c
parentipc/mqueue: enforce hard limits (diff)
downloadlinux-5b5c4d1a1440e94994c73dddbad7be0676cd8b9a.tar.xz
linux-5b5c4d1a1440e94994c73dddbad7be0676cd8b9a.zip
ipc/mqueue: update maximums for the mqueue subsystem
Commit b231cca4381e ("message queues: increase range limits") changed the maximum size of a message in a message queue from INT_MAX to 8192*128. Unfortunately, we had customers that relied on a size much larger than 8192*128 on their production systems. After reviewing POSIX, we found that it is silent on the maximum message size. We did find a couple other areas in which it was not silent. Fix up the mqueue maximums so that the customer's system can continue to work, and document both the POSIX and real world requirements in ipc_namespace.h so that we don't have this issue crop back up. Also, commit 9cf18e1dd74cd0 ("ipc: HARD_MSGMAX should be higher not lower on 64bit") fiddled with HARD_MSGMAX without realizing that the number was intentionally in place to limit the msg queue depth to one that was small enough to kmalloc an array of pointers (hence why we divided 128k by sizeof(long)). If we wish to meet POSIX requirements, we have no choice but to change our allocation to a vmalloc instead (at least for the large queue size case). With that, it's possible to increase our allowed maximum to the POSIX requirements (or more if we choose). [sfr@canb.auug.org.au: using vmalloc requires including vmalloc.h] Signed-off-by: Doug Ledford <dledford@redhat.com> Cc: Serge E. Hallyn <serue@us.ibm.com> Cc: Amerigo Wang <amwang@redhat.com> Cc: Joe Korty <joe.korty@ccur.com> Cc: Jiri Slaby <jslaby@suse.cz> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Manfred Spraul <manfred@colorfullife.com> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r--ipc/mqueue.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 6e10a55a78c5..f8eba5e46c5a 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -24,6 +24,7 @@
#include <linux/mqueue.h>
#include <linux/msg.h>
#include <linux/skbuff.h>
+#include <linux/vmalloc.h>
#include <linux/netlink.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
@@ -152,7 +153,10 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
info->attr.mq_msgsize = attr->mq_msgsize;
}
mq_msg_tblsz = info->attr.mq_maxmsg * sizeof(struct msg_msg *);
- info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
+ if (mq_msg_tblsz > KMALLOC_MAX_SIZE)
+ info->messages = vmalloc(mq_msg_tblsz);
+ else
+ info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
if (!info->messages)
goto out_inode;
@@ -262,7 +266,10 @@ static void mqueue_evict_inode(struct inode *inode)
spin_lock(&info->lock);
for (i = 0; i < info->attr.mq_curmsgs; i++)
free_msg(info->messages[i]);
- kfree(info->messages);
+ if (info->attr.mq_maxmsg * sizeof(struct msg_msg *) > KMALLOC_MAX_SIZE)
+ vfree(info->messages);
+ else
+ kfree(info->messages);
spin_unlock(&info->lock);
/* Total amount of bytes accounted for the mqueue */