On Tue, Jun 25, 2019 at 10:57:07AM +0530, Anshuman Khandual wrote: > On 06/24/2019 10:22 PM, Mark Rutland wrote: > > On Fri, Jun 21, 2019 at 03:35:53PM +0100, Steve Capper wrote: > >> On Wed, Jun 19, 2019 at 09:47:40AM +0530, Anshuman Khandual wrote: > >>> +static void free_hotplug_page_range(struct page *page, size_t size) > >>> +{ > >>> + WARN_ON(!page || PageReserved(page)); > >>> + free_pages((unsigned long)page_address(page), get_order(size)); > >>> +} > >> > >> We are dealing with power of 2 number of pages, it makes a lot more > >> sense (to me) to replace the size parameter with order. > >> > >> Also, all the callers are for known compile-time sizes, so we could just > >> translate the size parameter as follows to remove any usage of get_order? > >> PAGE_SIZE -> 0 > >> PMD_SIZE -> PMD_SHIFT - PAGE_SHIFT > >> PUD_SIZE -> PUD_SHIFT - PAGE_SHIFT > > > > Now that I look at this again, the above makes sense to me. > > > > I'd requested the current form (which I now realise is broken), since > > back in v2 the code looked like: > > > > static void free_pagetable(struct page *page, int order) > > { > > ... > > free_pages((unsigned long)page_address(page), order); > > ... > > } > > > > ... with callsites looking like: > > > > free_pagetable(pud_page(*pud), get_order(PUD_SIZE)); > > > > ... which I now see is off by PAGE_SHIFT, and we inherited that bug in > > the current code, so the calculated order is vastly larger than it > > should be. It's worrying that doesn't seem to be caught by anything in > > testing. :/ > > get_order() returns the minimum page allocation order for a given size > which already takes into account PAGE_SHIFT i.e get_order(PAGE_SIZE) > returns 0. Phew. Let's leave this as is then -- it's clearer/simpler than using the SHIFT constants, performance isn't a major concern in this path, and it's very likely that GCC will inline and constant-fold this away regardless. Sorry for the noise, and thanks for correcting me. Mark.