aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/msg.c
diff options
context:
space:
mode:
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}