Skip to content

Commit 0050ee0

Browse files
manfred-colorfutorvalds
authored andcommitted
ipc/msg: increase MSGMNI, remove scaling
SysV can be abused to allocate locked kernel memory. For most systems, a small limit doesn't make sense, see the discussion with regards to SHMMAX. Therefore: increase MSGMNI to the maximum supported. And: If we ignore the risk of locking too much memory, then an automatic scaling of MSGMNI doesn't make sense. Therefore the logic can be removed. The code preserves auto_msgmni to avoid breaking any user space applications that expect that the value exists. Notes: 1) If an administrator must limit the memory allocations, then he can set MSGMNI as necessary. Or he can disable sysv entirely (as e.g. done by Android). 2) MSGMAX and MSGMNB are intentionally not increased, as these values are used to control latency vs. throughput: If MSGMNB is large, then msgsnd() just returns and more messages can be queued before a task switch to a task that calls msgrcv() is forced. [[email protected]: coding-style fixes] Signed-off-by: Manfred Spraul <[email protected]> Cc: Davidlohr Bueso <[email protected]> Cc: Rafael Aquini <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent e843e7d commit 0050ee0

File tree

9 files changed

+45
-298
lines changed

9 files changed

+45
-298
lines changed

Documentation/sysctl/kernel.txt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,12 @@ set during run time.
116116

117117
auto_msgmni:
118118

119-
Enables/Disables automatic recomputing of msgmni upon memory add/remove
120-
or upon ipc namespace creation/removal (see the msgmni description
121-
above). Echoing "1" into this file enables msgmni automatic recomputing.
122-
Echoing "0" turns it off. auto_msgmni default value is 1.
119+
This variable has no effect and may be removed in future kernel
120+
releases. Reading it always returns 0.
121+
Up to Linux 3.17, it enabled/disabled automatic recomputing of msgmni
122+
upon memory add/remove or upon ipc namespace creation/removal.
123+
Echoing "1" into this file enabled msgmni automatic recomputing.
124+
Echoing "0" turned it off. auto_msgmni default value was 1.
123125

124126

125127
==============================================================

include/linux/ipc_namespace.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,6 @@
77
#include <linux/notifier.h>
88
#include <linux/nsproxy.h>
99

10-
/*
11-
* ipc namespace events
12-
*/
13-
#define IPCNS_MEMCHANGED 0x00000001 /* Notify lowmem size changed */
14-
#define IPCNS_CREATED 0x00000002 /* Notify new ipc namespace created */
15-
#define IPCNS_REMOVED 0x00000003 /* Notify ipc namespace removed */
16-
17-
#define IPCNS_CALLBACK_PRI 0
18-
1910
struct user_namespace;
2011

2112
struct ipc_ids {
@@ -38,7 +29,6 @@ struct ipc_namespace {
3829
unsigned int msg_ctlmni;
3930
atomic_t msg_bytes;
4031
atomic_t msg_hdrs;
41-
int auto_msgmni;
4232

4333
size_t shm_ctlmax;
4434
size_t shm_ctlall;
@@ -77,18 +67,8 @@ extern atomic_t nr_ipc_ns;
7767
extern spinlock_t mq_lock;
7868

7969
#ifdef CONFIG_SYSVIPC
80-
extern int register_ipcns_notifier(struct ipc_namespace *);
81-
extern int cond_register_ipcns_notifier(struct ipc_namespace *);
82-
extern void unregister_ipcns_notifier(struct ipc_namespace *);
83-
extern int ipcns_notify(unsigned long);
8470
extern void shm_destroy_orphaned(struct ipc_namespace *ns);
8571
#else /* CONFIG_SYSVIPC */
86-
static inline int register_ipcns_notifier(struct ipc_namespace *ns)
87-
{ return 0; }
88-
static inline int cond_register_ipcns_notifier(struct ipc_namespace *ns)
89-
{ return 0; }
90-
static inline void unregister_ipcns_notifier(struct ipc_namespace *ns) { }
91-
static inline int ipcns_notify(unsigned long l) { return 0; }
9272
static inline void shm_destroy_orphaned(struct ipc_namespace *ns) {}
9373
#endif /* CONFIG_SYSVIPC */
9474

include/uapi/linux/msg.h

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,16 +51,28 @@ struct msginfo {
5151
};
5252

5353
/*
54-
* Scaling factor to compute msgmni:
55-
* the memory dedicated to msg queues (msgmni * msgmnb) should occupy
56-
* at most 1/MSG_MEM_SCALE of the lowmem (see the formula in ipc/msg.c):
57-
* up to 8MB : msgmni = 16 (MSGMNI)
58-
* 4 GB : msgmni = 8K
59-
* more than 16 GB : msgmni = 32K (IPCMNI)
54+
* MSGMNI, MSGMAX and MSGMNB are default values which can be
55+
* modified by sysctl.
56+
*
57+
* MSGMNI is the upper limit for the number of messages queues per
58+
* namespace.
59+
* It has been chosen to be as large possible without facilitating
60+
* scenarios where userspace causes overflows when adjusting the limits via
61+
* operations of the form retrieve current limit; add X; update limit".
62+
*
63+
* MSGMNB is the default size of a new message queue. Non-root tasks can
64+
* decrease the size with msgctl(IPC_SET), root tasks
65+
* (actually: CAP_SYS_RESOURCE) can both increase and decrease the queue
66+
* size. The optimal value is application dependent.
67+
* 16384 is used because it was always used (since 0.99.10)
68+
*
69+
* MAXMAX is the maximum size of an individual message, it's a global
70+
* (per-namespace) limit that applies for all message queues.
71+
* It's set to 1/2 of MSGMNB, to ensure that at least two messages fit into
72+
* the queue. This is also an arbitrary choice (since 2.6.0).
6073
*/
61-
#define MSG_MEM_SCALE 32
6274

63-
#define MSGMNI 16 /* <= IPCMNI */ /* max # of msg queue identifiers */
75+
#define MSGMNI 32000 /* <= IPCMNI */ /* max # of msg queue identifiers */
6476
#define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */
6577
#define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */
6678

ipc/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#
44

55
obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o
6-
obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o ipcns_notifier.o syscall.o
6+
obj-$(CONFIG_SYSVIPC) += util.o msgutil.o msg.o sem.o shm.o syscall.o
77
obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o
88
obj_mq-$(CONFIG_COMPAT) += compat_mq.o
99
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)

ipc/ipc_sysctl.c

Lines changed: 17 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -62,29 +62,6 @@ static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
6262
return err;
6363
}
6464

