[CRIU] [PATCH 1/3] dump: save /proc/pid/cmdline

Pavel Emelyanov xemul at parallels.com
Wed Apr 22 02:49:09 PDT 2015


On 04/19/2015 09:50 PM, Ruslan Kuprieiev wrote:
> We need it to produce core dump notes and don't use it on restore.

Can you check what's the difference between /proc/pid/cmdline and
the comm in /proc/pid/stat from the kernel point of view? Can we
drive them from one another?

Otherwise the patch looks OK.

-- Pavel

> Signed-off-by: Ruslan Kuprieiev <kupruser at gmail.com>
> ---
>  cr-dump.c            | 13 +++++++++++--
>  include/image.h      |  1 +
>  include/proc_parse.h |  1 +
>  proc_parse.c         | 35 +++++++++++++++++++++++++++++++++++
>  protobuf/core.proto  |  2 ++
>  pstree.c             |  4 +++-
>  6 files changed, 53 insertions(+), 3 deletions(-)
> 
> diff --git a/cr-dump.c b/cr-dump.c
> index ac41865..0ec3444 100644
> --- a/cr-dump.c
> +++ b/cr-dump.c
> @@ -653,7 +653,8 @@ int dump_thread_core(int pid, CoreEntry *core, const struct parasite_dump_thread
>  static int dump_task_core_all(struct pstree_item *item,
>  		const struct proc_pid_stat *stat,
>  		const struct parasite_dump_misc *misc,
> -		const struct cr_imgset *cr_imgset)
> +		const struct cr_imgset *cr_imgset,
> +		char cmdline[])
>  {
>  	struct cr_img *img;
>  	CoreEntry *core = item->core[0];
> @@ -669,6 +670,7 @@ static int dump_task_core_all(struct pstree_item *item,
>  		goto err;
>  
>  	strncpy((char *)core->tc->comm, stat->comm, TASK_COMM_LEN);
> +	strncpy((char *)core->tc->cmdline, cmdline, TASK_CMDLINE_LEN);
>  	core->tc->flags = stat->flags;
>  	core->tc->task_state = item->state;
>  	core->tc->exit_code = 0;
> @@ -1459,6 +1461,7 @@ static int dump_one_task(struct pstree_item *item)
>  	struct cr_imgset *cr_imgset = NULL;
>  	struct parasite_drain_fd *dfds = NULL;
>  	struct proc_posix_timers_stat proc_args;
> +	char cmdline[TASK_CMDLINE_LEN];
>  
>  	INIT_LIST_HEAD(&vmas.h);
>  	vmas.nr = 0;
> @@ -1478,6 +1481,12 @@ static int dump_one_task(struct pstree_item *item)
>  	if (ret < 0)
>  		goto err;
>  
> +	ret = parse_pid_cmdline(pid, cmdline);
> +	if (ret) {
> +		pr_err("Parse cmdline (pid: %d) failed with %d\n", pid, ret);
> +		goto err;
> +	}
> +
>  	ret = collect_mappings(pid, &vmas);
>  	if (ret) {
>  		pr_err("Collect mappings (pid: %d) failed with %d\n", pid, ret);
> @@ -1604,7 +1613,7 @@ static int dump_one_task(struct pstree_item *item)
>  		goto err_cure;
>  	}
>  
> -	ret = dump_task_core_all(item, &pps_buf, &misc, cr_imgset);
> +	ret = dump_task_core_all(item, &pps_buf, &misc, cr_imgset, cmdline);
>  	if (ret) {
>  		pr_err("Dump core (pid: %d) failed with %d\n", pid, ret);
>  		goto err_cure;
> diff --git a/include/image.h b/include/image.h
> index 55e63dd..3e6d584 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -106,6 +106,7 @@
>  #define CR_CAP_SIZE	2
>  
>  #define TASK_COMM_LEN 16
> +#define TASK_CMDLINE_LEN 80
>  
>  #define TASK_ALIVE		0x1
>  #define TASK_DEAD		0x2
> diff --git a/include/proc_parse.h b/include/proc_parse.h
> index e5d59d2..3ca93ef 100644
> --- a/include/proc_parse.h
> +++ b/include/proc_parse.h
> @@ -157,6 +157,7 @@ struct vm_area_list;
>  extern bool add_skip_mount(const char *mountpoint);
>  extern struct mount_info *parse_mountinfo(pid_t pid, struct ns_id *nsid, bool for_dump);
>  extern int parse_pid_stat(pid_t pid, struct proc_pid_stat *s);
> +extern int parse_pid_cmdline(pid_t pid, char cmdline[]);
>  extern int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list);
>  extern int parse_self_maps_lite(struct vm_area_list *vms);
>  extern int parse_pid_status(pid_t pid, struct proc_status_creds *);
> diff --git a/proc_parse.c b/proc_parse.c
> index 5d50979..a283c9a 100644
> --- a/proc_parse.c
> +++ b/proc_parse.c
> @@ -615,6 +615,41 @@ err_n:
>  
>  }
>  
> +int parse_pid_cmdline(pid_t pid, char cmdline[])
> +{
> +	int fd;
> +	ssize_t n;
> +	char *p;
> +
> +	fd = open_proc(pid, "cmdline");
> +	if (fd < 0)
> +		return -1;
> +
> +	n = read(fd, buf, BUF_SIZE);
> +	/* 0 is okay, as it may be zombie */
> +	if (n < 0) {
> +		pr_perror("Can't read cmdline for %d\n", pid);
> +		close(fd);
> +		return -1;
> +	}
> +
> +	close(fd);
> +
> +	/*
> +	 * cmdline contains null-separated strings,
> +	 * so we need to replace '\0's with spaces.
> +	 */
> +	for (p = buf; p < buf + n; p++)
> +		if (*p == '\0')
> +			*p = ' ';
> +
> +	*p = '\0';
> +
> +	strncpy(cmdline, buf, TASK_CMDLINE_LEN);
> +
> +	return 0;
> +}
> +
>  int parse_pid_stat(pid_t pid, struct proc_pid_stat *s)
>  {
>  	char *tok, *p;
> diff --git a/protobuf/core.proto b/protobuf/core.proto
> index 1f44a47..d6cce24 100644
> --- a/protobuf/core.proto
> +++ b/protobuf/core.proto
> @@ -25,6 +25,8 @@ message task_core_entry {
>  	optional uint32			cg_set		= 9;
>  
>  	optional signal_queue_entry	signals_s	= 10;
> +
> +	optional string			cmdline		= 11;
>  }
>  
>  message task_kobj_ids_entry {
> diff --git a/pstree.c b/pstree.c
> index 2dbcb04..f97423c 100644
> --- a/pstree.c
> +++ b/pstree.c
> @@ -37,7 +37,7 @@ CoreEntry *core_entry_alloc(int th, int tsk)
>  
>  	sz = sizeof(CoreEntry);
>  	if (tsk) {
> -		sz += sizeof(TaskCoreEntry) + TASK_COMM_LEN;
> +		sz += sizeof(TaskCoreEntry) + TASK_COMM_LEN + TASK_CMDLINE_LEN;
>  		if (th) {
>  			sz += sizeof(TaskRlimitsEntry);
>  			sz += RLIM_NLIMITS * sizeof(RlimitEntry *);
> @@ -60,6 +60,8 @@ CoreEntry *core_entry_alloc(int th, int tsk)
>  			task_core_entry__init(core->tc);
>  			core->tc->comm = xptr_pull_s(&m, TASK_COMM_LEN);
>  			memzero(core->tc->comm, TASK_COMM_LEN);
> +			core->tc->cmdline = xptr_pull_s(&m, TASK_CMDLINE_LEN);
> +			memzero(core->tc->cmdline, TASK_CMDLINE_LEN);
>  
>  			if (th) {
>  				TaskRlimitsEntry *rls;
> 



More information about the CRIU mailing list