diff options
author | Nadia Derbey <Nadia.Derbey@bull.net> | 2007-10-19 02:40:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:44 -0400 |
commit | 7ca7e564e049d8b350ec9d958ff25eaa24226352 (patch) | |
tree | e3c1397dc898dbd7c685c6a052425e7346eb79d1 /ipc/msg.c | |
parent | d2b20b11547cefc89d6c81937e81afaf3c62808b (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.c | 115 |
1 files changed, 70 insertions, 45 deletions
@@ -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 | ||
84 | static void freeque (struct ipc_namespace *ns, struct msg_queue *msq, int id); | 83 | static void freeque(struct ipc_namespace *, struct msg_queue *); |
85 | static int newque (struct ipc_namespace *ns, key_t key, int msgflg); | 84 | static int newque (struct ipc_namespace *ns, key_t key, int msgflg); |
86 | #ifdef CONFIG_PROC_FS | 85 | #ifdef CONFIG_PROC_FS |
87 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); | 86 | static 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 | ||
99 | int msg_init_ns(struct ipc_namespace *ns) | 98 | int msg_init_ns(struct ipc_namespace *ns) |
@@ -110,20 +109,24 @@ int msg_init_ns(struct ipc_namespace *ns) | |||
110 | 109 | ||
111 | void msg_exit_ns(struct ipc_namespace *ns) | 110 | void 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 | ||
142 | static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s) | ||
143 | { | ||
144 | ipc_rmid(&msg_ids(ns), &s->q_perm); | ||
145 | } | ||
146 | |||
139 | static int newque (struct ipc_namespace *ns, key_t key, int msgflg) | 147 | static 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 | ||
179 | static inline void ss_add(struct msg_queue *msq, struct msg_sender *mss) | 191 | static 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 | */ |
233 | static void freeque(struct ipc_namespace *ns, struct msg_queue *msq, int id) | 245 | static 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) | |||
255 | asmlinkage long sys_msgget(key_t key, int msgflg) | 267 | asmlinkage 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, |