]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ipc: add sysctl to specify desired next object id
authorStanislav Kinsbursky <skinsbursky@parallels.com>
Fri, 9 Nov 2012 03:05:05 +0000 (14:05 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 14 Nov 2012 04:55:22 +0000 (15:55 +1100)
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).

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>
include/linux/ipc_namespace.h
ipc/ipc_sysctl.c
ipc/util.c
ipc/util.h

index 5499c92a91539afcc0987d49fe6477acad2d16e4..8704e40e79bca6387fa7605c6c4ce8337053d198 100644 (file)
@@ -24,6 +24,7 @@ struct ipc_ids {
        unsigned short seq_max;
        struct rw_semaphore rw_mutex;
        struct idr ipcs_idr;
+       int next_id;
 };
 
 struct ipc_namespace {
index 00fba2bab87d8019739e4645f98e21559688dcbe..d06d77af1a41ba58200ad980b8d90253fdef499f 100644 (file)
@@ -158,6 +158,7 @@ static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
 
 static int zero;
 static int one = 1;
+static int int_max = INT_MAX;
 
 static struct ctl_table ipc_kern_table[] = {
        {
@@ -227,6 +228,33 @@ static struct ctl_table ipc_kern_table[] = {
                .extra1         = &zero,
                .extra2         = &one,
        },
+       {
+               .procname       = "sem_next_id",
+               .data           = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
+               .maxlen         = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &int_max,
+       },
+       {
+               .procname       = "msg_next_id",
+               .data           = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
+               .maxlen         = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &int_max,
+       },
+       {
+               .procname       = "shm_next_id",
+               .data           = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
+               .maxlen         = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
+               .mode           = 0644,
+               .proc_handler   = proc_ipc_dointvec_minmax,
+               .extra1         = &zero,
+               .extra2         = &int_max,
+       },
        {}
 };
 
index 72fd0785ac948b4c3813a2aac8f463ea41e7955f..a961e469433ade3cba9dcf7ad51f39d193694527 100644 (file)
@@ -122,6 +122,7 @@ void ipc_init_ids(struct ipc_ids *ids)
 
        ids->in_use = 0;
        ids->seq = 0;
+       ids->next_id = -1;
        {
                int seq_limit = INT_MAX/SEQ_MULTIPLIER;
                if (seq_limit > USHRT_MAX)
@@ -252,6 +253,7 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        kuid_t euid;
        kgid_t egid;
        int id, err;
+       int next_id = ids->next_id;
 
        if (size > IPCMNI)
                size = IPCMNI;
@@ -264,7 +266,8 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        rcu_read_lock();
        spin_lock(&new->lock);
 
-       err = idr_get_new(&ids->ipcs_idr, new, &id);
+       err = idr_get_new_above(&ids->ipcs_idr, new,
+                               (next_id < 0) ? 0 : ipcid_to_idx(next_id), &id);
        if (err) {
                spin_unlock(&new->lock);
                rcu_read_unlock();
@@ -277,9 +280,14 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
        new->cuid = new->uid = euid;
        new->gid = new->cgid = egid;
 
-       new->seq = ids->seq++;
-       if(ids->seq > ids->seq_max)
-               ids->seq = 0;
+       if (next_id < 0) {
+               new->seq = ids->seq++;
+               if(ids->seq > ids->seq_max)
+                       ids->seq = 0;
+       } else {
+               new->seq = ipcid_to_seqx(next_id);
+               ids->next_id = -1;
+       }
 
        new->id = ipc_buildid(id, new->seq);
        return id;
index c8fe2f7631e9b616177d69c8ac614e901db669d2..a61e0ca2bffd05c0d3d5dd390df95e140a4b4186 100644 (file)
@@ -92,6 +92,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
 #define IPC_SHM_IDS    2
 
 #define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)
+#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER)
 
 /* must be called with ids->rw_mutex acquired for writing */
 int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);