Files
makedumpfile/makedumpfile-exclude-compound-pages.patch

128 lines
3.7 KiB
Diff

From: Petr Tesarik <ptesarik@suse.cz>
Date: Fri Jun 13 11:57:03 2014 +0200
Subject: Treat compound pages as a single entity
References: bnc#873232
Patch-mainline: not yet
For a compound page, the head page determines whether the page should be
kept or excluded.
Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
makedumpfile.c | 57 +++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 43 insertions(+), 14 deletions(-)
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -4652,6 +4652,7 @@ __exclude_unnecessary_pages(unsigned lon
unsigned char *pcache;
unsigned int _count, _mapcount = 0;
unsigned long flags, mapping, private = 0;
+ int nr_pages;
/*
* If a multi-page exclusion is pending, do it first
@@ -4671,7 +4672,13 @@ __exclude_unnecessary_pages(unsigned lon
pfn_read_start = ULONGLONG_MAX;
pfn_read_end = 0;
- for (pfn = pfn_start; pfn < pfn_end; pfn++, mem_map += SIZE(page)) {
+ for (pfn = pfn_start; pfn < pfn_end; pfn += nr_pages, mem_map += nr_pages * SIZE(page)) {
+ unsigned long long *pfn_counter;
+
+ /*
+ * Process one page by default.
+ */
+ nr_pages = 1;
/*
* If this pfn doesn't belong to target region, skip this pfn.
@@ -4723,18 +4730,32 @@ __exclude_unnecessary_pages(unsigned lon
private = ULONG(pcache + OFFSET(page.private));
/*
+ * Check for compound pages.
+ */
+ if (isCompoundHead(flags) && (pfn + 1 <= pfn_read_end)) {
+ unsigned char *ptail;
+ unsigned long order;
+
+ ptail = pcache + SIZE(page);
+ order = ULONG(ptail + OFFSET(page.lru) +
+ OFFSET(list_head.prev));
+ if (order && order < sizeof(unsigned long) * 8 &&
+ (pfn & ((1UL << order) - 1)) == 0 &&
+ (OFFSET(page.private) == NOT_FOUND_STRUCTURE ||
+ ULONG(ptail + OFFSET(page.private)) == mem_map)) {
+ nr_pages = 1UL << order;
+ }
+ }
+
+ /*
* Exclude the free page managed by a buddy
* Use buddy identification of free pages whether cyclic or not.
*/
if ((info->dump_level & DL_EXCLUDE_FREE)
&& info->page_is_buddy
&& info->page_is_buddy(flags, _mapcount, private, _count)) {
- int nr_pages = 1 << private;
-
- exclude_range(&pfn_free, pfn, pfn + nr_pages, cycle);
-
- pfn += nr_pages - 1;
- mem_map += (nr_pages - 1) * SIZE(page);
+ nr_pages = 1 << private;
+ pfn_counter = &pfn_free;
}
/*
* Exclude the cache page without the private page.
@@ -4742,8 +4763,7 @@ __exclude_unnecessary_pages(unsigned lon
else if ((info->dump_level & DL_EXCLUDE_CACHE)
&& (isLRU(flags) || isSwapCache(flags))
&& !isPrivate(flags) && !isAnon(mapping)) {
- if (clear_bit_on_2nd_bitmap_for_kernel(pfn, cycle))
- pfn_cache++;
+ pfn_counter = &pfn_cache;
}
/*
* Exclude the cache page with the private page.
@@ -4751,23 +4771,32 @@ __exclude_unnecessary_pages(unsigned lon
else if ((info->dump_level & DL_EXCLUDE_CACHE_PRI)
&& (isLRU(flags) || isSwapCache(flags))
&& !isAnon(mapping)) {
- if (clear_bit_on_2nd_bitmap_for_kernel(pfn, cycle))
- pfn_cache_private++;
+ pfn_counter = &pfn_cache_private;
}
/*
* Exclude the data page of the user process.
*/
else if ((info->dump_level & DL_EXCLUDE_USER_DATA)
&& isAnon(mapping)) {
- if (clear_bit_on_2nd_bitmap_for_kernel(pfn, cycle))
- pfn_user++;
+ pfn_counter = &pfn_user;
}
/*
* Exclude the hwpoison page.
*/
else if (isHWPOISON(flags)) {
+ pfn_counter = &pfn_hwpoison;
+ }
+ /*
+ * Page not excluded
+ */
+ else
+ continue;
+
+ if (nr_pages == 1) {
if (clear_bit_on_2nd_bitmap_for_kernel(pfn, cycle))
- pfn_hwpoison++;
+ (*pfn_counter)++;
+ } else {
+ exclude_range(pfn_counter, pfn, pfn + nr_pages, cycle);
}
}
return TRUE;