[CRIU] [PATCH 1/3] IPC: dump shared memory
Kinsbursky Stanislav
skinsbursky at openvz.org
Fri Feb 3 08:56:45 EST 2012
From: Stanislav Kinsbursky <skinsbursky at parallels.com>
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