lkml.org 
[lkml]   [1998]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
From
Subjectremoval of 4056 bytes msgsnd/msgrcv limit (patch)
Date
Hello,

Appended below is patch to remove the 4056 byte ipc message limits, and the
64K message queue limits. These limits are made dynamic (adjustable via
proc/sysctl).

vmalloc is used for "large" messages (over MSGMAX). Since there were limiting
unsigned short fields in msgid_ds there is now a msqid_ds_kernel structure
where unsigned int is used instead. The fields that were formerly __wwait,
and __rwait in the user land msqid_ds structure are now used to return
the msg_cbytes, and msg_qbytes fields -- the old fields are also set for
backwards compatability, but they will be insufficient if >64K messages or
message queues are used.

As one can now potentially use a lot of unswappable kernel memory for messages
the total amount of such memory is now limited by a KERN_MSGPOOL sysctl.

I would appriciate anybody that is interested to try these out, and give me
any feedback. If possible I would like to see this change in 2.2 -- most
of the changes are quite simple (primarily search and replaces to accomodate
the split of the user/kernel msqid_ds structures). I know that at least db2
for linux would be able to use this -- however we would prefer not to have
to ship kernel patches with our distribution.

Also appended below is a replacement userland sys/msq_buf.h and a msgctl
function that hides the differences in whether the running kernel supports
large message queues or not. You can use this to patch ipcs so that it will
ipcs -q shows the correct info if using large message queues.

Peeter
--
Peeter Joot peeterj@ca.ibm.com

---------------------------------------------------------------------------
kernel patch (2.1.131)
---------------------------------------------------------------------------

diff -ur linux-2.1.131.orig/Documentation/sysctl/kernel.txt linux-2.1.131.clean/Documentation/sysctl/kernel.txt
--- linux-2.1.131.orig/Documentation/sysctl/kernel.txt Sun Dec 6 09:06:57 1998
+++ linux-2.1.131.clean/Documentation/sysctl/kernel.txt Sun Dec 6 09:03:10 1998
@@ -25,6 +25,9 @@
- java-appletviewer [ binfmt_java, obsolete ]
- java-interpreter [ binfmt_java, obsolete ]
- modprobe ==> Documentation/kmod.txt
+- msgmax [ sysv ipc ]
+- msgmnb [ sysv ipc ]
+- msgpool [ sysv ipc ]
- osrelease
- ostype
- panic
@@ -33,6 +36,7 @@
- real-root-dev ==> Documentation/initrd.txt
- reboot-cmd [ SPARC only ]
- sg-big-buff [ generic SCSI device (sg) ]
+- shmmax [ sysv ipc ]
- version
- zero-paged [ PPC only ]

@@ -89,6 +93,38 @@

==============================================================

+msgmax:
+
+This value can be used to query and set the run time limit
+on the maximum message size that can be sent. This defaults
+to MSGMAX, which despite it's small size (4056) seems to have
+been sufficient for a long time.
+
+msgmax is now effectively limited by physical memory. Users
+should note that indiscriminately increasing this limit is not
+a good idea since queued messages are stored in non swappable
+kernel space. Increasing this limit should be accompanied
+with suitable modifications to msgmnb and msgpool.
+
+==============================================================
+
+msgmnb:
+
+This value can be used to query and set the default maximum
+number of bytes in a message queue. Note that this can also
+be set on a per queue basis via msgctl, but a root user is
+required to do so. This value defaults to MSGMNB.
+
+==============================================================
+
+msgpool:
+
+This value can be used to query and set the maximum total
+number of bytes in all message queues. This value defaults
+to MSGPOOL*1024.
+
+==============================================================
+
osrelease, ostype & version:

# cat osrelease
@@ -164,6 +200,15 @@
There shouldn't be any reason to change this value. If
you can come up with one, you probably know what you
are doing anyway :)
+
+==============================================================
+
+shmmax:
+
+This value can be used to query and set the run time limit
+on the maximum shared memory segment size that can be created.
+Shared memory segments up to 1Gb are now supported in the
+kernel. This value defaults to SHMMAX.

