Kexec Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Brennan <stephen.s.brennan@oracle.com>
To: Tao Liu <ltao@redhat.com>
Cc: yamazaki-msmt@nec.com, k-hagio-ab@nec.com, kexec@lists.infradead.org
Subject: Re: [PATCH makedumpfile 3/9] Share page information with extension callbacks
Date: Mon, 17 Aug 2026 08:27:21 -0700	[thread overview]
Message-ID: <87ecfwdaxy.fsf@oracle.com> (raw)
In-Reply-To: <CAO7dBbU6tfVHLO6LW5ZQXbApqychfo=hAtXd8pD+Z7MXFF7fgg@mail.gmail.com>

Tao Liu <ltao@redhat.com> writes:
> Hi Stephen,
>
> On Tue, Jul 14, 2026 at 12:46 PM Stephen Brennan
> <stephen.s.brennan@oracle.com> wrote:
>>
>> In __exclude_unnecessary_pages(), we extract several fields related
>> to the page. Some of these, like compound_order and compound_dtor, have
>> logic specific to the kernel version.
>>
>> Extensions can, of course, determine these values for themselves, but
>> it's extra work, and duplicates logic that may need to be updated
>> frequently with new kernel versions. What's more, if we put all the
>> values together in a single structure, helpers like isSlab() and others
>> can be implemented in terms of that structure and shared with the
>> extensions in order to further simplify their implementation.
>>
>> With that in mind, group the per-page variables into a structure and
>> share them with extension callbacks. This breaks the extension API,
>> but since a release hasn't yet happened, it seems reasonable to do so.
>>
>> Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
>> ---
>>  extension.c    |  8 ++---
>>  extension.h    |  3 +-
>>  makedumpfile.c | 83 +++++++++++++++++++++++++-------------------------
>>  makedumpfile.h | 16 ++++++++++
>>  4 files changed, 64 insertions(+), 46 deletions(-)
>>
>> diff --git a/extension.c b/extension.c
>> index 5188c1f..9b29f0c 100644
>> --- a/extension.c
>> +++ b/extension.c
>> @@ -10,7 +10,7 @@
>>  #include "kallsyms.h"
>>  #include "btf_info.h"
>>
>> -typedef int (*callback_fn)(unsigned long, const void *);
>> +typedef int (*callback_fn)(unsigned long, const void *, const struct pginfo *);
>>
> The function signature of callbacks are changed, it will be better to
> update them in extensions/sample.c as well:
>
> int extension_callback(unsigned long pfn, const void *pcache)
> {
> return PG_UNDECID;
> }
>
> Since it will serve as a reference for future extension authors.

Hi Tao,

Thanks for the catch, I will send a v2 with this and a few other fixes.

Thanks,
Stephen