65-
static int proc_ipc_callback_dointvec_minmax(struct ctl_table *table, int write,
66-
void __user *buffer, size_t *lenp, loff_t *ppos)
67-
{
68-
struct ctl_table ipc_table;
69-
size_t lenp_bef = *lenp;
70-
int rc;
71-
72-
memcpy(&ipc_table, table, sizeof(ipc_table));
73-
ipc_table.data = get_ipc(table);
74-
75-
rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
76-
77-
if (write && !rc && lenp_bef == *lenp)
78-
/*
79-
* Tunable has successfully been changed by hand. Disable its
80-
* automatic adjustment. This simply requires unregistering
81-
* the notifiers that trigger recalculation.
82-
*/
83-
unregister_ipcns_notifier(current->nsproxy->ipc_ns);
84-
85-
return rc;
86-
}
87-
8865
static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
8966
void __user *buffer, size_t *lenp, loff_t *ppos)
9067
{
@@ -96,63 +73,27 @@ static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
9673
lenp, ppos);
9774
}
9875

99-
/*
100-
* Routine that is called when the file "auto_msgmni" has successfully been
101-
* written.
102-
* Two values are allowed:
103-
* 0: unregister msgmni's callback routine from the ipc namespace notifier
104-
* chain. This means that msgmni won't be recomputed anymore upon memory
105-
* add/remove or ipc namespace creation/removal.
106-
* 1: register back the callback routine.
107-
*/
108-
static void ipc_auto_callback(int val)
109-
{
110-
if (!val)
111-
unregister_ipcns_notifier(current->nsproxy->ipc_ns);
112-
else {
113-
/*
114-
* Re-enable automatic recomputing only if not already
115-
* enabled.
116-
*/
117-
recompute_msgmni(current->nsproxy->ipc_ns);
118-
cond_register_ipcns_notifier(current->nsproxy->ipc_ns);
119-
}
120-
}
121-
122-
static int proc_ipcauto_dointvec_minmax(struct ctl_table *table, int write,
76+
static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
12377
void __user *buffer, size_t *lenp, loff_t *ppos)
12478
{
12579
struct ctl_table ipc_table;
126-
int oldval;
127-
int rc;
80+
int dummy = 0;
12881

12982
memcpy(&ipc_table, table, sizeof(ipc_table));
130-
ipc_table.data = get_ipc(table);
131-
oldval = *((int *)(ipc_table.data));
83+
ipc_table.data = &dummy;
13284

133-
rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
85+
if (write)
86+
pr_info_once("writing to auto_msgmni has no effect");
13487

135-
if (write && !rc) {
136-
int newval = *((int *)(ipc_table.data));
137-
/*
138-
* The file "auto_msgmni" has correctly been set.
139-
* React by (un)registering the corresponding tunable, if the
140-
* value has changed.
141-
*/
142-
if (newval != oldval)
143-
ipc_auto_callback(newval);
144-
}
145-
146-
return rc;
88+
return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
14789
}
14890

