On 8/1/2019 2:31 PM, Kazuhito Hagio wrote:
> On 8/1/2019 1:22 PM, Dave Anderson wrote:
>>
>>
>> ----- Original Message -----
>>> Hi Dave,
>>>
>>> I noticed that the "timer" command prints somewhat wrongly for RHEL7.6 or
>>> later kernels (not including RHEL8 / upstream) and found that it is because
>>> struct tvec and tvec_root have an array of list_head, instead of hlist_head
>>> in upstream kernels.
>>>
>>> So the following patch looks good only for RHEL7, but I don't know how we
>>> should determine the list type in order to switch the size, etc in this 
>>> case.
>>> What do you think?
>>
>> Try using the MEMBER_TYPE_NAME() macro.  For example, adding this to 
>> cmd_test():
> 
> Nice. I'll try to rewrite the patch with it.

I choose to add head_size arg to do_timer_list_v3().
This tested OK on RHEL7.6 and kernel 4.2.1.

Signed-off-by: Kazuhito Hagio <[email protected]>
---
diff --git a/kernel.c b/kernel.c
index a79e5a3010ea..7804aef2074b 100644
--- a/kernel.c
+++ b/kernel.c
@@ -53,7 +53,7 @@ static void dump_timer_data_timer_bases(const ulong *cpus);
 struct tv_range;
 static void init_tv_ranges(struct tv_range *, int, int, int);
 static int do_timer_list(ulong,int, ulong *, void *,ulong *, ulong *, struct 
tv_range *, ulong);
-static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *, ulong *, 
ulong);
+static int do_timer_list_v3(ulong, int, ulong *, void *,ulong *, ulong *, 
ulong, long);
 struct timer_bases_data;
 static int do_timer_list_v4(struct timer_bases_data *, ulong);
 static int compare_timer_data(const void *, const void *);
@@ -8376,7 +8376,12 @@ dump_timer_data_tvec_bases_v3(const ulong *cpus)
        char buf4[BUFSIZE];
 
        vec_root_size = vec_size = 0;
-       head_size = SIZE(hlist_head);
+
+       if (STREQ(MEMBER_TYPE_NAME("tvec_root", "vec"), "list_head"))
+               /* for RHEL7.6 or later */
+               head_size = SIZE(list_head);
+       else
+               head_size = SIZE(hlist_head);
 
        if ((i = get_array_length("tvec_root.vec", NULL, head_size)))
                vec_root_size = i;
@@ -8414,15 +8419,15 @@ next_cpu:
        init_tv_ranges(tv, vec_root_size, vec_size, cpu);
 
        count += do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
-               vec_root_size, vec, NULL, NULL, NULL, 0);
+               vec_root_size, vec, NULL, NULL, NULL, 0, head_size);
        count += do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
-               vec_size, vec, NULL, NULL, NULL, 0);
+               vec_size, vec, NULL, NULL, NULL, 0, head_size);
        count += do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
-               vec_size, vec, NULL, NULL, NULL, 0);
+               vec_size, vec, NULL, NULL, NULL, 0, head_size);
        count += do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
-               vec_size, vec, NULL, NULL, NULL, 0);
+               vec_size, vec, NULL, NULL, NULL, 0, head_size);
        count += do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
-               vec_size, vec, NULL, NULL, NULL, 0);
+               vec_size, vec, NULL, NULL, NULL, 0, head_size);
 
        if (count)
                td = (struct timer_data *)
@@ -8433,16 +8438,16 @@ next_cpu:
 
        get_symbol_data("jiffies", sizeof(ulong), &jiffies);
 
-       do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec),
-               vec_root_size, vec, (void *)td, &highest, &highest_tte, 
jiffies);
-       do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec),
-               vec_size, vec, (void *)td, &highest, &highest_tte, jiffies);
-       do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec),
-               vec_size, vec, (void *)td, &highest, &highest_tte, jiffies);
-       do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec),
-               vec_size, vec, (void *)td, &highest, &highest_tte, jiffies);
-       tdx = do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec),
-               vec_size, vec, (void *)td, &highest, &highest_tte, jiffies);
+       do_timer_list_v3(tv[1].base + OFFSET(tvec_root_s_vec), vec_root_size,
+               vec, (void *)td, &highest, &highest_tte, jiffies, head_size);
+       do_timer_list_v3(tv[2].base + OFFSET(tvec_s_vec), vec_size,
+               vec, (void *)td, &highest, &highest_tte, jiffies, head_size);
+       do_timer_list_v3(tv[3].base + OFFSET(tvec_s_vec), vec_size,
+               vec, (void *)td, &highest, &highest_tte, jiffies, head_size);
+       do_timer_list_v3(tv[4].base + OFFSET(tvec_s_vec), vec_size,
+               vec, (void *)td, &highest, &highest_tte, jiffies, head_size);
+       tdx = do_timer_list_v3(tv[5].base + OFFSET(tvec_s_vec), vec_size,
+               vec, (void *)td, &highest, &highest_tte, jiffies, head_size);
 
        qsort(td, tdx, sizeof(struct timer_data), compare_timer_data);
 
@@ -8786,7 +8791,8 @@ do_timer_list_v3(ulong vec_kvaddr,
              void *option, 
              ulong *highest,
              ulong *highest_tte,
-             ulong jiffies)
+             ulong jiffies,
+             long head_size)
 {
        int i, t; 
        int count, tdx;
@@ -8804,19 +8810,24 @@ do_timer_list_v3(ulong vec_kvaddr,
                        tdx++;
        }
 
-       readmem(vec_kvaddr, KVADDR, vec, SIZE(hlist_head) * size, 
+       readmem(vec_kvaddr, KVADDR, vec, head_size * size,
                "timer_list vec array", FAULT_ON_ERROR);
 
        ld = &list_data;
        timer_list_buf = GETBUF(SIZE(timer_list));
 
-       for (i = count = 0; i < size; i++, vec_kvaddr += SIZE(hlist_head)) {
+       for (i = count = 0; i < size; i++, vec_kvaddr += head_size) {
 
-               if (vec[i] == 0)
-                       continue;
+               if (head_size == SIZE(list_head)) {
+                       if (vec[i*2] == vec_kvaddr)
+                               continue;
+               } else {
+                       if (vec[i] == 0)
+                               continue;
+               }
 
                BZERO(ld, sizeof(struct list_data));
-               ld->start = vec[i];
+               ld->start = (head_size == SIZE(list_head)) ? vec[i*2] : vec[i];
                ld->list_head_offset = OFFSET(timer_list_entry);
                ld->end = vec_kvaddr;
                ld->flags = RETURN_ON_LIST_ERROR;

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to