diff options
author | Stanislav Kinsbursky <skinsbursky@parallels.com> | 2013-01-04 18:34:50 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-01-04 19:11:45 -0500 |
commit | 03f595668017f1a1fb971c02fc37140bc6e7bb1c (patch) | |
tree | 3aa5c4b32b5fd396f0d74679548de8c09ca195a1 /ipc | |
parent | 9afdacda0252fc1ddb7907728e878518edbcdfce (diff) |
ipc: add sysctl to specify desired next object id
Add 3 new variables and sysctls to tune them (by one "next_id" variable
for messages, semaphores and shared memory respectively). This variable
can be used to set desired id for next allocated IPC object. By default
it's equal to -1 and old behaviour is preserved. If this variable is
non-negative, then desired idr will be extracted from it and used as a
start value to search for free IDR slot.
Notes:
1) this patch doesn't guarantee that the new object will have desired
id. So it's up to user space how to handle new object with wrong id.
2) After a sucessful id allocation attempt, "next_id" will be set back
to -1 (if it was non-negative).
[akpm@linux-foundation.org: checkpatch fixes]
Signed-off-by: Stanislav Kinsbursky <skinsbursky@parallels.com>
Cc: Serge Hallyn <serge.hallyn@canonical.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/ipc_sysctl.c | 32 | ||||
-rw-r--r-- | ipc/util.c | 16 | ||||
-rw-r--r-- | ipc/util.h | 1 |
3 files changed, 45 insertions, 4 deletions
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 00fba2bab87d..130dfece27ac 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c | |||
@@ -158,6 +158,9 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, | |||
158 | 158 | ||
159 | static int zero; | 159 | static int zero; |
160 | static int one = 1; | 160 | static int one = 1; |
161 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
162 | static int int_max = INT_MAX; | ||
163 | #endif | ||
161 | 164 | ||
162 | static struct ctl_table ipc_kern_table[] = { | 165 | static struct ctl_table ipc_kern_table[] = { |
163 | { | 166 | { |
@@ -227,6 +230,35 @@ static struct ctl_table ipc_kern_table[] = { | |||
227 | .extra1 = &zero, | 230 | .extra1 = &zero, |
228 | .extra2 = &one, | 231 | .extra2 = &one, |
229 | }, | 232 | }, |
233 | #ifdef CONFIG_CHECKPOINT_RESTORE | ||
234 | { | ||
235 | .procname = "sem_next_id", | ||
236 | .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, | ||
237 | .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), | ||
238 | .mode = 0644, | ||
239 | .proc_handler = proc_ipc_dointvec_minmax, | ||
240 | .extra1 = &zero, | ||
241 | .extra2 = &int_max, | ||
242 | }, | ||
243 | { | ||
244 | .procname = "msg_next_id", | ||
245 | .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, | ||
246 | .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), | ||
247 | .mode = 0644, | ||
248 | .proc_handler = proc_ipc_dointvec_minmax, | ||
249 | .extra1 = &zero, | ||
250 | .extra2 = &int_max, | ||
251 | }, | ||
252 | { | ||
253 | .procname = "shm_next_id", | ||
254 | .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, | ||
255 | .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), | ||
256 | .mode = 0644, | ||
257 | .proc_handler = proc_ipc_dointvec_minmax, | ||
258 | .extra1 = &zero, | ||
259 | .extra2 = &int_max, | ||
260 | }, | ||
261 | #endif | ||
230 | {} | 262 | {} |
231 | }; | 263 | }; |
232 | 264 | ||
diff --git a/ipc/util.c b/ipc/util.c index 72fd0785ac94..74e1d9c7a98a 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids) | |||
122 | 122 | ||
123 | ids->in_use = 0; | 123 | ids->in_use = 0; |
124 | ids->seq = 0; | 124 | ids->seq = 0; |
125 | ids->next_id = -1; | ||
125 | { | 126 | { |
126 | int seq_limit = INT_MAX/SEQ_MULTIPLIER; | 127 | int seq_limit = INT_MAX/SEQ_MULTIPLIER; |
127 | if (seq_limit > USHRT_MAX) | 128 | if (seq_limit > USHRT_MAX) |
@@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
252 | kuid_t euid; | 253 | kuid_t euid; |
253 | kgid_t egid; | 254 | kgid_t egid; |
254 | int id, err; | 255 | int id, err; |
256 | int next_id = ids->next_id; | ||
255 | 257 | ||
256 | if (size > IPCMNI) | 258 | if (size > IPCMNI) |
257 | size = IPCMNI; | 259 | size = IPCMNI; |
@@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
264 | rcu_read_lock(); | 266 | rcu_read_lock(); |
265 | spin_lock(&new->lock); | 267 | spin_lock(&new->lock); |
266 | 268 | ||
267 | err = idr_get_new(&ids->ipcs_idr, new, &id); | 269 | err = idr_get_new_above(&ids->ipcs_idr, new, |
270 | (next_id < 0) ? 0 : ipcid_to_idx(next_id), &id); | ||
268 | if (err) { | 271 | if (err) { |
269 | spin_unlock(&new->lock); | 272 | spin_unlock(&new->lock); |
270 | rcu_read_unlock(); | 273 | rcu_read_unlock(); |
@@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
277 | new->cuid = new->uid = euid; | 280 | new->cuid = new->uid = euid; |
278 | new->gid = new->cgid = egid; | 281 | new->gid = new->cgid = egid; |
279 | 282 | ||
280 | new->seq = ids->seq++; | 283 | if (next_id < 0) { |
281 | if(ids->seq > ids->seq_max) | 284 | new->seq = ids->seq++; |
282 | ids->seq = 0; | 285 | if (ids->seq > ids->seq_max) |
286 | ids->seq = 0; | ||
287 | } else { | ||
288 | new->seq = ipcid_to_seqx(next_id); | ||
289 | ids->next_id = -1; | ||
290 | } | ||
283 | 291 | ||
284 | new->id = ipc_buildid(id, new->seq); | 292 | new->id = ipc_buildid(id, new->seq); |
285 | return id; | 293 | return id; |
diff --git a/ipc/util.h b/ipc/util.h index c8fe2f7631e9..a61e0ca2bffd 100644 --- a/ipc/util.h +++ b/ipc/util.h | |||
@@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header, | |||
92 | #define IPC_SHM_IDS 2 | 92 | #define IPC_SHM_IDS 2 |
93 | 93 | ||
94 | #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) | 94 | #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) |
95 | #define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER) | ||
95 | 96 | ||
96 | /* must be called with ids->rw_mutex acquired for writing */ | 97 | /* must be called with ids->rw_mutex acquired for writing */ |
97 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); | 98 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); |