14991
#else
15092
#define proc_ipc_doulongvec_minmax NULL
15193
#define proc_ipc_dointvec NULL
15294
#define proc_ipc_dointvec_minmax NULL
15395
#define proc_ipc_dointvec_minmax_orphans NULL
154-
#define proc_ipc_callback_dointvec_minmax NULL
155-
#define proc_ipcauto_dointvec_minmax NULL
96+
#define proc_ipc_auto_msgmni NULL
15697
#endif
15798

15899
static int zero;
@@ -204,10 +145,19 @@ static struct ctl_table ipc_kern_table[] = {
204145
.data = &init_ipc_ns.msg_ctlmni,
205146
.maxlen = sizeof(init_ipc_ns.msg_ctlmni),
206147
.mode = 0644,
207-
.proc_handler = proc_ipc_callback_dointvec_minmax,
148+
.proc_handler = proc_ipc_dointvec_minmax,
208149
.extra1 = &zero,
209150
.extra2 = &int_max,
210151
},
152+
{
153+
.procname = "auto_msgmni",
154+
.data = NULL,
155+
.maxlen = sizeof(int),
156+
.mode = 0644,
157+
.proc_handler = proc_ipc_auto_msgmni,
158+
.extra1 = &zero,
159+
.extra2 = &one,
160+
},
211161
{
212162
.procname = "msgmnb",
213163
.data = &init_ipc_ns.msg_ctlmnb,
@@ -224,15 +174,6 @@ static struct ctl_table ipc_kern_table[] = {
224174
.mode = 0644,
225175
.proc_handler = proc_ipc_dointvec,
226176
},
227-
{
228-
.procname = "auto_msgmni",
229-
.data = &init_ipc_ns.auto_msgmni,
230-
.maxlen = sizeof(int),
231-
.mode = 0644,
232-
.proc_handler = proc_ipcauto_dointvec_minmax,
233-
.extra1 = &zero,
234-
.extra2 = &one,
235-
},
236177
#ifdef CONFIG_CHECKPOINT_RESTORE
237178
{
238179
.procname = "sem_next_id",

ipc/ipcns_notifier.c

Lines changed: 0 additions & 92 deletions
This file was deleted.

ipc/msg.c

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -989,43 +989,12 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz,
989989
return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill);
990990
}
991991

992-
/*
993-
* Scale msgmni with the available lowmem size: the memory dedicated to msg
994-
* queues should occupy at most 1/MSG_MEM_SCALE of lowmem.
995-
* Also take into account the number of nsproxies created so far.
996-
* This should be done staying within the (MSGMNI , IPCMNI/nr_ipc_ns) range.
997-
*/
998-
void recompute_msgmni(struct ipc_namespace *ns)
999-
{
1000-
struct sysinfo i;
1001-
unsigned long allowed;
1002-
int nb_ns;
1003-
1004-
si_meminfo(&i);
1005-
allowed = (((i.totalram - i.totalhigh) / MSG_MEM_SCALE) * i.mem_unit)
1006-
/ MSGMNB;
1007-
nb_ns = atomic_read(&nr_ipc_ns);
1008-
allowed /= nb_ns;
1009-
1010-
if (allowed < MSGMNI) {
1011-
ns->msg_ctlmni = MSGMNI;
1012-
return;
1013-
}
1014-
1015-
if (allowed > IPCMNI / nb_ns) {
1016-
ns->msg_ctlmni = IPCMNI / nb_ns;
1017-
return;
1018-
}
1019-
1020-
ns->msg_ctlmni = allowed;
1021-
}
1022992

1023993
void msg_init_ns(struct ipc_namespace *ns)
1024994
{
1025995
ns->msg_ctlmax = MSGMAX;
1026996
ns->msg_ctlmnb = MSGMNB;
1027-
1028-
recompute_msgmni(ns);
997+
ns->msg_ctlmni = MSGMNI;
1029998

1030999
atomic_set(&ns->msg_bytes, 0);
10311000
atomic_set(&ns->msg_hdrs, 0);
@@ -1069,9 +1038,6 @@ void __init msg_init(void)
10691038
{
10701039
msg_init_ns(&init_ipc_ns);
10711040

1072-
printk(KERN_INFO "msgmni has been set to %d\n",
1073-
init_ipc_ns.msg_ctlmni);
1074-
10751041
ipc_init_proc_interface("sysvipc/msg",
10761042
" key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n",
10771043
IPC_MSG_IDS, sysvipc_msg_proc_show);

0 commit comments

Comments
 (0)