Re: [RFC PATCH 3/4] kho: Implement page-aware refcount restoration
Mike Rapoport <[email protected]>
| Newsgroups | org.infradead.lists.kexec,org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <178341290877.3292146.335016287917708290.b4-review@b4> |
> The KHO restoration logic currently forces a refcount of 1 on every > page of a multi-page block. While that is correct for split pages, it > violates the expectations of the buddy allocator for high-order > non-compound pages allocated by kernel user (like the DMA allocator), > where tail pages are expected to have a refcount of 0. > > Update the restoration path to respect the preserved page type stored > in the page->private metadata. For KHO_PAGE_CONTIG blocks, only the > head page is given a reference count of 1. For KHO_PAGE_SPLIT blocks, > every page is given a reference count of 1. > > Signed-off-by: Pranjal Shrivastava <[email protected]> > > diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_handover.c > index d6e81f72fe5de..f6ca5e24c7407 100644 > --- a/kernel/liveupdate/kexec_handover.c > +++ b/kernel/liveupdate/kexec_handover.c > @@ -375,11 +375,18 @@ int kho_radix_walk_tree(struct kho_radix_tree *tree, > } > EXPORT_SYMBOL_GPL(kho_radix_walk_tree); > > -/* For physically contiguous 0-order pages. */ > -static void kho_init_pages(struct page *page, unsigned long nr_pages) > +/* For physically contiguous pages. */ > +static void kho_restore_refcounts(struct page *page, unsigned long nr_pages, > + enum kho_page_type type) Why did you change the function name? It's there to ensure proper initialization of struct pages for preserved memory and refcount is the only part of that. > { > - for (unsigned long i = 0; i < nr_pages; i++) { > - set_page_count(page + i, 1); > + /* Head page always gets refcount of 1. */ > + set_page_count(page, 1); > + clear_page_tag_ref(page); > + > + for (unsigned long i = 1; i < nr_pages; i++) { > + unsigned int count = (type == KHO_PAGE_SPLIT) ? 1 : 0; The count is same for all iterations, why not initialize it outside the loop? > + > + set_page_count(page + i, count); > /* Clear each page's codetag to avoid accounting mismatch. */ > clear_page_tag_ref(page + i); > } > @@ -387,16 +394,7 @@ static void kho_init_pages(struct page *page, unsigned long nr_pages) > > static void kho_init_folio(struct page *page, unsigned int order) > { > - unsigned long nr_pages = (1 << order); > - > - /* Head page gets refcount of 1. */ > - set_page_count(page, 1); > - /* Clear head page's codetag to avoid accounting mismatch. */ > - clear_page_tag_ref(page); > - > - /* For higher order folios, tail pages get a page count of zero. */ > - for (unsigned long i = 1; i < nr_pages; i++) > - set_page_count(page + i, 0); > + kho_restore_refcounts(page, 1 << order, KHO_PAGE_CONTIG); Ah, I see you wanted to reuse the same code for folios. In this case you could add a helper for refcount initialization and call it from here and from kho_init_pages(). -- Sincerely yours, Mike.