aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/msg.c
diff options
context:
space:
mode:
authorNadia Derbey <Nadia.Derbey@bull.net>2007-10-19 02:40:48 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-19 14:53:44 -0400
commit7ca7e564e049d8b350ec9d958ff25eaa24226352 (patch)
treee3c1397dc898dbd7c685c6a052425e7346eb79d1 /ipc/msg.c
parentd2b20b11547cefc89d6c81937e81afaf3c62808b (diff)
ipc: store ipcs into IDRs
This patch introduces ipcs storage into IDRs. The main changes are: . This ipc_ids structure is changed: the entries array is changed into a root idr structure. . The grow_ary() routine is removed: it is not needed anymore when adding an ipc structure, since we are now using the IDR facility. . The ipc_rmid() routine interface is changed: . there is no need for this routine to return the pointer passed in as argument: it is now declared as a void . since the id is now part of the kern_ipc_perm structure, no need to have it as an argument to the routine Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/msg.c')
-rw-r--r--ipc/msg.c115
1 files changed, 70 insertions, 45 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index 319468609b76..08591a0278ce 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -75,13 +75,12 @@ static struct ipc_ids init_msg_ids;
75 75
76#define msg_lock(ns, id) ((struct msg_queue*)ipc_lock(&msg_ids(ns), id)) 76#define msg_lock(ns, id) ((struct msg_queue*)ipc_lock(&msg_ids(ns), id))
77#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm) 77#define msg_unlock(msq) ipc_unlock(&(msq)->q_perm)
78#define msg_rmid(ns, id) ((struct msg_queue*)ipc_rmid(&msg_ids(ns), id))
79#define msg_checkid(ns, msq, msgid) \ 78#define msg_checkid(ns, msq, msgid) \
80 ipc_checkid(&msg_ids(ns), &msq->q_perm, msgid) 79 ipc_checkid(&msg_ids(ns), &msq->q_perm, msgid)
81#define msg_buildid(ns, id, seq) \ 80#define msg_buildid(ns, id, seq) \
82 ipc_buildid(&msg_ids(ns), id, seq) 81 ipc_buildid(&msg_ids(ns), id, seq)
83 82
84static void freeque (struct ipc_namespace *ns, struct msg_queue *msq, int id); 83static void freeque(struct ipc_namespace *, struct msg_queue *);
85static int newque (struct ipc_namespace *ns, key_t key, int msgflg); 84static int newque (struct ipc_namespace *ns, key_t key, int msgflg);
86#ifdef CONFIG_PROC_FS 85#ifdef CONFIG_PROC_FS
87static int sysvipc_msg_proc_show(struct seq_file *s, void *it); 86static int sysvipc_msg_proc_show(struct seq_file *s, void *it);
@@ -93,7 +92,7 @@ static void __msg_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
93 ns->msg_ctlmax = MSGMAX; 92 ns->msg_ctlmax = MSGMAX;
94 ns->msg_ctlmnb = MSGMNB; 93 ns->msg_ctlmnb = MSGMNB;
95 ns->msg_ctlmni = MSGMNI; 94 ns->msg_ctlmni = MSGMNI;
96 ipc_init_ids(ids, ns->msg_ctlmni); 95 ipc_init_ids(ids);
97} 96}
98 97
99int msg_init_ns(struct ipc_namespace *ns) 98int msg_init_ns(struct ipc_namespace *ns)
@@ -110,20 +109,24 @@ int msg_init_ns(struct ipc_namespace *ns)
110 109
111void msg_exit_ns(struct ipc_namespace *ns) 110void msg_exit_ns(struct ipc_namespace *ns)
112{ 111{
113 int i;
114 struct msg_queue *msq; 112 struct msg_queue *msq;
113 int next_id;
114 int total, in_use;
115 115
116 mutex_lock(&msg_ids(ns).mutex); 116 mutex_lock(&msg_ids(ns).mutex);
117 for (i = 0; i <= msg_ids(ns).max_id; i++) { 117
118 msq = msg_lock(ns, i); 118 in_use = msg_ids(ns).in_use;
119
120 for (total = 0, next_id = 0; total < in_use; next_id++) {
121 msq = idr_find(&msg_ids(ns).ipcs_idr, next_id);
119 if (msq == NULL) 122 if (msq == NULL)
120 continue; 123 continue;
121 124 ipc_lock_by_ptr(&msq->q_perm);
122 freeque(ns, msq, i); 125 freeque(ns, msq);
126 total++;
123 } 127 }
124 mutex_unlock(&msg_ids(ns).mutex); 128 mutex_unlock(&msg_ids(ns).mutex);
125 129
126 ipc_fini_ids(ns->ids[IPC_MSG_IDS]);
127 kfree(ns->ids[IPC_MSG_IDS]); 130 kfree(ns->ids[IPC_MSG_IDS]);
128 ns->ids[IPC_MSG_IDS] = NULL; 131 ns->ids[IPC_MSG_IDS] = NULL;
129} 132}
@@ -136,6 +139,11 @@ void __init msg_init(void)
136 IPC_MSG_IDS, sysvipc_msg_proc_show); 139 IPC_MSG_IDS, sysvipc_msg_proc_show);
137} 140}
138 141
142static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
143{
144 ipc_rmid(&msg_ids(ns), &s->q_perm);
145}
146
139static int newque (struct ipc_namespace *ns, key_t key, int msgflg) 147static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
140{ 148{
141 struct msg_queue *msq; 149 struct msg_queue *msq;
@@ -155,6 +163,9 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
155 return retval; 163 return retval;
156 } 164 }
157 165
166 /*
167 * ipc_addid() locks msq
168 */
158 id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); 169 id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni);
159 if (id == -1) { 170 if (id == -1) {
160 security_msg_queue_free(msq); 171 security_msg_queue_free(msq);
@@ -162,7 +173,7 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
162 return -ENOSPC; 173 return -ENOSPC;
163 } 174 }
164 175
165 msq->q_id = msg_buildid(ns, id, msq->q_perm.seq); 176 msq->q_perm.id = msg_buildid(ns, id, msq->q_perm.seq);
166 msq->q_stime = msq->q_rtime = 0; 177 msq->q_stime = msq->q_rtime = 0;
167 msq->q_ctime = get_seconds(); 178 msq->q_ctime = get_seconds();
168 msq->q_cbytes = msq->q_qnum = 0; 179 msq->q_cbytes = msq->q_qnum = 0;
@@ -171,9 +182,10 @@ static int newque (struct ipc_namespace *ns, key_t key, int msgflg)
171 INIT_LIST_HEAD(&msq->q_messages); 182 INIT_LIST_HEAD(&msq->q_messages);
172 INIT_LIST_HEAD(&msq->q_receivers); 183 INIT_LIST_HEAD(&msq->q_receivers);
173 INIT_LIST_HEAD(&msq->q_senders); 184 INIT_LIST_HEAD(&msq->q_senders);
185
174 msg_unlock(msq); 186 msg_unlock(msq);
175 187
176 return msq->q_id; 188 return msq->q_perm.id;
177} 189}
178 190
179static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss) 191static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss)
@@ -225,18 +237,18 @@ static void expunge_all(struct msg_queue *msq, int res)
225/* 237/*
226 * freeque() wakes up waiters on the sender and receiver waiting queue, 238 * freeque() wakes up waiters on the sender and receiver waiting queue,
227 * removes the message queue from message queue ID 239 * removes the message queue from message queue ID
228 * array, and cleans up all the messages associated with this queue. 240 * IDR, and cleans up all the messages associated with this queue.
229 * 241 *
230 * msg_ids.mutex and the spinlock for this message queue is hold 242 * msg_ids.mutex and the spinlock for this message queue are held
231 * before freeque() is called. msg_ids.mutex remains locked on exit. 243 * before freeque() is called. msg_ids.mutex remains locked on exit.
232 */ 244 */
233static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id) 245static void freeque(struct ipc_namespace *ns, struct msg_queue *msq)
234{ 246{
235 struct list_head *tmp; 247 struct list_head *tmp;
236 248
237 expunge_all(msq, -EIDRM); 249 expunge_all(msq, -EIDRM);
238 ss_wakeup(&msq->q_senders, 1); 250 ss_wakeup(&msq->q_senders, 1);
239 msq = msg_rmid(ns, id); 251 msg_rmid(ns, msq);
240 msg_unlock(msq); 252 msg_unlock(msq);
241 253
242 tmp = msq->q_messages.next; 254 tmp = msq->q_messages.next;
@@ -255,36 +267,51 @@ static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id)
255asmlinkage long sys_msgget(key_t key, int msgflg) 267asmlinkage long sys_msgget(key_t key, int msgflg)
256{ 268{
257 struct msg_queue *msq; 269 struct msg_queue *msq;
258 int id, ret = -EPERM; 270 int ret;
259 struct ipc_namespace *ns; 271 struct ipc_namespace *ns;
260 272
261 ns = current->nsproxy->ipc_ns; 273 ns = current->nsproxy->ipc_ns;
262 274
263 mutex_lock(&msg_ids(ns).mutex); 275 ret = idr_pre_get(&msg_ids(ns).ipcs_idr, GFP_KERNEL);
264 if (key == IPC_PRIVATE) 276
265 ret = newque(ns, key, msgflg); 277 if (key == IPC_PRIVATE) {
266 else if ((id = ipc_findkey(&msg_ids(ns), key)) == -1) { /* key not used */ 278 if (!ret)
267 if (!(msgflg & IPC_CREAT)) 279 ret = -ENOMEM;
268 ret = -ENOENT; 280 else {
269 else 281 mutex_lock(&msg_ids(ns).mutex);
270 ret = newque(ns, key, msgflg); 282 ret = newque(ns, key, msgflg);
271 } else if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) { 283 mutex_unlock(&msg_ids(ns).mutex);
272 ret = -EEXIST; 284 }
273 } else { 285 } else {
274 msq = msg_lock(ns, id); 286 mutex_lock(&msg_ids(ns).mutex);
275 BUG_ON(msq == NULL); 287 msq = (struct msg_queue *) ipc_findkey(&msg_ids(ns), key);
276 if (ipcperms(&msq->q_perm, msgflg)) 288 if (msq == NULL) {
277 ret = -EACCES; 289 /* key not used */
278 else { 290 if (!(msgflg & IPC_CREAT))
279 int qid = msg_buildid(ns, id, msq->q_perm.seq); 291 ret = -ENOENT;
280 292 else if (!ret)
281 ret = security_msg_queue_associate(msq, msgflg); 293 ret = -ENOMEM;
282 if (!ret) 294 else
283 ret = qid; 295 ret = newque(ns, key, msgflg);
296 } else {
297 /* msq has been locked by ipc_findkey() */
298
299 if (msgflg & IPC_CREAT && msgflg & IPC_EXCL)
300 ret = -EEXIST;
301 else {
302 if (ipcperms(&msq->q_perm, msgflg))
303 ret = -EACCES;
304 else {
305 ret = security_msg_queue_associate(
306 msq, msgflg);
307 if (!ret)
308 ret = msq->q_perm.id;
309 }
310 }
311 msg_unlock(msq);
284 } 312 }
285 msg_unlock(msq); 313 mutex_unlock(&msg_ids(ns).mutex);
286 } 314 }
287 mutex_unlock(&msg_ids(ns).mutex);
288 315
289 return ret; 316 return ret;
290} 317}
@@ -430,13 +457,13 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
430 msginfo.msgpool = MSGPOOL; 457 msginfo.msgpool = MSGPOOL;
431 msginfo.msgtql = MSGTQL; 458 msginfo.msgtql = MSGTQL;
432 } 459 }
433 max_id = msg_ids(ns).max_id; 460 max_id = ipc_get_maxid(&msg_ids(ns));
434 mutex_unlock(&msg_ids(ns).mutex); 461 mutex_unlock(&msg_ids(ns).mutex);
435 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo))) 462 if (copy_to_user(buf, &msginfo, sizeof(struct msginfo)))
436 return -EFAULT; 463 return -EFAULT;
437 return (max_id < 0) ? 0 : max_id; 464 return (max_id < 0) ? 0 : max_id;
438 } 465 }
439 case MSG_STAT: 466 case MSG_STAT: /* msqid is an index rather than a msg queue id */
440 case IPC_STAT: 467 case IPC_STAT:
441 { 468 {
442 struct msqid64_ds tbuf; 469 struct msqid64_ds tbuf;
@@ -444,8 +471,6 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
444 471
445 if (!buf) 472 if (!buf)
446 return -EFAULT; 473 return -EFAULT;
447 if (cmd == MSG_STAT && msqid >= msg_ids(ns).entries->size)
448 return -EINVAL;
449 474
450 memset(&tbuf, 0, sizeof(tbuf)); 475 memset(&tbuf, 0, sizeof(tbuf));
451 476
@@ -454,7 +479,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
454 return -EINVAL; 479 return -EINVAL;
455 480
456 if (cmd == MSG_STAT) { 481 if (cmd == MSG_STAT) {
457 success_return = msg_buildid(ns, msqid, msq->q_perm.seq); 482 success_return = msq->q_perm.id;
458 } else { 483 } else {
459 err = -EIDRM; 484 err = -EIDRM;
460 if (msg_checkid(ns, msq, msqid)) 485 if (msg_checkid(ns, msq, msqid))
@@ -552,7 +577,7 @@ asmlinkage long sys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf)
552 break; 577 break;
553 } 578 }
554 case IPC_RMID: 579 case IPC_RMID:
555 freeque(ns, msq, msqid); 580 freeque(ns, msq);
556 break; 581 break;
557 } 582 }
558 err = 0; 583 err = 0;
@@ -926,7 +951,7 @@ static int sysvipc_msg_proc_show(struct seq_file *s, void *it)
926 return seq_printf(s, 951 return seq_printf(s,
927 "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n", 952 "%10d %10d %4o %10lu %10lu %5u %5u %5u %5u %5u %5u %10lu %10lu %10lu\n",
928 msq->q_perm.key, 953 msq->q_perm.key,
929 msq->q_id, 954 msq->q_perm.id,
930 msq->q_perm.mode, 955 msq->q_perm.mode,
931 msq->q_cbytes, 956 msq->q_cbytes,
932 msq->q_qnum, 957 msq->q_qnum,