aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/shm.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/shm.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/shm.c')
-rw-r--r--ipc/shm.c116
1 files changed, 69 insertions, 47 deletions
diff --git a/ipc/shm.c b/ipc/shm.c
index b9d272900a1e..dcc333239683 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -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
90static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) 90static 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
113void shm_exit_ns(struct ipc_namespace *ns) 113void 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
149static inline struct shmid_kernel *shm_rmid(struct ipc_namespace *ns, int id) 153static 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
154static inline int shm_addid(struct ipc_namespace *ns, struct shmid_kernel *shp) 158static 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)
184static void shm_destroy(struct ipc_namespace *ns, struct shmid_kernel *shp) 188static 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
413no_id: 418no_id:
414 fput(file); 419 fput(file);
@@ -421,37 +426,52 @@ no_file:
421asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) 426asmlinkage 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
550static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, 570static 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,