Sometimes kernel image is generated without CONFIG_SCHEDSTATS or CONFIG_SCHED_INFO. Where relevant commit id is f6db83479932 ("sched/stat: Simplify the sched_info accounting") - CONFIG_SCHED_INFO: KERNEL_VERSION >= LINUX(4,2,0) - CONFIG_SCHEDSTATS: KERNEL_VERSION < LINUX(4,2,0) Running crash-utility with above kernel image, "ps -l" option cannot display all processes sorted with most recently-run process. Also "ps -m" option cannot display all processes with timestamp. crash> ps -l or crash> ps -m ps: last-run timestamps do not exist in this kernel Usage: ps [-k|-u|-G] [-s] [-p|-c|-t|-[l|m][-C cpu]|-a|-g|-r|-S] [pid | task | command] ... Enter "help ps" for details. This is because output of "ps -l|-m" depends on task_struct.sched_info.last_arrival. Without CONFIG_SCHEDSTATS or CONFIG_SCHED_INFO, 'sched_info' field is not included in task_struct. So we make "ps -l|-m" option to access 'exec_start' field of sched_entity where 'exec_start' is task_struct.se.exec_start. With this patch, "ps -l|-m" option works well without CONFIG_SCHEDSTATS or CONFIG_SCHED_INFO. Signed-off-by: Austin Kim <austindh.kim@xxxxxxxxx> --- defs.h | 2 ++ symbols.c | 2 ++ task.c | 20 ++++++++++++++++---- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/defs.h b/defs.h index bf2c59b..5dda176 100644 --- a/defs.h +++ b/defs.h @@ -2168,6 +2168,8 @@ struct offset_table { /* stash of commonly-used offsets */ long sbitmap_queue_min_shallow_depth; long sbq_wait_state_wait_cnt; long sbq_wait_state_wait; + long task_struct_sched_entity; + long se_exec_start; }; struct size_table { /* stash of commonly-used sizes */ diff --git a/symbols.c b/symbols.c index ba5e274..e5abe87 100644 --- a/symbols.c +++ b/symbols.c @@ -8892,6 +8892,8 @@ dump_offset_table(char *spec, ulong makestruct) OFFSET(sched_rt_entity_run_list)); fprintf(fp, " sched_info_last_arrival: %ld\n", OFFSET(sched_info_last_arrival)); + fprintf(fp, " se_exec_start: %ld\n", + OFFSET(se_exec_start)); fprintf(fp, " task_struct_thread_info: %ld\n", OFFSET(task_struct_thread_info)); fprintf(fp, " task_struct_stack: %ld\n", diff --git a/task.c b/task.c index 864c838..55e2312 100644 --- a/task.c +++ b/task.c @@ -334,9 +334,15 @@ task_init(void) if (VALID_MEMBER(task_struct_sched_info)) MEMBER_OFFSET_INIT(sched_info_last_arrival, "sched_info", "last_arrival"); + MEMBER_OFFSET_INIT(task_struct_sched_entity, "task_struct", "se"); + if (VALID_MEMBER(task_struct_sched_entity)) { + STRUCT_SIZE_INIT(sched_entity, "sched_entity"); + MEMBER_OFFSET_INIT(se_exec_start, "sched_entity", "exec_start"); + } if (VALID_MEMBER(task_struct_last_run) || VALID_MEMBER(task_struct_timestamp) || - VALID_MEMBER(sched_info_last_arrival)) { + VALID_MEMBER(sched_info_last_arrival) || + VALID_MEMBER(se_exec_start)) { char buf[BUFSIZE]; strcpy(buf, "alias last ps -l"); alias_init(buf); @@ -3559,7 +3565,8 @@ cmd_ps(void) case 'm': if (INVALID_MEMBER(task_struct_last_run) && INVALID_MEMBER(task_struct_timestamp) && - INVALID_MEMBER(sched_info_last_arrival)) { + INVALID_MEMBER(sched_info_last_arrival) && + INVALID_MEMBER(se_exec_start)) { error(INFO, "last-run timestamps do not exist in this kernel\n"); argerrs++; @@ -3574,7 +3581,8 @@ cmd_ps(void) case 'l': if (INVALID_MEMBER(task_struct_last_run) && INVALID_MEMBER(task_struct_timestamp) && - INVALID_MEMBER(sched_info_last_arrival)) { + INVALID_MEMBER(sched_info_last_arrival) && + INVALID_MEMBER(se_exec_start)) { error(INFO, "last-run timestamps do not exist in this kernel\n"); argerrs++; @@ -6020,7 +6028,11 @@ task_last_run(ulong task) timestamp = tt->last_task_read ? ULONGLONG(tt->task_struct + OFFSET(task_struct_sched_info) + OFFSET(sched_info_last_arrival)) : 0; - + else if (VALID_MEMBER(se_exec_start)) + timestamp = tt->last_task_read ? ULONGLONG(tt->task_struct + + OFFSET(task_struct_sched_entity) + + OFFSET(se_exec_start)) : 0; + return timestamp; } -- 2.20.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility