--- defs.h | 4 ++ memory.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 121 insertions(+), 40 deletions(-) diff --git a/defs.h b/defs.h index 8fc5121..ede0830 100644 --- a/defs.h +++ b/defs.h @@ -2214,7 +2214,11 @@ struct vm_table { /* kernel VM-related data */ ulong kmem_cache_len_nodes; ulong PG_reserved; ulong PG_slab; + ulong PG_head; + ulong PG_tail; + ulong PG_head_mask; ulong PG_head_tail_mask; + int is_pageflags_extended; /* CONFIG_PAGEFLAGS_EXTENDED */ int kmem_cache_namelen; ulong page_hash_table; int page_hash_table_len; diff --git a/memory.c b/memory.c index 051800f..2208553 100644 --- a/memory.c +++ b/memory.c @@ -268,6 +268,13 @@ static int generic_write_dumpfile(ulonglong, void *, long, char *, ulong); static int page_to_nid(ulong); static int get_kmem_cache_list(ulong **); static int get_kmem_cache_slub_data(long, struct meminfo *); +static int __is_page_head(const char *); +static int is_page_head(ulong); +static int __is_page_tail(const char *); +static int is_page_tail(ulong); +static int __compound_order(const char *); +static int compound_order(ulong); +static ulong __compound_head(const char *); static ulong compound_head(ulong); static long count_partial(ulong, struct meminfo *); static ulong get_freepointer(struct meminfo *, void *); @@ -4866,34 +4873,32 @@ PG_slab_flag_init(void) } } - if (vt->flags & KMALLOC_SLUB) { - /* - * PG_slab and the following are hardwired for - * kernels prior to the pageflags enumerator. + if (enumerator_value("PG_head", &flags) && + enumerator_value("PG_tail", &flags2)) { + vt->PG_head = 1L << flags; + vt->PG_tail = 1L << flags2; + vt->is_pageflags_extended = 1; + if (CRASHDEBUG(2)) + fprintf(fp, "PG_head: %lx, PG_tail: %lx\n", + vt->PG_head, vt->PG_tail); + } else if (enumerator_value("PG_compound", &flags) && + enumerator_value("PG_reclaim", &flags2)) { + vt->PG_head_mask = 1L << flags; + vt->PG_head_tail_mask = (1L << flags) | (1L << flags2); + if (CRASHDEBUG(2)) + fprintf(fp, "PG_head_mask: %lx, PG_head_tail_mask: %lx\n", + vt->PG_head_mask, vt->PG_head_tail_mask); + } else if (vt->flags & KMALLOC_SLUB) { + /* + * PG_slab and the following are hardwired for + * kernels prior to the pageflags enumerator. */ -#define PG_compound 14 /* Part of a compound page */ -#define PG_reclaim 17 /* To be reclaimed asap */ - vt->PG_head_tail_mask = ((1L << PG_compound) | (1L << PG_reclaim)); - - if (enumerator_value("PG_tail", (long *)&flags)) - vt->PG_head_tail_mask = (1L << flags); - else if (enumerator_value("PG_compound", (long *)&flags) && - enumerator_value("PG_reclaim", (long *)&flags2)) { - vt->PG_head_tail_mask = ((1L << flags) | (1L << flags2)); - if (CRASHDEBUG(2)) - fprintf(fp, "PG_head_tail_mask: %lx\n", - vt->PG_head_tail_mask); - } - } else { - if (enumerator_value("PG_tail", (long *)&flags)) - vt->PG_head_tail_mask = (1L << flags); - else if (enumerator_value("PG_compound", (long *)&flags) && - enumerator_value("PG_reclaim", (long *)&flags2)) { - vt->PG_head_tail_mask = ((1L << flags) | (1L << flags2)); - if (CRASHDEBUG(2)) - fprintf(fp, "PG_head_tail_mask: %lx (PG_compound|PG_reclaim)\n", - vt->PG_head_tail_mask); - } +#define PG_compound 14 /* Part of a compound page */ +#define PG_reclaim 17 /* To be reclaimed asap */ + vt->PG_head_mask = 1L << PG_compound; + vt->PG_head_tail_mask = (1L << PG_compound) | (1L << PG_reclaim); + if (CRASHDEBUG(2)) + fprintf(fp, "hardwired PG_compound and PG_reclaim\n"); } if (!vt->PG_slab) @@ -13213,7 +13218,13 @@ dump_vm_table(int verbose) fprintf(fp, " PG_reserved: %lx\n", vt->PG_reserved); fprintf(fp, " PG_slab: %ld (%lx)\n", vt->PG_slab, (ulong)1 << vt->PG_slab); - fprintf(fp, " PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask); + if (vt->is_pageflags_extended) { + fprintf(fp, " PG_head: %lx\n", vt->PG_head); + fprintf(fp, " PG_tail: %lx\n", vt->PG_tail); + } else { + fprintf(fp, " PG_head_mask: %lx\n", vt->PG_head_mask); + fprintf(fp, " PG_head_tail_mask: %lx\n", vt->PG_head_tail_mask); + } fprintf(fp, " nr_pageflags: %d\n", vt->nr_pageflags); fprintf(fp, " pageflags_data: %s\n", @@ -18179,6 +18190,80 @@ get_kmem_cache_list(ulong **cache_buf) return cnt; } +static int +__is_page_head(const char *p) +{ + ulong flags = ULONG(p + OFFSET(page_flags)); + + return vt->is_pageflags_extended ? flags & vt->PG_head : + flags & vt->PG_head_tail_mask == vt->PG_head_mask; +} + +static int +is_page_head(ulong page) +{ + ulong flags; + + if (!readmem(page + OFFSET(page_flags), KVADDR, &flags, sizeof(flags), + "page.flags", RETURN_ON_ERROR)) + return 1; + + return vt->is_pageflags_extended ? flags & vt->PG_head : + flags & vt->PG_head_tail_mask == vt->PG_head_mask; +} + +static int +__is_page_tail(const char *p) +{ + ulong flags = ULONG(p + OFFSET(page_flags)); + + return vt->is_pageflags_extended ? flags & vt->PG_tail : + flags & vt->PG_head_tail_mask == vt->PG_head_tail_mask; +} + +static int +is_page_tail(ulong page) +{ + ulong flags; + + if (!readmem(page + OFFSET(page_flags), KVADDR, &flags, sizeof(flags), + "page.flags", RETURN_ON_ERROR)) + return 0; + + return vt->is_pageflags_extended ? flags & vt->PG_tail : + flags & vt->PG_head_tail_mask == vt->PG_head_tail_mask; +} + +static int +__compound_order(const char *p) +{ + if (!__is_page_head(p)) + return 0; + + return ULONG(p + SIZE(page) + OFFSET(page_lru) + OFFSET(list_head_prev)); +} + +static int +compound_order(ulong page) +{ + + ulong order = 0; + + if (is_page_head(page)) + readmem(page + SIZE(page) + OFFSET(page_lru) + OFFSET(list_head_prev), + KVADDR, &order, sizeof(order), "page.lru.prev", FAULT_ON_ERROR); + + return order; +} + +/* + * In contrast to compound_head(), this function only can be used on a tail page. + */ +static ulong +__compound_head(const char *p) +{ + return ULONG(p + OFFSET(page_first_page)); +} /* * Get the address of the head page of a compound page. @@ -18186,19 +18271,11 @@ get_kmem_cache_list(ulong **cache_buf) static ulong compound_head(ulong page) { - ulong flags, first_page;; + if (is_page_tail(page)) + readmem(page + OFFSET(page_first_page), KVADDR, &page, + sizeof(page), "page.first_page", RETURN_ON_ERROR); - first_page = page; - - if (!readmem(page+OFFSET(page_flags), KVADDR, &flags, sizeof(ulong), - "page.flags", RETURN_ON_ERROR)) - return first_page; - - if ((flags & vt->PG_head_tail_mask) == vt->PG_head_tail_mask) - readmem(page+OFFSET(page_first_page), KVADDR, &first_page, - sizeof(ulong), "page.first_page", RETURN_ON_ERROR); - - return first_page; + return page; } long -- 2.2.0.rc0.207.ga3a616c -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility