Root/
1 | /* |
2 | * Copyright (C) 2007 |
3 | * |
4 | * Author: Eric Biederman <ebiederm@xmision.com> |
5 | * |
6 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License as |
8 | * published by the Free Software Foundation, version 2 of the |
9 | * License. |
10 | */ |
11 | |
12 | #include <linux/module.h> |
13 | #include <linux/ipc.h> |
14 | #include <linux/nsproxy.h> |
15 | #include <linux/sysctl.h> |
16 | #include <linux/uaccess.h> |
17 | #include <linux/ipc_namespace.h> |
18 | #include <linux/msg.h> |
19 | #include "util.h" |
20 | |
21 | static void *get_ipc(ctl_table *table) |
22 | { |
23 | char *which = table->data; |
24 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; |
25 | which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; |
26 | return which; |
27 | } |
28 | |
29 | #ifdef CONFIG_PROC_SYSCTL |
30 | static int proc_ipc_dointvec(ctl_table *table, int write, |
31 | void __user *buffer, size_t *lenp, loff_t *ppos) |
32 | { |
33 | struct ctl_table ipc_table; |
34 | memcpy(&ipc_table, table, sizeof(ipc_table)); |
35 | ipc_table.data = get_ipc(table); |
36 | |
37 | return proc_dointvec(&ipc_table, write, buffer, lenp, ppos); |
38 | } |
39 | |
40 | static int proc_ipc_callback_dointvec(ctl_table *table, int write, |
41 | void __user *buffer, size_t *lenp, loff_t *ppos) |
42 | { |
43 | struct ctl_table ipc_table; |
44 | size_t lenp_bef = *lenp; |
45 | int rc; |
46 | |
47 | memcpy(&ipc_table, table, sizeof(ipc_table)); |
48 | ipc_table.data = get_ipc(table); |
49 | |
50 | rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos); |
51 | |
52 | if (write && !rc && lenp_bef == *lenp) |
53 | /* |
54 | * Tunable has successfully been changed by hand. Disable its |
55 | * automatic adjustment. This simply requires unregistering |
56 | * the notifiers that trigger recalculation. |
57 | */ |
58 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); |
59 | |
60 | return rc; |
61 | } |
62 | |
63 | static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, |
64 | void __user *buffer, size_t *lenp, loff_t *ppos) |
65 | { |
66 | struct ctl_table ipc_table; |
67 | memcpy(&ipc_table, table, sizeof(ipc_table)); |
68 | ipc_table.data = get_ipc(table); |
69 | |
70 | return proc_doulongvec_minmax(&ipc_table, write, buffer, |
71 | lenp, ppos); |
72 | } |
73 | |
74 | /* |
75 | * Routine that is called when the file "auto_msgmni" has successfully been |
76 | * written. |
77 | * Two values are allowed: |
78 | * 0: unregister msgmni's callback routine from the ipc namespace notifier |
79 | * chain. This means that msgmni won't be recomputed anymore upon memory |
80 | * add/remove or ipc namespace creation/removal. |
81 | * 1: register back the callback routine. |
82 | */ |
83 | static void ipc_auto_callback(int val) |
84 | { |
85 | if (!val) |
86 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); |
87 | else { |
88 | /* |
89 | * Re-enable automatic recomputing only if not already |
90 | * enabled. |
91 | */ |
92 | recompute_msgmni(current->nsproxy->ipc_ns); |
93 | cond_register_ipcns_notifier(current->nsproxy->ipc_ns); |
94 | } |
95 | } |
96 | |
97 | static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, |
98 | void __user *buffer, size_t *lenp, loff_t *ppos) |
99 | { |
100 | struct ctl_table ipc_table; |
101 | size_t lenp_bef = *lenp; |
102 | int oldval; |
103 | int rc; |
104 | |
105 | memcpy(&ipc_table, table, sizeof(ipc_table)); |
106 | ipc_table.data = get_ipc(table); |
107 | oldval = *((int *)(ipc_table.data)); |
108 | |
109 | rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); |
110 | |
111 | if (write && !rc && lenp_bef == *lenp) { |
112 | int newval = *((int *)(ipc_table.data)); |
113 | /* |
114 | * The file "auto_msgmni" has correctly been set. |
115 | * React by (un)registering the corresponding tunable, if the |
116 | * value has changed. |
117 | */ |
118 | if (newval != oldval) |
119 | ipc_auto_callback(newval); |
120 | } |
121 | |
122 | return rc; |
123 | } |
124 | |
125 | #else |
126 | #define proc_ipc_doulongvec_minmax NULL |
127 | #define proc_ipc_dointvec NULL |
128 | #define proc_ipc_callback_dointvec NULL |
129 | #define proc_ipcauto_dointvec_minmax NULL |
130 | #endif |
131 | |
132 | static int zero; |
133 | static int one = 1; |
134 | |
135 | static struct ctl_table ipc_kern_table[] = { |
136 | { |
137 | .procname = "shmmax", |
138 | .data = &init_ipc_ns.shm_ctlmax, |
139 | .maxlen = sizeof (init_ipc_ns.shm_ctlmax), |
140 | .mode = 0644, |
141 | .proc_handler = proc_ipc_doulongvec_minmax, |
142 | }, |
143 | { |
144 | .procname = "shmall", |
145 | .data = &init_ipc_ns.shm_ctlall, |
146 | .maxlen = sizeof (init_ipc_ns.shm_ctlall), |
147 | .mode = 0644, |
148 | .proc_handler = proc_ipc_doulongvec_minmax, |
149 | }, |
150 | { |
151 | .procname = "shmmni", |
152 | .data = &init_ipc_ns.shm_ctlmni, |
153 | .maxlen = sizeof (init_ipc_ns.shm_ctlmni), |
154 | .mode = 0644, |
155 | .proc_handler = proc_ipc_dointvec, |
156 | }, |
157 | { |
158 | .procname = "msgmax", |
159 | .data = &init_ipc_ns.msg_ctlmax, |
160 | .maxlen = sizeof (init_ipc_ns.msg_ctlmax), |
161 | .mode = 0644, |
162 | .proc_handler = proc_ipc_dointvec, |
163 | }, |
164 | { |
165 | .procname = "msgmni", |
166 | .data = &init_ipc_ns.msg_ctlmni, |
167 | .maxlen = sizeof (init_ipc_ns.msg_ctlmni), |
168 | .mode = 0644, |
169 | .proc_handler = proc_ipc_callback_dointvec, |
170 | }, |
171 | { |
172 | .procname = "msgmnb", |
173 | .data = &init_ipc_ns.msg_ctlmnb, |
174 | .maxlen = sizeof (init_ipc_ns.msg_ctlmnb), |
175 | .mode = 0644, |
176 | .proc_handler = proc_ipc_dointvec, |
177 | }, |
178 | { |
179 | .procname = "sem", |
180 | .data = &init_ipc_ns.sem_ctls, |
181 | .maxlen = 4*sizeof (int), |
182 | .mode = 0644, |
183 | .proc_handler = proc_ipc_dointvec, |
184 | }, |
185 | { |
186 | .procname = "auto_msgmni", |
187 | .data = &init_ipc_ns.auto_msgmni, |
188 | .maxlen = sizeof(int), |
189 | .mode = 0644, |
190 | .proc_handler = proc_ipcauto_dointvec_minmax, |
191 | .extra1 = &zero, |
192 | .extra2 = &one, |
193 | }, |
194 | {} |
195 | }; |
196 | |
197 | static struct ctl_table ipc_root_table[] = { |
198 | { |
199 | .procname = "kernel", |
200 | .mode = 0555, |
201 | .child = ipc_kern_table, |
202 | }, |
203 | {} |
204 | }; |
205 | |
206 | static int __init ipc_sysctl_init(void) |
207 | { |
208 | register_sysctl_table(ipc_root_table); |
209 | return 0; |
210 | } |
211 | |
212 | __initcall(ipc_sysctl_init); |
213 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9