On Wed, Feb 22, 2023 at 5:36 PM <crash-utility-request@redhat.com> wrote:
Date: Wed, 22 Feb 2023 14:32:09 +0800
From: Tao Liu <ltao@redhat.com>
To: crash-utility@redhat.com
Subject: [Crash-utility] [PATCH] Fix for "search" command failing in
        maple tree kernel
Message-ID: <20230222063208.96447-1-ltao@redhat.com>
Content-Type: text/plain; charset="US-ASCII"; x-default=true

Kernel with maple tree enabled doesn't have mmap as a member of mm_struct[1],
so OFFSET(mm_struct_mmap) case needed to be handled differently for
maple tree kernel.

 
Thank you for the fix, Tao. We missed this case last time.
 
For the patch with Kazu's warning fix: Ack.

Thanks.
Lianbo

Before:
crash> search -u a

search: invalid structure member offset: mm_struct_mmap
        FILE: memory.c  LINE: 14255  FUNCTION: address_space_start()

[crash] error trace: 549500 => 548fff => 5f1c91 => 5f1c13

  5f1c13: OFFSET_verify.part.36+51
  5f1c91: OFFSET_verify+49
  548fff: address_space_start+106
  549500: cmd_search+855

search: invalid structure member offset: mm_struct_mmap
        FILE: memory.c  LINE: 14255  FUNCTION: address_space_start()

After:
crash> search -u a
7ffea63e6440: a

[1]: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=763ecb035029f500d7e6dc99acd1ad299b7726a1

Signed-off-by: Tao Liu <ltao@redhat.com>
---
 memory.c | 87 ++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 65 insertions(+), 22 deletions(-)

diff --git a/memory.c b/memory.c
index d9cd616..63ea9f4 100644
--- a/memory.c
+++ b/memory.c
@@ -14245,14 +14245,28 @@ vaddr_type(ulong vaddr, struct task_context *tc)
 static int
 address_space_start(struct task_context *tc, ulong *addr)
 {
-        ulong vma;
+       ulong mm_mt, entry_num, i, vma = 0;
         char *vma_buf;
+       struct list_pair *entry_list;

         if (!tc->mm_struct)
                 return FALSE;

-        fill_mm_struct(tc->mm_struct);
-        vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
+       if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) {
+               mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt);
+               entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL);
+               entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair));
+               do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list);
+               for (i = 0; i < entry_num; i++) {
+                       if (!!(vma = (ulong)entry_list[i].value))
+                               break;
+               }
+               FREEBUF(entry_list);
+       } else {
+               fill_mm_struct(tc->mm_struct);
+               vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
+       }
+
         if (!vma)
                 return FALSE;
        vma_buf = fill_vma_cache(vma);
@@ -15491,6 +15505,30 @@ search_physical(struct searchinfo *si)
        FREEBUF(pagebuf);
 }

+static bool
+check_vma(ulong vma, ulong vaddr, ulong *vm_next, ulong *nextvaddr)
+{
+       char *vma_buf;
+       ulong vm_start, vm_end;
+
+       vma_buf = fill_vma_cache(vma);
+
+       vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
+       vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
+       if (vm_next)
+               *vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
+
+       if (vaddr <= vm_start) {
+               *nextvaddr = vm_start;
+               return TRUE;
+       }
+
+       if ((vaddr > vm_start) && (vaddr < vm_end)) {
+               *nextvaddr = vaddr;
+               return TRUE;
+       }
+       return FALSE;
+}

 /*
  *  Return the next mapped user virtual address page that comes after
@@ -15503,34 +15541,39 @@ next_upage(struct task_context *tc, ulong vaddr, ulong *nextvaddr)
        char *vma_buf;
         ulong vm_start, vm_end;
        ulong vm_next;
+       ulong mm_mt, entry_num, i;
+       struct list_pair *entry_list;

         if (!tc->mm_struct)
                 return FALSE;

-        fill_mm_struct(tc->mm_struct);
-       vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));
+       fill_mm_struct(tc->mm_struct);
+       vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE();  /* first possible page */
        total_vm = ULONG(tt->mm_struct + OFFSET(mm_struct_total_vm));
-
-       if (!vma || (total_vm == 0))
+       if (!total_vm)
                return FALSE;

-       vaddr = VIRTPAGEBASE(vaddr) + PAGESIZE();  /* first possible page */
-
-        for ( ; vma; vma = vm_next) {
-                vma_buf = fill_vma_cache(vma);
-
-                vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start));
-                vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end));
-                vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next));
-
-               if (vaddr <= vm_start) {
-                       *nextvaddr = vm_start;
-                       return TRUE;
+       if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) {
+               mm_mt = tc->mm_struct + OFFSET(mm_struct_mm_mt);
+               entry_num = do_maple_tree(mm_mt, MAPLE_TREE_COUNT, NULL);
+               entry_list = (struct list_pair *)GETBUF(entry_num * sizeof(struct list_pair));
+               do_maple_tree(mm_mt, MAPLE_TREE_GATHER, entry_list);
+               for (i = 0; i < entry_num; i++) {
+                       if (!!(vma = (ulong)entry_list[i].value) &&
+                           check_vma(vma, vaddr, NULL, nextvaddr)) {
+                               FREEBUF(entry_list);
+                               return TRUE;
+                       }
                }
+               FREEBUF(entry_list);
+       } else {
+               vma = ULONG(tt->mm_struct + OFFSET(mm_struct_mmap));

-               if ((vaddr > vm_start) && (vaddr < vm_end)) {
-                       *nextvaddr = vaddr;
-                       return TRUE;
+               if (!vma)
+                       return FALSE;
+               for ( ; vma; vma = vm_next) {
+                       if (check_vma(vma, vaddr, &vm_next, nextvaddr))
+                               return TRUE;
                }
        }

--
2.33.1