On 16.12.19 17:22, Alexander Duyck wrote: > On Mon, 2019-12-16 at 12:36 +0100, David Hildenbrand wrote: >> [...] >>> +/** >>> + * __putback_isolated_page - Return a now-isolated page back where we got it >>> + * @page: Page that was isolated >>> + * @order: Order of the isolated page >>> + * >>> + * This function is meant to return a page pulled from the free lists via >>> + * __isolate_free_page back to the free lists they were pulled from. >>> + */ >>> +void __putback_isolated_page(struct page *page, unsigned int order) >>> +{ >>> + struct zone *zone = page_zone(page); >>> + unsigned long pfn; >>> + unsigned int mt; >>> + >>> + /* zone lock should be held when this function is called */ >>> + lockdep_assert_held(&zone->lock); >>> + >>> + pfn = page_to_pfn(page); >>> + mt = get_pfnblock_migratetype(page, pfn); >> >> IMHO get_pageblock_migratetype() would be nicer - I guess the compiler >> will optimize out the double page_to_pfn(). > > The thing is I need the page_to_pfn call already in order to pass the > value to __free_one_page. With that being the case why not juse use > get_pfnblock_migratetype? I was reading set_pageblock_migratetype(page, migratetype); And wondered why we don't use straight forward get_pageblock_migratetype() but instead something that looks like a micro-optimization > > Also there are some scenarios where __page_to_pfn is not that simple a > call with us having to get the node ID so we can find the pgdat structure > to perform the calculation. I'm not sure the compiler would be ble to > figure out that the result is the same for both calls, so it is better to > make it explicit. Only in case of CONFIG_SPARSEMEM we have to go via the section - but I doubt this is really worth optimizing here. But yeah, I'm fine with this change, only "IMHO get_pageblock_migratetype() would be nicer" :) > >>> + >>> + /* Return isolated page to tail of freelist. */ >>> + __free_one_page(page, pfn, zone, order, mt); >>> +} >>> + >>> /* >>> * Update NUMA hit/miss statistics >>> * >>> diff --git a/mm/page_isolation.c b/mm/page_isolation.c >>> index 04ee1663cdbe..d93d2be0070f 100644 >>> --- a/mm/page_isolation.c >>> +++ b/mm/page_isolation.c >>> @@ -134,13 +134,11 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype) >>> __mod_zone_freepage_state(zone, nr_pages, migratetype); >>> } >>> set_pageblock_migratetype(page, migratetype); >>> + if (isolated_page) >>> + __putback_isolated_page(page, order); >>> zone->nr_isolate_pageblock--; >>> out: >>> spin_unlock_irqrestore(&zone->lock, flags); >>> - if (isolated_page) { >>> - post_alloc_hook(page, order, __GFP_MOVABLE); >>> - __free_pages(page, order); >>> - } >> >> So If I get it right: >> >> post_alloc_hook() does quite some stuff like >> - arch_alloc_page(page, order); >> - kernel_map_pages(page, 1 << order, 1) >> - kasan_alloc_pages() >> - kernel_poison_pages(1) >> - set_page_owner() >> >> Which free_pages_prepare() will undo, like >> - reset_page_owner() >> - kernel_poison_pages(0) >> - arch_free_page() >> - kernel_map_pages() >> - kasan_free_nondeferred_pages() >> >> Both would be skipped now - which sounds like the right thing to do IMHO >> (and smells like quite a performance improvement). I haven't verified if >> actually everything we skip in free_pages_prepare() is safe (I think it >> is, it seems to be mostly relevant for actually used/allocated pages). > > That was kind of my thought on this. Basically the logic I was following > was that the code path will call move_freepages_block that bypasses all of > the above mentioned calls if the pages it is moving will not be merged. If > it is safe in that case my assumption is that it should be safe to just > call __putback_isolated_page in such a case as it also bypasses the block > above, but it supports merging the page with other pages that are already > on the freelist. Makes sense to me Acked-by: David Hildenbrand <david@xxxxxxxxxx> -- Thanks, David / dhildenb