On Tue, 23 Feb 2021 15:57:40 +0100 Gerald Schaefer <gerald.schae...@linux.ibm.com> wrote:
[...] > What I do not understand is how __free_huge_page() would be called at all > in the call trace below (set_max_huge_pages -> alloc_pool_huge_page -> > __free_huge_page -> hugepage_subpool_put_pages). From the code it seems > that this should not be possible, so I must be missing something. Ok, looking more closely at the dump and code, I see that __free_huge_page() was called via alloc_pool_huge_page -> put_page() -> destroy_compound_page() -> compound_page_dtors[2]. It doesn't feel right that alloc_pool_huge_page() ends up freeing the newly allocated page again. Maybe some refcounting race, so that put_page() wrongly assumes it was the last reference? Also from the dump, I could reconstruct the (head) struct page pointer that __free_huge_page() was called with. Here is the content of the head and the first tail page, maybe it can help. page->private in the tail page was zeroed already in __free_huge_page(), but its original value was the broken *spool pointer 0000004e00000000, as seen in the register output of the backtrace. crash> struct -x page 0000037203dec000 struct page { flags = 0x3ffff00000010000, { { lru = { next = 0x37203dec008, prev = 0x37203dec008 }, mapping = 0x0, index = 0x0, private = 0x0 }, { dma_addr = 0x37203dec008 }, { { slab_list = { next = 0x37203dec008, prev = 0x37203dec008 }, { next = 0x37203dec008, pages = 0x372, pobjects = 0x3dec008 } }, slab_cache = 0x0, freelist = 0x0, { s_mem = 0x0, counters = 0x0, { inuse = 0x0, objects = 0x0, frozen = 0x0 } } }, { compound_head = 0x37203dec008, compound_dtor = 0x0, compound_order = 0x0, compound_mapcount = { counter = 0x3dec008 }, compound_nr = 0x0 }, { _compound_pad_1 = 0x37203dec008, hpage_pinned_refcount = { counter = 0x372 }, deferred_list = { next = 0x0, prev = 0x0 } }, { _pt_pad_1 = 0x37203dec008, pmd_huge_pte = 0x37203dec008, _pt_pad_2 = 0x0, { pt_mm = 0x0, pt_frag_refcount = { counter = 0x0 } }, ptl = { { rlock = { raw_lock = { lock = 0x0 } } } } }, { pgmap = 0x37203dec008, zone_device_data = 0x37203dec008 }, callback_head = { next = 0x37203dec008, func = 0x37203dec008 } }, { _mapcount = { counter = 0xffffffff }, page_type = 0xffffffff, active = 0xffffffff, units = 0xffffffff }, _refcount = { counter = 0x0 }, memcg_data = 0x0 } crash> struct -x page 0000037203dec040 struct page { flags = 0x3ffff00000000000, { { lru = { next = 0x37203dec001, prev = 0x2080372ffffffff }, mapping = 0x10000000400, index = 0x2, private = 0x0 }, { dma_addr = 0x37203dec001 }, { { slab_list = { next = 0x37203dec001, prev = 0x2080372ffffffff }, { next = 0x37203dec001, pages = 0x2080372, pobjects = 0xffffffff } }, slab_cache = 0x10000000400, freelist = 0x2, { s_mem = 0x0, counters = 0x0, { inuse = 0x0, objects = 0x0, frozen = 0x0 } } }, { compound_head = 0x37203dec001, compound_dtor = 0x2, compound_order = 0x8, compound_mapcount = { counter = 0xffffffff }, compound_nr = 0x100 }, { _compound_pad_1 = 0x37203dec001, hpage_pinned_refcount = { counter = 0x2080372 }, deferred_list = { next = 0x10000000400, prev = 0x2 } }, { _pt_pad_1 = 0x37203dec001, pmd_huge_pte = 0x2080372ffffffff, _pt_pad_2 = 0x10000000400, { pt_mm = 0x2, pt_frag_refcount = { counter = 0x0 } }, ptl = { { rlock = { raw_lock = { lock = 0x0 } } } } }, { pgmap = 0x37203dec001, zone_device_data = 0x2080372ffffffff }, callback_head = { next = 0x37203dec001, func = 0x2080372ffffffff } }, { _mapcount = { counter = 0xffffffff }, page_type = 0xffffffff, active = 0xffffffff, units = 0xffffffff }, _refcount = { counter = 0x0 }, memcg_data = 0x0 }