[CRIU] [PATCH v2 1/3] IPC: dump shared memory

Kinsbursky Stanislav skinsbursky at openvz.org
Fri Feb 3 12:00:11 EST 2012



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

---
 include/image.h |   11 +++++
 ipc_ns.c        |  112 +++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 111 insertions(+), 12 deletions(-)

diff --git a/include/image.h b/include/image.h
index 8e6a000..fd52bb0 100644
--- a/include/image.h
+++ b/include/image.h
@@ -121,6 +121,17 @@ struct ipc_ns_entry {
 	u32	in_use[3];
 } __packed;
 
+struct ipc_shm_entry {
+	u32	key;
+	u32	uid;
+	u32	gid;
+	u32	cuid;
+	u32	cgid;
+	u32	mode;
+	u64	size;
+	u32	id;
+} __packed;
+
 #define VMA_AREA_NONE		(0 <<  0)
 #define VMA_AREA_REGULAR	(1 <<  0)	/* Dumpable area */
 #define VMA_AREA_STACK		(1 <<  1)
diff --git a/ipc_ns.c b/ipc_ns.c
index 3336d8c..34a4c92 100644
--- a/ipc_ns.c
+++ b/ipc_ns.c
@@ -15,6 +15,7 @@
 
 struct ipc_ns_data {
 	struct ipc_ns_entry entry;
+	struct ipc_shm_entry *shm;
 };
 
 #define IPC_SEM_IDS		0
@@ -79,22 +80,73 @@ static int collect_ipc_sem(void *data)
 	return 0;
 }
 
-static int collect_ipc_shm(void *data)
+static int collect_ipc_shm_seg(int id, struct ipc_shm_entry *entry)
 {
-	int fd;
-	int ret;
-	struct shmid_ds shmid;
+#if defined (__GLIBC__) && __GLIBC__ >= 2
+#define KEY __key
+#else
+#define KEY key
+#endif
+	int shmid;
+	struct shmid_ds ds;
+	struct ipc_perm *ipcp = &ds.shm_perm;
+	struct ipc_shm_data *shm_data;
+
+	shmid = shmctl(id, SHM_STAT, &ds);
+	if (shmid < 0)
+		return -ENOENT;
+
+	entry->key = ipcp->KEY;
+	entry->uid = ipcp->uid;
+	entry->gid = ipcp->gid;
+	entry->cuid = ipcp->cuid;
+	entry->cgid = ipcp->cgid;
+	entry->mode = ipcp->mode;
+	entry->size = ds.shm_segsz;
+	entry->id = shmid;
+
+	pr_info("id: %-10d ", shmid);
+	pr_info("key: 0x%08x ", ipcp->KEY);
+	pr_info("uid: %-10d gid: %-10d ", ipcp->uid, ipcp->gid);
+	pr_info("cpid: %-10d lpid: %-10d ", ds.shm_cpid, ds.shm_lpid);
+	pr_info ("mode: %-10o size: %-10lu nattch: %-10ld %-6s %-6s\n",
+		ipcp->mode & 0777,(unsigned long) ds.shm_segsz,
+		(long) ds.shm_nattch, ipcp->mode & SHM_DEST ? "dest" : "",
+		ipcp->mode & SHM_LOCKED ? "locked" : "");
 
-	ret = shmctl(0, IPC_INFO, &shmid);
-	if (ret < 0)
-		pr_perror("semctl failed");
+	return 0;
+}
 
-	if (ret) {
-		pr_err("IPC shared memory migration is not supported yet\n");
-		return -EINVAL;
+static int collect_ipc_shm(struct ipc_shm_entry **entries)
+{
+	int i, maxid;
+	struct shm_info shmid;
+	int err, slot;
+
+	maxid = shmctl(0, SHM_INFO, (void *)&shmid);
+	if (maxid < 0) {
+		pr_perror("shmctl(SHM_INFO) failed with %d\n", errno);
+		return -errno;
 	}
 
-	return 0;
+	pr_info("Collect %d IPC shared memory segments\n", shmid.used_ids);
+	*entries = xmalloc(shmid.used_ids * sizeof(struct ipc_shm_entry));
+	if (*entries == NULL) {
+		pr_perror("failed to allocate memory for SHM entries\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0, slot = 0; i <= maxid; i++) {
+		err = collect_ipc_shm_seg(i, &(*entries)[slot]);
+		if (!err)
+			slot++;
+	}
+	if (slot != shmid.used_ids) {
+		pr_err("Failed to collect %d (only %d succeeded)\n", shmid.used_ids, slot);
+		xfree(*entries);
+		return -EFAULT;
+	}
+	return shmid.used_ids;
 }
 
 static int collect_ipc_tun(struct ipc_ns_entry *e)
@@ -113,7 +165,7 @@ static int collect_ipc_data(struct ipc_ns_data *ipc)
 	entry->in_use[IPC_SEM_IDS] = ret = collect_ipc_sem(NULL);
 	if (ret < 0)
 		return ret;
-	entry->in_use[IPC_SHM_IDS] = ret = collect_ipc_shm(NULL);
+	entry->in_use[IPC_SHM_IDS] = ret = collect_ipc_shm(&ipc->shm);
 	if (ret < 0)
 		return ret;
 	ret = collect_ipc_tun(entry);
@@ -123,6 +175,35 @@ static int collect_ipc_data(struct ipc_ns_data *ipc)
 	return 0;
 }
 
+static int dump_ipc_shm(int fd, struct ipc_ns_data *ipc)
+{
+	int err;
+	int seg_nr = ipc->entry.in_use[IPC_SHM_IDS];
+	struct ipc_shm_entry *shm = ipc->shm;
+	void *data;
+
+	while (seg_nr--) {
+		err = write_img(fd, shm++);
+		if (err < 0) {
+			pr_err("Failed to write IPC shared memory structure\n");
+			return err;
+		}
+		data = shmat(shm->id, NULL, SHM_RDONLY);
+		if (data == (void *)-1) {
+			pr_err("Failed to attach IPC shared memory\n");
+			return -EFAULT;
+		}
+		err = write_img_buf(fd, data, round_up(shm->size, sizeof(u32)));
+		if (err < 0) {
+			pr_err("Failed to write IPC shared memory data\n");
+			return err;
+		}
+		if (shmdt(data))
+			pr_err("Failed to detach IPC shared memory\n");
+	}
+	return 0;
+}
+
 static int dump_ipc_data(int fd, struct ipc_ns_data *ipc)
 {
 	int err;
@@ -132,6 +213,13 @@ static int dump_ipc_data(int fd, struct ipc_ns_data *ipc)
 		pr_err("Failed to write IPC namespace entry\n");
 		return err;
 	}
+
+	err = dump_ipc_shm(fd, ipc);
+	if (err < 0) {
+		pr_err("Failed to write IPC shared memory\n");
+		return err;
+	}
+
 	return 0;
 }
 



More information about the CRIU mailing list