[CRIU] [PATCH 2/2] protobuf: migration of IPC semaphores using protobuf

Kinsbursky Stanislav skinsbursky at openvz.org
Thu May 24 11:34:28 EDT 2012


From: Stanislav Kinsbursky <skinsbursky at openvz.org>

Signed-off-by: Stanislav Kinsbursky <skinsbursky at openvz.org>
---
 ipc_ns.c |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 152 insertions(+), 2 deletions(-)
-------------- next part --------------
diff --git a/ipc_ns.c b/ipc_ns.c
index 6dfe8f0..d38e80a 100644
--- a/ipc_ns.c
+++ b/ipc_ns.c
@@ -7,6 +7,8 @@
 #include <sys/sem.h>
 #include <sys/shm.h>
 
+#include "protobuf/ipc_sem.pb-c.h"
+
 #include "util.h"
 #include "crtools.h"
 #include "syscall.h"
@@ -90,6 +92,53 @@ static void pr_ipc_sem_entry(unsigned int loglevel, const struct ipc_sem_entry *
 #define pr_info_ipc_sem_entry(sem)		pr_ipc_sem_entry(LOG_INFO, sem)
 #define pr_msg_ipc_sem_entry(sem)		pr_ipc_sem_entry(LOG_MSG, sem)
 
+static int dump_ipc_sem_desc_protobuf(int fd, int id, const struct semid_ds *ds)
+{
+	IpcSemEntry sem;
+	int ret;
+	void *buf;
+
+	ipc_sem_entry__init(&sem);
+	sem.id = id;
+	sem.key = ds->sem_perm.KEY;
+	sem.uid = ds->sem_perm.uid;
+	sem.gid = ds->sem_perm.gid;
+	sem.cuid = ds->sem_perm.cuid;
+	sem.cgid = ds->sem_perm.cgid;
+	sem.mode = ds->sem_perm.mode;
+
+	sem.values.len = ds->sem_nsems * sizeof(u16);
+	sem.values.data = xmalloc(sem.values.len);
+	if (sem.values.data == NULL) {
+		pr_err("Failed to alloc memory for semaphore values\n");
+		return -ENOMEM;
+	}
+
+	ret = semctl(id, 0, GETALL, sem.values.data);
+	if (ret < 0) {
+		pr_perror("Failed to get semaphore set values");
+		return -errno;
+	}
+	pr_info_ipc_sem_array(ds->sem_nsems, (void *)&sem.values.data);
+
+	ret = ipc_sem_entry__get_packed_size(&sem);
+	pr_info("sem_size: %d\n", ret);
+
+	buf = xmalloc(ret);
+	if (buf == NULL) {
+		pr_err("Failed to alloc memory for semaphore\n");
+		return -ENOMEM;;
+	}
+	ipc_sem_entry__pack(&sem, buf);
+	ret = write_img_buf(fd, buf, ret);
+	if (ret < 0) {
+		pr_err("Failed to write IPC semaphores set\n");
+		return ret;
+	}
+	return 0;
+}
+
+#if 0
 static int dump_ipc_sem_set(int fd, const struct ipc_sem_entry *entry)
 {
 	int ret, size;
@@ -136,6 +185,7 @@ static int dump_ipc_sem_desc(int fd, int id, const struct semid_ds *ds)
 	}
 	return dump_ipc_sem_set(fd, &sem);
 }
+#endif
 
 static int dump_ipc_sem(int fd)
 {
@@ -161,7 +211,7 @@ static int dump_ipc_sem(int fd)
 			pr_perror("Failed to get stats for IPC semaphore set");
 			break;
 		}
-		ret = dump_ipc_sem_desc(fd, id, &ds);
+		ret = dump_ipc_sem_desc_protobuf(fd, id, &ds);
 		if (!ret)
 			slot++;
 	}
@@ -568,6 +618,7 @@ void show_ipc_var(int fd, struct cr_options *o)
 	pr_img_tail(CR_FD_IPCNS);
 }
 
