pfn and num is the data which eppic scritps give to makedumpfile for mm page
filtering, so any page within [pfn ~ pfn + num) can be filtered. Since
makedumpfile will iterate the pfn in an ascending order, the pfn & num
linked lists are also organized in a ascending order by pfn, so if one pfn
is hit by one list, the following pfn is more likely to be hit either by
this list again, or the one after, and a cur variable is used for saving
the current list to speedup the checking process.
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
erase_info.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++
erase_info.h | 8 ++++++
makedumpfile.c | 18 ++++++++++---
3 files changed, 91 insertions(+), 4 deletions(-)
diff --git a/erase_info.c b/erase_info.c
index b67d1d0..d68e1a2 100644
--- a/erase_info.c
+++ b/erase_info.c
@@ -2466,3 +2466,72 @@ get_size_eraseinfo(void)
return size_eraseinfo;
}
+static struct ft_page_info *ft_head = NULL;
+
+/*
+ * Insert the ft_page_info blocks into ft_head by ascending pfn.
+ */
+int
+update_filter_pages_info(unsigned long pfn, unsigned long num)
+{
+ struct ft_page_info *p;
+ struct ft_page_info *new_p = malloc(sizeof(struct ft_page_info));
+
+ if (!new_p) {
+ ERRMSG("Can't allocate memory for ft_page_info at %lx\n", pfn);
+ return 1;
+ }
+ new_p->pfn = pfn;
+ new_p->num = num;
+ new_p->next = NULL;
+
+ if (!ft_head || ft_head->pfn > new_p->pfn) {
+ new_p->next = ft_head;
+ ft_head = new_p;
+ return 0;
+ }
+
+ p = ft_head;
+ while (p->next != NULL && p->next->pfn < new_p->pfn) {
+ p = p->next;
+ }
+
+ new_p->next = p->next;
+ p->next = new_p;
+ return 0;
+}
+
+/*
+ * Check if the pfn page should be filtered.
+ *
+ * pfn and ft_head are in ascending order, so save the current ft_page_info
+ * block into **p because it is likely to hit again next time.
+ */
+int
+filter_page(unsigned long pfn, struct ft_page_info **p)
+{
+ if (ft_head == NULL)
+ return 0;
+
+ if (*p == NULL)
+ *p = ft_head;
+
+ /* Handle the 1st gap */
+ if (pfn >= 0 && pfn < ft_head->pfn)
+ return 0;
+
+ /* Handle ft_page_info blocks and following gaps */
+ while ((*p)->next) {
+ if (pfn >= (*p)->pfn && pfn < (*p)->pfn + (*p)->num)
+ return 1; // filter this page
+ if (pfn >= (*p)->pfn + (*p)->num && pfn < (*p)->next->pfn)
+ return 0; // save this page
+ *p = (*p)->next;
+ }
+
+ /* Handle the last gap */
+ if (pfn >= (*p)->pfn + (*p)->num)
+ return 0;
+ else
+ return 1;
+}
\ No newline at end of file
diff --git a/erase_info.h b/erase_info.h
index b363a40..4552dfc 100644
--- a/erase_info.h
+++ b/erase_info.h
@@ -64,6 +64,14 @@ void filter_data_buffer_parallel(unsigned char *buf, unsigned long long
paddr,
size_t size, pthread_mutex_t *mutex);
unsigned long get_size_eraseinfo(void);
int update_filter_info_raw(unsigned long long, int, int);
+int update_filter_pages_info(unsigned long, unsigned long);
+
+struct ft_page_info {
+ unsigned long pfn;
+ unsigned long num;
+ struct ft_page_info *next;
+};
+int filter_page(unsigned long, struct ft_page_info **p);
#endif /* _ERASE_INFO_H */
diff --git a/makedumpfile.c b/makedumpfile.c
index 2d3b08b..33fad32 100644
--- a/makedumpfile.c
+++ b/makedumpfile.c
@@ -100,6 +100,7 @@ mdf_pfn_t pfn_user;
mdf_pfn_t pfn_free;
mdf_pfn_t pfn_hwpoison;
mdf_pfn_t pfn_offline;
+mdf_pfn_t pfn_eppic;
mdf_pfn_t pfn_elf_excluded;
mdf_pfn_t num_dumped;
@@ -6453,6 +6454,7 @@ __exclude_unnecessary_pages(unsigned long mem_map,
unsigned int order_offset, dtor_offset;
unsigned long flags, mapping, private = 0;
unsigned long compound_dtor, compound_head = 0;
+ struct ft_page_info *cur = NULL;
/*
* If a multi-page exclusion is pending, do it first
@@ -6670,6 +6672,13 @@ check_order:
else if (isOffline(flags, _mapcount)) {
pfn_counter = &pfn_offline;
}
+ /*
+ * Exclude pages that specified by eppic script
+ */
+ else if (filter_page(pfn, &cur)) {
+ nr_pages = 1;
+ pfn_counter = &pfn_eppic;
+ }
/*
* Unexcludable page
*/
@@ -8217,7 +8226,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct
cache_data *cd_page)
*/
if (info->flag_cyclic) {
pfn_zero = pfn_cache = pfn_cache_private = 0;
- pfn_user = pfn_free = pfn_hwpoison = pfn_offline = 0;
+ pfn_user = pfn_free = pfn_hwpoison = pfn_offline = pfn_eppic = 0;
pfn_memhole = info->max_mapnr;
}
@@ -9555,7 +9564,7 @@ write_kdump_pages_and_bitmap_cyclic(struct cache_data *cd_header,
struct cache_d
* Reset counter for debug message.
*/
pfn_zero = pfn_cache = pfn_cache_private = 0;
- pfn_user = pfn_free = pfn_hwpoison = pfn_offline = 0;
+ pfn_user = pfn_free = pfn_hwpoison = pfn_offline = pfn_eppic = 0;
pfn_memhole = info->max_mapnr;
/*
@@ -10504,7 +10513,7 @@ print_report(void)
pfn_original = info->max_mapnr - pfn_memhole;
pfn_excluded = pfn_zero + pfn_cache + pfn_cache_private
- + pfn_user + pfn_free + pfn_hwpoison + pfn_offline;
+ + pfn_user + pfn_free + pfn_hwpoison + pfn_offline + pfn_eppic;
REPORT_MSG("\n");
REPORT_MSG("Original pages : 0x%016llx\n", pfn_original);
@@ -10520,6 +10529,7 @@ print_report(void)
REPORT_MSG(" Free pages : 0x%016llx\n", pfn_free);
REPORT_MSG(" Hwpoison pages : 0x%016llx\n", pfn_hwpoison);
REPORT_MSG(" Offline pages : 0x%016llx\n", pfn_offline);
+ REPORT_MSG(" Eppic filtered pages : 0x%016llx\n", pfn_eppic);
REPORT_MSG(" Remaining pages : 0x%016llx\n",
pfn_original - pfn_excluded);
@@ -10560,7 +10570,7 @@ print_mem_usage(void)
pfn_original = info->max_mapnr - pfn_memhole;
pfn_excluded = pfn_zero + pfn_cache + pfn_cache_private
- + pfn_user + pfn_free + pfn_hwpoison + pfn_offline;
+ + pfn_user + pfn_free + pfn_hwpoison + pfn_offline + pfn_eppic;
shrinking = (pfn_original - pfn_excluded) * 100;
shrinking = shrinking / pfn_original;
total_size = info->page_size * pfn_original;
--
2.47.0