[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