diff options
author | Nadia Derbey <Nadia.Derbey@bull.net> | 2007-10-19 02:40:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-19 14:53:44 -0400 |
commit | 7748dbfaa010b12d5fb9ddf80199534c565c6bce (patch) | |
tree | c6756de4007c29fdcb405d54173a4322d48ff631 /ipc/util.c | |
parent | 7ca7e564e049d8b350ec9d958ff25eaa24226352 (diff) |
ipc: unify the syscalls code
This patch introduces a change into the sys_msgget(), sys_semget() and
sys_shmget() routines: they now share a common code, which is better for
maintainability.
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/util.c')
-rw-r--r-- | ipc/util.c | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/ipc/util.c b/ipc/util.c index 2a205875d277..03b88798f71f 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -197,7 +197,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header, | |||
197 | * If key is found ipc contains its ipc structure | 197 | * If key is found ipc contains its ipc structure |
198 | */ | 198 | */ |
199 | 199 | ||
200 | struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) | 200 | static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) |
201 | { | 201 | { |
202 | struct kern_ipc_perm *ipc; | 202 | struct kern_ipc_perm *ipc; |
203 | int next_id; | 203 | int next_id; |
@@ -301,6 +301,105 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | /** | 303 | /** |
304 | * ipcget_new - create a new ipc object | ||
305 | * @ns: namespace | ||
306 | * @ids: identifer set | ||
307 | * @ops: the actual creation routine to call | ||
308 | * @params: its parameters | ||
309 | * | ||
310 | * This routine is called sys_msgget, sys_semget() and sys_shmget() when | ||
311 | * the key is IPC_PRIVATE | ||
312 | */ | ||
313 | int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
314 | struct ipc_ops *ops, struct ipc_params *params) | ||
315 | { | ||
316 | int err; | ||
317 | |||
318 | err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); | ||
319 | |||
320 | if (!err) | ||
321 | return -ENOMEM; | ||
322 | |||
323 | mutex_lock(&ids->mutex); | ||
324 | err = ops->getnew(ns, params); | ||
325 | mutex_unlock(&ids->mutex); | ||
326 | |||
327 | return err; | ||
328 | } | ||
329 | |||
330 | /** | ||
331 | * ipc_check_perms - check security and permissions for an IPC | ||
332 | * @ipcp: ipc permission set | ||
333 | * @ids: identifer set | ||
334 | * @ops: the actual security routine to call | ||
335 | * @params: its parameters | ||
336 | */ | ||
337 | static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, | ||
338 | struct ipc_params *params) | ||
339 | { | ||
340 | int err; | ||
341 | |||
342 | if (ipcperms(ipcp, params->flg)) | ||
343 | err = -EACCES; | ||
344 | else { | ||
345 | err = ops->associate(ipcp, params->flg); | ||
346 | if (!err) | ||
347 | err = ipcp->id; | ||
348 | } | ||
349 | |||
350 | return err; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * ipcget_public - get an ipc object or create a new one | ||
355 | * @ns: namespace | ||
356 | * @ids: identifer set | ||
357 | * @ops: the actual creation routine to call | ||
358 | * @params: its parameters | ||
359 | * | ||
360 | * This routine is called sys_msgget, sys_semget() and sys_shmget() when | ||
361 | * the key is not IPC_PRIVATE | ||
362 | */ | ||
363 | int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
364 | struct ipc_ops *ops, struct ipc_params *params) | ||
365 | { | ||
366 | struct kern_ipc_perm *ipcp; | ||
367 | int flg = params->flg; | ||
368 | int err; | ||
369 | |||
370 | err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); | ||
371 | |||
372 | mutex_lock(&ids->mutex); | ||
373 | ipcp = ipc_findkey(ids, params->key); | ||
374 | if (ipcp == NULL) { | ||
375 | /* key not used */ | ||
376 | if (!(flg & IPC_CREAT)) | ||
377 | err = -ENOENT; | ||
378 | else if (!err) | ||
379 | err = -ENOMEM; | ||
380 | else | ||
381 | err = ops->getnew(ns, params); | ||
382 | } else { | ||
383 | /* ipc object has been locked by ipc_findkey() */ | ||
384 | |||
385 | if (flg & IPC_CREAT && flg & IPC_EXCL) | ||
386 | err = -EEXIST; | ||
387 | else { | ||
388 | err = 0; | ||
389 | if (ops->more_checks) | ||
390 | err = ops->more_checks(ipcp, params); | ||
391 | if (!err) | ||
392 | err = ipc_check_perms(ipcp, ops, params); | ||
393 | } | ||
394 | ipc_unlock(ipcp); | ||
395 | } | ||
396 | mutex_unlock(&ids->mutex); | ||
397 | |||
398 | return err; | ||
399 | } | ||
400 | |||
401 | |||
402 | /** | ||
304 | * ipc_rmid - remove an IPC identifier | 403 | * ipc_rmid - remove an IPC identifier |
305 | * @ids: identifier set | 404 | * @ids: identifier set |
306 | * @id: ipc perm structure containing the identifier to remove | 405 | * @id: ipc perm structure containing the identifier to remove |