aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/util.c
diff options
context:
space:
mode:
authorStanislav Kinsbursky <skinsbursky@parallels.com>2013-01-04 18:34:50 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-01-04 19:11:45 -0500
commit03f595668017f1a1fb971c02fc37140bc6e7bb1c (patch)
tree3aa5c4b32b5fd396f0d74679548de8c09ca195a1 /ipc/util.c
parent9afdacda0252fc1ddb7907728e878518edbcdfce (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/util.c')
-rw-r--r--ipc/util.c16
1 files changed, 12 insertions, 4 deletions
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;