[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