diff options
-rw-r--r-- | Documentation/sysctl/kernel.txt | 10 | ||||
-rw-r--r-- | include/linux/ipc_namespace.h | 20 | ||||
-rw-r--r-- | include/uapi/linux/msg.h | 28 | ||||
-rw-r--r-- | ipc/Makefile | 2 | ||||
-rw-r--r-- | ipc/ipc_sysctl.c | 93 | ||||
-rw-r--r-- | ipc/ipcns_notifier.c | 92 | ||||
-rw-r--r-- | ipc/msg.c | 36 | ||||
-rw-r--r-- | ipc/namespace.c | 22 | ||||
-rw-r--r-- | ipc/util.c | 40 |
9 files changed, 45 insertions, 298 deletions
diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index b5d0c8501a18..75511efefc64 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt | |||
@@ -116,10 +116,12 @@ set during run time. | |||
116 | 116 | ||
117 | auto_msgmni: | 117 | auto_msgmni: |
118 | 118 | ||
119 | Enables/Disables automatic recomputing of msgmni upon memory add/remove | 119 | This variable has no effect and may be removed in future kernel |
120 | or upon ipc namespace creation/removal (see the msgmni description | 120 | releases. Reading it always returns 0. |
121 | above). Echoing "1" into this file enables msgmni automatic recomputing. | 121 | Up to Linux 3.17, it enabled/disabled automatic recomputing of msgmni |
122 | Echoing "0" turns it off. auto_msgmni default value is 1. | 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. | ||
123 | 125 | ||
124 | 126 | ||
125 | ============================================================== | 127 | ============================================================== |
diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index 35e7eca4e33b..e365d5ec69cb 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h | |||
@@ -7,15 +7,6 @@ | |||
7 | #include <linux/notifier.h> | 7 | #include <linux/notifier.h> |
8 | #include <linux/nsproxy.h> | 8 | #include <linux/nsproxy.h> |
9 | 9 | ||
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 | |||
19 | struct user_namespace; | 10 | struct user_namespace; |
20 | 11 | ||
21 | struct ipc_ids { | 12 | struct ipc_ids { |
@@ -38,7 +29,6 @@ struct ipc_namespace { | |||
38 | unsigned int msg_ctlmni; | 29 | unsigned int msg_ctlmni; |
39 | atomic_t msg_bytes; | 30 | atomic_t msg_bytes; |
40 | atomic_t msg_hdrs; | 31 | atomic_t msg_hdrs; |
41 | int auto_msgmni; | ||
42 | 32 | ||
43 | size_t shm_ctlmax; | 33 | size_t shm_ctlmax; |
44 | size_t shm_ctlall; | 34 | size_t shm_ctlall; |
@@ -77,18 +67,8 @@ extern atomic_t nr_ipc_ns; | |||
77 | extern spinlock_t mq_lock; | 67 | extern spinlock_t mq_lock; |
78 | 68 | ||
79 | #ifdef CONFIG_SYSVIPC | 69 | #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); | ||
84 | extern void shm_destroy_orphaned(struct ipc_namespace *ns); | 70 | extern void shm_destroy_orphaned(struct ipc_namespace *ns); |
85 | #else /* CONFIG_SYSVIPC */ | 71 | #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; } | ||
92 | static inline void shm_destroy_orphaned(struct ipc_namespace *ns) {} | 72 | static inline void shm_destroy_orphaned(struct ipc_namespace *ns) {} |
93 | #endif /* CONFIG_SYSVIPC */ | 73 | #endif /* CONFIG_SYSVIPC */ |
94 | 74 | ||
diff --git a/include/uapi/linux/msg.h b/include/uapi/linux/msg.h index a70375526578..f51c8001dbe5 100644 --- a/include/uapi/linux/msg.h +++ b/include/uapi/linux/msg.h | |||
@@ -51,16 +51,28 @@ struct msginfo { | |||
51 | }; | 51 | }; |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Scaling factor to compute msgmni: | 54 | * MSGMNI, MSGMAX and MSGMNB are default values which can be |
55 | * the memory dedicated to msg queues (msgmni * msgmnb) should occupy | 55 | * modified by sysctl. |
56 | * at most 1/MSG_MEM_SCALE of the lowmem (see the formula in ipc/msg.c): | 56 | * |
57 | * up to 8MB : msgmni = 16 (MSGMNI) | 57 | * MSGMNI is the upper limit for the number of messages queues per |
58 | * 4 GB : msgmni = 8K | 58 | * namespace. |
59 | * more than 16 GB : msgmni = 32K (IPCMNI) | 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). | ||
60 | */ | 73 | */ |
61 | #define MSG_MEM_SCALE 32 | ||
62 | 74 | ||
63 | #define MSGMNI 16 /* <= IPCMNI */ /* max # of msg queue identifiers */ | 75 | #define MSGMNI 32000 /* <= IPCMNI */ /* max # of msg queue identifiers */ |
64 | #define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */ | 76 | #define MSGMAX 8192 /* <= INT_MAX */ /* max size of message (bytes) */ |
65 | #define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */ | 77 | #define MSGMNB 16384 /* <= INT_MAX */ /* default max size of a message queue */ |
66 | 78 | ||
diff --git a/ipc/Makefile b/ipc/Makefile index 9075e172e52c..86c7300ecdf5 100644 --- a/ipc/Makefile +++ b/ipc/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_SYSVIPC_COMPAT) += compat.o | 5 | 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 |
7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o | 7 | obj-$(CONFIG_SYSVIPC_SYSCTL) += ipc_sysctl.o |
8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o | 8 | obj_mq-$(CONFIG_COMPAT) += compat_mq.o |
9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) | 9 | obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y) |
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index e8075b247497..8ad93c29f511 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c | |||
@@ -62,29 +62,6 @@ static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, | |||
62 | return err; | 62 | return err; |
63 | } | 63 | } |
64 | 64 | ||
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 | |||
88 | static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, | 65 | static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, |
89 | void __user *buffer, size_t *lenp, loff_t *ppos) | 66 | void __user *buffer, size_t *lenp, loff_t *ppos) |
90 | { | 67 | { |
@@ -96,54 +73,19 @@ static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, | |||
96 | lenp, ppos); | 73 | lenp, ppos); |
97 | } | 74 | } |
98 | 75 | ||
99 | /* | 76 | static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, |
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, | ||
123 | void __user *buffer, size_t *lenp, loff_t *ppos) | 77 | void __user *buffer, size_t *lenp, loff_t *ppos) |
124 | { | 78 | { |
125 | struct ctl_table ipc_table; | 79 | struct ctl_table ipc_table; |
126 | int oldval; | 80 | int dummy = 0; |
127 | int rc; | ||
128 | 81 | ||
129 | memcpy(&ipc_table, table, sizeof(ipc_table)); | 82 | memcpy(&ipc_table, table, sizeof(ipc_table)); |
130 | ipc_table.data = get_ipc(table); | 83 | ipc_table.data = &dummy; |
131 | oldval = *((int *)(ipc_table.data)); | ||
132 | 84 | ||
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"); | ||
134 | 87 | ||
135 | if (write && !rc) { | 88 | return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); |
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; | ||
147 | } | 89 | } |
148 | 90 | ||
149 | #else | 91 | #else |
@@ -151,8 +93,7 @@ static int proc_ipcauto_dointvec_minmax(struct ctl_table *table, int write, | |||
151 | #define proc_ipc_dointvec NULL | 93 | #define proc_ipc_dointvec NULL |
152 | #define proc_ipc_dointvec_minmax NULL | 94 | #define proc_ipc_dointvec_minmax NULL |
153 | #define proc_ipc_dointvec_minmax_orphans NULL | 95 | #define proc_ipc_dointvec_minmax_orphans NULL |
154 | #define proc_ipc_callback_dointvec_minmax NULL | 96 | #define proc_ipc_auto_msgmni NULL |
155 | #define proc_ipcauto_dointvec_minmax NULL | ||
156 | #endif | 97 | #endif |
157 | 98 | ||
158 | static int zero; | 99 | static int zero; |
@@ -204,11 +145,20 @@ static struct ctl_table ipc_kern_table[] = { | |||
204 | .data = &init_ipc_ns.msg_ctlmni, | 145 | .data = &init_ipc_ns.msg_ctlmni, |
205 | .maxlen = sizeof(init_ipc_ns.msg_ctlmni), | 146 | .maxlen = sizeof(init_ipc_ns.msg_ctlmni), |
206 | .mode = 0644, | 147 | .mode = 0644, |
207 | .proc_handler = proc_ipc_callback_dointvec_minmax, | 148 | .proc_handler = proc_ipc_dointvec_minmax, |
208 | .extra1 = &zero, | 149 | .extra1 = &zero, |
209 | .extra2 = &int_max, | 150 | .extra2 = &int_max, |
210 | }, | 151 | }, |
211 | { | 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 | }, | ||
161 | { | ||
212 | .procname = "msgmnb", | 162 | .procname = "msgmnb", |
213 | .data = &init_ipc_ns.msg_ctlmnb, | 163 | .data = &init_ipc_ns.msg_ctlmnb, |
214 | .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), | 164 | .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), |
@@ -224,15 +174,6 @@ static struct ctl_table ipc_kern_table[] = { | |||
224 | .mode = 0644, | 174 | .mode = 0644, |
225 | .proc_handler = proc_ipc_dointvec, | 175 | .proc_handler = proc_ipc_dointvec, |
226 | }, | 176 | }, |
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 | }, | ||
236 | #ifdef CONFIG_CHECKPOINT_RESTORE | 177 | #ifdef CONFIG_CHECKPOINT_RESTORE |
237 | { | 178 | { |
238 | .procname = "sem_next_id", | 179 | .procname = "sem_next_id", |
diff --git a/ipc/ipcns_notifier.c b/ipc/ipcns_notifier.c deleted file mode 100644 index b9b31a4f77e1..000000000000 --- a/ipc/ipcns_notifier.c +++ /dev/null | |||
@@ -1,92 +0,0 @@ | |||
1 | /* | ||
2 | * linux/ipc/ipcns_notifier.c | ||
3 | * Copyright (C) 2007 BULL SA. Nadia Derbey | ||
4 | * | ||
5 | * Notification mechanism for ipc namespaces: | ||
6 | * The callback routine registered in the memory chain invokes the ipcns | ||
7 | * notifier chain with the IPCNS_MEMCHANGED event. | ||
8 | * Each callback routine registered in the ipcns namespace recomputes msgmni | ||
9 | * for the owning namespace. | ||
10 | */ | ||
11 | |||
12 | #include <linux/msg.h> | ||
13 | #include <linux/rcupdate.h> | ||
14 | #include <linux/notifier.h> | ||
15 | #include <linux/nsproxy.h> | ||
16 | #include <linux/ipc_namespace.h> | ||
17 | |||
18 | #include "util.h" | ||
19 | |||
20 | |||
21 | |||
22 | static BLOCKING_NOTIFIER_HEAD(ipcns_chain); | ||
23 | |||
24 | |||
25 | static int ipcns_callback(struct notifier_block *self, | ||
26 | unsigned long action, void *arg) | ||
27 | { | ||
28 | struct ipc_namespace *ns; | ||
29 | |||
30 | switch (action) { | ||
31 | case IPCNS_MEMCHANGED: /* amount of lowmem has changed */ | ||
32 | case IPCNS_CREATED: | ||
33 | case IPCNS_REMOVED: | ||
34 | /* | ||
35 | * It's time to recompute msgmni | ||
36 | */ | ||
37 | ns = container_of(self, struct ipc_namespace, ipcns_nb); | ||
38 | /* | ||
39 | * No need to get a reference on the ns: the 1st job of | ||
40 | * free_ipc_ns() is to unregister the callback routine. | ||
41 | * blocking_notifier_chain_unregister takes the wr lock to do | ||
42 | * it. | ||
43 | * When this callback routine is called the rd lock is held by | ||
44 | * blocking_notifier_call_chain. | ||
45 | * So the ipc ns cannot be freed while we are here. | ||
46 | */ | ||
47 | recompute_msgmni(ns); | ||
48 | break; | ||
49 | default: | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | return NOTIFY_OK; | ||
54 | } | ||
55 | |||
56 | int register_ipcns_notifier(struct ipc_namespace *ns) | ||
57 | { | ||
58 | int rc; | ||
59 | |||
60 | memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb)); | ||
61 | ns->ipcns_nb.notifier_call = ipcns_callback; | ||
62 | ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI; | ||
63 | rc = blocking_notifier_chain_register(&ipcns_chain, &ns->ipcns_nb); | ||
64 | if (!rc) | ||
65 | ns->auto_msgmni = 1; | ||
66 | return rc; | ||
67 | } | ||
68 | |||
69 | int cond_register_ipcns_notifier(struct ipc_namespace *ns) | ||
70 | { | ||
71 | int rc; | ||
72 | |||
73 | memset(&ns->ipcns_nb, 0, sizeof(ns->ipcns_nb)); | ||
74 | ns->ipcns_nb.notifier_call = ipcns_callback; | ||
75 | ns->ipcns_nb.priority = IPCNS_CALLBACK_PRI; | ||
76 | rc = blocking_notifier_chain_cond_register(&ipcns_chain, | ||
77 | &ns->ipcns_nb); | ||
78 | if (!rc) | ||
79 | ns->auto_msgmni = 1; | ||
80 | return rc; | ||
81 | } | ||
82 | |||
83 | void unregister_ipcns_notifier(struct ipc_namespace *ns) | ||
84 | { | ||
85 | blocking_notifier_chain_unregister(&ipcns_chain, &ns->ipcns_nb); | ||
86 | ns->auto_msgmni = 0; | ||
87 | } | ||
88 | |||
89 | int ipcns_notify(unsigned long val) | ||
90 | { | ||
91 | return blocking_notifier_call_chain(&ipcns_chain, val, NULL); | ||
92 | } | ||
@@ -989,43 +989,12 @@ SYSCALL_DEFINE5(msgrcv, int, msqid, struct msgbuf __user *, msgp, size_t, msgsz, | |||
989 | return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); | 989 | return do_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg, do_msg_fill); |
990 | } | 990 | } |
991 | 991 | ||
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 | } | ||
1022 | 992 | ||
1023 | void msg_init_ns(struct ipc_namespace *ns) | 993 | void msg_init_ns(struct ipc_namespace *ns) |
1024 | { | 994 | { |
1025 | ns->msg_ctlmax = MSGMAX; | 995 | ns->msg_ctlmax = MSGMAX; |
1026 | ns->msg_ctlmnb = MSGMNB; | 996 | ns->msg_ctlmnb = MSGMNB; |
1027 | 997 | ns->msg_ctlmni = MSGMNI; | |
1028 | recompute_msgmni(ns); | ||
1029 | 998 | ||
1030 | atomic_set(&ns->msg_bytes, 0); | 999 | atomic_set(&ns->msg_bytes, 0); |
1031 | atomic_set(&ns->msg_hdrs, 0); | 1000 | atomic_set(&ns->msg_hdrs, 0); |
@@ -1069,9 +1038,6 @@ void __init msg_init(void) | |||
1069 | { | 1038 | { |
1070 | msg_init_ns(&init_ipc_ns); | 1039 | msg_init_ns(&init_ipc_ns); |
1071 | 1040 | ||
1072 | printk(KERN_INFO "msgmni has been set to %d\n", | ||
1073 | init_ipc_ns.msg_ctlmni); | ||
1074 | |||
1075 | ipc_init_proc_interface("sysvipc/msg", | 1041 | ipc_init_proc_interface("sysvipc/msg", |
1076 | " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", | 1042 | " key msqid perms cbytes qnum lspid lrpid uid gid cuid cgid stime rtime ctime\n", |
1077 | IPC_MSG_IDS, sysvipc_msg_proc_show); | 1043 | IPC_MSG_IDS, sysvipc_msg_proc_show); |
diff --git a/ipc/namespace.c b/ipc/namespace.c index b54468e48e32..1a3ffd40356e 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c | |||
@@ -45,14 +45,6 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns, | |||
45 | msg_init_ns(ns); | 45 | msg_init_ns(ns); |
46 | shm_init_ns(ns); | 46 | shm_init_ns(ns); |
47 | 47 | ||
48 | /* | ||
49 | * msgmni has already been computed for the new ipc ns. | ||
50 | * Thus, do the ipcns creation notification before registering that | ||
51 | * new ipcns in the chain. | ||
52 | */ | ||
53 | ipcns_notify(IPCNS_CREATED); | ||
54 | register_ipcns_notifier(ns); | ||
55 | |||
56 | ns->user_ns = get_user_ns(user_ns); | 48 | ns->user_ns = get_user_ns(user_ns); |
57 | 49 | ||
58 | return ns; | 50 | return ns; |
@@ -99,25 +91,11 @@ void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, | |||
99 | 91 | ||
100 | static void free_ipc_ns(struct ipc_namespace *ns) | 92 | static void free_ipc_ns(struct ipc_namespace *ns) |
101 | { | 93 | { |
102 | /* | ||
103 | * Unregistering the hotplug notifier at the beginning guarantees | ||
104 | * that the ipc namespace won't be freed while we are inside the | ||
105 | * callback routine. Since the blocking_notifier_chain_XXX routines | ||
106 | * hold a rw lock on the notifier list, unregister_ipcns_notifier() | ||
107 | * won't take the rw lock before blocking_notifier_call_chain() has | ||
108 | * released the rd lock. | ||
109 | */ | ||
110 | unregister_ipcns_notifier(ns); | ||
111 | sem_exit_ns(ns); | 94 | sem_exit_ns(ns); |
112 | msg_exit_ns(ns); | 95 | msg_exit_ns(ns); |
113 | shm_exit_ns(ns); | 96 | shm_exit_ns(ns); |
114 | atomic_dec(&nr_ipc_ns); | 97 | atomic_dec(&nr_ipc_ns); |
115 | 98 | ||
116 | /* | ||
117 | * Do the ipcns removal notification after decrementing nr_ipc_ns in | ||
118 | * order to have a correct value when recomputing msgmni. | ||
119 | */ | ||
120 | ipcns_notify(IPCNS_REMOVED); | ||
121 | put_user_ns(ns->user_ns); | 99 | put_user_ns(ns->user_ns); |
122 | proc_free_inum(ns->proc_inum); | 100 | proc_free_inum(ns->proc_inum); |
123 | kfree(ns); | 101 | kfree(ns); |
diff --git a/ipc/util.c b/ipc/util.c index 88adc329888c..106bed0378ab 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -71,44 +71,6 @@ struct ipc_proc_iface { | |||
71 | int (*show)(struct seq_file *, void *); | 71 | int (*show)(struct seq_file *, void *); |
72 | }; | 72 | }; |
73 | 73 | ||
74 | static void ipc_memory_notifier(struct work_struct *work) | ||
75 | { | ||
76 | ipcns_notify(IPCNS_MEMCHANGED); | ||
77 | } | ||
78 | |||
79 | static int ipc_memory_callback(struct notifier_block *self, | ||
80 | unsigned long action, void *arg) | ||
81 | { | ||
82 | static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier); | ||
83 | |||
84 | switch (action) { | ||
85 | case MEM_ONLINE: /* memory successfully brought online */ | ||
86 | case MEM_OFFLINE: /* or offline: it's time to recompute msgmni */ | ||
87 | /* | ||
88 | * This is done by invoking the ipcns notifier chain with the | ||
89 | * IPC_MEMCHANGED event. | ||
90 | * In order not to keep the lock on the hotplug memory chain | ||
91 | * for too long, queue a work item that will, when waken up, | ||
92 | * activate the ipcns notification chain. | ||
93 | */ | ||
94 | schedule_work(&ipc_memory_wq); | ||
95 | break; | ||
96 | case MEM_GOING_ONLINE: | ||
97 | case MEM_GOING_OFFLINE: | ||
98 | case MEM_CANCEL_ONLINE: | ||
99 | case MEM_CANCEL_OFFLINE: | ||
100 | default: | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | return NOTIFY_OK; | ||
105 | } | ||
106 | |||
107 | static struct notifier_block ipc_memory_nb = { | ||
108 | .notifier_call = ipc_memory_callback, | ||
109 | .priority = IPC_CALLBACK_PRI, | ||
110 | }; | ||
111 | |||
112 | /** | 74 | /** |
113 | * ipc_init - initialise ipc subsystem | 75 | * ipc_init - initialise ipc subsystem |
114 | * | 76 | * |
@@ -124,8 +86,6 @@ static int __init ipc_init(void) | |||
124 | sem_init(); | 86 | sem_init(); |
125 | msg_init(); | 87 | msg_init(); |
126 | shm_init(); | 88 | shm_init(); |
127 | register_hotmemory_notifier(&ipc_memory_nb); | ||
128 | register_ipcns_notifier(&init_ipc_ns); | ||
129 | return 0; | 89 | return 0; |
130 | } | 90 | } |
131 | device_initcall(ipc_init); | 91 | device_initcall(ipc_init); |