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 <[email protected]>
---
 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
[email protected]
https://listman.redhat.com/mailman/listinfo/crash-utility

Reply via email to