Commit f3ca8d5d authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] posix message queue update

From: Manfred Spraul <manfred@colorfullife.com>

My discussion with Ulrich had one result:

- mq_setattr can accept implementation defined flags.  Right now we have
  none, but we might add some later (e.g.  switch to CLOCK_MONOTONIC for
  mq_timed{send,receive} or something similar).  When we add flags, we
  might need the fields for additional information.  And they don't hurt.
  Therefore add four __reserved fields to mq_attr.

- fail mq_setattr if we get unknown flags - otherwise glibc can't detect
  if it's running on a future kernel that supports new features.

- use memset to initialize the mq_attr structure - theoretically we could
  leak kernel memory.

- Only set O_NONBLOCK in mq_attr, explicitely clear O_RDWR & friends.
  openposix uses getattr, attr |=O_NONBLOCK, setattr - a sane approach. 
  Without clearing O_RDWR, this fails.

I've retested all openposix conformance tests with the new patch - the two
new FAILED tests check undefined behavior.  Note that I won't have net
access until Sunday - if the message queue patch breaks something important
either ask Krzysztof or drop it.

Ulrich had another good idea for SIGEV_THREAD, but I must think about it.
It would mean less complexitiy in glibc, but more code in the kernel.  I'm
not yet convinced that it's overall better.
parent b95db642
...@@ -27,6 +27,7 @@ struct mq_attr { ...@@ -27,6 +27,7 @@ struct mq_attr {
long mq_maxmsg; /* maximum number of messages */ long mq_maxmsg; /* maximum number of messages */
long mq_msgsize; /* maximum message size */ long mq_msgsize; /* maximum message size */
long mq_curmsgs; /* number of messages currently queued */ long mq_curmsgs; /* number of messages currently queued */
long __reserved[4]; /* ignored for input, zeroed for output */
}; };
#define NOTIFY_NONE 0 #define NOTIFY_NONE 0
......
...@@ -121,7 +121,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode) ...@@ -121,7 +121,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode)
INIT_LIST_HEAD(&info->e_wait_q[1].list); INIT_LIST_HEAD(&info->e_wait_q[1].list);
info->notify_owner = 0; info->notify_owner = 0;
info->qsize = 0; info->qsize = 0;
info->attr.mq_curmsgs = 0; memset(&info->attr, 0, sizeof(info->attr));
info->attr.mq_maxmsg = DFLT_MSGMAX; info->attr.mq_maxmsg = DFLT_MSGMAX;
info->attr.mq_msgsize = DFLT_MSGSIZEMAX; info->attr.mq_msgsize = DFLT_MSGSIZEMAX;
info->messages = kmalloc(DFLT_MSGMAX * sizeof(struct msg_msg *), GFP_KERNEL); info->messages = kmalloc(DFLT_MSGMAX * sizeof(struct msg_msg *), GFP_KERNEL);
...@@ -1082,6 +1082,8 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, ...@@ -1082,6 +1082,8 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
if (u_mqstat != NULL) { if (u_mqstat != NULL) {
if (copy_from_user(&mqstat, u_mqstat, sizeof(struct mq_attr))) if (copy_from_user(&mqstat, u_mqstat, sizeof(struct mq_attr)))
return -EFAULT; return -EFAULT;
if (mqstat.mq_flags & (~O_NONBLOCK))
return -EINVAL;
} }
ret = -EBADF; ret = -EBADF;
...@@ -1097,7 +1099,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, ...@@ -1097,7 +1099,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
spin_lock(&info->lock); spin_lock(&info->lock);
omqstat = info->attr; omqstat = info->attr;
omqstat.mq_flags = filp->f_flags; omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
if (u_mqstat) { if (u_mqstat) {
if (mqstat.mq_flags & O_NONBLOCK) if (mqstat.mq_flags & O_NONBLOCK)
filp->f_flags |= O_NONBLOCK; filp->f_flags |= O_NONBLOCK;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment