aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/msg.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-06 19:35:10 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-06 19:35:10 -0400
commit57d326169e878a1a37b2bccd1cf81f6809ee67b9 (patch)
tree86ed74ae4dc2beaebce1c67b8459f1873b777d3a /ipc/msg.c
parent7b215de3d0abbc4f6daf2efd19e8809af0564490 (diff)
parent0244756edc4b98c129e92c7061d9f383708cf786 (diff)
Merge branch 'akpm' (patches from Andrew Morton) into next
Merge more updates from Andrew Morton: - Most of the rest of MM. This includes "mark remap_file_pages syscall as deprecated" but the actual "replace remap_file_pages syscall with emulation" is held back. I guess we'll need to work out when to pull the trigger on that one. - various minor cleanups to obscure filesystems - the drivers/rtc queue - hfsplus updates - ufs, hpfs, fatfs, affs, reiserfs - Documentation/ - signals - procfs - cpu hotplug - lib/idr.c - rapidio - sysctl - ipc updates * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (171 commits) ufs: sb mutex merge + mutex_destroy powerpc: update comments for generic idle conversion cris: update comments for generic idle conversion idle: remove cpu_idle() forward declarations nbd: zero from and len fields in NBD_CMD_DISCONNECT. mm: convert some level-less printks to pr_* MAINTAINERS: adi-buildroot-devel is moderated MAINTAINERS: add linux-api for review of API/ABI changes mm/kmemleak-test.c: use pr_fmt for logging fs/dlm/debug_fs.c: replace seq_printf by seq_puts fs/dlm/lockspace.c: convert simple_str to kstr fs/dlm/config.c: convert simple_str to kstr mm: mark remap_file_pages() syscall as deprecated mm: memcontrol: remove unnecessary memcg argument from soft limit functions mm: memcontrol: clean up memcg zoneinfo lookup mm/memblock.c: call kmemleak directly from memblock_(alloc|free) mm/mempool.c: update the kmemleak stack trace for mempool allocations lib/radix-tree.c: update the kmemleak stack trace for radix tree allocations mm: introduce kmemleak_update_trace() mm/kmemleak.c: use %u to print ->checksum ...
Diffstat (limited to 'ipc/msg.c')
-rw-r--r--ipc/msg.c188
1 files changed, 92 insertions, 96 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index 649853105a5d..c5d8e3749985 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -39,12 +39,10 @@
39#include <linux/ipc_namespace.h> 39#include <linux/ipc_namespace.h>
40 40
41#include <asm/current.h> 41#include <asm/current.h>
42#include <asm/uaccess.h> 42#include <linux/uaccess.h>
43#include "util.h" 43#include "util.h"
44 44
45/* 45/* one msg_receiver structure for each sleeping receiver */
46 * one msg_receiver structure for each sleeping receiver:
47 */
48struct msg_receiver { 46struct msg_receiver {
49 struct list_head r_list; 47 struct list_head r_list;
50 struct task_struct *r_tsk; 48 struct task_struct *r_tsk;
@@ -53,6 +51,12 @@ struct msg_receiver {
53 long r_msgtype; 51 long r_msgtype;
54 long r_maxsize; 52 long r_maxsize;
55 53
54 /*
55 * Mark r_msg volatile so that the compiler
56 * does not try to get smart and optimize
57 * it. We rely on this for the lockless
58 * receive algorithm.
59 */
56 struct msg_msg *volatile r_msg; 60 struct msg_msg *volatile r_msg;
57}; 61};
58 62
@@ -70,75 +74,6 @@ struct msg_sender {
70 74
71#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS]) 75#define msg_ids(ns) ((ns)->ids[IPC_MSG_IDS])
72 76
73static void freeque(struct ipc_namespace *, struct kern_ipc_perm *);
74static int newque(struct ipc_namespace *, struct ipc_params *);
75#ifdef CONFIG_PROC_FS
76static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
77#endif
78
79/*
80 * Scale msgmni with the available lowmem size: the memory dedicated to msg
81 * queues should occupy at most 1/MSG_MEM_SCALE of lowmem.
82 * Also take into account the number of nsproxies created so far.
83 * This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range.
84 */
85void recompute_msgmni(struct ipc_namespace *ns)
86{
87 struct sysinfo i;
88 unsigned long allowed;
89 int nb_ns;
90
91 si_meminfo(&i);
92 allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit)
93 / MSGMNB;
94 nb_ns = atomic_read(&nr_ipc_ns);
95 allowed /= nb_ns;
96
97 if (allowed < MSGMNI) {
98 ns->msg_ctlmni = MSGMNI;
99 return;
100 }
101
102 if (allowed > IPCMNI / nb_ns) {
103 ns->msg_ctlmni = IPCMNI / nb_ns;
104 return;
105 }
106
107 ns->msg_ctlmni = allowed;
108}
109
110void msg_init_ns(struct ipc_namespace *ns)
111{
112 ns->msg_ctlmax = MSGMAX;
113 ns->msg_ctlmnb = MSGMNB;
114
115 recompute_msgmni(ns);
116
117 atomic_set(&ns->msg_bytes, 0);
118 atomic_set(&ns->msg_hdrs, 0);
119 ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
120}
121
122#ifdef CONFIG_IPC_NS
123void msg_exit_ns(struct ipc_namespace *ns)
124{
125 free_ipcs(ns, &msg_ids(ns), freeque);
126 idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr);
127}
128#endif
129
130void __init msg_init(void)
131{
132 msg_init_ns(&init_ipc_ns);
133
134 printk(KERN_INFO "msgmni has been set to %d\n",
135 init_ipc_ns.msg_ctlmni);
136
137 ipc_init_proc_interface("sysvipc/msg",
138 " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
139 IPC_MSG_IDS, sysvipc_msg_proc_show);
140}
141
142static inline struct msg_queue *msq_obtain_object(struct ipc_namespace *ns, int id) 77static inline struct msg_queue *msq_obtain_object(struct ipc_namespace *ns, int id)
143{ 78{
144 struct kern_ipc_perm *ipcp = ipc_obtain_object(&msg_ids(ns), id); 79 struct kern_ipc_perm *ipcp = ipc_obtain_object(&msg_ids(ns), id);
@@ -227,7 +162,7 @@ static int newque(struct ipc_namespace *ns, struct ipc_params *params)
227static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss) 162static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
228{ 163{
229 mss->tsk = current; 164 mss->tsk = current;
230 current->state = TASK_INTERRUPTIBLE; 165 __set_current_state(TASK_INTERRUPTIBLE);
231 list_add_tail(&mss->list, &msq->q_senders); 166 list_add_tail(&mss->list, &msq->q_senders);
232} 167}
233 168
@@ -306,15 +241,14 @@ static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
306SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg) 241SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg)
307{ 242{
308 struct ipc_namespace *ns; 243 struct ipc_namespace *ns;
309 struct ipc_ops msg_ops; 244 static const struct ipc_ops msg_ops = {
245 .getnew = newque,
246 .associate = msg_security,
247 };
310 struct ipc_params msg_params; 248 struct ipc_params msg_params;
311 249
312 ns = current->nsproxy->ipc_ns; 250 ns = current->nsproxy->ipc_ns;
313 251
314 msg_ops.getnew = newque;
315 msg_ops.associate = msg_security;
316 msg_ops.more_checks = NULL;
317
318 msg_params.key = key; 252 msg_params.key = key;
319 msg_params.flg = msgflg; 253 msg_params.flg = msgflg;
320 254
@@ -612,23 +546,22 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
612 546
613static int testmsg(struct msg_msg *msg, long type, int mode) 547static int testmsg(struct msg_msg *msg, long type, int mode)
614{ 548{
615 switch (mode) 549 switch (mode) {
616 { 550 case SEARCH_ANY:
617 case SEARCH_ANY: 551 case SEARCH_NUMBER:
618 case SEARCH_NUMBER: 552 return 1;
553 case SEARCH_LESSEQUAL:
554 if (msg->m_type <= type)
619 return 1; 555 return 1;
620 case SEARCH_LESSEQUAL: 556 break;
621 if (msg->m_type <= type) 557 case SEARCH_EQUAL:
622 return 1; 558 if (msg->m_type == type)
623 break; 559 return 1;
624 case SEARCH_EQUAL: 560 break;
625 if (msg->m_type == type) 561 case SEARCH_NOTEQUAL:
626 return 1; 562 if (msg->m_type != type)
627 break; 563 return 1;
628 case SEARCH_NOTEQUAL: 564 break;
629 if (msg->m_type != type)
630 return 1;
631 break;
632 } 565 }
633 return 0; 566 return 0;
634} 567}
@@ -978,7 +911,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
978 else 911 else
979 msr_d.r_maxsize = bufsz; 912 msr_d.r_maxsize = bufsz;
980 msr_d.r_msg = ERR_PTR(-EAGAIN); 913 msr_d.r_msg = ERR_PTR(-EAGAIN);
981 current->state = TASK_INTERRUPTIBLE; 914 __set_current_state(TASK_INTERRUPTIBLE);
982 915
983 ipc_unlock_object(&msq->q_perm); 916 ipc_unlock_object(&msq->q_perm);
984 rcu_read_unlock(); 917 rcu_read_unlock();
@@ -1056,6 +989,57 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
1056 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); 989 return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
1057} 990}
1058 991
992/*
993 * Scale msgmni with the available lowmem size: the memory dedicated to msg
994 * queues should occupy at most 1/MSG_MEM_SCALE of lowmem.
995 * Also take into account the number of nsproxies created so far.
996 * This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range.
997 */
998void recompute_msgmni(struct ipc_namespace *ns)
999{
1000 struct sysinfo i;
1001 unsigned long allowed;
1002 int nb_ns;
1003
1004 si_meminfo(&i);
1005 allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit)
1006 / MSGMNB;
1007 nb_ns = atomic_read(&nr_ipc_ns);
1008 allowed /= nb_ns;
1009
1010 if (allowed < MSGMNI) {
1011 ns->msg_ctlmni = MSGMNI;
1012 return;
1013 }
1014
1015 if (allowed > IPCMNI / nb_ns) {
1016 ns->msg_ctlmni = IPCMNI / nb_ns;
1017 return;
1018 }
1019
1020 ns->msg_ctlmni = allowed;
1021}
1022
1023void msg_init_ns(struct ipc_namespace *ns)
1024{
1025 ns->msg_ctlmax = MSGMAX;
1026 ns->msg_ctlmnb = MSGMNB;
1027
1028 recompute_msgmni(ns);
1029
1030 atomic_set(&ns->msg_bytes, 0);
1031 atomic_set(&ns->msg_hdrs, 0);
1032 ipc_init_ids(&ns->ids[IPC_MSG_IDS]);
1033}
1034
1035#ifdef CONFIG_IPC_NS
1036void msg_exit_ns(struct ipc_namespace *ns)
1037{
1038 free_ipcs(ns, &msg_ids(ns), freeque);
1039 idr_destroy(&ns->ids[IPC_MSG_IDS].ipcs_idr);
1040}
1041#endif
1042
1059#ifdef CONFIG_PROC_FS 1043#ifdef CONFIG_PROC_FS
1060static int sysvipc_msg_proc_show(struct seq_file *s, void *it) 1044static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
1061{ 1045{
@@ -1080,3 +1064,15 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
1080 msq->q_ctime); 1064 msq->q_ctime);
1081} 1065}
1082#endif 1066#endif
1067
1068void __init msg_init(void)
1069{
1070 msg_init_ns(&init_ipc_ns);
1071
1072 printk(KERN_INFO "msgmni has been set to %d\n",
1073 init_ipc_ns.msg_ctlmni);
1074
1075 ipc_init_proc_interface("sysvipc/msg",
1076 " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
1077 IPC_MSG_IDS, sysvipc_msg_proc_show);
1078}