Since memory.c:vm_area_dump will iterate all vma, this patch mainly introduces maple tree vma iteration to it. We extract the code which handles each vma into a function. If mm_struct_mmap exist, aka the linked list of vma iteration available, we goto the original way; if not and mm_struct_mm_mt exist, aka maple tree is available, then we goto the maple tree vma iteration. Signed-off-by: Tao Liu <ltao@xxxxxxxxxx> --- Makefile | 4 +- defs.h | 1 + maple_tree_vma.h | 3 +- memory.c | 311 ++++++++++++++++++++++++++++------------------- 4 files changed, 188 insertions(+), 131 deletions(-) diff --git a/Makefile b/Makefile index d545bc0..4d7549c 100644 --- a/Makefile +++ b/Makefile @@ -59,7 +59,7 @@ IBM_HFILES=ibm_common.h SADUMP_HFILES=sadump.h UNWIND_HFILES=unwind.h unwind_i.h rse.h unwind_x86.h unwind_x86_64.h VMWARE_HFILES=vmware_vmss.h -MAPLE_TREE_HFILES=maple_tree.h xarray.h +MAPLE_TREE_HFILES=maple_tree.h xarray.h maple_tree_vma.h CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ kernel.c test.c gdb_interface.c configure.c net.c dev.c bpf.c \ @@ -355,7 +355,7 @@ filesys.o: ${GENERIC_HFILES} filesys.c help.o: ${GENERIC_HFILES} help.c ${CC} -c ${CRASH_CFLAGS} help.c ${WARNING_OPTIONS} ${WARNING_ERROR} -memory.o: ${GENERIC_HFILES} memory.c +memory.o: ${GENERIC_HFILES} ${MAPLE_TREE_HFILES} memory.c ${CC} -c ${CRASH_CFLAGS} memory.c ${WARNING_OPTIONS} ${WARNING_ERROR} test.o: ${GENERIC_HFILES} test.c diff --git a/defs.h b/defs.h index afdcf6c..d4be477 100644 --- a/defs.h +++ b/defs.h @@ -1332,6 +1332,7 @@ struct offset_table { /* stash of commonly-used offsets */ long percpu_struct_halt_ra; long percpu_struct_halt_pv; long mm_struct_mmap; + long mm_struct_mm_mt; long mm_struct_pgd; long mm_struct_rss; long mm_struct_anon_rss; diff --git a/maple_tree_vma.h b/maple_tree_vma.h index 0e006dc..0b861ff 100644 --- a/maple_tree_vma.h +++ b/maple_tree_vma.h @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0 */ #include "maple_tree.h" -#define for_each_vma(vmi, vma) while ((vma = vma_next(&(vmi))) != NULL) +#define for_each_vma(vmi, vma) \ + while ((vma = (ulong)vma_next(&(vmi))) != 0) struct vma_iterator { struct ma_state mas; diff --git a/memory.c b/memory.c index 7339f0c..00f7c9a 100644 --- a/memory.c +++ b/memory.c @@ -21,6 +21,7 @@ #include <ctype.h> #include <netinet/in.h> #include <byteswap.h> +#include "maple_tree_vma.h" struct meminfo { /* general purpose memory information structure */ ulong cache; /* used by the various memory searching/dumping */ @@ -362,6 +363,7 @@ vm_init(void) MEMBER_OFFSET_INIT(task_struct_mm, "task_struct", "mm"); MEMBER_OFFSET_INIT(mm_struct_mmap, "mm_struct", "mmap"); + MEMBER_OFFSET_INIT(mm_struct_mm_mt, "mm_struct", "mm_mt"); MEMBER_OFFSET_INIT(mm_struct_pgd, "mm_struct", "pgd"); MEMBER_OFFSET_INIT(mm_struct_rss, "mm_struct", "rss"); if (!VALID_MEMBER(mm_struct_rss)) @@ -3866,7 +3868,7 @@ bailout: * for references -- and only then does a display */ -#define PRINT_VM_DATA() \ +#define PRINT_VM_DATA(buf4, buf5, tm) \ { \ fprintf(fp, "%s %s ", \ mkstring(buf4, VADDR_PRLEN, CENTER|LJUST, "MM"), \ @@ -3888,7 +3890,7 @@ bailout: mkstring(buf5, 8, CENTER|LJUST, NULL)); \ } -#define PRINT_VMA_DATA() \ +#define PRINT_VMA_DATA(buf1, buf2, buf3, buf4, vma) \ fprintf(fp, "%s%s%s%s%s %6llx%s%s\n", \ mkstring(buf4, VADDR_PRLEN, CENTER|LJUST|LONG_HEX, MKSTR(vma)), \ space(MINSPACE), \ @@ -3917,18 +3919,164 @@ bailout: (DO_REF_SEARCH(X) && (string_exists(S)) && FILENAME_COMPONENT((S),(X)->str)) #define VM_REF_FOUND(X) ((X) && ((X)->cmdflags & VM_REF_HEADER)) -ulong -vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) -{ - struct task_context *tc; +struct handle_each_vm_area_args { + ulong task; + ulong flag; + ulong vaddr; + struct reference *ref; + char *vma_header; + char *buf1; + char *buf2; + char *buf3; + char *buf4; + char *buf5; ulong vma; + char **vma_buf; + struct task_mem_usage *tm; + int *found; + int *single_vma_found; + unsigned int radix; + struct task_context *tc; + ulong *single_vma; +}; + +ulong handle_each_vm_area(struct handle_each_vm_area_args *args) +{ + char *dentry_buf, *file_buf; ulong vm_start; ulong vm_end; ulong vm_next, vm_mm; - char *dentry_buf, *vma_buf, *file_buf; ulonglong vm_flags; ulong vm_file, inode; ulong dentry, vfsmnt; + + if ((args->flag & PHYSADDR) && !DO_REF_SEARCH(args->ref)) + fprintf(fp, "%s", args->vma_header); + + inode = 0; + BZERO(args->buf1, BUFSIZE); + *(args->vma_buf) = fill_vma_cache(args->vma); + + vm_mm = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_mm)); + vm_end = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_end)); + vm_start = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_start)); + vm_flags = get_vm_flags(*(args->vma_buf)); + vm_file = ULONG(*(args->vma_buf) + OFFSET(vm_area_struct_vm_file)); + + if (args->flag & PRINT_SINGLE_VMA) { + if (args->vma != *(args->single_vma)) + return 0; + fprintf(fp, "%s", args->vma_header); + *(args->single_vma_found) = TRUE; + } + + if (args->flag & PRINT_VMA_STRUCTS) { + dump_struct("vm_area_struct", args->vma, args->radix); + return 0; + } + + if (vm_file && !(args->flag & VERIFY_ADDR)) { + file_buf = fill_file_cache(vm_file); + dentry = ULONG(file_buf + OFFSET(file_f_dentry)); + dentry_buf = NULL; + if (dentry) { + dentry_buf = fill_dentry_cache(dentry); + if (VALID_MEMBER(file_f_vfsmnt)) { + vfsmnt = ULONG(file_buf + + OFFSET(file_f_vfsmnt)); + get_pathname(dentry, args->buf1, BUFSIZE, + 1, vfsmnt); + } else { + get_pathname(dentry, args->buf1, BUFSIZE, + 1, 0); + } + } + if ((args->flag & PRINT_INODES) && dentry) { + inode = ULONG(dentry_buf + + OFFSET(dentry_d_inode)); + } + } + + if (!(args->flag & UVADDR) || ((args->flag & UVADDR) && + ((args->vaddr >= vm_start) && (args->vaddr < vm_end)))) { + *(args->found) = TRUE; + + if (args->flag & VERIFY_ADDR) + return args->vma; + + if (DO_REF_SEARCH(args->ref)) { + if (VM_REF_CHECK_HEXVAL(args->ref, args->vma) || + VM_REF_CHECK_HEXVAL(args->ref, (ulong)vm_flags) || + VM_REF_CHECK_STRING(args->ref, args->buf1)) { + if (!(args->ref->cmdflags & VM_REF_HEADER)) { + print_task_header(fp, args->tc, 0); + PRINT_VM_DATA(args->buf4, args->buf5, args->tm); + args->ref->cmdflags |= VM_REF_HEADER; + } + if (!(args->ref->cmdflags & VM_REF_VMA) || + (args->ref->cmdflags & VM_REF_PAGE)) { + fprintf(fp, "%s", args->vma_header); + args->ref->cmdflags |= VM_REF_VMA; + args->ref->cmdflags &= ~VM_REF_PAGE; + args->ref->ref1 = args->vma; + } + PRINT_VMA_DATA(args->buf1, args->buf2, + args->buf3, args->buf4, args->vma); + } + + if (vm_area_page_dump(args->vma, args->task, + vm_start, vm_end, vm_mm, args->ref)) { + if (!(args->ref->cmdflags & VM_REF_HEADER)) { + print_task_header(fp, args->tc, 0); + PRINT_VM_DATA(args->buf4, args->buf5, args->tm); + args->ref->cmdflags |= VM_REF_HEADER; + } + if (!(args->ref->cmdflags & VM_REF_VMA) || + (args->ref->ref1 != args->vma)) { + fprintf(fp, "%s", args->vma_header); + PRINT_VMA_DATA(args->buf1, args->buf2, + args->buf3, args->buf4, args->vma); + args->ref->cmdflags |= VM_REF_VMA; + args->ref->ref1 = args->vma; + } + + args->ref->cmdflags |= VM_REF_DISPLAY; + vm_area_page_dump(args->vma, args->task, + vm_start, vm_end, vm_mm, args->ref); + args->ref->cmdflags &= ~VM_REF_DISPLAY; + } + + return 0; + } + + if (inode) { + fprintf(fp, "%lx%s%s%s%s%s%6llx%s%lx %s\n", + args->vma, space(MINSPACE), + mkstring(args->buf2, UVADDR_PRLEN, RJUST|LONG_HEX, + MKSTR(vm_start)), space(MINSPACE), + mkstring(args->buf3, UVADDR_PRLEN, RJUST|LONG_HEX, + MKSTR(vm_end)), space(MINSPACE), + vm_flags, space(MINSPACE), inode, args->buf1); + } else { + PRINT_VMA_DATA(args->buf1, args->buf2, + args->buf3, args->buf4, args->vma); + + if (args->flag & (PHYSADDR|PRINT_SINGLE_VMA)) + vm_area_page_dump(args->vma, args->task, + vm_start, vm_end, vm_mm, args->ref); + } + + if (args->flag & UVADDR) + return args->vma; + } + return 0; +} + +ulong +vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) +{ + struct task_context *tc; + ulong vma; ulong single_vma; unsigned int radix; int single_vma_found; @@ -3940,6 +4088,7 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) char buf4[BUFSIZE]; char buf5[BUFSIZE]; char vma_header[BUFSIZE]; + char *vma_buf; tc = task_to_context(task); tm = &task_mem_usage; @@ -3973,14 +4122,14 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) if (VM_REF_CHECK_HEXVAL(ref, tm->mm_struct_addr) || VM_REF_CHECK_HEXVAL(ref, tm->pgd_addr)) { print_task_header(fp, tc, 0); - PRINT_VM_DATA(); + PRINT_VM_DATA(buf4, buf5, tm); fprintf(fp, "\n"); return (ulong)NULL; } if (!(flag & (UVADDR|PRINT_MM_STRUCT|PRINT_VMA_STRUCTS|PRINT_SINGLE_VMA)) && !DO_REF_SEARCH(ref)) - PRINT_VM_DATA(); + PRINT_VM_DATA(buf4, buf5, tm); if (!tm->mm_struct_addr) { if (pc->curcmd_flags & MM_STRUCT_FORCE) { @@ -4004,9 +4153,6 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) return (ulong)NULL; } - readmem(tm->mm_struct_addr + OFFSET(mm_struct_mmap), KVADDR, - &vma, sizeof(void *), "mm_struct mmap", FAULT_ON_ERROR); - sprintf(vma_header, "%s%s%s%s%s FLAGS%sFILE\n", mkstring(buf1, VADDR_PRLEN, CENTER|LJUST, "VMA"), space(MINSPACE), @@ -4019,125 +4165,34 @@ vm_area_dump(ulong task, ulong flag, ulong vaddr, struct reference *ref) !DO_REF_SEARCH(ref)) fprintf(fp, "%s", vma_header); - for (found = FALSE; vma; vma = vm_next) { - - if ((flag & PHYSADDR) && !DO_REF_SEARCH(ref)) - fprintf(fp, "%s", vma_header); - - inode = 0; - BZERO(buf1, BUFSIZE); - vma_buf = fill_vma_cache(vma); - - vm_mm = ULONG(vma_buf + OFFSET(vm_area_struct_vm_mm)); - vm_end = ULONG(vma_buf + OFFSET(vm_area_struct_vm_end)); - vm_next = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); - vm_start = ULONG(vma_buf + OFFSET(vm_area_struct_vm_start)); - vm_flags = get_vm_flags(vma_buf); - vm_file = ULONG(vma_buf + OFFSET(vm_area_struct_vm_file)); - - if (flag & PRINT_SINGLE_VMA) { - if (vma != single_vma) - continue; - fprintf(fp, "%s", vma_header); - single_vma_found = TRUE; - } - - if (flag & PRINT_VMA_STRUCTS) { - dump_struct("vm_area_struct", vma, radix); - continue; - } - - if (vm_file && !(flag & VERIFY_ADDR)) { - file_buf = fill_file_cache(vm_file); - dentry = ULONG(file_buf + OFFSET(file_f_dentry)); - dentry_buf = NULL; - if (dentry) { - dentry_buf = fill_dentry_cache(dentry); - if (VALID_MEMBER(file_f_vfsmnt)) { - vfsmnt = ULONG(file_buf + - OFFSET(file_f_vfsmnt)); - get_pathname(dentry, buf1, BUFSIZE, - 1, vfsmnt); - } else { - get_pathname(dentry, buf1, BUFSIZE, - 1, 0); - } - } - if ((flag & PRINT_INODES) && dentry) { - inode = ULONG(dentry_buf + - OFFSET(dentry_d_inode)); - } - } - - if (!(flag & UVADDR) || ((flag & UVADDR) && - ((vaddr >= vm_start) && (vaddr < vm_end)))) { - found = TRUE; + found = FALSE; - if (flag & VERIFY_ADDR) + struct handle_each_vm_area_args args = { + .task = task, .flag = flag, .vaddr = vaddr, + .ref = ref, .vma_header = vma_header, .buf1 = buf1, + .buf2 = buf2, .buf3 = buf3, .buf4 = buf4, + .buf5 = buf5, .vma_buf = &vma_buf, .tm = tm, + .found = &found, .single_vma_found = &single_vma_found, + .radix = radix, .tc = tc, .single_vma = &single_vma, + }; + + if (INVALID_MEMBER(mm_struct_mmap) && VALID_MEMBER(mm_struct_mm_mt)) { + VMA_ITERATOR(vmi, (struct maple_tree *) + (tm->mm_struct_addr + OFFSET(mm_struct_mm_mt)), 0); + for_each_vma(vmi, vma) { + args.vma = vma; + if (handle_each_vm_area(&args)) return vma; - - if (DO_REF_SEARCH(ref)) { - if (VM_REF_CHECK_HEXVAL(ref, vma) || - VM_REF_CHECK_HEXVAL(ref, (ulong)vm_flags) || - VM_REF_CHECK_STRING(ref, buf1)) { - if (!(ref->cmdflags & VM_REF_HEADER)) { - print_task_header(fp, tc, 0); - PRINT_VM_DATA(); - ref->cmdflags |= VM_REF_HEADER; - } - if (!(ref->cmdflags & VM_REF_VMA) || - (ref->cmdflags & VM_REF_PAGE)) { - fprintf(fp, "%s", vma_header); - ref->cmdflags |= VM_REF_VMA; - ref->cmdflags &= ~VM_REF_PAGE; - ref->ref1 = vma; - } - PRINT_VMA_DATA(); - } - - if (vm_area_page_dump(vma, task, - vm_start, vm_end, vm_mm, ref)) { - if (!(ref->cmdflags & VM_REF_HEADER)) { - print_task_header(fp, tc, 0); - PRINT_VM_DATA(); - ref->cmdflags |= VM_REF_HEADER; - } - if (!(ref->cmdflags & VM_REF_VMA) || - (ref->ref1 != vma)) { - fprintf(fp, "%s", vma_header); - PRINT_VMA_DATA(); - ref->cmdflags |= VM_REF_VMA; - ref->ref1 = vma; - } - - ref->cmdflags |= VM_REF_DISPLAY; - vm_area_page_dump(vma, task, - vm_start, vm_end, vm_mm, ref); - ref->cmdflags &= ~VM_REF_DISPLAY; - } - - continue; - } - - if (inode) { - fprintf(fp, "%lx%s%s%s%s%s%6llx%s%lx %s\n", - vma, space(MINSPACE), - mkstring(buf2, UVADDR_PRLEN, RJUST|LONG_HEX, - MKSTR(vm_start)), space(MINSPACE), - mkstring(buf3, UVADDR_PRLEN, RJUST|LONG_HEX, - MKSTR(vm_end)), space(MINSPACE), - vm_flags, space(MINSPACE), inode, buf1); - } else { - PRINT_VMA_DATA(); - - if (flag & (PHYSADDR|PRINT_SINGLE_VMA)) - vm_area_page_dump(vma, task, - vm_start, vm_end, vm_mm, ref); - } - - if (flag & UVADDR) + } + } else { + readmem(tm->mm_struct_addr + OFFSET(mm_struct_mmap), KVADDR, + &vma, sizeof(void *), "mm_struct mmap", FAULT_ON_ERROR); + while (vma) { + args.vma = vma; + if (handle_each_vm_area(&args)) return vma; - } + vma = ULONG(vma_buf + OFFSET(vm_area_struct_vm_next)); + } } if (flag & VERIFY_ADDR) -- 2.33.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://listman.redhat.com/mailman/listinfo/crash-utility Contribution Guidelines: https://github.com/crash-utility/crash/wiki