--- dynpageflags-dave/include/linux/dyn_pageflags.h | 20 ++++++++++++++++++-- dynpageflags-dave/include/linux/mmzone.h | 13 +++++++++++++ dynpageflags-dave/lib/dyn_pageflags.c | 15 +++++++++++---- 3 files changed, 42 insertions(+), 6 deletions(-) diff -puN include/linux/dyn_pageflags.h~unflat_dyn_pageflags include/linux/dyn_pageflags.h --- dynpageflags/include/linux/dyn_pageflags.h~unflat_dyn_pageflags 2005-02-21 08:31:38.000000000 -0800 +++ dynpageflags-dave/include/linux/dyn_pageflags.h 2005-02-21 09:42:36.000000000 -0800 @@ -14,12 +14,28 @@ typedef unsigned long ** dyn_pageflags_t; +enum pageflags_type { + PRESENT_PAGES_ONLY, + ALL_PAGES +}; + #define BITNUMBER(page) (page_to_pfn(page)) #define PAGEBIT(page) ((int) ((page_to_pfn(page))%(8 * sizeof(unsigned long)))) #define BITS_PER_PAGE (PAGE_SIZE * 8) -#define PAGES_PER_BITMAP ((max_mapnr + BITS_PER_PAGE - 1) / BITS_PER_PAGE) + +/* + * This MAX_MAPNR definition should probably go in place of max_mapnr + * in a real mm header + */ +#ifdef CONFIG_FLATMEM +#define MAX_MAPNR (max_mapnr) +#else +#define MAX_MAPNR (MAX_PHYSADDR_BITS-PAGE_SHIFT) +#endif +#define PAGES_PER_BITMAP ((MAX_MAPNR + BITS_PER_PAGE - 1) / BITS_PER_PAGE) + #define PAGENUMBER(page) (BITNUMBER(page) / BITS_PER_PAGE) #define PAGEINDEX(page) ((BITNUMBER(page) - (BITS_PER_PAGE * PAGENUMBER(page)))/(8*sizeof(unsigned long))) @@ -37,7 +53,7 @@ typedef unsigned long ** dyn_pageflags_t */ extern void clear_dyn_pageflags(dyn_pageflags_t pagemap); -extern int allocate_dyn_pageflags(dyn_pageflags_t *pagemap); +extern int allocate_dyn_pageflags(dyn_pageflags_t *pagemap, enum pageflags_type); extern int free_dyn_pageflags(dyn_pageflags_t *pagemap); /* Used by Suspend2 */ diff -puN lib/dyn_pageflags.c~unflat_dyn_pageflags lib/dyn_pageflags.c --- dynpageflags/lib/dyn_pageflags.c~unflat_dyn_pageflags 2005-02-21 08:31:39.000000000 -0800 +++ dynpageflags-dave/lib/dyn_pageflags.c 2005-02-21 09:42:23.000000000 -0800 @@ -38,7 +38,7 @@ void clear_dyn_pageflags(dyn_pageflags_t * Description: Allocate a bitmap for local page flags. * Arguments: dyn_pageflags_t *: Pointer to the bitmap. */ -int allocate_dyn_pageflags(dyn_pageflags_t *pagemap) +int allocate_dyn_pageflags(dyn_pageflags_t *pagemap, enum pageflags_type type) { int i; @@ -47,12 +47,17 @@ int allocate_dyn_pageflags(dyn_pageflags *pagemap = kmalloc(sizeof(void *) * PAGES_PER_BITMAP, GFP_ATOMIC); for (i = 0; i < PAGES_PER_BITMAP; i++) { + int pfn = i * BITS_PER_PAGE; + if ((type == PRESENT_PAGES_ONLY) && + !pfn_valid_range(i, i + BITS_PER_PAGE)) + continue; + (*pagemap)[i] = (unsigned long *) get_zeroed_page(GFP_ATOMIC); if (!(*pagemap)[i]) { printk("Error. Unable to allocate memory for " "dynamic pageflags."); free_dyn_pageflags(pagemap); - return 1; + return -ENOMEM; } } return 0; @@ -69,8 +74,10 @@ int free_dyn_pageflags(dyn_pageflags_t * if (!*pagemap) return 1; - for (i = 0; i < PAGES_PER_BITMAP; i++) - free_pages((unsigned long) (*pagemap)[i], 0); + for (i = 0; i < PAGES_PER_BITMAP; i++) { + if (pagemap[i]) + free_pages((unsigned long) (*pagemap)[i], 0); + } kfree(*pagemap); *pagemap = NULL; diff -puN include/linux/mmzone.h~unflat_dyn_pageflags include/linux/mmzone.h --- dynpageflags/include/linux/mmzone.h~unflat_dyn_pageflags 2005-02-21 09:16:28.000000000 -0800 +++ dynpageflags-dave/include/linux/mmzone.h 2005-02-21 09:21:18.000000000 -0800 @@ -410,6 +410,19 @@ extern struct pglist_data contig_page_da #error ZONES_SHIFT > MAX_ZONES_SHIFT #endif +#ifndef CONFIG_SPARSEMEM +static inline int pfn_valid_range(int start_pfn, int end_pfn) +{ + return pfn_valid(start) || pfn_valid(end); +} +#else +static inline int pfn_valid_range(int start_pfn, int end_pfn) +{ + return valid_section_nr(start_pfn >> PAGES_PER_SECTION) || + valid_section_nr(end_pfn >> PAGES_PER_SECTION); +} +#endif + #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ #endif /* _LINUX_MMZONE_H */ _