2003-06-06 13:47:58

by Dhruv Anand

[permalink] [raw]
Subject: [RFC][PATCH 2.5.70] dynamically tuning msgtql

Hi,
Please find below the patch (RFC) that makes msgtql dynamically tunable
through /proc interface.

1) IPC_NOWAIT flag not handled.
Handling this will cause overheads (additional queue, wake-ups etc).
Please comment.

Or Handling IPC_NOWAIT may require:
a) An additional global queue for processes when message to be
queued is > msgtql && IPC_NOWAIT flag is not set.
Please comment.

Thanks,
Dhruv

diff -Nur linux-2.5.70/include/linux/msg.h linux-2.5.70msg/include/linux/msg.h
--- linux-2.5.70/include/linux/msg.h Tue May 27 06:30:40 2003
+++ linux-2.5.70msg/include/linux/msg.h Fri Jun 6 14:31:26 2003
@@ -49,13 +49,13 @@
unsigned short msgseg;
};

-#define MSGMNI 16 /* <= IPCMNI */ /* max # of msg queue identifiers */
-#define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */
-#define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */
+#define MSGMNI 16 /* <= IPCMNI */ /* max # of msg queue identifiers */
+#define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */
+#define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */
+#define MSGTQL 0x7fffffff /* <= INT_MAX */ /* number of system message */

/* unused */
#define MSGPOOL (MSGMNI*MSGMNB/1024) /* size in kilobytes of message pool */
-#define MSGTQL MSGMNB /* 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 */
diff -Nur linux-2.5.70/include/linux/sysctl.h linux-2.5.70msg/include/linux/sysctl.h
--- linux-2.5.70/include/linux/sysctl.h Tue May 27 06:30:40 2003
+++ linux-2.5.70msg/include/linux/sysctl.h Fri Jun 6 14:00:54 2003
@@ -130,6 +130,7 @@
KERN_PIDMAX=55, /* int: PID # limit */
KERN_CORE_PATTERN=56, /* string: pattern for core-file names */
KERN_PANIC_ON_OOPS=57, /* int: whether we will panic on an oops */
+ KERN_MSGTQL=57, /* int: Maximum number of messages system wide */
};


diff -Nur linux-2.5.70/ipc/msg.c linux-2.5.70msg/ipc/msg.c
--- linux-2.5.70/ipc/msg.c Tue May 27 06:30:20 2003
+++ linux-2.5.70msg/ipc/msg.c Fri Jun 6 18:43:42 2003
@@ -32,6 +32,9 @@
int msg_ctlmax = MSGMAX;
int msg_ctlmnb = MSGMNB;
int msg_ctlmni = MSGMNI;
+int msg_ctltql = MSGTQL;
+static int msg_count = 0; /* counter for MSGTQL */
+static spinlock_t msg_count_lock; /* spinlock for MSGTQL */

/* one msg_receiver structure for each sleeping receiver */
struct msg_receiver {
@@ -137,6 +140,9 @@

seg = msg->next;
kfree(msg);
+ spin_lock(&msg_count_lock);
+ msg_count--;
+ spin_unlock(&msg_count_lock);
while(seg != NULL) {
struct msg_msgseg* tmp = seg->next;
kfree(seg);
@@ -154,48 +160,59 @@
alen = len;
if(alen > DATALEN_MSG)
alen = DATALEN_MSG;
-
- msg = (struct msg_msg *) kmalloc (sizeof(*msg) + alen, GFP_KERNEL);
- if(msg==NULL)
- return ERR_PTR(-ENOMEM);
-
- msg->next = NULL;
- msg->security = NULL;
-
- if (copy_from_user(msg+1, src, alen)) {
- err = -EFAULT;
- goto out_err;
- }
-
- len -= alen;
- src = ((char*)src)+alen;
- pseg = &msg->next;
- while(len > 0) {
- struct msg_msgseg* seg;
- alen = len;
- if(alen > DATALEN_SEG)
- alen = DATALEN_SEG;
- seg = (struct msg_msgseg *) kmalloc (sizeof(*seg) + alen, GFP_KERNEL);
- if(seg==NULL) {
- err=-ENOMEM;
- goto out_err;
+
+ spin_lock(&msg_count_lock);
+ if(msg_count < msg_ctltql){
+ msg = (struct msg_msg *) kmalloc (sizeof(*msg) + alen, GFP_KERNEL);
+ if(msg==NULL) {
+ spin_unlock(msg_count_lock);
+ return ERR_PTR(-ENOMEM);
}
- *pseg = seg;
- seg->next = NULL;
- if(copy_from_user (seg+1, src, alen)) {
+ msg_count++;
+ spin_unlock(msg_count_lock);
+ msg->next = NULL;
+ msg->security = NULL;
+
+ if (copy_from_user(msg+1, src, alen)) {
err = -EFAULT;
goto out_err;
}
- pseg = &seg->next;
+
len -= alen;
src = ((char*)src)+alen;
- }
+ pseg = &msg->next;
+ while(len > 0) {
+ struct msg_msgseg* seg;
+ alen = len;
+ if(alen > DATALEN_SEG)
+ alen = DATALEN_SEG;
+ seg = (struct msg_msgseg *) kmalloc (sizeof(*seg) + alen, GFP_KERNEL);
+ if(seg==NULL) {
+ err=-ENOMEM;
+ goto out_err;
+ }
+ *pseg = seg;
+ seg->next = NULL;
+ if(copy_from_user (seg+1, src, alen)) {
+ err = -EFAULT;
+ goto out_err;
+ }
+ pseg = &seg->next;
+ len -= alen;
+ src = ((char*)src)+alen;
+ }

- err = security_msg_msg_alloc(msg);
- if (err)
- goto out_err;
+ err = security_msg_msg_alloc(msg);
+ if (err)
+ goto out_err;

- return msg;
+ return msg;
+ }
+ else {
+ spin_unlock(&msg_count_lock);
+ err= -EAGAIN;
+ return ERR_PTR(err);
+ }

out_err:
free_msg(msg);
diff -Nur linux-2.5.70/kernel/sysctl.c linux-2.5.70msg/kernel/sysctl.c
--- linux-2.5.70/kernel/sysctl.c Tue May 27 06:30:23 2003
+++ linux-2.5.70msg/kernel/sysctl.c Fri Jun 6 14:35:06 2003
@@ -61,6 +61,9 @@
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535;
static int minolduid;
+static int zero = 0;
+static int one = 1;
+static int one_hundred = 100;

#ifdef CONFIG_KMOD
extern char modprobe_path[];
@@ -78,6 +81,7 @@
extern int msg_ctlmax;
extern int msg_ctlmnb;
extern int msg_ctlmni;
+extern int msg_ctltql;
extern int sem_ctls[];
#endif

@@ -235,6 +239,8 @@
0644, NULL, &proc_dointvec},
{KERN_MSGMNB, "msgmnb", &msg_ctlmnb, sizeof (int),
0644, NULL, &proc_dointvec},
+ {KERN_MSGTQL, "msgtql", &msg_ctltql, sizeof (int),
+ 0644, NULL, &proc_dointvec_minmax, NULL, NULL, &zero, NULL},
{KERN_SEM, "sem", &sem_ctls, 4*sizeof (int),
0644, NULL, &proc_dointvec},
#endif
@@ -270,9 +276,6 @@

/* Constants for minimum and maximum testing in vm_table.
We use these as one-element integer vectors. */
-static int zero = 0;
-static int one = 1;
-static int one_hundred = 100;


static ctl_table vm_table[] = {