From: Jakub Jelinek <jakub@redhat.com>

POSIX requires EINVAL to be set if:
"The process or thread would have blocked, and the abs_timeout parameter
specified a nanoseconds field value less than zero or greater than or equal
to 1000 million."
but 2.6.5-mm3 returns -EINVAL even if the process or thread would not block
(if the queue is not empty for timedreceive or not full for timedsend).


---

 25-akpm/ipc/mqueue.c |   14 +++++++++-----
 1 files changed, 9 insertions(+), 5 deletions(-)

diff -puN ipc/mqueue.c~mq-timespec-checking-fix ipc/mqueue.c
--- 25/ipc/mqueue.c~mq-timespec-checking-fix	Fri Apr  9 16:30:36 2004
+++ 25-akpm/ipc/mqueue.c	Fri Apr  9 16:30:36 2004
@@ -765,8 +765,7 @@ asmlinkage long sys_mq_timedsend(mqd_t m
 	if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
 		return -EINVAL;
 
-	if (unlikely((timeout = prepare_timeout(u_abs_timeout)) < 0))
-		return timeout;
+	timeout = prepare_timeout(u_abs_timeout);
 
 	ret = -EBADF;
 	filp = fget(mqdes);
@@ -802,6 +801,9 @@ asmlinkage long sys_mq_timedsend(mqd_t m
 		if (filp->f_flags & O_NONBLOCK) {
 			spin_unlock(&info->lock);
 			ret = -EAGAIN;
+		} else if (unlikely(timeout < 0)) {
+			spin_unlock(&info->lock);
+			ret = timeout;
 		} else {
 			wait.task = current;
 			wait.msg = (void *) msg_ptr;
@@ -842,9 +844,7 @@ asmlinkage ssize_t sys_mq_timedreceive(m
 	struct mqueue_inode_info *info;
 	struct ext_wait_queue wait;
 
-
-	if (unlikely((timeout = prepare_timeout(u_abs_timeout)) < 0))
-		return timeout;
+	timeout = prepare_timeout(u_abs_timeout);
 
 	ret = -EBADF;
 	filp = fget(mqdes);
@@ -871,6 +871,10 @@ asmlinkage ssize_t sys_mq_timedreceive(m
 			spin_unlock(&info->lock);
 			ret = -EAGAIN;
 			msg_ptr = NULL;
+		} else if (unlikely(timeout < 0)) {
+			spin_unlock(&info->lock);
+			ret = timeout;
+			msg_ptr = NULL;
 		} else {
 			wait.task = current;
 			wait.state = STATE_NONE;

_