==============================================================

diff -ur linux-2.1.131.orig/include/linux/msg.h linux-2.1.131.clean/include/linux/msg.h
--- linux-2.1.131.orig/include/linux/msg.h Fri Jun 5 02:34:06 1998
+++ linux-2.1.131.clean/include/linux/msg.h Sun Dec 6 08:33:42 1998
@@ -12,22 +12,56 @@
#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/

/* one msqid structure for each queue on the system */
-struct msqid_ds {
+struct msqid_ds_base {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message on queue */
struct msg *msg_last; /* last message in queue */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
+};
+
+#ifdef __KERNEL__
+
+struct msqid_ds_kernel {
+ struct msqid_ds_base u;
struct wait_queue *wwait;
struct wait_queue *rwait;
- unsigned short msg_cbytes; /* current number of bytes on queue */
+ unsigned int msg_cbytes; /* current number of bytes on queue */
+ unsigned short msg_qnum; /* number of messages in queue */
+ unsigned int msg_qbytes; /* max number of bytes on queue */
+ __kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_ipc_pid_t msg_lrpid; /* last receive pid */
+};
+
+#endif
+
+struct msqid_ds {
+ struct msqid_ds_base u;
+ /* unions used to maintain size on 64 bit platforms */
+ union { void * __wwait ; unsigned int msg_cbytes; } c;
+ union { void * __rwait ; unsigned int msg_qbytes; } q;
+ unsigned short old_msg_cbytes; /* current number of bytes on queue */
unsigned short msg_qnum; /* number of messages in queue */
- unsigned short msg_qbytes; /* max number of bytes on queue */
+ unsigned short old_msg_qbytes; /* max number of bytes on queue */
__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};

+#if 0
+#if !defined __KERNEL__ && (!defined(__GLIBC__) || __GLIBC__ < 2)
+/* glibc < 2 doesn't have sys/msg.h -- do we support the use of 2.1 kernel
+ * headers on older systems?
+ */
+#define msg_perm u.msg_perm
+#define msg_stime u.msg_stime
+#define msg_rtime u.msg_rtime
+#define msg_ctime u.msg_ctime
+#define msg_cbytes c.msg_cbytes
+#define msg_qbytes q.msg_qbytes
+#endif
+#endif
+
/* message buffer for msgsnd and msgrcv calls */
struct msgbuf {
long mtype; /* type of message */
@@ -47,12 +81,15 @@
};

#define MSGMNI 128 /* <= 1K */ /* max # of msg queue identifiers */
-#define MSGMAX 4056 /* <= 4056 */ /* max size of message (bytes) */
-#define MSGMNB 16384 /* ? */ /* default max size of a message queue */
+
+/* Default values, now configurable at run time */
+#define MSGMAX 4056 /* <= 4056 */ /* max size of message (bytes) */
+#define MSGMNB 16384 /* default max size of a message queue */
+#define __MSGPOOL (MSGMNI*MSGMNB) /* size of message pool */
+#define MSGPOOL (__MSGPOOL/1024) /* size in kilobytes of message pool */

/* unused */
-#define MSGPOOL (MSGMNI*MSGMNB/1024) /* size in kilobytes of message pool */
-#define MSGTQL MSGMNB /* number of system message headers */
+#define MSGTQL (MSGMNB*MSGMNI) /* max number of system message headers */
#define MSGMAP MSGMNB /* number of entries in message map */
#define MSGSSZ 16 /* message segment size */
#define __MSGSEG ((MSGPOOL*1024)/ MSGSSZ) /* max no. of segments */
@@ -66,7 +103,7 @@
long msg_type;
char *msg_spot; /* message text address */
time_t msg_stime; /* msgsnd time */
- short msg_ts; /* message text size */
+ int msg_ts; /* message text size */
};

asmlinkage int sys_msgget (key_t key, int msgflg);
diff -ur linux-2.1.131.orig/include/linux/sysctl.h linux-2.1.131.clean/include/linux/sysctl.h
--- linux-2.1.131.orig/include/linux/sysctl.h Sat Dec 5 01:34:18 1998
+++ linux-2.1.131.clean/include/linux/sysctl.h Sun Dec 6 08:41:14 1998
@@ -89,6 +89,10 @@
KERN_SG_BIG_BUFF=29,
KERN_ACCT=30, /* BSD process accounting parameters */
KERN_PPC_L2CR=31, /* l2cr register on PPC */
+ KERN_SHMMAX=32, /* int: Maximum shared memory segment */
+ KERN_MSGMAX=33, /* int: Maximum size of a messege */
+ KERN_MSGMNB=34, /* int: Maximum message queue size */
+ KERN_MSGPOOL=35, /* int: Maximum system message pool size */
};


diff -ur linux-2.1.131.orig/ipc/msg.c linux-2.1.131.clean/ipc/msg.c
--- linux-2.1.131.orig/ipc/msg.c Sat Dec 5 01:34:49 1998
+++ linux-2.1.131.clean/ipc/msg.c Sun Dec 6 09:16:19 1998
@@ -2,11 +2,12 @@
* linux/ipc/msg.c
* Copyright (C) 1992 Krishna Balasubramanian
*
+ * Remove 4056 byte MSGMAX restriction and 64K restrictions, limits made dynamic
* Removed all the remaining kerneld mess
* Catch the -EFAULT stuff properly
* Use GFP_KERNEL for messages as in 1.2
* Fixed up the unchecked user space derefs
- * Copyright (C) 1998 Alan Cox & Andi Kleen
+ * Copyright (C) 1998 Alan Cox, Andi Kleen & Peeter Joot
*
*/

@@ -15,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/vmalloc.h>

#include <asm/uaccess.h>

@@ -24,7 +26,7 @@
static int newque (key_t key, int msgflg);
static int findkey (key_t key);

-static struct msqid_ds *msgque[MSGMNI];
+static struct msqid_ds_kernel *msgque[MSGMNI];
static int msgbytes = 0;
static int msghdrs = 0;
static unsigned short msg_seq = 0;
@@ -32,12 +34,16 @@
static int max_msqid = 0;
static struct wait_queue *msg_lock = NULL;

+int msgmax = MSGMAX;
+int msgmnb = MSGMNB;
+int msgpool = __MSGPOOL;
+
void __init msg_init (void)
{
int id;

for (id = 0; id < MSGMNI; id++)
- msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_UNUSED;
msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;
msg_lock = NULL;
return;
@@ -45,13 +51,13 @@

static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
{
- int id;
- struct msqid_ds *msq;
+ int id, error;
+ struct msqid_ds_kernel *msq;
struct ipc_perm *ipcp;
struct msg *msgh;
long mtype;

- if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
+ if (msgsz > msgmax || (long) msgsz < 0 || msqid < 0)
return -EINVAL;
if (get_user(mtype, &msgp->mtype))
return -EFAULT;
@@ -61,43 +67,54 @@
msq = msgque [id];
if (msq == IPC_UNUSED || msq == IPC_NOID)
return -EINVAL;
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;

slept:
- if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
+ if (msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI)
return -EIDRM;

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;
- }
+
+ /* There were two identical if statements here ? */
+ if ((msgsz + msq->msg_cbytes > msq->msg_qbytes) ||
+ (msgsz + msgbytes > msgpool)) {
+ /* 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*/
- msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL);
- if (!msgh)
- return -ENOMEM;
- msgh->msg_spot = (char *) (msgh + 1);
+ if (msgsz < MSGMAX) {
+ /* Standard small message: */
+ msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz,
+ GFP_KERNEL);
+ if (!msgh)
+ return -ENOMEM;
+ msgh->msg_spot = (char *) (msgh + 1);
+ } else {
+ msgh = (struct msg *) kmalloc (sizeof(*msgh), GFP_KERNEL);
+ if (!msgh)
+ return -ENOMEM;
+ msgh->msg_spot = (char *) vmalloc(msgsz);
+ if (!msgh->msg_spot)
+ kfree(msgh);
+ }

if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz))
{
- kfree(msgh);
- return -EFAULT;
+ error = -EFAULT;
+ goto free_buf;
}

if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
- || msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
- kfree(msgh);
- return -EIDRM;
+ || msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI) {
+ error = -EIDRM;
+ goto free_buf;
}

msgh->msg_next = NULL;
@@ -105,25 +122,31 @@
msgh->msg_type = mtype;
msgh->msg_stime = CURRENT_TIME;

- if (!msq->msg_first)
- msq->msg_first = msq->msg_last = msgh;
+ if (!msq->u.msg_first)
+ msq->u.msg_first = msq->u.msg_last = msgh;
else {
- msq->msg_last->msg_next = msgh;
- msq->msg_last = msgh;
+ msq->u.msg_last->msg_next = msgh;
+ msq->u.msg_last = msgh;
}
msq->msg_cbytes += msgsz;
- msgbytes += msgsz;
+ msgbytes += msgsz;
msghdrs++;
msq->msg_qnum++;
msq->msg_lspid = current->pid;
- msq->msg_stime = CURRENT_TIME;
+ msq->u.msg_stime = CURRENT_TIME;
wake_up (&msq->rwait);
return 0;
+
+free_buf:
+ if (msgsz >= MSGMAX)
+ vfree(msgh->msg_spot);
+ kfree(msgh);
+ return error;
}