> Thaks,
> Tao Liu
>
>>  struct extension_handle_cb {
>>         void *handle;
>> @@ -306,14 +306,14 @@ fail:
>>   * 1) Include the page if anyone says PG_INCLUDE, and
>>   * 2) Exclude the page if no one says PG_INCLUDE, but one or more say PG_EXCLUDE.
>>   */
>> -int run_extension_callback(unsigned long pfn, const void *pcache)
>> +int run_extension_callback(unsigned long pfn, const void *pcache, const struct pginfo *inf)
>>  {
>>         int result;
>>         int ret = PG_UNDECID;
>>
>>         for (int i = 0; i < handle_cbs_len; i++) {
>>                 if (handle_cbs[i]->cb) {
>> -                       result = handle_cbs[i]->cb(pfn, pcache);
>> +                       result = handle_cbs[i]->cb(pfn, pcache, inf);
>>                         if (result == PG_INCLUDE) {
>>                                 ret = result;
>>                                 goto out;
>> @@ -341,7 +341,7 @@ bool add_extension_opts(char *opt)
>>         return false;
>>  }
>>
>> -int run_extension_callback(unsigned long pfn, const void *pcache)
>> +int run_extension_callback(unsigned long pfn, const void *pcache, const struct pginfo *i)
>>  {
>>         return PG_UNDECID;
>>  }
>> diff --git a/extension.h b/extension.h
>> index ba8d32a..22af9a6 100644
>> --- a/extension.h
>> +++ b/extension.h
>> @@ -2,12 +2,13 @@
>>  #define _EXTENSION_H
>>  #include <stdbool.h>
>>
>> +struct pginfo;
>>  enum {
>>         PG_INCLUDE,     // Exntesion will keep the page
>>         PG_EXCLUDE,     // Exntesion will discard the page
>>         PG_UNDECID,     // Exntesion makes no decision
>>  };
>> -int run_extension_callback(unsigned long pfn, const void *pcache);
>> +int run_extension_callback(unsigned long pfn, const void *pcache, const struct pginfo *i);
>>  void init_extensions(void);
>>  void cleanup_extensions(void);
>>  bool add_extension_opts(char *opt);
>> diff --git a/makedumpfile.c b/makedumpfile.c
>> index e882b84..a4c9bbf 100644
>> --- a/makedumpfile.c
>> +++ b/makedumpfile.c
>> @@ -6466,12 +6466,13 @@ __exclude_unnecessary_pages(unsigned long mem_map,
>>         mdf_pfn_t pfn_read_start, pfn_read_end;
>>         unsigned char *page_cache;
>>         unsigned char *pcache;
>> -       unsigned int _count, _mapcount = 0, compound_order = 0;
>> +       struct pginfo i;
>>         unsigned int order_offset, dtor_offset;
>> -       unsigned long flags, mapping, private = 0;
>> -       unsigned long compound_dtor, compound_head = 0;
>>         int filter_pg;
>>
>> +       i._mapcount = i.compound_order = 0;
>> +       i.private = i.compound_dtor = i.compound_head = 0;
>> +
>>         /*
>>          * If a multi-page exclusion is pending, do it first
>>          */
>> @@ -6543,21 +6544,21 @@ __exclude_unnecessary_pages(unsigned long mem_map,
>>                         pfn_read_end   = pfn + pfn_mm - 1;
>>                 }
>>
>> -               flags   = ULONG(pcache + OFFSET(page.flags));
>> -               _count  = UINT(pcache + OFFSET(page._refcount));
>> -               mapping = ULONG(pcache + OFFSET(page.mapping));
>> +               i.flags   = ULONG(pcache + OFFSET(page.flags));
>> +               i._count  = UINT(pcache + OFFSET(page._refcount));
>> +               i.mapping = ULONG(pcache + OFFSET(page.mapping));
>>
>>                 if (OFFSET(page._mapcount) != NOT_FOUND_STRUCTURE)
>> -                       _mapcount = UINT(pcache + OFFSET(page._mapcount));
>> +                       i._mapcount = UINT(pcache + OFFSET(page._mapcount));
>>
>> -               compound_order = 0;
>> -               compound_dtor = 0;
>> +               i.compound_order = 0;
>> +               i.compound_dtor = 0;
>>                 /*
>>                  * The last pfn of the mem_map cache must not be compound head
>>                  * page since all compound pages are aligned to its page order
>>                  * and PGMM_CACHED is a power of 2.
>>                  */
>> -               if ((index_pg < PGMM_CACHED - 1) && isCompoundHead(flags)) {
>> +               if ((index_pg < PGMM_CACHED - 1) && isCompoundHead(i.flags)) {
>>                         unsigned char *addr = pcache + SIZE(page);
>>
>>                         /*
>> @@ -6567,10 +6568,10 @@ __exclude_unnecessary_pages(unsigned long mem_map,
>>                         if (NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE) != NOT_FOUND_NUMBER) {
>>                                 unsigned long _flags_1 = ULONG(addr + OFFSET(page.flags));
>>
>> -                               compound_order = _flags_1 & 0xff;
>> +                               i.compound_order = _flags_1 & 0xff;
>>
>> -                               if (_mapcount == (int)NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE))
>> -                                       compound_dtor = IS_HUGETLB;
>> +                               if (i._mapcount == (int)NUMBER(PAGE_HUGETLB_MAPCOUNT_VALUE))
>> +                                       i.compound_dtor = IS_HUGETLB;
>>
>>                                 goto check_order;
>>                         }
>> @@ -6582,19 +6583,19 @@ __exclude_unnecessary_pages(unsigned long mem_map,
>>                         if (NUMBER(PG_hugetlb) != NOT_FOUND_NUMBER) {
>>                                 unsigned long _flags_1 = ULONG(addr + OFFSET(page.flags));
>>
>> -                               compound_order = _flags_1 & 0xff;
>> +                               i.compound_order = _flags_1 & 0xff;
>>
>>                                 if (_flags_1 & (1UL << NUMBER(PG_hugetlb)))
>> -                                       compound_dtor = IS_HUGETLB;
>> +                                       i.compound_dtor = IS_HUGETLB;
>>
>>                                 goto check_order;
>>                         }
>>
>>                         if (order_offset) {
>>                                 if (info->kernel_version >= KERNEL_VERSION(4, 16, 0))
>> -                                       compound_order = UCHAR(addr + order_offset);
>> +                                       i.compound_order = UCHAR(addr + order_offset);
>>                                 else
>> -                                       compound_order = USHORT(addr + order_offset);
>> +                                       i.compound_order = USHORT(addr + order_offset);
>>                         }
>>
>>                         if (dtor_offset) {
>> @@ -6603,40 +6604,40 @@ __exclude_unnecessary_pages(unsigned long mem_map,
>>                                  * to the ID of it since linux-4.4.
>>                                  */
>>                                 if (info->kernel_version >= KERNEL_VERSION(4, 16, 0))
>> -                                       compound_dtor = UCHAR(addr + dtor_offset);
>> +                                       i.compound_dtor = UCHAR(addr + dtor_offset);
>>                                 else if (info->kernel_version >= KERNEL_VERSION(4, 4, 0))
>> -                                       compound_dtor = USHORT(addr + dtor_offset);
>> +                                       i.compound_dtor = USHORT(addr + dtor_offset);
>>                                 else
>> -                                       compound_dtor = ULONG(addr + dtor_offset);
>> +                                       i.compound_dtor = ULONG(addr + dtor_offset);
>>                         }
>>  check_order:
>> -                       if ((compound_order >= sizeof(unsigned long) * 8)
>> -                           || ((pfn & ((1UL << compound_order) - 1)) != 0)) {
>> +                       if ((i.compound_order >= sizeof(unsigned long) * 8)
>> +                           || ((pfn & ((1UL << i.compound_order) - 1)) != 0)) {
>>                                 /* Invalid order */
>> -                               compound_order = 0;
>> +                               i.compound_order = 0;
>>                         }
>>                 }
>>                 if (OFFSET(page.compound_head) != NOT_FOUND_STRUCTURE)
>> -                       compound_head = ULONG(pcache + OFFSET(page.compound_head));
>> +                       i.compound_head = ULONG(pcache + OFFSET(page.compound_head));
>>
>>                 if (OFFSET(page.private) != NOT_FOUND_STRUCTURE)
>> -                       private = ULONG(pcache + OFFSET(page.private));
>> +                       i.private = ULONG(pcache + OFFSET(page.private));
>>
>> -               nr_pages = 1 << compound_order;
>> +               nr_pages = 1 << i.compound_order;
>>                 pfn_counter = NULL;
>>
>>                 /*
>>                  * Excludable compound tail pages must have already been excluded by
>>                  * exclude_range(), don't need to check them here.
>>                  */
>> -               if (compound_head & 1)
>> +               if (i.compound_head & 1)
>>                         continue;
>>
>>                 /*
>>                  * Include pages that specified by user via
>>                  * makedumpfile extensions
>>                  */
>> -               filter_pg = run_extension_callback(pfn, pcache);
>> +               filter_pg = run_extension_callback(pfn, pcache, &i);
>>                 if (filter_pg == PG_INCLUDE)
>>                         continue;
>>
>> @@ -6646,14 +6647,14 @@ check_order:
>>                  */
>>                 if ((info->dump_level & DL_EXCLUDE_FREE)
>>                     && info->page_is_buddy
>> -                   && info->page_is_buddy(flags, _mapcount, private, _count)) {
>> +                   && info->page_is_buddy(i.flags, i._mapcount, i.private, i._count)) {
>>                         if ((ARRAY_LENGTH(zone.free_area) != NOT_FOUND_STRUCTURE) &&
>> -                           (private >= ARRAY_LENGTH(zone.free_area))) {
>> +                           (i.private >= ARRAY_LENGTH(zone.free_area))) {
>>                                 MSG("WARNING: Invalid free page order: pfn=%llx, order=%lu, max order=%lu\n",
>> -                                   pfn, private, ARRAY_LENGTH(zone.free_area) - 1);
>> +                                   pfn, i.private, ARRAY_LENGTH(zone.free_area) - 1);
>>                                 continue;
>>                         }
>> -                       nr_pages = 1 << private;
>> +                       nr_pages = 1 << i.private;
>>                         pfn_counter = &pfn_free;
>>                 }
>>                 /*
>> @@ -6663,7 +6664,7 @@ check_order:
>>                  * accepted immediately without being on the list.
>>                  */
>>                 else if ((info->dump_level & DL_EXCLUDE_FREE)
>> -                       && isUnaccepted(_mapcount)) {
>> +                       && isUnaccepted(i._mapcount)) {
>>                         nr_pages = 1 << (ARRAY_LENGTH(zone.free_area) - 1);
>>                         pfn_counter = &pfn_free;
>>                 }
>> @@ -6671,17 +6672,17 @@ check_order:
>>                  * Exclude the non-private cache page.
>>                  */
>>                 else if ((info->dump_level & DL_EXCLUDE_CACHE)
>> -                   && is_cache_page(flags)
>> -                   && !isPrivate(flags) && !isAnon(mapping, flags, _mapcount)) {
>> +                   && is_cache_page(i.flags)
>> +                   && !isPrivate(i.flags) && !isAnon(i.mapping, i.flags, i._mapcount)) {
>>                         pfn_counter = &pfn_cache;
>>                 }
>>                 /*
>>                  * Exclude the cache page whether private or non-private.
>>                  */
>>                 else if ((info->dump_level & DL_EXCLUDE_CACHE_PRI)
>> -                   && is_cache_page(flags)
>> -                   && !isAnon(mapping, flags, _mapcount)) {
>> -                       if (isPrivate(flags))
>> +                   && is_cache_page(i.flags)
>> +                   && !isAnon(i.mapping, i.flags, i._mapcount)) {
>> +                       if (isPrivate(i.flags))
>>                                 pfn_counter = &pfn_cache_private;
>>                         else
>>                                 pfn_counter = &pfn_cache;
>> @@ -6692,19 +6693,19 @@ check_order:
>>                  *  - hugetlbfs pages
>>                  */
>>                 else if ((info->dump_level & DL_EXCLUDE_USER_DATA)
>> -                        && (isAnon(mapping, flags, _mapcount) || isHugetlb(compound_dtor))) {
>> +                        && (isAnon(i.mapping, i.flags, i._mapcount) || isHugetlb(i.compound_dtor))) {
>>                         pfn_counter = &pfn_user;
>>                 }
>>                 /*
>>                  * Exclude the hwpoison page.
>>                  */
>> -               else if (isHWPOISON(flags)) {
>> +               else if (isHWPOISON(i.flags)) {
>>                         pfn_counter = &pfn_hwpoison;
>>                 }
>>                 /*
>>                  * Exclude pages that are logically offline.
>>                  */
>> -               else if (isOffline(flags, _mapcount)) {
>> +               else if (isOffline(i.flags, i._mapcount)) {
>>                         pfn_counter = &pfn_offline;
>>                 }
>>                 /*
>> diff --git a/makedumpfile.h b/makedumpfile.h
>> index 4f707c7..87f973d 100644
>> --- a/makedumpfile.h
>> +++ b/makedumpfile.h
>> @@ -1507,6 +1507,22 @@ struct ppc64_vmemmap {
>>         unsigned long           virt;
>>  };
>>
>> +/* Per-page information determined during page filtering which may be useful
>> + * to extensions making their decisions */
>> +struct pginfo {
>> +       unsigned long flags;
>> +       unsigned long mapping;
>> +       /* Present whenever OFFSET(page.private) != NOT_FOUND_STRUCTURE */
>> +       unsigned long private;
>> +       unsigned long compound_dtor;
>> +       /* Present whenever OFFSET(page.compound_head) != NOT_FOUND_STRUCTURE */
>> +       unsigned long compound_head;
>> +       unsigned int _count;
>> +       /* Present whenever OFFSET(page._mapcount) != NOT_FOUND_STRUCTURE */
>> +       unsigned int _mapcount;
>> +       unsigned int compound_order;
>> +};
>> +
>>  struct DumpInfo {
>>         int32_t         kernel_version;      /* version of first kernel*/
>>         struct timeval  timestamp;
>> --
>> 2.47.3
>>


  reply	other threads:[~2026-08-17 15:27 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-14  0:45 [PATCH makedumpfile 0/9] Improvements to makedumpfile extensions, plus userspace stack tracing extension Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 1/9] Do not call extensions for tail pages Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 2/9] Honor CFLAGS in extension/Makefile Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 3/9] Share page information with extension callbacks Stephen Brennan
2026-08-12  4:01   ` Tao Liu
2026-08-17 15:27     ` Stephen Brennan [this message]
2026-07-14  0:45 ` [PATCH makedumpfile 4/9] Introduce a stat for pages retained by extension Stephen Brennan
2026-08-13  2:15   ` Tao Liu
2026-08-13  4:54     ` HAGIO KAZUHITO(萩尾 一仁)
2026-08-17  3:44       ` Tao Liu
2026-08-17 19:58         ` Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 5/9] Move page checks into makedumpfile.h Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 6/9] Simplify arguments for page checks Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 7/9] Add PG_INCLUDE_HEAD extension return status Stephen Brennan
2026-08-07 16:24   ` Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 8/9] Add userstack extension Stephen Brennan
2026-07-14  0:45 ` [PATCH makedumpfile 9/9] Add elfheader extension Stephen Brennan
2026-08-03 15:55 ` [PATCH makedumpfile 0/9] Improvements to makedumpfile extensions, plus userspace stack tracing extension Stephen Brennan
2026-08-04  4:43   ` Tao Liu
2026-08-07  1:52 ` HAGIO KAZUHITO(萩尾 一仁)
2026-08-07  7:57   ` Tao Liu
2026-08-07 21:24     ` Stephen Brennan
2026-08-08  4:44       ` HAGIO KAZUHITO(萩尾 一仁)
2026-08-11  6:11         ` Tao Liu
2026-08-12  1:31           ` HAGIO KAZUHITO(萩尾 一仁)
2026-08-12  5:07             ` Tao Liu
2026-08-13  2:51               ` Tao Liu
2026-08-17 20:02             ` Stephen Brennan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87ecfwdaxy.fsf@oracle.com \
    --to=stephen.s.brennan@oracle.com \
    --cc=k-hagio-ab@nec.com \
    --cc=kexec@lists.infradead.org \
    --cc=ltao@redhat.com \
    --cc=yamazaki-msmt@nec.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox