[CRIU] [PATCH v3 1/4] IPC: dump shared memory
Kir Kolyshkin
kir at openvz.org
Wed Feb 8 13:48:08 EST 2012
On 02/08/2012 09:26 PM, Kinsbursky Stanislav wrote:
>
> Signed-off-by: Stanislav Kinsbursky<skinsbursky at parallels.com>
>
> ---
> crtools.c | 6 +++
> include/crtools.h | 5 ++-
> include/image.h | 17 +++++++++
> ipc_ns.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++-----
> 4 files changed, 123 insertions(+), 11 deletions(-)
>
> diff --git a/crtools.c b/crtools.c
> index 6f6c254..c43eeab 100644
> --- a/crtools.c
> +++ b/crtools.c
> @@ -116,6 +116,12 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
> .fmt = FMT_FNAME_IPCNS_VAR,
> .magic = IPCNS_VAR_MAGIC,
> },
> +
> + /* IPC namespace shared memory */
> + [CR_FD_IPCNS_SHM] = {
> + .fmt = FMT_FNAME_IPCNS_SHM,
> + .magic = IPCNS_SHM_MAGIC,
> + },
> };
>
> static struct cr_fdset *alloc_cr_fdset(void)
> diff --git a/include/crtools.h b/include/crtools.h
> index 868ab38..cf7a46b 100644
> --- a/include/crtools.h
> +++ b/include/crtools.h
> @@ -38,6 +38,7 @@ enum {
> CR_FD_PSTREE,
> CR_FD_UTSNS,
> CR_FD_IPCNS_VAR,
> + CR_FD_IPCNS_SHM,
>
> CR_FD_MAX
> };
> @@ -80,6 +81,7 @@ extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
> #define FMT_FNAME_CREDS "creds-%d.img"
> #define FMT_FNAME_UTSNS "utsns-%d.img"
> #define FMT_FNAME_IPCNS_VAR "ipcns-var-%d.img"
> +#define FMT_FNAME_IPCNS_SHM "ipcns-shm-%d.img"
>
> extern int get_image_path(char *path, int size, const char *fmt, int pid);
>
> @@ -111,7 +113,8 @@ struct cr_fdset {
> CR_FD_DESC_USE(CR_FD_CREDS) )
> #define CR_FD_DESC_NS (\
> CR_FD_DESC_USE(CR_FD_UTSNS) |\
> - CR_FD_DESC_USE(CR_FD_IPCNS_VAR) )
> + CR_FD_DESC_USE(CR_FD_IPCNS_VAR) |\
> + CR_FD_DESC_USE(CR_FD_IPCNS_SHM) )
If you move the ending bracket ) to a separate line, your next patches
will be 1 line shorter and easier to read.
> #define CR_FD_DESC_NONE (0)
>
> int cr_dump_tasks(pid_t pid, struct cr_options *opts);
> diff --git a/include/image.h b/include/image.h
> index 84712a9..01a3b86 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -22,6 +22,7 @@
> #define UTSNS_MAGIC 0x54473203 /* Smolensk */
> #define CREDS_MAGIC 0x54023547 /* Kozelsk */
> #define IPCNS_VAR_MAGIC 0x53115007 /* Samara */
> +#define IPCNS_SHM_MAGIC 0x46283044 /* Odessa */
>
> #define PIPEFS_MAGIC 0x50495045
>
> @@ -125,6 +126,22 @@ struct ipc_var_entry {
> u32 mq_msgsize_max;
> } __packed;
>
> +struct ipc_seg {
> + u32 key;
> + u32 uid;
> + u32 gid;
> + u32 cuid;
> + u32 cgid;
> + u32 mode;
> + u32 id;
> + u8 pad[4];
> +} __packed;
> +
> +struct ipc_shm_entry {
> + struct ipc_seg seg;
> + u64 size;
> +} __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 de51715..877c16d 100644
> --- a/ipc_ns.c
> +++ b/ipc_ns.c
> @@ -13,6 +13,36 @@
> #include "namespaces.h"
> #include "sysctl.h"
>
> +static void print_ipc_seg(const struct ipc_seg *seg)
> +{
> + pr_info("id: %-10d key: 0x%08x ", seg->id, seg->key);
> + pr_info("uid: %-10d gid: %-10d ", seg->uid, seg->gid);
> + pr_info("cuid: %-10d cgid: %-10d ", seg->cuid, seg->cgid);
> + pr_info ("mode: %-10o ", seg->mode);
An extra space
> +}
> +
> +static void fill_ipc_seg(int id, struct ipc_seg *seg, const struct ipc_perm *ipcp)
> +{
> +#if defined (__GLIBC__)&& __GLIBC__>= 2
> +#define KEY __key
> +#else
> +#define KEY key
> +#endif
I would add a comment here saying something like (if I get it right) we
compile this file with and without glibc headers, and that struct
ipc_perm is different for kernel and glibc; in particular, kernel
version has item named 'key' while in glibc it is '__key', thus the define.
> + seg->id = id;
> + seg->key = ipcp->KEY;
> + seg->uid = ipcp->uid;
> + seg->gid = ipcp->gid;
> + seg->cuid = ipcp->cuid;
> + seg->cgid = ipcp->cgid;
> + seg->mode = ipcp->mode;
> +}
Add
#undef KEY
> +
> +static void print_ipc_shm(const struct ipc_shm_entry *shm)
> +{
> + print_ipc_seg(&shm->seg);
> + pr_info ("size: %-10lu\n", shm->size);
extra space
> +}
> +
> static int ipc_sysctl_req(struct ipc_var_entry *e, int op)
> {
> struct sysctl_req req[] = {
> @@ -71,21 +101,77 @@ static int dump_ipc_sem(void *data)
> return 0;
> }
>
> -static int dump_ipc_shm(void *data)
> +/*
> + * TODO: Function below should be later improved to locate and dump only dirty
> + * pages via updated sys_mincore().
> + */
> +static int dump_ipc_shm_pages(int fd, const struct ipc_shm_entry *shm)
> {
> - int fd;
> + void *data;
> int ret;
> - struct shmid_ds shmid;
>
> - ret = shmctl(0, IPC_INFO,&shmid);
> - if (ret< 0)
> - pr_perror("semctl failed");
> + data = shmat(shm->seg.id, NULL, SHM_RDONLY);
> + if (data == (void *)-1) {
> + pr_err("Failed to attach IPC shared memory\n");
Use pr_perror() here.
> + return -EFAULT;
> + }
> + ret = write_img_buf(fd, data, round_up(shm->size, sizeof(u32)));
> + if (ret< 0) {
> + pr_err("Failed to write IPC shared memory data\n");
> + return ret;
> + }
> + if (shmdt(data))
> + pr_err("Failed to detach IPC shared memory\n");
ditto
>
> - if (ret) {
> - pr_err("IPC shared memory migration is not supported yet\n");
> - return -EINVAL;
> + return 0;
> +}
> +
> +static int dump_ipc_shm_seg(int fd, int id, const struct shmid_ds *ds)
> +{
> + struct ipc_shm_entry shm;
> + int ret;
> +
> + fill_ipc_seg(id,&shm.seg,&ds->shm_perm);
> + shm.size = ds->shm_segsz;
> + print_ipc_shm(&shm);
> +
> + ret = write_img(fd,&shm);
> + if (ret< 0) {
> + pr_err("Failed to write IPC shared memory segment\n");
> + return ret;
> }
> + return dump_ipc_shm_pages(fd,&shm);
> +}
>
> +static int dump_ipc_shm(int fd)
> +{
> + int i, maxid, slot;
> + struct shm_info info;
> +
> + maxid = shmctl(0, SHM_INFO, (void *)&info);
> + if (maxid< 0) {
> + pr_perror("shmctl(SHM_INFO) failed with %d\n", errno);
no need for \n
> + return -errno;
> + }
> +
> + pr_info("IPC shared memory segments: %d\n", info.used_ids);
> + for (i = 0, slot = 0; i<= maxid; i++) {
> + struct shmid_ds ds;
> + int id, ret;
> +
> + id = shmctl(i, SHM_STAT,&ds);
> + if (id< 0)
> + continue;
> + ret = dump_ipc_shm_seg(fd, id,&ds);
> + if (ret< 0)
> + return ret;
> + slot++;
> + }
> + if (slot != info.used_ids) {
> + pr_err("Failed to collect %d (only %d succeeded)\n",
> + info.used_ids, slot);
> + return -EFAULT;
> + }
> return 0;
> }
>
> @@ -115,7 +201,7 @@ static int dump_ipc_data(const struct cr_fdset *fdset)
> ret = dump_ipc_var(fdset->fds[CR_FD_IPCNS_VAR]);
> if (ret< 0)
> return ret;
> - ret = dump_ipc_shm(0);
> + ret = dump_ipc_shm(fdset->fds[CR_FD_IPCNS_SHM]);
> if (ret< 0)
> return ret;
> ret = dump_ipc_msg(0);
>
> _______________________________________________
> CRIU mailing list
> CRIU at openvz.org
> https://openvz.org/mailman/listinfo/criu
More information about the CRIU
mailing list