[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