aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/mqueue.c
diff options
context:
space:
mode:
authorSerge E. Hallyn <serue@us.ibm.com>2009-04-06 22:01:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:09 -0400
commit614b84cf4e4a920d2af32b8f147ea1e3b8c27ea6 (patch)
tree52478e38cd400042bd89f123c4101c95943ae492 /ipc/mqueue.c
parent909e6d94795654040ed416ac69858d5d2ce66dd3 (diff)
namespaces: mqueue ns: move mqueue_mnt into struct ipc_namespace
Move mqueue vfsmount plus a few tunables into the ipc_namespace struct. The CONFIG_IPC_NS boolean and the ipc_namespace struct will serve both the posix message queue namespaces and the SYSV ipc namespaces. The sysctl code will be fixed separately in patch 3. After just this patch, making a change to posix mqueue tunables always changes the values in the initial ipc namespace. Signed-off-by: Cedric Le Goater <clg@fr.ibm.com> Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc/mqueue.c')
-rw-r--r--ipc/mqueue.c124
1 files changed, 68 insertions, 56 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 916785363f0f..a3673a09069a 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -31,6 +31,7 @@
31#include <linux/mutex.h> 31#include <linux/mutex.h>
32#include <linux/nsproxy.h> 32#include <linux/nsproxy.h>
33#include <linux/pid.h> 33#include <linux/pid.h>
34#include <linux/ipc_namespace.h>
34 35
35#include <net/sock.h> 36#include <net/sock.h>
36#include "util.h" 37#include "util.h"
@@ -46,12 +47,6 @@
46#define STATE_PENDING 1 47#define STATE_PENDING 1
47#define STATE_READY 2 48#define STATE_READY 2
48 49
49/* default values */
50#define DFLT_QUEUESMAX 256 /* max number of message queues */
51#define DFLT_MSGMAX 10 /* max number of messages in each queue */
52#define HARD_MSGMAX (131072/sizeof(void*))
53#define DFLT_MSGSIZEMAX 8192 /* max message size */
54
55/* 50/*
56 * Define the ranges various user-specified maximum values can 51 * Define the ranges various user-specified maximum values can
57 * be set to. 52 * be set to.
@@ -95,12 +90,6 @@ static void remove_notification(struct mqueue_inode_info *info);
95 90
96static spinlock_t mq_lock; 91static spinlock_t mq_lock;
97static struct kmem_cache *mqueue_inode_cachep; 92static struct kmem_cache *mqueue_inode_cachep;
98static struct vfsmount *mqueue_mnt;
99
100static unsigned int queues_count;
101static unsigned int queues_max = DFLT_QUEUESMAX;
102static unsigned int msg_max = DFLT_MSGMAX;
103static unsigned int msgsize_max = DFLT_MSGSIZEMAX;
104 93
105static struct ctl_table_header * mq_sysctl_table; 94static struct ctl_table_header * mq_sysctl_table;
106 95
@@ -109,11 +98,27 @@ static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode)
109 return container_of(inode, struct mqueue_inode_info, vfs_inode); 98 return container_of(inode, struct mqueue_inode_info, vfs_inode);
110} 99}
111 100
101void mq_init_ns(struct ipc_namespace *ns)
102{
103 ns->mq_queues_count = 0;
104 ns->mq_queues_max = DFLT_QUEUESMAX;
105 ns->mq_msg_max = DFLT_MSGMAX;
106 ns->mq_msgsize_max = DFLT_MSGSIZEMAX;
107 ns->mq_mnt = mntget(init_ipc_ns.mq_mnt);
108}
109
110void mq_exit_ns(struct ipc_namespace *ns)
111{
112 /* will need to clear out ns->mq_mnt->mnt_sb->s_fs_info here */
113 mntput(ns->mq_mnt);
114}
115
112static struct inode *mqueue_get_inode(struct super_block *sb, int mode, 116static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
113 struct mq_attr *attr) 117 struct mq_attr *attr)
114{ 118{
115 struct user_struct *u = current_user(); 119 struct user_struct *u = current_user();
116 struct inode *inode; 120 struct inode *inode;
121 struct ipc_namespace *ipc_ns = &init_ipc_ns;
117 122
118 inode = new_inode(sb); 123 inode = new_inode(sb);
119 if (inode) { 124 if (inode) {
@@ -141,8 +146,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
141 info->qsize = 0; 146 info->qsize = 0;
142 info->user = NULL; /* set when all is ok */ 147 info->user = NULL; /* set when all is ok */
143 memset(&info->attr, 0, sizeof(info->attr)); 148 memset(&info->attr, 0, sizeof(info->attr));
144 info->attr.mq_maxmsg = msg_max; 149 info->attr.mq_maxmsg = ipc_ns->mq_msg_max;
145 info->attr.mq_msgsize = msgsize_max; 150 info->attr.mq_msgsize = ipc_ns->mq_msgsize_max;
146 if (attr) { 151 if (attr) {
147 info->attr.mq_maxmsg = attr->mq_maxmsg; 152 info->attr.mq_maxmsg = attr->mq_maxmsg;
148 info->attr.mq_msgsize = attr->mq_msgsize; 153 info->attr.mq_msgsize = attr->mq_msgsize;
@@ -242,6 +247,7 @@ static void mqueue_delete_inode(struct inode *inode)
242 struct user_struct *user; 247 struct user_struct *user;
243 unsigned long mq_bytes; 248 unsigned long mq_bytes;
244 int i; 249 int i;
250 struct ipc_namespace *ipc_ns = &init_ipc_ns;
245 251
246 if (S_ISDIR(inode->i_mode)) { 252 if (S_ISDIR(inode->i_mode)) {
247 clear_inode(inode); 253 clear_inode(inode);
@@ -262,7 +268,7 @@ static void mqueue_delete_inode(struct inode *inode)
262 if (user) { 268 if (user) {
263 spin_lock(&mq_lock); 269 spin_lock(&mq_lock);
264 user->mq_bytes -= mq_bytes; 270 user->mq_bytes -= mq_bytes;
265 queues_count--; 271 ipc_ns->mq_queues_count--;
266 spin_unlock(&mq_lock); 272 spin_unlock(&mq_lock);
267 free_uid(user); 273 free_uid(user);
268 } 274 }
@@ -274,21 +280,23 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
274 struct inode *inode; 280 struct inode *inode;
275 struct mq_attr *attr = dentry->d_fsdata; 281 struct mq_attr *attr = dentry->d_fsdata;
276 int error; 282 int error;
283 struct ipc_namespace *ipc_ns = &init_ipc_ns;
277 284
278 spin_lock(&mq_lock); 285 spin_lock(&mq_lock);
279 if (queues_count >= queues_max && !capable(CAP_SYS_RESOURCE)) { 286 if (ipc_ns->mq_queues_count >= ipc_ns->mq_queues_max &&
287 !capable(CAP_SYS_RESOURCE)) {
280 error = -ENOSPC; 288 error = -ENOSPC;
281 goto out_lock; 289 goto out_unlock;
282 } 290 }
283 queues_count++; 291 ipc_ns->mq_queues_count++;
284 spin_unlock(&mq_lock); 292 spin_unlock(&mq_lock);
285 293
286 inode = mqueue_get_inode(dir->i_sb, mode, attr); 294 inode = mqueue_get_inode(dir->i_sb, mode, attr);
287 if (!inode) { 295 if (!inode) {
288 error = -ENOMEM; 296 error = -ENOMEM;
289 spin_lock(&mq_lock); 297 spin_lock(&mq_lock);
290 queues_count--; 298 ipc_ns->mq_queues_count--;
291 goto out_lock; 299 goto out_unlock;
292 } 300 }
293 301
294 dir->i_size += DIRENT_SIZE; 302 dir->i_size += DIRENT_SIZE;
@@ -297,7 +305,7 @@ static int mqueue_create(struct inode *dir, struct dentry *dentry,
297 d_instantiate(dentry, inode); 305 d_instantiate(dentry, inode);
298 dget(dentry); 306 dget(dentry);
299 return 0; 307 return 0;
300out_lock: 308out_unlock:
301 spin_unlock(&mq_lock); 309 spin_unlock(&mq_lock);
302 return error; 310 return error;
303} 311}
@@ -562,7 +570,7 @@ static void remove_notification(struct mqueue_inode_info *info)
562 info->notify_owner = NULL; 570 info->notify_owner = NULL;
563} 571}
564 572
565static int mq_attr_ok(struct mq_attr *attr) 573static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
566{ 574{
567 if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0) 575 if (attr->mq_maxmsg <= 0 || attr->mq_msgsize <= 0)
568 return 0; 576 return 0;
@@ -570,8 +578,8 @@ static int mq_attr_ok(struct mq_attr *attr)
570 if (attr->mq_maxmsg > HARD_MSGMAX) 578 if (attr->mq_maxmsg > HARD_MSGMAX)
571 return 0; 579 return 0;
572 } else { 580 } else {
573 if (attr->mq_maxmsg > msg_max || 581 if (attr->mq_maxmsg > ipc_ns->mq_msg_max ||
574 attr->mq_msgsize > msgsize_max) 582 attr->mq_msgsize > ipc_ns->mq_msgsize_max)
575 return 0; 583 return 0;
576 } 584 }
577 /* check for overflow */ 585 /* check for overflow */
@@ -587,8 +595,9 @@ static int mq_attr_ok(struct mq_attr *attr)
587/* 595/*
588 * Invoked when creating a new queue via sys_mq_open 596 * Invoked when creating a new queue via sys_mq_open
589 */ 597 */
590static struct file *do_create(struct dentry *dir, struct dentry *dentry, 598static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
591 int oflag, mode_t mode, struct mq_attr *attr) 599 struct dentry *dentry, int oflag, mode_t mode,
600 struct mq_attr *attr)
592{ 601{
593 const struct cred *cred = current_cred(); 602 const struct cred *cred = current_cred();
594 struct file *result; 603 struct file *result;
@@ -596,14 +605,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
596 605
597 if (attr) { 606 if (attr) {
598 ret = -EINVAL; 607 ret = -EINVAL;
599 if (!mq_attr_ok(attr)) 608 if (!mq_attr_ok(ipc_ns, attr))
600 goto out; 609 goto out;
601 /* store for use during create */ 610 /* store for use during create */
602 dentry->d_fsdata = attr; 611 dentry->d_fsdata = attr;
603 } 612 }
604 613
605 mode &= ~current_umask(); 614 mode &= ~current_umask();
606 ret = mnt_want_write(mqueue_mnt); 615 ret = mnt_want_write(ipc_ns->mq_mnt);
607 if (ret) 616 if (ret)
608 goto out; 617 goto out;
609 ret = vfs_create(dir->d_inode, dentry, mode, NULL); 618 ret = vfs_create(dir->d_inode, dentry, mode, NULL);
@@ -611,24 +620,25 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
611 if (ret) 620 if (ret)
612 goto out_drop_write; 621 goto out_drop_write;
613 622
614 result = dentry_open(dentry, mqueue_mnt, oflag, cred); 623 result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
615 /* 624 /*
616 * dentry_open() took a persistent mnt_want_write(), 625 * dentry_open() took a persistent mnt_want_write(),
617 * so we can now drop this one. 626 * so we can now drop this one.
618 */ 627 */
619 mnt_drop_write(mqueue_mnt); 628 mnt_drop_write(ipc_ns->mq_mnt);
620 return result; 629 return result;
621 630
622out_drop_write: 631out_drop_write:
623 mnt_drop_write(mqueue_mnt); 632 mnt_drop_write(ipc_ns->mq_mnt);
624out: 633out:
625 dput(dentry); 634 dput(dentry);
626 mntput(mqueue_mnt); 635 mntput(ipc_ns->mq_mnt);
627 return ERR_PTR(ret); 636 return ERR_PTR(ret);
628} 637}
629 638
630/* Opens existing queue */ 639/* Opens existing queue */
631static struct file *do_open(struct dentry *dentry, int oflag) 640static struct file *do_open(struct ipc_namespace *ipc_ns,
641 struct dentry *dentry, int oflag)
632{ 642{
633 const struct cred *cred = current_cred(); 643 const struct cred *cred = current_cred();
634 644
@@ -637,17 +647,17 @@ static struct file *do_open(struct dentry *dentry, int oflag)
637 647
638 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { 648 if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
639 dput(dentry); 649 dput(dentry);
640 mntput(mqueue_mnt); 650 mntput(ipc_ns->mq_mnt);
641 return ERR_PTR(-EINVAL); 651 return ERR_PTR(-EINVAL);
642 } 652 }
643 653
644 if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { 654 if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
645 dput(dentry); 655 dput(dentry);
646 mntput(mqueue_mnt); 656 mntput(ipc_ns->mq_mnt);
647 return ERR_PTR(-EACCES); 657 return ERR_PTR(-EACCES);
648 } 658 }
649 659
650 return dentry_open(dentry, mqueue_mnt, oflag, cred); 660 return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
651} 661}
652 662
653SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode, 663SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
@@ -658,6 +668,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
658 char *name; 668 char *name;
659 struct mq_attr attr; 669 struct mq_attr attr;
660 int fd, error; 670 int fd, error;
671 struct ipc_namespace *ipc_ns = &init_ipc_ns;
661 672
662 if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) 673 if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
663 return -EFAULT; 674 return -EFAULT;
@@ -671,13 +682,13 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
671 if (fd < 0) 682 if (fd < 0)
672 goto out_putname; 683 goto out_putname;
673 684
674 mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex); 685 mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
675 dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); 686 dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
676 if (IS_ERR(dentry)) { 687 if (IS_ERR(dentry)) {
677 error = PTR_ERR(dentry); 688 error = PTR_ERR(dentry);
678 goto out_err; 689 goto out_err;
679 } 690 }
680 mntget(mqueue_mnt); 691 mntget(ipc_ns->mq_mnt);
681 692
682 if (oflag & O_CREAT) { 693 if (oflag & O_CREAT) {
683 if (dentry->d_inode) { /* entry already exists */ 694 if (dentry->d_inode) { /* entry already exists */
@@ -685,10 +696,10 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
685 error = -EEXIST; 696 error = -EEXIST;
686 if (oflag & O_EXCL) 697 if (oflag & O_EXCL)
687 goto out; 698 goto out;
688 filp = do_open(dentry, oflag); 699 filp = do_open(ipc_ns, dentry, oflag);
689 } else { 700 } else {
690 filp = do_create(mqueue_mnt->mnt_root, dentry, 701 filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
691 oflag, mode, 702 dentry, oflag, mode,
692 u_attr ? &attr : NULL); 703 u_attr ? &attr : NULL);
693 } 704 }
694 } else { 705 } else {
@@ -696,7 +707,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
696 if (!dentry->d_inode) 707 if (!dentry->d_inode)
697 goto out; 708 goto out;
698 audit_inode(name, dentry); 709 audit_inode(name, dentry);
699 filp = do_open(dentry, oflag); 710 filp = do_open(ipc_ns, dentry, oflag);
700 } 711 }
701 712
702 if (IS_ERR(filp)) { 713 if (IS_ERR(filp)) {
@@ -709,13 +720,13 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, mode_t, mode,
709 720
710out: 721out:
711 dput(dentry); 722 dput(dentry);
712 mntput(mqueue_mnt); 723 mntput(ipc_ns->mq_mnt);
713out_putfd: 724out_putfd:
714 put_unused_fd(fd); 725 put_unused_fd(fd);
715out_err: 726out_err:
716 fd = error; 727 fd = error;
717out_upsem: 728out_upsem:
718 mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); 729 mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
719out_putname: 730out_putname:
720 putname(name); 731 putname(name);
721 return fd; 732 return fd;
@@ -727,14 +738,15 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
727 char *name; 738 char *name;
728 struct dentry *dentry; 739 struct dentry *dentry;
729 struct inode *inode = NULL; 740 struct inode *inode = NULL;
741 struct ipc_namespace *ipc_ns = &init_ipc_ns;
730 742
731 name = getname(u_name); 743 name = getname(u_name);
732 if (IS_ERR(name)) 744 if (IS_ERR(name))
733 return PTR_ERR(name); 745 return PTR_ERR(name);
734 746
735 mutex_lock_nested(&mqueue_mnt->mnt_root->d_inode->i_mutex, 747 mutex_lock_nested(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex,
736 I_MUTEX_PARENT); 748 I_MUTEX_PARENT);
737 dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name)); 749 dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
738 if (IS_ERR(dentry)) { 750 if (IS_ERR(dentry)) {
739 err = PTR_ERR(dentry); 751 err = PTR_ERR(dentry);
740 goto out_unlock; 752 goto out_unlock;
@@ -748,16 +760,16 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
748 inode = dentry->d_inode; 760 inode = dentry->d_inode;
749 if (inode) 761 if (inode)
750 atomic_inc(&inode->i_count); 762 atomic_inc(&inode->i_count);
751 err = mnt_want_write(mqueue_mnt); 763 err = mnt_want_write(ipc_ns->mq_mnt);
752 if (err) 764 if (err)
753 goto out_err; 765 goto out_err;
754 err = vfs_unlink(dentry->d_parent->d_inode, dentry); 766 err = vfs_unlink(dentry->d_parent->d_inode, dentry);
755 mnt_drop_write(mqueue_mnt); 767 mnt_drop_write(ipc_ns->mq_mnt);
756out_err: 768out_err:
757 dput(dentry); 769 dput(dentry);
758 770
759out_unlock: 771out_unlock:
760 mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex); 772 mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
761 putname(name); 773 putname(name);
762 if (inode) 774 if (inode)
763 iput(inode); 775 iput(inode);
@@ -1214,14 +1226,14 @@ static int msg_maxsize_limit_max = MAX_MSGSIZEMAX;
1214static ctl_table mq_sysctls[] = { 1226static ctl_table mq_sysctls[] = {
1215 { 1227 {
1216 .procname = "queues_max", 1228 .procname = "queues_max",
1217 .data = &queues_max, 1229 .data = &init_ipc_ns.mq_queues_max,
1218 .maxlen = sizeof(int), 1230 .maxlen = sizeof(int),
1219 .mode = 0644, 1231 .mode = 0644,
1220 .proc_handler = &proc_dointvec, 1232 .proc_handler = &proc_dointvec,
1221 }, 1233 },
1222 { 1234 {
1223 .procname = "msg_max", 1235 .procname = "msg_max",
1224 .data = &msg_max, 1236 .data = &init_ipc_ns.mq_msg_max,
1225 .maxlen = sizeof(int), 1237 .maxlen = sizeof(int),
1226 .mode = 0644, 1238 .mode = 0644,
1227 .proc_handler = &proc_dointvec_minmax, 1239 .proc_handler = &proc_dointvec_minmax,
@@ -1230,7 +1242,7 @@ static ctl_table mq_sysctls[] = {
1230 }, 1242 },
1231 { 1243 {
1232 .procname = "msgsize_max", 1244 .procname = "msgsize_max",
1233 .data = &msgsize_max, 1245 .data = &init_ipc_ns.mq_msgsize_max,
1234 .maxlen = sizeof(int), 1246 .maxlen = sizeof(int),
1235 .mode = 0644, 1247 .mode = 0644,
1236 .proc_handler = &proc_dointvec_minmax, 1248 .proc_handler = &proc_dointvec_minmax,
@@ -1276,13 +1288,13 @@ static int __init init_mqueue_fs(void)
1276 if (error) 1288 if (error)
1277 goto out_sysctl; 1289 goto out_sysctl;
1278 1290
1279 if (IS_ERR(mqueue_mnt = kern_mount(&mqueue_fs_type))) { 1291 init_ipc_ns.mq_mnt = kern_mount(&mqueue_fs_type);
1280 error = PTR_ERR(mqueue_mnt); 1292 if (IS_ERR(init_ipc_ns.mq_mnt)) {
1293 error = PTR_ERR(init_ipc_ns.mq_mnt);
1281 goto out_filesystem; 1294 goto out_filesystem;
1282 } 1295 }
1283 1296
1284 /* internal initialization - not common for vfs */ 1297 /* internal initialization - not common for vfs */
1285 queues_count = 0;
1286 spin_lock_init(&mq_lock); 1298 spin_lock_init(&mq_lock);
1287 1299
1288 return 0; 1300 return 0;