patch-2.2.14 linux/ipc/msg.c
Next file: linux/ipc/sem.c
Previous file: linux/init/main.c
Back to the patch index
Back to the overall index
- Lines: 91
- Date:
Tue Jan 4 10:12:25 2000
- Orig file:
v2.2.13/linux/ipc/msg.c
- Orig date:
Fri Nov 20 11:43:19 1998
diff -u --recursive --new-file v2.2.13/linux/ipc/msg.c linux/ipc/msg.c
@@ -50,6 +50,7 @@
struct ipc_perm *ipcp;
struct msg *msgh;
long mtype;
+ int err;
if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
return -EINVAL;
@@ -70,34 +71,38 @@
if (ipcperms(ipcp, S_IWUGO))
return -EACCES;
- if (msgsz + msq->msg_cbytes > msq->msg_qbytes) {
- if (msgsz + msq->msg_cbytes > msq->msg_qbytes) {
- /* still no space in queue */
- if (msgflg & IPC_NOWAIT)
- return -EAGAIN;
- if (signal_pending(current))
- return -EINTR;
- interruptible_sleep_on (&msq->wwait);
- goto slept;
- }
+ if (msgsz + msq->msg_cbytes > msq->msg_qbytes || msq->msg_qnum>= MSGQNUM) {
+ /* still no space in queue */
+ if (msgflg & IPC_NOWAIT)
+ return -EAGAIN;
+ if (signal_pending(current))
+ return -EINTR;
+ interruptible_sleep_on (&msq->wwait);
+ goto slept;
}
-
- /* allocate message header and text space*/
+
+ /* Charge first to avoid races */
+ msgbytes += msgsz;
+ msghdrs++;
+ msq->msg_qnum++;
+ msq->msg_cbytes += msgsz;
+
+ /* allocate message header and text space */
+ err = -ENOMEM;
msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL);
- if (!msgh)
- return -ENOMEM;
+ if (!msgh)
+ goto uncharge;
msgh->msg_spot = (char *) (msgh + 1);
- if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz))
- {
- kfree(msgh);
- return -EFAULT;
+ err = -EFAULT;
+ if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz)) {
+ goto uncharge;
}
+ err = -EIDRM;
if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
|| msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
- kfree(msgh);
- return -EIDRM;
+ goto uncharge;
}
msgh->msg_next = NULL;
@@ -111,14 +116,19 @@
msq->msg_last->msg_next = msgh;
msq->msg_last = msgh;
}
- msq->msg_cbytes += msgsz;
- msgbytes += msgsz;
- msghdrs++;
- msq->msg_qnum++;
msq->msg_lspid = current->pid;
msq->msg_stime = CURRENT_TIME;
wake_up (&msq->rwait);
return 0;
+
+uncharge:
+ msgbytes -= msgsz;
+ msghdrs--;
+ msq->msg_qnum--;
+ msq->msg_cbytes -= msgsz;
+ if (msgh)
+ kfree(msgh);
+ return err;
}
static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)