[CRIU] [PATCH 1/2] ipc: add new flag for preset shmem id on creation

Stanislav Kinsbursky skinsbursky at parallels.com
Thu Feb 2 08:07:49 EST 2012


This patch is required for checkpoint/restore of IPC shared memory segments.

The patch introduces new flag IPC_PRESET, which is interpreted as direction to
use passed key as the id of new segment to create on sys_shmget() call. IOW,
kernel will try allocate new segment in specified slot.
If slot is not emply, them -EEXIST returned.
Note: key and id will be identical for such segment after creation.

Signed-off-by: Stanislav Kinsbursky <skinsbursky at parallels.com>

---
 include/linux/ipc.h |    1 +
 ipc/shm.c           |    6 ++++++
 ipc/util.c          |    5 ++++-
 3 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/include/linux/ipc.h b/include/linux/ipc.h
index 30e8161..9dec1be 100644
--- a/include/linux/ipc.h
+++ b/include/linux/ipc.h
@@ -24,6 +24,7 @@ struct ipc_perm
 #define IPC_CREAT  00001000   /* create if key is nonexistent */
 #define IPC_EXCL   00002000   /* fail if key exists */
 #define IPC_NOWAIT 00004000   /* return error on wait */
+#define IPC_PRESET 00040000   /* set key as the id */
 
 /* these fields are used by the DIPC package so the kernel as standard
    should avoid using them if possible */
diff --git a/ipc/shm.c b/ipc/shm.c
index 02ecf2c..ac545d0 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -467,6 +467,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 		return -ENOMEM;
 
 	shp->shm_perm.key = key;
+	shp->shm_perm.id = 0;
 	shp->shm_perm.mode = (shmflg & S_IRWXUGO);
 	shp->mlock_user = NULL;
 
@@ -498,6 +499,11 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
 	if (IS_ERR(file))
 		goto no_file;
 
+	if (shmflg & IPC_PRESET) {
+		shp->shm_perm.id = key;
+		shp->shm_perm.seq = (unsigned long) key / SEQ_MULTIPLIER;
+	}
+
 	id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni);
 	if (id < 0) {
 		error = id;
diff --git a/ipc/util.c b/ipc/util.c
index 75261a3..9078560 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -264,7 +264,7 @@ 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, ipcid_to_idx(new->id), &id);
 	if (err) {
 		spin_unlock(&new->lock);
 		rcu_read_unlock();
@@ -277,6 +277,9 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
 	new->cuid = new->uid = euid;
 	new->gid = new->cgid = egid;
 
+	if (new->id)
+		return id;
+
 	new->seq = ids->seq++;
 	if(ids->seq > ids->seq_max)
 		ids->seq = 0;



More information about the CRIU mailing list