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/shm.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/shm.c')
-rw-r--r-- | ipc/shm.c | 116 |
1 files changed, 69 insertions, 47 deletions
@@ -84,7 +84,7 @@ static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids) | |||
84 | ns->shm_ctlall = SHMALL; | 84 | ns->shm_ctlall = SHMALL; |
85 | ns->shm_ctlmni = SHMMNI; | 85 | ns->shm_ctlmni = SHMMNI; |
86 | ns->shm_tot = 0; | 86 | ns->shm_tot = 0; |
87 | ipc_init_ids(ids, 1); | 87 | ipc_init_ids(ids); |
88 | } | 88 | } |
89 | 89 | ||
90 | static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) | 90 | static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) |
@@ -112,20 +112,24 @@ int shm_init_ns(struct ipc_namespace *ns) | |||
112 | 112 | ||
113 | void shm_exit_ns(struct ipc_namespace *ns) | 113 | void shm_exit_ns(struct ipc_namespace *ns) |
114 | { | 114 | { |
115 | int i; | ||
116 | struct shmid_kernel *shp; | 115 | struct shmid_kernel *shp; |
116 | int next_id; | ||
117 | int total, in_use; | ||
117 | 118 | ||
118 | mutex_lock(&shm_ids(ns).mutex); | 119 | mutex_lock(&shm_ids(ns).mutex); |
119 | for (i = 0; i <= shm_ids(ns).max_id; i++) { | 120 | |
120 | shp = shm_lock(ns, i); | 121 | in_use = shm_ids(ns).in_use; |
122 | |||
123 | for (total = 0, next_id = 0; total < in_use; next_id++) { | ||
124 | shp = idr_find(&shm_ids(ns).ipcs_idr, next_id); | ||
121 | if (shp == NULL) | 125 | if (shp == NULL) |
122 | continue; | 126 | continue; |
123 | 127 | ipc_lock_by_ptr(&shp->shm_perm); | |
124 | do_shm_rmid(ns, shp); | 128 | do_shm_rmid(ns, shp); |
129 | total++; | ||
125 | } | 130 | } |
126 | mutex_unlock(&shm_ids(ns).mutex); | 131 | mutex_unlock(&shm_ids(ns).mutex); |
127 | 132 | ||
128 | ipc_fini_ids(ns->ids[IPC_SHM_IDS]); | ||
129 | kfree(ns->ids[IPC_SHM_IDS]); | 133 | kfree(ns->ids[IPC_SHM_IDS]); |
130 | ns->ids[IPC_SHM_IDS] = NULL; | 134 | ns->ids[IPC_SHM_IDS] = NULL; |
131 | } | 135 | } |
@@ -146,9 +150,9 @@ static inline int shm_checkid(struct ipc_namespace *ns, | |||
146 | return 0; | 150 | return 0; |
147 | } | 151 | } |
148 | 152 | ||
149 | static inline struct shmid_kernel *shm_rmid(struct ipc_namespace *ns, int id) | 153 | static inline void shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *s) |
150 | { | 154 | { |
151 | return (struct shmid_kernel *)ipc_rmid(&shm_ids(ns), id); | 155 | ipc_rmid(&shm_ids(ns), &s->shm_perm); |
152 | } | 156 | } |
153 | 157 | ||
154 | static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp) | 158 | static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp) |
@@ -184,7 +188,7 @@ static void shm_open(struct vm_area_struct *vma) | |||
184 | static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) | 188 | static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) |
185 | { | 189 | { |
186 | ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; | 190 | ns->shm_tot -= (shp->shm_segsz + PAGE_SIZE - 1) >> PAGE_SHIFT; |
187 | shm_rmid(ns, shp->id); | 191 | shm_rmid(ns, shp); |
188 | shm_unlock(shp); | 192 | shm_unlock(shp); |
189 | if (!is_file_hugepages(shp->shm_file)) | 193 | if (!is_file_hugepages(shp->shm_file)) |
190 | shmem_lock(shp->shm_file, 0, shp->mlock_user); | 194 | shmem_lock(shp->shm_file, 0, shp->mlock_user); |
@@ -398,17 +402,18 @@ static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size) | |||
398 | shp->shm_ctim = get_seconds(); | 402 | shp->shm_ctim = get_seconds(); |
399 | shp->shm_segsz = size; | 403 | shp->shm_segsz = size; |
400 | shp->shm_nattch = 0; | 404 | shp->shm_nattch = 0; |
401 | shp->id = shm_buildid(ns, id, shp->shm_perm.seq); | 405 | shp->shm_perm.id = shm_buildid(ns, id, shp->shm_perm.seq); |
402 | shp->shm_file = file; | 406 | shp->shm_file = file; |
403 | /* | 407 | /* |
404 | * shmid gets reported as "inode#" in /proc/pid/maps. | 408 | * shmid gets reported as "inode#" in /proc/pid/maps. |
405 | * proc-ps tools use this. Changing this will break them. | 409 | * proc-ps tools use this. Changing this will break them. |
406 | */ | 410 | */ |
407 | file->f_dentry->d_inode->i_ino = shp->id; | 411 | file->f_dentry->d_inode->i_ino = shp->shm_perm.id; |
408 | 412 | ||
409 | ns->shm_tot += numpages; | 413 | ns->shm_tot += numpages; |
414 | error = shp->shm_perm.id; | ||
410 | shm_unlock(shp); | 415 | shm_unlock(shp); |
411 | return shp->id; | 416 | return error; |
412 | 417 | ||
413 | no_id: | 418 | no_id: |
414 | fput(file); | 419 | fput(file); |
@@ -421,37 +426,52 @@ no_file: | |||
421 | asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) | 426 | asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) |
422 | { | 427 | { |
423 | struct shmid_kernel *shp; | 428 | struct shmid_kernel *shp; |
424 | int err, id = 0; | 429 | int err; |
425 | struct ipc_namespace *ns; | 430 | struct ipc_namespace *ns; |
426 | 431 | ||
427 | ns = current->nsproxy->ipc_ns; | 432 | ns = current->nsproxy->ipc_ns; |
428 | 433 | ||
429 | mutex_lock(&shm_ids(ns).mutex); | 434 | err = idr_pre_get(&shm_ids(ns).ipcs_idr, GFP_KERNEL); |
435 | |||
430 | if (key == IPC_PRIVATE) { | 436 | if (key == IPC_PRIVATE) { |
431 | err = newseg(ns, key, shmflg, size); | 437 | if (!err) |
432 | } else if ((id = ipc_findkey(&shm_ids(ns), key)) == -1) { | 438 | err = -ENOMEM; |
433 | if (!(shmflg & IPC_CREAT)) | 439 | else { |
434 | err = -ENOENT; | 440 | mutex_lock(&shm_ids(ns).mutex); |
435 | else | ||
436 | err = newseg(ns, key, shmflg, size); | 441 | err = newseg(ns, key, shmflg, size); |
437 | } else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) { | 442 | mutex_unlock(&shm_ids(ns).mutex); |
438 | err = -EEXIST; | 443 | } |
439 | } else { | 444 | } else { |
440 | shp = shm_lock(ns, id); | 445 | mutex_lock(&shm_ids(ns).mutex); |
441 | BUG_ON(shp==NULL); | 446 | shp = (struct shmid_kernel *) ipc_findkey(&shm_ids(ns), key); |
442 | if (shp->shm_segsz < size) | 447 | if (shp == NULL) { |
443 | err = -EINVAL; | 448 | if (!(shmflg & IPC_CREAT)) |
444 | else if (ipcperms(&shp->shm_perm, shmflg)) | 449 | err = -ENOENT; |
445 | err = -EACCES; | 450 | else if (!err) |
446 | else { | 451 | err = -ENOMEM; |
447 | int shmid = shm_buildid(ns, id, shp->shm_perm.seq); | 452 | else |
448 | err = security_shm_associate(shp, shmflg); | 453 | err = newseg(ns, key, shmflg, size); |
449 | if (!err) | 454 | } else { |
450 | err = shmid; | 455 | /* shp has been locked by ipc_findkey() */ |
456 | |||
457 | if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) | ||
458 | err = -EEXIST; | ||
459 | else { | ||
460 | if (shp->shm_segsz < size) | ||
461 | err = -EINVAL; | ||
462 | else if (ipcperms(&shp->shm_perm, shmflg)) | ||
463 | err = -EACCES; | ||
464 | else { | ||
465 | err = security_shm_associate(shp, | ||
466 | shmflg); | ||
467 | if (!err) | ||
468 | err = shp->shm_perm.id; | ||
469 | } | ||
470 | } | ||
471 | shm_unlock(shp); | ||
451 | } | 472 | } |
452 | shm_unlock(shp); | 473 | mutex_unlock(&shm_ids(ns).mutex); |
453 | } | 474 | } |
454 | mutex_unlock(&shm_ids(ns).mutex); | ||
455 | 475 | ||
456 | return err; | 476 | return err; |
457 | } | 477 | } |
@@ -550,17 +570,20 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf | |||
550 | static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, | 570 | static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, |
551 | unsigned long *swp) | 571 | unsigned long *swp) |
552 | { | 572 | { |
553 | int i; | 573 | int next_id; |
574 | int total, in_use; | ||
554 | 575 | ||
555 | *rss = 0; | 576 | *rss = 0; |
556 | *swp = 0; | 577 | *swp = 0; |
557 | 578 | ||
558 | for (i = 0; i <= shm_ids(ns).max_id; i++) { | 579 | in_use = shm_ids(ns).in_use; |
580 | |||
581 | for (total = 0, next_id = 0; total < in_use; next_id++) { | ||
559 | struct shmid_kernel *shp; | 582 | struct shmid_kernel *shp; |
560 | struct inode *inode; | 583 | struct inode *inode; |
561 | 584 | ||
562 | shp = shm_get(ns, i); | 585 | shp = shm_get(ns, next_id); |
563 | if(!shp) | 586 | if (shp == NULL) |
564 | continue; | 587 | continue; |
565 | 588 | ||
566 | inode = shp->shm_file->f_path.dentry->d_inode; | 589 | inode = shp->shm_file->f_path.dentry->d_inode; |
@@ -575,6 +598,8 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, | |||
575 | *swp += info->swapped; | 598 | *swp += info->swapped; |
576 | spin_unlock(&info->lock); | 599 | spin_unlock(&info->lock); |
577 | } | 600 | } |
601 | |||
602 | total++; | ||
578 | } | 603 | } |
579 | } | 604 | } |
580 | 605 | ||
@@ -611,7 +636,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
611 | if(copy_shminfo_to_user (buf, &shminfo, version)) | 636 | if(copy_shminfo_to_user (buf, &shminfo, version)) |
612 | return -EFAULT; | 637 | return -EFAULT; |
613 | /* reading a integer is always atomic */ | 638 | /* reading a integer is always atomic */ |
614 | err= shm_ids(ns).max_id; | 639 | err = ipc_get_maxid(&shm_ids(ns)); |
615 | if(err<0) | 640 | if(err<0) |
616 | err = 0; | 641 | err = 0; |
617 | goto out; | 642 | goto out; |
@@ -631,7 +656,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
631 | shm_info.shm_tot = ns->shm_tot; | 656 | shm_info.shm_tot = ns->shm_tot; |
632 | shm_info.swap_attempts = 0; | 657 | shm_info.swap_attempts = 0; |
633 | shm_info.swap_successes = 0; | 658 | shm_info.swap_successes = 0; |
634 | err = shm_ids(ns).max_id; | 659 | err = ipc_get_maxid(&shm_ids(ns)); |
635 | mutex_unlock(&shm_ids(ns).mutex); | 660 | mutex_unlock(&shm_ids(ns).mutex); |
636 | if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { | 661 | if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { |
637 | err = -EFAULT; | 662 | err = -EFAULT; |
@@ -651,11 +676,8 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf) | |||
651 | if(shp==NULL) { | 676 | if(shp==NULL) { |
652 | err = -EINVAL; | 677 | err = -EINVAL; |
653 | goto out; | 678 | goto out; |
654 | } else if(cmd==SHM_STAT) { | 679 | } else if (cmd == SHM_STAT) { |
655 | err = -EINVAL; | 680 | result = shp->shm_perm.id; |
656 | if (shmid > shm_ids(ns).max_id) | ||
657 | goto out_unlock; | ||
658 | result = shm_buildid(ns, shmid, shp->shm_perm.seq); | ||
659 | } else { | 681 | } else { |
660 | err = shm_checkid(ns, shp,shmid); | 682 | err = shm_checkid(ns, shp,shmid); |
661 | if(err) | 683 | if(err) |
@@ -925,7 +947,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | |||
925 | 947 | ||
926 | file->private_data = sfd; | 948 | file->private_data = sfd; |
927 | file->f_mapping = shp->shm_file->f_mapping; | 949 | file->f_mapping = shp->shm_file->f_mapping; |
928 | sfd->id = shp->id; | 950 | sfd->id = shp->shm_perm.id; |
929 | sfd->ns = get_ipc_ns(ns); | 951 | sfd->ns = get_ipc_ns(ns); |
930 | sfd->file = shp->shm_file; | 952 | sfd->file = shp->shm_file; |
931 | sfd->vm_ops = NULL; | 953 | sfd->vm_ops = NULL; |
@@ -1094,7 +1116,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it) | |||
1094 | format = BIG_STRING; | 1116 | format = BIG_STRING; |
1095 | return seq_printf(s, format, | 1117 | return seq_printf(s, format, |
1096 | shp->shm_perm.key, | 1118 | shp->shm_perm.key, |
1097 | shp->id, | 1119 | shp->shm_perm.id, |
1098 | shp->shm_perm.mode, | 1120 | shp->shm_perm.mode, |
1099 | shp->shm_segsz, | 1121 | shp->shm_segsz, |
1100 | shp->shm_cprid, | 1122 | shp->shm_cprid, |