static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
{
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;
struct ipc_perm *ipcp;
struct msg *tmsg, *leastp = NULL;
struct msg *nmsg = NULL;
@@ -136,7 +159,7 @@
msq = msgque [id];
if (msq == IPC_NOID || msq == IPC_UNUSED)
return -EINVAL;
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;

/*
* find message of correct type.
@@ -145,7 +168,7 @@
* msgtyp < 0 => get message with least type must be < abs(msgtype).
*/
while (!nmsg) {
- if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
+ if (msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI) {
return -EIDRM;
}
if (ipcperms (ipcp, S_IRUGO)) {
@@ -153,23 +176,23 @@
}

if (msgtyp == 0)
- nmsg = msq->msg_first;
+ nmsg = msq->u.msg_first;
else if (msgtyp > 0) {
if (msgflg & MSG_EXCEPT) {
- for (tmsg = msq->msg_first; tmsg;
+ for (tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_type != msgtyp)
break;
nmsg = tmsg;
} else {
- for (tmsg = msq->msg_first; tmsg;
+ for (tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_type == msgtyp)
break;
nmsg = tmsg;
}
} else {
- for (leastp = tmsg = msq->msg_first; tmsg;
+ for (leastp = tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_type < leastp->msg_type)
leastp = tmsg;
@@ -182,21 +205,21 @@
return -E2BIG;
}
msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;
- if (nmsg == msq->msg_first)
- msq->msg_first = nmsg->msg_next;
+ if (nmsg == msq->u.msg_first)
+ msq->u.msg_first = nmsg->msg_next;
else {
- for (tmsg = msq->msg_first; tmsg;
+ for (tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_next == nmsg)
break;
tmsg->msg_next = nmsg->msg_next;
- if (nmsg == msq->msg_last)
- msq->msg_last = tmsg;
+ if (nmsg == msq->u.msg_last)
+ msq->u.msg_last = tmsg;
}
if (!(--msq->msg_qnum))
- msq->msg_last = msq->msg_first = NULL;
+ msq->u.msg_last = msq->u.msg_first = NULL;

- msq->msg_rtime = CURRENT_TIME;
+ msq->u.msg_rtime = CURRENT_TIME;
msq->msg_lrpid = current->pid;
msgbytes -= nmsg->msg_ts;
msghdrs--;
@@ -205,6 +228,8 @@
if (put_user (nmsg->msg_type, &msgp->mtype) ||
copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz))
msgsz = -EFAULT;
+ if (nmsg->msg_ts >= MSGMAX)
+ vfree(nmsg->msg_spot);
kfree(nmsg);
return msgsz;
} else { /* did not find a message */
@@ -244,14 +269,14 @@
static int findkey (key_t key)
{
int id;
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;

for (id = 0; id <= max_msqid; id++) {
while ((msq = msgque[id]) == IPC_NOID)
interruptible_sleep_on (&msg_lock);
if (msq == IPC_UNUSED)
continue;
- if (key == msq->msg_perm.key)
+ if (key == msq->u.msg_perm.key)
return id;
}
return -1;
@@ -260,48 +285,48 @@
static int newque (key_t key, int msgflg)
{
int id;
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;
struct ipc_perm *ipcp;

for (id = 0; id < MSGMNI; id++)
if (msgque[id] == IPC_UNUSED) {
- msgque[id] = (struct msqid_ds *) IPC_NOID;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_NOID;
goto found;
}
return -ENOSPC;

found:
- msq = (struct msqid_ds *) kmalloc (sizeof (*msq), GFP_KERNEL);
+ msq = (struct msqid_ds_kernel *) kmalloc (sizeof (*msq), GFP_KERNEL);
if (!msq) {
- msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_UNUSED;
wake_up (&msg_lock);
return -ENOMEM;
}
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;
ipcp->mode = (msgflg & S_IRWXUGO);
ipcp->key = key;
ipcp->cuid = ipcp->uid = current->euid;
ipcp->gid = ipcp->cgid = current->egid;
- msq->msg_perm.seq = msg_seq;
- msq->msg_first = msq->msg_last = NULL;
+ msq->u.msg_perm.seq = msg_seq;
+ msq->u.msg_first = msq->u.msg_last = NULL;
msq->rwait = msq->wwait = NULL;
msq->msg_cbytes = msq->msg_qnum = 0;
msq->msg_lspid = msq->msg_lrpid = 0;
- msq->msg_stime = msq->msg_rtime = 0;
- msq->msg_qbytes = MSGMNB;
- msq->msg_ctime = CURRENT_TIME;
+ msq->u.msg_stime = msq->u.msg_rtime = 0;
+ msq->msg_qbytes = msgmnb;
+ msq->u.msg_ctime = CURRENT_TIME;
if (id > max_msqid)
max_msqid = id;
msgque[id] = msq;
used_queues++;
wake_up (&msg_lock);
- return (unsigned int) msq->msg_perm.seq * MSGMNI + id;
+ return (unsigned int) msq->u.msg_perm.seq * MSGMNI + id;
}

asmlinkage int sys_msgget (key_t key, int msgflg)
{
int id, ret = -EPERM;
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;

lock_kernel();
if (key == IPC_PRIVATE)
@@ -317,10 +342,10 @@
msq = msgque[id];
if (msq == IPC_UNUSED || msq == IPC_NOID)
ret = -EIDRM;
- else if (ipcperms(&msq->msg_perm, msgflg))
+ else if (ipcperms(&msq->u.msg_perm, msgflg))
ret = -EACCES;
else
- ret = (unsigned int) msq->msg_perm.seq * MSGMNI + id;
+ ret = (unsigned int) msq->u.msg_perm.seq * MSGMNI + id;
}
unlock_kernel();
return ret;
@@ -328,24 +353,26 @@

static void freeque (int id)
{
- struct msqid_ds *msq = msgque[id];
+ struct msqid_ds_kernel *msq = msgque[id];
struct msg *msgp, *msgh;

- msq->msg_perm.seq++;
+ msq->u.msg_perm.seq++;
msg_seq = (msg_seq+1) % ((unsigned)(1<<31)/MSGMNI); /* increment, but avoid overflow */
msgbytes -= msq->msg_cbytes;
if (id == max_msqid)
while (max_msqid && (msgque[--max_msqid] == IPC_UNUSED));
- msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_UNUSED;
used_queues--;
while (waitqueue_active(&msq->rwait) || waitqueue_active(&msq->wwait)) {
wake_up (&msq->rwait);
wake_up (&msq->wwait);
schedule();
}
- for (msgp = msq->msg_first; msgp; msgp = msgh ) {
+ for (msgp = msq->u.msg_first; msgp; msgp = msgh ) {
msgh = msgp->msg_next;
msghdrs--;
+ if (msgp->msg_ts >= MSGMAX)
+ vfree(msgp->msg_spot);
kfree(msgp);
}
kfree(msq);
@@ -354,9 +381,10 @@
asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
{
int id, err = -EINVAL;
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;
struct msqid_ds tbuf;
struct ipc_perm *ipcp;
+ unsigned int msg_qbytes;

lock_kernel();
if (msqid < 0 || cmd < 0)
@@ -370,17 +398,20 @@
{
struct msginfo msginfo;
msginfo.msgmni = MSGMNI;
- msginfo.msgmax = MSGMAX;
- msginfo.msgmnb = MSGMNB;
- msginfo.msgmap = MSGMAP;
- msginfo.msgpool = MSGPOOL;
- msginfo.msgtql = MSGTQL;
+ msginfo.msgmax = msgmax;
+ msginfo.msgmnb = msgmnb;
msginfo.msgssz = MSGSSZ;
msginfo.msgseg = MSGSEG;
if (cmd == MSG_INFO) {
- msginfo.msgpool = used_queues;
+ /* was used_queues ? */
+ msginfo.msgpool = msgbytes;
msginfo.msgmap = msghdrs;
- msginfo.msgtql = msgbytes;
+ /* was msgbytes ? */
+ msginfo.msgtql = used_queues;
+ } else {
+ msginfo.msgpool = msgpool/1024;
+ msginfo.msgmap = MSGMAP;
+ msginfo.msgtql = MSGTQL;
}

err = -EFAULT;
@@ -399,16 +430,18 @@
if (msq == IPC_UNUSED || msq == IPC_NOID)
goto out;
err = -EACCES;
- if (ipcperms (&msq->msg_perm, S_IRUGO))
+ if (ipcperms (&msq->u.msg_perm, S_IRUGO))
goto out;
- id = (unsigned int) msq->msg_perm.seq * MSGMNI + msqid;
- tbuf.msg_perm = msq->msg_perm;
- tbuf.msg_stime = msq->msg_stime;
- tbuf.msg_rtime = msq->msg_rtime;
- tbuf.msg_ctime = msq->msg_ctime;
- tbuf.msg_cbytes = msq->msg_cbytes;
+ id = (unsigned int) msq->u.msg_perm.seq * MSGMNI + msqid;
+ tbuf.u.msg_perm = msq->u.msg_perm;
+ tbuf.u.msg_stime = msq->u.msg_stime;
+ tbuf.u.msg_rtime = msq->u.msg_rtime;
+ tbuf.u.msg_ctime = msq->u.msg_ctime;
+ tbuf.c.msg_cbytes = msq->msg_cbytes;
+ tbuf.q.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_cbytes = (unsigned short)msq->msg_cbytes;
tbuf.msg_qnum = msq->msg_qnum;
- tbuf.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_qbytes = (unsigned short)msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
err = -EFAULT;
@@ -435,22 +468,24 @@
if (msq == IPC_UNUSED || msq == IPC_NOID)
goto out;
err = -EIDRM;
- if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
+ if (msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI)
goto out;
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;

switch (cmd) {
case IPC_STAT:
err = -EACCES;
if (ipcperms (ipcp, S_IRUGO))
goto out;
- tbuf.msg_perm = msq->msg_perm;
- tbuf.msg_stime = msq->msg_stime;
- tbuf.msg_rtime = msq->msg_rtime;
- tbuf.msg_ctime = msq->msg_ctime;
- tbuf.msg_cbytes = msq->msg_cbytes;
+ tbuf.u.msg_perm = msq->u.msg_perm;
+ tbuf.u.msg_stime = msq->u.msg_stime;
+ tbuf.u.msg_rtime = msq->u.msg_rtime;
+ tbuf.u.msg_ctime = msq->u.msg_ctime;
+ tbuf.c.msg_cbytes = msq->msg_cbytes;
+ tbuf.q.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_cbytes = (unsigned short)msq->msg_cbytes;
tbuf.msg_qnum = msq->msg_qnum;
- tbuf.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_qbytes = (unsigned short)msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
err = -EFAULT;
@@ -463,14 +498,18 @@
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
/* We _could_ check for CAP_CHOWN above, but we don't */
goto out;
- if (tbuf.msg_qbytes > MSGMNB && !capable(CAP_SYS_RESOURCE))
+ if (tbuf.old_msg_qbytes == 0)
+ msg_qbytes = tbuf.q.msg_qbytes;
+ else
+ msg_qbytes = tbuf.old_msg_qbytes;
+ if (msg_qbytes > msgmnb && !capable(CAP_SYS_RESOURCE))
goto out;
- msq->msg_qbytes = tbuf.msg_qbytes;
- ipcp->uid = tbuf.msg_perm.uid;
- ipcp->gid = tbuf.msg_perm.gid;
+ msq->msg_qbytes = msg_qbytes;
+ ipcp->uid = tbuf.u.msg_perm.uid;
+ ipcp->gid = tbuf.u.msg_perm.gid;
ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
- (S_IRWXUGO & tbuf.msg_perm.mode);
- msq->msg_ctime = CURRENT_TIME;
+ (S_IRWXUGO & tbuf.u.msg_perm.mode);
+ msq->u.msg_ctime = CURRENT_TIME;
err = 0;
goto out;
case IPC_RMID:
diff -ur linux-2.1.131.orig/ipc/shm.c linux-2.1.131.clean/ipc/shm.c
--- linux-2.1.131.orig/ipc/shm.c Sat Dec 5 01:34:49 1998
+++ linux-2.1.131.clean/ipc/shm.c Sat Dec 5 01:38:20 1998
@@ -126,6 +126,8 @@
return (unsigned int) shp->u.shm_perm.seq * SHMMNI + id;
}

+int shmmax = SHMMAX;
+
asmlinkage int sys_shmget (key_t key, int size, int shmflg)
{
struct shmid_kernel *shp;
@@ -133,7 +135,7 @@

down(&current->mm->mmap_sem);
lock_kernel();
- if (size < 0 || size > SHMMAX) {
+ if (size < 0 || size > shmmax) {
err = -EINVAL;
} else if (key == IPC_PRIVATE) {
err = newseg(key, shmflg, size);
@@ -228,7 +230,7 @@
if (!buf)
goto out;
shminfo.shmmni = SHMMNI;
- shminfo.shmmax = SHMMAX;
+ shminfo.shmmax = shmmax;
shminfo.shmmin = SHMMIN;
shminfo.shmall = SHMALL;
shminfo.shmseg = SHMSEG;
diff -ur linux-2.1.131.orig/kernel/sysctl.c linux-2.1.131.clean/kernel/sysctl.c
--- linux-2.1.131.orig/kernel/sysctl.c Sat Dec 5 01:34:49 1998
+++ linux-2.1.131.clean/kernel/sysctl.c Sun Dec 6 08:39:42 1998
@@ -42,6 +42,12 @@
#ifdef CONFIG_CHR_DEV_SG
extern int sg_big_buff;
#endif
+#ifdef CONFIG_SYSVIPC
+extern int shmmax;
+extern int msgmax;
+extern int msgmnb;
+extern int msgpool;
+#endif

#ifdef __sparc__
extern char reboot_command [];
@@ -194,6 +200,16 @@
#ifdef CONFIG_BSD_PROCESS_ACCT
{KERN_ACCT, "acct", &acct_parm, 3*sizeof(int),
0644, NULL, &proc_dointvec},
+#endif
+#ifdef CONFIG_SYSVIPC
+ {KERN_SHMMAX, "shmmax", &shmmax, sizeof (int),
+ 0644, NULL, &proc_dointvec},
+ {KERN_MSGMAX, "msgmax", &msgmax, sizeof (int),
+ 0644, NULL, &proc_dointvec},
+ {KERN_MSGMNB, "msgmnb", &msgmnb, sizeof (int),
+ 0644, NULL, &proc_dointvec},
+ {KERN_MSGPOOL, "msgpool", &msgpool, sizeof (int),
+ 0644, NULL, &proc_dointvec},
#endif
{0}
};
---------------------------------------------------------------------------
sys/msq_buf.h replacement:
---------------------------------------------------------------------------
/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, August 1995.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.

The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */

#ifndef _SYS_MSQ_BUF_H

#define _SYS_MSQ_BUF_H 1
#include <features.h>

#include <sys/types.h>

/* Define options for message queue functions. */
#define MSG_NOERROR 010000 /* no error if message is too big */
#define MSG_EXCEPT 020000 /* recv any msg except of specified type */

__BEGIN_DECLS

/* Structure of record for one message inside the kernel.
The type `struct __msg' is opaque. */
struct msqid_ds
{
struct ipc_perm msg_perm; /* structure describing operation permission */
struct msg *__msg_first; /* pointer to first message on queue */
struct msg *__msg_last; /* pointer to last message on queue */
__time_t msg_stime; /* time of last msgsnd command */
__time_t msg_rtime; /* time of last msgrcv command */
__time_t msg_ctime; /* time of last change */
unsigned int __msg_cbytes; /* current number of bytes on queue */
#if defined(__alpha__)
/* what is the proper 64 bit test macro for this */
unsigned int __pad0;
#endif
unsigned int msg_qbytes; /* max number of bytes allowed on queue */
#if defined(__alpha__)
unsigned int __pad1;
#endif
unsigned short int __old_msg_cbytes;
unsigned short int msg_qnum; /* number of messages currently on queue */
unsigned short int __old_msg_qbytes;
__ipc_pid_t msg_lspid; /* pid of last msgsnd() */
__ipc_pid_t msg_lrpid; /* pid of last msgrcv() */
};
#ifdef __USE_MISC

#define msg_cbytes __msg_cbytes

/* ipcs ctl commands */
#define MSG_STAT 11
#define MSG_INFO 12
/* buffer for msgctl calls IPC_INFO, MSG_INFO */
struct msginfo
{
int msgpool;
int msgmap;
int msgmax;
int msgmnb;
int msgmni;
int msgssz;
int msgtql;
ushort msgseg;
};
#endif /* __USE_MISC */
__END_DECLS

#endif /* _SYS_MSQ_BUF_H */
---------------------------------------------------------------------------
msg_big.c -- defines my_msgctl() for use with above msq_buf.h -- to use
#define msg_ctl to my_msgctl in other code.
---------------------------------------------------------------------------
#include <sys/msg.h>
#include <sys/sysctl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
int __kernel_large_msqqueue_support = 0;

void
__test_large_msqqueues (void)
__attribute__ ((__constructor__));

void __test_large_msqqueues (void)
{
int rc;
int name[] =
{CTL_KERN, KERN_MSGMAX};
rc = sysctl (name, 2, 0, 0, 0, 0);
if (rc == 0)
__kernel_large_msqqueue_support = 1;
}
#ifndef MSG_STAT
#define MSG_STAT 11
#endif

#ifdef msgctl
#undef msgctl
#endif

int
my_msgctl (int msqid, int cmd, struct msqid_ds *buf)
{
int rc;
switch (cmd)
{
case MSG_STAT:
case IPC_STAT:
if (!buf) {
errno = EINVAL;
return -1;
}
rc = msgctl (msqid, cmd, buf);
if (__kernel_large_msqqueue_support == 0 &&
rc == 0 && errno != EFAULT)
{
buf->msg_qbytes = buf->__old_msg_qbytes;
buf->__msg_cbytes = buf->__old_msg_cbytes;
}
return rc;
case IPC_SET:
if (!buf) {
errno = EINVAL;
return -1;
}
/* This alters the semantics of the system call slightly, as
* it would be possible to get a segv here, rather than a polite
* -1 return code and EFAULT errno -- I don't think it is a big deal.
*/
if (__kernel_large_msqqueue_support == 0)
buf->__old_msg_qbytes = buf->msg_qbytes;
else
buf->__old_msg_qbytes = 0;
default:
return msgctl (msqid, cmd, buf);
}
}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:45    [W:0.074 / U:23.956 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site