aboutsummaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2010-12-09 12:17:25 -0500
committerThomas Gleixner <tglx@linutronix.de>2010-12-09 12:17:25 -0500
commitd834a9dcecae834cd6b2bc5e50e1907738d9cf6a (patch)
tree0589d753465d3fe359ba451ba6cb7798df03aaa2 /ipc
parenta38c5380ef9f088be9f49b6e4c5d80af8b1b5cd4 (diff)
parentf658bcfb2607bf0808966a69cf74135ce98e5c2d (diff)
Merge branch 'x86/amd-nb' into x86/apic-cleanups
Reason: apic cleanup series depends on x86/apic, x86/amd-nb x86/platform Conflicts: arch/x86/include/asm/io_apic.h Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'ipc')
-rw-r--r--ipc/compat.c6
-rw-r--r--ipc/compat_mq.c5
-rw-r--r--ipc/mqueue.c12
-rw-r--r--ipc/shm.c66
4 files changed, 63 insertions, 26 deletions
diff --git a/ipc/compat.c b/ipc/compat.c
index 9dc2c7d3c9e6..845a28738d3a 100644
--- a/ipc/compat.c
+++ b/ipc/compat.c
@@ -241,6 +241,8 @@ long compat_sys_semctl(int first, int second, int third, void __user *uptr)
241 struct semid64_ds __user *up64; 241 struct semid64_ds __user *up64;
242 int version = compat_ipc_parse_version(&third); 242 int version = compat_ipc_parse_version(&third);
243 243
244 memset(&s64, 0, sizeof(s64));
245
244 if (!uptr) 246 if (!uptr)
245 return -EINVAL; 247 return -EINVAL;
246 if (get_user(pad, (u32 __user *) uptr)) 248 if (get_user(pad, (u32 __user *) uptr))
@@ -421,6 +423,8 @@ long compat_sys_msgctl(int first, int second, void __user *uptr)
421 int version = compat_ipc_parse_version(&second); 423 int version = compat_ipc_parse_version(&second);
422 void __user *p; 424 void __user *p;
423 425
426 memset(&m64, 0, sizeof(m64));
427
424 switch (second & (~IPC_64)) { 428 switch (second & (~IPC_64)) {
425 case IPC_INFO: 429 case IPC_INFO:
426 case IPC_RMID: 430 case IPC_RMID:
@@ -594,6 +598,8 @@ long compat_sys_shmctl(int first, int second, void __user *uptr)
594 int err, err2; 598 int err, err2;
595 int version = compat_ipc_parse_version(&second); 599 int version = compat_ipc_parse_version(&second);
596 600
601 memset(&s64, 0, sizeof(s64));
602
597 switch (second & (~IPC_64)) { 603 switch (second & (~IPC_64)) {
598 case IPC_RMID: 604 case IPC_RMID:
599 case SHM_LOCK: 605 case SHM_LOCK:
diff --git a/ipc/compat_mq.c b/ipc/compat_mq.c
index d8d1e9ff4e88..380ea4fe08e7 100644
--- a/ipc/compat_mq.c
+++ b/ipc/compat_mq.c
@@ -53,6 +53,9 @@ asmlinkage long compat_sys_mq_open(const char __user *u_name,
53 void __user *p = NULL; 53 void __user *p = NULL;
54 if (u_attr && oflag & O_CREAT) { 54 if (u_attr && oflag & O_CREAT) {
55 struct mq_attr attr; 55 struct mq_attr attr;
56
57 memset(&attr, 0, sizeof(attr));
58
56 p = compat_alloc_user_space(sizeof(attr)); 59 p = compat_alloc_user_space(sizeof(attr));
57 if (get_compat_mq_attr(&attr, u_attr) || 60 if (get_compat_mq_attr(&attr, u_attr) ||
58 copy_to_user(p, &attr, sizeof(attr))) 61 copy_to_user(p, &attr, sizeof(attr)))
@@ -127,6 +130,8 @@ asmlinkage long compat_sys_mq_getsetattr(mqd_t mqdes,
127 struct mq_attr __user *p = compat_alloc_user_space(2 * sizeof(*p)); 130 struct mq_attr __user *p = compat_alloc_user_space(2 * sizeof(*p));
128 long ret; 131 long ret;
129 132
133 memset(&mqstat, 0, sizeof(mqstat));
134
130 if (u_mqstat) { 135 if (u_mqstat) {
131 if (get_compat_mq_attr(&mqstat, u_mqstat) || 136 if (get_compat_mq_attr(&mqstat, u_mqstat) ||
132 copy_to_user(p, &mqstat, sizeof(mqstat))) 137 copy_to_user(p, &mqstat, sizeof(mqstat)))
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c60e519e2917..035f4399edbc 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -116,6 +116,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb,
116 116
117 inode = new_inode(sb); 117 inode = new_inode(sb);
118 if (inode) { 118 if (inode) {
119 inode->i_ino = get_next_ino();
119 inode->i_mode = mode; 120 inode->i_mode = mode;
120 inode->i_uid = current_fsuid(); 121 inode->i_uid = current_fsuid();
121 inode->i_gid = current_fsgid(); 122 inode->i_gid = current_fsgid();
@@ -210,13 +211,13 @@ out:
210 return error; 211 return error;
211} 212}
212 213
213static int mqueue_get_sb(struct file_system_type *fs_type, 214static struct dentry *mqueue_mount(struct file_system_type *fs_type,
214 int flags, const char *dev_name, 215 int flags, const char *dev_name,
215 void *data, struct vfsmount *mnt) 216 void *data)
216{ 217{
217 if (!(flags & MS_KERNMOUNT)) 218 if (!(flags & MS_KERNMOUNT))
218 data = current->nsproxy->ipc_ns; 219 data = current->nsproxy->ipc_ns;
219 return get_sb_ns(fs_type, flags, data, mqueue_fill_super, mnt); 220 return mount_ns(fs_type, flags, data, mqueue_fill_super);
220} 221}
221 222
222static void init_once(void *foo) 223static void init_once(void *foo)
@@ -769,7 +770,7 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
769 770
770 inode = dentry->d_inode; 771 inode = dentry->d_inode;
771 if (inode) 772 if (inode)
772 atomic_inc(&inode->i_count); 773 ihold(inode);
773 err = mnt_want_write(ipc_ns->mq_mnt); 774 err = mnt_want_write(ipc_ns->mq_mnt);
774 if (err) 775 if (err)
775 goto out_err; 776 goto out_err;
@@ -1219,6 +1220,7 @@ static const struct file_operations mqueue_file_operations = {
1219 .flush = mqueue_flush_file, 1220 .flush = mqueue_flush_file,
1220 .poll = mqueue_poll_file, 1221 .poll = mqueue_poll_file,
1221 .read = mqueue_read_file, 1222 .read = mqueue_read_file,
1223 .llseek = default_llseek,
1222}; 1224};
1223 1225
1224static const struct super_operations mqueue_super_ops = { 1226static const struct super_operations mqueue_super_ops = {
@@ -1230,7 +1232,7 @@ static const struct super_operations mqueue_super_ops = {
1230 1232
1231static struct file_system_type mqueue_fs_type = { 1233static struct file_system_type mqueue_fs_type = {
1232 .name = "mqueue", 1234 .name = "mqueue",
1233 .get_sb = mqueue_get_sb, 1235 .mount = mqueue_mount,
1234 .kill_sb = kill_litter_super, 1236 .kill_sb = kill_litter_super,
1235}; 1237};
1236 1238
diff --git a/ipc/shm.c b/ipc/shm.c
index 52ed77eb9713..7d3bb22a9302 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -108,7 +108,11 @@ void __init shm_init (void)
108{ 108{
109 shm_init_ns(&init_ipc_ns); 109 shm_init_ns(&init_ipc_ns);
110 ipc_init_proc_interface("sysvipc/shm", 110 ipc_init_proc_interface("sysvipc/shm",
111 " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime\n", 111#if BITS_PER_LONG <= 32
112 " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n",
113#else
114 " key shmid perms size cpid lpid nattch uid gid cuid cgid atime dtime ctime rss swap\n",
115#endif
112 IPC_SHM_IDS, sysvipc_shm_proc_show); 116 IPC_SHM_IDS, sysvipc_shm_proc_show);
113} 117}
114 118
@@ -298,6 +302,7 @@ static const struct file_operations shm_file_operations = {
298#ifndef CONFIG_MMU 302#ifndef CONFIG_MMU
299 .get_unmapped_area = shm_get_unmapped_area, 303 .get_unmapped_area = shm_get_unmapped_area,
300#endif 304#endif
305 .llseek = noop_llseek,
301}; 306};
302 307
303static const struct file_operations shm_file_operations_huge = { 308static const struct file_operations shm_file_operations_huge = {
@@ -305,6 +310,7 @@ static const struct file_operations shm_file_operations_huge = {
305 .fsync = shm_fsync, 310 .fsync = shm_fsync,
306 .release = shm_release, 311 .release = shm_release,
307 .get_unmapped_area = shm_get_unmapped_area, 312 .get_unmapped_area = shm_get_unmapped_area,
313 .llseek = noop_llseek,
308}; 314};
309 315
310int is_file_shm_hugepages(struct file *file) 316int is_file_shm_hugepages(struct file *file)
@@ -473,6 +479,7 @@ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_
473 { 479 {
474 struct shmid_ds out; 480 struct shmid_ds out;
475 481
482 memset(&out, 0, sizeof(out));
476 ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm); 483 ipc64_perm_to_ipc_perm(&in->shm_perm, &out.shm_perm);
477 out.shm_segsz = in->shm_segsz; 484 out.shm_segsz = in->shm_segsz;
478 out.shm_atime = in->shm_atime; 485 out.shm_atime = in->shm_atime;
@@ -542,6 +549,34 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf
542} 549}
543 550
544/* 551/*
552 * Calculate and add used RSS and swap pages of a shm.
553 * Called with shm_ids.rw_mutex held as a reader
554 */
555static void shm_add_rss_swap(struct shmid_kernel *shp,
556 unsigned long *rss_add, unsigned long *swp_add)
557{
558 struct inode *inode;
559
560 inode = shp->shm_file->f_path.dentry->d_inode;
561
562 if (is_file_hugepages(shp->shm_file)) {
563 struct address_space *mapping = inode->i_mapping;
564 struct hstate *h = hstate_file(shp->shm_file);
565 *rss_add += pages_per_huge_page(h) * mapping->nrpages;
566 } else {
567#ifdef CONFIG_SHMEM
568 struct shmem_inode_info *info = SHMEM_I(inode);
569 spin_lock(&info->lock);
570 *rss_add += inode->i_mapping->nrpages;
571 *swp_add += info->swapped;
572 spin_unlock(&info->lock);
573#else
574 *rss_add += inode->i_mapping->nrpages;
575#endif
576 }
577}
578
579/*
545 * Called with shm_ids.rw_mutex held as a reader 580 * Called with shm_ids.rw_mutex held as a reader
546 */ 581 */
547static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, 582static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
@@ -558,30 +593,13 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
558 for (total = 0, next_id = 0; total < in_use; next_id++) { 593 for (total = 0, next_id = 0; total < in_use; next_id++) {
559 struct kern_ipc_perm *ipc; 594 struct kern_ipc_perm *ipc;
560 struct shmid_kernel *shp; 595 struct shmid_kernel *shp;
561 struct inode *inode;
562 596
563 ipc = idr_find(&shm_ids(ns).ipcs_idr, next_id); 597 ipc = idr_find(&shm_ids(ns).ipcs_idr, next_id);
564 if (ipc == NULL) 598 if (ipc == NULL)
565 continue; 599 continue;
566 shp = container_of(ipc, struct shmid_kernel, shm_perm); 600 shp = container_of(ipc, struct shmid_kernel, shm_perm);
567 601
568 inode = shp->shm_file->f_path.dentry->d_inode; 602 shm_add_rss_swap(shp, rss, swp);
569
570 if (is_file_hugepages(shp->shm_file)) {
571 struct address_space *mapping = inode->i_mapping;
572 struct hstate *h = hstate_file(shp->shm_file);
573 *rss += pages_per_huge_page(h) * mapping->nrpages;
574 } else {
575#ifdef CONFIG_SHMEM
576 struct shmem_inode_info *info = SHMEM_I(inode);
577 spin_lock(&info->lock);
578 *rss += inode->i_mapping->nrpages;
579 *swp += info->swapped;
580 spin_unlock(&info->lock);
581#else
582 *rss += inode->i_mapping->nrpages;
583#endif
584 }
585 603
586 total++; 604 total++;
587 } 605 }
@@ -1070,6 +1088,9 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
1070static int sysvipc_shm_proc_show(struct seq_file *s, void *it) 1088static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
1071{ 1089{
1072 struct shmid_kernel *shp = it; 1090 struct shmid_kernel *shp = it;
1091 unsigned long rss = 0, swp = 0;
1092
1093 shm_add_rss_swap(shp, &rss, &swp);
1073 1094
1074#if BITS_PER_LONG <= 32 1095#if BITS_PER_LONG <= 32
1075#define SIZE_SPEC "%10lu" 1096#define SIZE_SPEC "%10lu"
@@ -1079,7 +1100,8 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
1079 1100
1080 return seq_printf(s, 1101 return seq_printf(s,
1081 "%10d %10d %4o " SIZE_SPEC " %5u %5u " 1102 "%10d %10d %4o " SIZE_SPEC " %5u %5u "
1082 "%5lu %5u %5u %5u %5u %10lu %10lu %10lu\n", 1103 "%5lu %5u %5u %5u %5u %10lu %10lu %10lu "
1104 SIZE_SPEC " " SIZE_SPEC "\n",
1083 shp->shm_perm.key, 1105 shp->shm_perm.key,
1084 shp->shm_perm.id, 1106 shp->shm_perm.id,
1085 shp->shm_perm.mode, 1107 shp->shm_perm.mode,
@@ -1093,6 +1115,8 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
1093 shp->shm_perm.cgid, 1115 shp->shm_perm.cgid,
1094 shp->shm_atim, 1116 shp->shm_atim,
1095 shp->shm_dtim, 1117 shp->shm_dtim,
1096 shp->shm_ctim); 1118 shp->shm_ctim,
1119 rss * PAGE_SIZE,
1120 swp * PAGE_SIZE);
1097} 1121}
1098#endif 1122#endif