> 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.


Reply via email to