[PATCH 00/10] Support free page filtering looking up mem_map array

Hatayama, Daisuke d.hatayama at jp.fujitsu.com
Wed Nov 14 20:55:04 EST 2012


> -----Original Message-----
> From: Atsushi Kumagai [mailto:kumagai-atsushi at mxc.nes.nec.co.jp]
> Sent: Wednesday, November 14, 2012 4:31 PM
[...]
> On Tue, 13 Nov 2012 10:03:37 +0000
> "Hatayama, Daisuke" <d.hatayama at jp.fujitsu.com> wrote:
> 
> > > -----Original Message-----
> > > From: kexec-bounces at lists.infradead.org
> > > [mailto:kexec-bounces at lists.infradead.org] On Behalf Of Hatayama,
> Daisuke
> > [..]>
> > > > -----Original Message-----
> > > > From: Atsushi Kumagai [mailto:kumagai-atsushi at mxc.nes.nec.co.jp]
> > > > Sent: Tuesday, November 13, 2012 4:56 PM
[...]
> It's basically good, but more fix is needed for setup_page_is_buddy().
> 
>    3706 static void
>    3707 setup_page_is_buddy(void)
>    3708 {
>    3709         if (NUMBER(PG_buddy) == NOT_FOUND_NUMBER) {
>    3710                 if (SIZE(pageflags) == NOT_FOUND_STRUCTURE)
>    3711                         info->page_is_buddy = page_is_buddy_v1;
> 
> In case that none of the values needed for mem_map array logic is given,
> the condition on line 3710 will be met regardless of kernel version.
> As a result, invalid logic will be used and freelist logic isn't used
> because page_is_buddy isn't NULL.
> 
> Additionally, the case above will be happen when using makedumpfile-1.5.0
> for recent kernels, which doesn't export necessary symbols.
> 
> So, I think that we need to change the statement on line 3710, but I have
> no idea without to check kernel version. If you have better way, I will
> adopt it.
> 

I'll first hard code PAGE_BUDDY_MAPCOUNT_VALUE for v2.6.38 and later. This is
a workaround until it is exported from kernel's VMCOREINFO. At the same time
I'll check NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) first and then SIZE(pageflags) in
setup_page_is_buddy(). By this, we can avoid the issue that page_is_buddy_v1
is wrongly used on recent kernels.

The remaining problematic kernel versions are the ones where:

- PG_buddy is not present, and
- enum pageflags is present but
- enum pageflags is not exported from VMCOREINFO.

These are exactly from v2.6.27 to 2.6.37. I'll cover this range by hard coding
PG_buddy. One concern was the fact that value of PG_buddy in this range varies
depending on CONFIG_PAGEFLAGS_EXTENDED. But as below, this config is not relevant
to the architectures supported by makedumpfile. It's no problem.

BTW, PAGE_BUDDY_MAPCOUNT_VALUE is now defined as macro. This is not useful
since we cannot get its value from vmlinux. I'll make a patch to redefine it
as enumeration later. It's originally signed integer, -128, so I think it's no
problem.

$ git grep ".*CONFIG_PAGEFLAGS_EXTEND.*" ./arch/
arch/um/defconfig:CONFIG_PAGEFLAGS_EXTENDED=y
arch/xtensa/configs/iss_defconfig:CONFIG_PAGEFLAGS_EXTENDED=y
arch/xtensa/configs/s6105_defconfig:CONFIG_PAGEFLAGS_EXTENDED=y

Next diff shows the idea I explain above. I'll add the same explanation in codes as
comments. The assumption behind these seems complicated and maintainance would be
difficult without any comments explaining why these are being done this way.

$ git diff
diff --git a/makedumpfile.c b/makedumpfile.c
index 98eb640..a1a39d5 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -1215,10 +1215,24 @@ get_value_for_old_linux(void)
                NUMBER(PG_swapcache) = PG_swapcache_ORIGINAL;
        if (NUMBER(PG_slab) == NOT_FOUND_NUMBER)
                NUMBER(PG_slab) = PG_slab_ORIGINAL;
-       if (NUMBER(PG_buddy) == NOT_FOUND_NUMBER
-           && info->kernel_version >= KERNEL_VERSION(2, 6, 17)
-           && info->kernel_version <= KERNEL_VERSION(2, 6, 26))
-               NUMBER(PG_buddy) = PG_buddy_v2_6_17_to_v2_6_26;
+       if (NUMBER(PG_buddy) == NOT_FOUND_NUMBER) {
+               if (info->kernel_version >= KERNEL_VERSION(2, 6, 17)
+                   && info->kernel_version <= KERNEL_VERSION(2, 6, 26))
+                       NUMBER(PG_buddy) = PG_buddy_v2_6_17_to_v2_6_26;
+               if (info->kernel_version >= KERNEL_VERSION(2, 6, 27)
+                   && info->kernel_version >= KERNEL_VERSION(2, 6, 37))
+                       NUMBER(PG_buddy) = 18;
+       }
+       if (NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) == NOT_FOUND_NUMBER) {
+               if (info->kernel_version == KERNEL_VERSION(2, 6, 38))
+                       NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) = -2;
+               if (info->kernel_version >= KERNEL_VERSION(2, 6, 39))
+                       NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) = -128;
+       }
+       if (SIZE(pageflags) == NOT_FOUND_STRUCTURE) {
+               if (info->kernel_version >= KERNEL_VERSION(2, 6, 27))
+                       SIZE(pageflags) = 4;
+       }
        return TRUE;
 }

@@ -3725,13 +3739,13 @@ static void
 setup_page_is_buddy(void)
 {
        if (NUMBER(PG_buddy) == NOT_FOUND_NUMBER) {
-               if (SIZE(pageflags) == NOT_FOUND_STRUCTURE)
-                       info->page_is_buddy = page_is_buddy_v1;
-               else if (NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) != NOT_FOUND_NUMBER)
+               if (NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE) != NOT_FOUND_NUMBER)
                        info->page_is_buddy = page_is_buddy_v3;
+               else if (SIZE(pageflags) == NOT_FOUND_STRUCTURE)
+                       info->page_is_buddy = page_is_buddy_v1;
                else {
-                       MSG("Can't select page_is_buddy handler; "
-                           "filtering free pages is disabled.\n");
+                       DEBUG_MSG("Can't select page_is_buddy handler; "
+                                 "follow freelist instead of mem_map.\n");
                }
        } else
                info->page_is_buddy = page_is_buddy_v2;

Thanks.
HATAYAMA, Daisuke




More information about the kexec mailing list