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

Ruslan Kuprieiev kupruser at gmail.com
Wed Apr 22 03:17:10 PDT 2015



On 22.04.15 12:49, Pavel Emelyanov wrote:
> 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?

The difference is simple, stat has the same as /proc/pid/comm has - just 
a last
part of the path to the executable. Cmdline in its turn has a full 
command that
user has executed including arguments.
For example:
➜  ~  cat /proc/self/stat
19419 (cat) R 19345 19419 19345 34844 19419 4218880 121 0 0 0 0 0 0 0 20 
0 1 0 56459494 13172736 174 18446744073709551615 4194304 4238788 
140735357310672 140735357310672 140481034782736 0 0 0 0 0 0 0 17 5 0 0 0 
0 0 6336016 6337300 36659200 140735357319149 140735357319169 
140735357319169 140735357321199 0
➜  ~  cat /proc/self/comm
cat
➜  ~  cat /proc/self/cmdline
cat/proc/self/cmdline

And we really need cmdline, as we need not only name of the executable 
but also
arguments that were passed.

And in task_struct we can see:
         char comm[TASK_COMM_LEN]; /* executable name excluding path

And cmdline is using:
         extern char *saved_command_line;

So kernel keeps them separately and I can't see a way to extract 
saved_command_line from comm.

> 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