[CRIU] Re: [PATCH v2 1/3] IPC: dump shared memory
Pavel Emelyanov
xemul at parallels.com
Fri Feb 3 12:13:44 EST 2012
On 02/03/2012 09:00 PM, Kinsbursky Stanislav wrote:
>
>
> 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;
What's the profit in first collecting this stuff and then dumping? Why now
write it right into a file at the time of reading from kernel?
> };
>
> #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