[CRIU] [PATCH v2 3/3] IPC: restore shared memory

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


v2: added check that real id created shared memory is equal to desired one.

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

---
 ipc_ns.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/ipc_ns.c b/ipc_ns.c
index ce950ea..7fce9be 100644
--- a/ipc_ns.c
+++ b/ipc_ns.c
@@ -22,6 +22,9 @@ struct ipc_ns_data {
 #define IPC_MSG_IDS		1
 #define IPC_SHM_IDS		2
 
+#define IPC_PRESET		00040000
+#define SHM_SET			15
+
 static int ipc_sysctl_req(struct ipc_ns_entry *e, int op)
 {
 	struct sysctl_req req[] = {
@@ -183,7 +186,7 @@ static int dump_ipc_shm(int fd, struct ipc_ns_data *ipc)
 	void *data;
 
 	while (seg_nr--) {
-		err = write_img(fd, shm++);
+		err = write_img(fd, shm);
 		if (err < 0) {
 			pr_err("Failed to write IPC shared memory structure\n");
 			return err;
@@ -193,6 +196,7 @@ static int dump_ipc_shm(int fd, struct ipc_ns_data *ipc)
 			pr_err("Failed to attach IPC shared memory\n");
 			return -EFAULT;
 		}
+		pr_err("Write %ld bytes (size: %ld)\n", round_up(shm->size, sizeof(u32)), shm->size);
 		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");
@@ -200,6 +204,7 @@ static int dump_ipc_shm(int fd, struct ipc_ns_data *ipc)
 		}
 		if (shmdt(data))
 			pr_err("Failed to detach IPC shared memory\n");
+		shm++;
 	}
 	return 0;
 }
@@ -296,6 +301,65 @@ void show_ipc_ns(int fd)
 	pr_img_tail(CR_FD_IPCNS);
 }
 
+static int prepare_ipc_shm(int fd, int entries)
+{
+	pr_info("Restoring IPC shared memory\n");
+	while (entries--) {
+		int ret, id;
+		struct ipc_shm_entry shm;
+		struct shmid_ds ds;
+		void *data;
+
+		ret = read_img(fd, &shm);
+		if (ret <= 0)
+			return -EIO;
+
+		print_ipc_shm(&shm);
+
+		id = shmget(shm.id, shm.size,
+			     shm.mode | IPC_CREAT | IPC_EXCL | IPC_PRESET);
+		if (id == -1) {
+			pr_err("Failed to create shm segment\n");
+			return -errno;
+		}
+
+		if (id != shm.id) {
+			pr_err("Failed to preset id (%d instead of %d)\n",
+								id, shm.id);
+			return -EFAULT;
+		}
+
+		ret = shmctl(id, SHM_STAT, &ds);
+		if (ret < 0) {
+			pr_err("Failed to stat shm segment\n");
+			return -errno;
+		}
+
+		ds.shm_perm.KEY = shm.key;
+		ret = shmctl(id, SHM_SET, &ds);
+		if (ret < 0) {
+			pr_err("Failed to set shm segment\n");
+			return -errno;
+		}
+
+		data = shmat(id, NULL, 0);
+		if (data == (void *)-1) {
+			pr_err("Failed to attach IPC shared memory\n");
+			return -errno;
+		}
+		ret = read_img_buf(fd, data, round_up(shm.size, sizeof(u32)));
+		if (ret < 0) {
+			pr_err("Failed to read IPC shared memory data\n");
+			return ret;
+		}
+		if (shmdt(data)) {
+			pr_err("Failed to detach IPC shared memory\n");
+			return -errno;
+		}
+	}
+	return 0;
+}
+
 static int prepare_ipc_tun(struct ipc_ns_entry *e)
 {
 	return ipc_sysctl_req(e, CTL_WRITE);
@@ -304,12 +368,15 @@ static int prepare_ipc_tun(struct ipc_ns_entry *e)
 static int prepare_ipc_data(int fd)
 {
 	int ret;
-	struct ipc_ns_data ipc;
+	struct ipc_ns_entry entry;
 
-	ret = read_img(fd, &ipc);
+	ret = read_img(fd, &entry);
 	if (ret <= 0)
 		return -EFAULT;
-	ret = prepare_ipc_tun(&ipc.entry);
+	ret = prepare_ipc_tun(&entry);
+	if (ret < 0)
+		return ret;
+	ret = prepare_ipc_shm(fd, entry.in_use[IPC_SHM_IDS]);
 	if (ret < 0)
 		return ret;
 	return 0;
@@ -319,6 +386,7 @@ int prepare_ipc_ns(int pid)
 {
 	int fd, ret;
 
+	pr_info("Restoring IPC namespace\n");
 	fd = open_image_ro(CR_FD_IPCNS, pid);
 	if (fd < 0)
 		return -1;



More information about the CRIU mailing list