From: Cliff Wickman <cpw@xxxxxxx> When the kernel free pages are not detectable with the 'buddy' method we do a scan for free pages. In cyclic mode that scan was performed over all of memory for each cycle region. This patch records the pfn ranges of each node on the first such cycle. Then ignores those nodes that are not within the cyclic region on subsequent scans. This shortens these subsequent scans. Diffed against makedumpfile-1.5.4 Signed-off-by: Cliff Wickman <cpw at sgi.com> --- makedumpfile.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) Index: makedumpfile-1.5.4/makedumpfile.c =================================================================== --- makedumpfile-1.5.4.orig/makedumpfile.c +++ makedumpfile-1.5.4/makedumpfile.c @@ -36,6 +36,16 @@ struct DumpInfo *info = NULL; char filename_stdout[] = FILENAME_STDOUT; +int nr_nodes; +int node_free_pfns_recorded = 0; +struct node_free_pfns { + unsigned long low_pfn; + unsigned long high_pfn; + long count; + int valid; +}; +struct node_free_pfns *nfp, *nfp1; + /* * The numbers of the excluded pages */ @@ -3609,7 +3619,7 @@ page_to_pfn(unsigned long page) } int -reset_bitmap_of_free_pages(unsigned long node_zones) +reset_bitmap_of_free_pages(unsigned long node_zones, int node) { int order, i, migrate_type, migrate_types; @@ -3653,6 +3663,18 @@ reset_bitmap_of_free_pages(unsigned long retcd = ANALYSIS_FAILED; return FALSE; } + if (info->flag_cyclic) { + nfp1 = nfp + node; + nfp1->valid = 1; + nfp1->count++; + for (i = 0; i < (1<<order); i++) { + pfn = start_pfn + i; + if (pfn > nfp1->high_pfn) + nfp1->high_pfn = pfn; + if (pfn < nfp1->low_pfn) + nfp1->low_pfn = pfn; + } + } if (!info->flag_cyclic || ((start_pfn >= info->cyclic_start_pfn) && @@ -3990,8 +4012,31 @@ _exclude_free_page(void) } if (!spanned_pages) continue; - if (!reset_bitmap_of_free_pages(zone)) + /*don't scan for free pages outside of the cyclic area*/ + if (info->flag_cyclic) { + nfp1 = nfp + node; + if (nfp1->valid) { + if (!nfp1->count) { + /* this node has no free pages */ + continue; + } + if (nfp1->high_pfn < info->cyclic_start_pfn) { + /* we're at a node lower than the current + cyclic region */ + continue; + } + if (nfp1->low_pfn > info->cyclic_end_pfn) { + /* we're up to a node that is all higher than + the current cyclic region */ + return TRUE; + } + } + } + if (!reset_bitmap_of_free_pages(zone, node)) return FALSE; + if (info->flag_cyclic) { + nfp1 = nfp + node; + } } if (num_nodes < vt.numnodes) { if ((node = next_online_node(node + 1)) < 0) { @@ -5306,12 +5351,39 @@ get_num_dumpable(void) unsigned long long get_num_dumpable_cyclic(void) { + int i; int cycle = 0; int lastcycle = 0; int newcycle = 1; + int node; unsigned long long pfn, num_dumpable=0; PROGRESS_MSG("Begin page counting phase.\n"); + /* build a table for free page pfn's per node */ + if ((node = next_online_node(0)) < 0) { + ERRMSG("Can't get first online node.\n"); + exit(1); + } + nr_nodes = 1; + while (node >= 0) { + if ((node = next_online_node(node + 1)) < 0) { + node = -1; + } else { + nr_nodes++; + } + } + if ((nfp = (struct node_free_pfns *) + malloc(nr_nodes * sizeof(struct node_free_pfns))) == NULL) { + ERRMSG("Can't malloc %d structures.\n", nr_nodes); + exit(1); + } + for (i = 0, nfp1 = nfp; i < nr_nodes; i++, nfp1++) { + nfp1->valid = 0; + nfp1->count = 0; + nfp1->low_pfn = 0xffffffffffffffff; + nfp1->high_pfn = 0; + } + for (pfn = 0; pfn < info->max_mapnr; pfn++) { if (newcycle) PROGRESS_MSG("Scan cycle %d\n", cycle + 1);