[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