+#if 0
 static int prepare_ipc_sem_values(int fd, const struct ipc_sem_entry *entry)
 {
 	int ret, size;
@@ -667,6 +718,105 @@ static int prepare_ipc_sem(int pid)
 	}
 	return close_safe(&fd);
 }
+#endif
+
+static int prepare_ipc_sem_values_protobuf(int fd, const IpcSemEntry *entry)
+{
+	int ret;
+
+	pr_info_ipc_sem_array(entry->values.len / sizeof(u16), (u16 *)entry->values.data);
+
+	ret = semctl(entry->id, 0, SETALL, (u16 *)entry->values.data);
+	if (ret < 0) {
+		pr_perror("Failed to set semaphores set values");
+		ret = -errno;
+	}
+	return ret;
+}
+
+static int prepare_ipc_sem_desc_protobuf(int fd, const IpcSemEntry *entry)
+{
+	int ret, id;
+	struct semid_ds ds;
+	int nsems = entry->values.len / sizeof(u16);
+
+	id = semget(entry->id, nsems,
+		     entry->mode | IPC_CREAT | IPC_EXCL | IPC_PRESET);
+	if (id == -1) {
+		pr_perror("Failed to create sem set");
+		return -errno;
+	}
+
+	if (id != entry->id) {
+		pr_err("Failed to preset id (%d instead of %d)\n",
+							id, entry->id);
+		return -EFAULT;
+	}
+
+	ret = semctl(id, 0, SEM_STAT, &ds);
+	if (ret < 0) {
+		pr_perror("Failed to stat sem set");
+		return -errno;
+	}
+
+	ds.sem_perm.KEY = entry->key;
+	ret = semctl(id, 0, SEM_SET, &ds);
+	if (ret < 0) {
+		pr_perror("Failed to update sem key");
+		return -errno;
+	}
+	ret = prepare_ipc_sem_values_protobuf(fd, entry);
+	if (ret < 0) {
+		pr_err("Failed to update sem pages\n");
+		return ret;
+	}
+	return 0;
+}
+
+static int prepare_ipc_sem_protobuf(int pid)
+{
+	int fd;
+	uint8_t buf[1024];
+	size_t offset = 4;
+
+	pr_info("Restoring IPC semaphores sets\n");
+
+	fd = open_image_ro(CR_FD_IPCNS_SEM, pid);
+	if (fd < 0)
+		return -1;
+
+	while (1) {
+		IpcSemEntry *entry;
+		int ret;
+
+		ret = read(fd, buf, 128);
+		if (ret < 0)
+			return -EIO;
+		if (ret == 0)
+			break;
+
+		pr_info("readed %d bytes\n", ret);
+
+		entry = ipc_sem_entry__unpack(NULL, ret, buf);
+		if (entry == NULL) {
+			pr_err("Failed to unpack semaphores set\n");
+			return -ENOMEM;
+		}
+
+		pr_info("ipc_sem_entry__get_packed_size(entry) %ld bytes\n", ipc_sem_entry__get_packed_size(entry));
+
+		ret = prepare_ipc_sem_desc_protobuf(fd, entry);
+		if (ret < 0) {
+			pr_err("Failed to prepare semaphores set\n");
+			return ret;
+		}
+
+		offset += ipc_sem_entry__get_packed_size(entry);
+		lseek(fd, offset, SEEK_SET);
+		ipc_sem_entry__free_unpacked(entry, NULL);
+	}
+	return close_safe(&fd);
+}
 
 static int prepare_ipc_msg_queue_messages(int fd, const struct ipc_msg_entry *entry)
 {
@@ -912,7 +1062,7 @@ int prepare_ipc_ns(int pid)
 	ret = prepare_ipc_msg(pid);
 	if (ret < 0)
 		return ret;
-	ret = prepare_ipc_sem(pid);
+	ret = prepare_ipc_sem_protobuf(pid);
 	if (ret < 0)
 		return ret;
 	return 0;


More information about the CRIU mailing list