diff -rup -X /usr/src/patchset-0.5/bin//dontdiff linux-2.6.13-rc3-mhp1-01_gfp_flags/include/linux/mmzone.h linux-2.6.13-rc3-mhp1-02_more_defines/include/linux/mmzone.h --- linux-2.6.13-rc3-mhp1-01_gfp_flags/include/linux/mmzone.h 2005-07-18 12:05:27.000000000 +0100 +++ linux-2.6.13-rc3-mhp1-02_more_defines/include/linux/mmzone.h 2005-07-18 12:24:33.000000000 +0100 @@ -21,6 +21,20 @@ #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER #endif +/* + * Reduce buddy heap fragmentation by keeping pages with similar + * reclaimability behavior together. The two bit field __GFP_RECLAIMBITS + * enumerates the following 4 kinds of page reclaimability: + */ +#define RCLM_TYPES 4 +#define RCLM_NORCLM 0 +#define RCLM_USER 1 +#define RCLM_KERN 2 +#define RCLM_FALLBACK 3 + +#define RCLM_SHIFT 17 /* Shift __GFP_RECLAIMBITS to RCLM_* values */ +#define BITS_PER_RCLM_TYPE 2 + struct free_area { struct list_head free_list; unsigned long nr_free; @@ -137,8 +151,47 @@ struct zone { * free areas of different sizes */ spinlock_t lock; - struct free_area free_area[MAX_ORDER]; + /* + * free_area to be removed in later patch as it is replaced by + * free_area_list + */ + struct free_area free_area[MAX_ORDER]; + +#ifndef CONFIG_SPARSEMEM + /* + * The map tracks what each 2^MAX_ORDER-1 sized block is being used for. + * Each 2^MAX_ORDER block have pages has BITS_PER_RCLM_TYPE bits in + * this map to remember what the block is for. When a page is freed, + * it's index within this bitmap is calculated in get_pageblock_type() + * This means that pages will always be freed into the correct list in + * free_area_lists + * + * The bits are set when a 2^MAX_ORDER block of pages is split + */ + unsigned long *free_area_usemap; +#endif + + /* + * free_area_lists contains buddies of split MAX_ORDER blocks indexed + * by their intended allocation type, while free_area_global contains + * whole MAX_ORDER blocks that can be used for any allocation type. + */ + struct free_area free_area_lists[RCLM_TYPES][MAX_ORDER]; + + /* + * A percentage of a zone is reserved for falling back to. Without + * a fallback, memory will slowly fragment over time meaning the + * placement policy only delays the fragmentation problem, not + * fixes it + */ + unsigned long fallback_reserve; + + /* + * When negative, 2^MAX_ORDER-1 sized blocks of pages will be reserved + * for fallbacks + */ + long fallback_balance; ZONE_PADDING(_pad1_) @@ -230,6 +283,18 @@ struct zone { } ____cacheline_maxaligned_in_smp; +static inline void inc_reserve_count(struct zone* zone, int type) +{ + if(type == RCLM_FALLBACK) + zone->fallback_reserve++; +} +static inline void dec_reserve_count(struct zone* zone, int type) +{ + if(type == RCLM_FALLBACK && zone->fallback_reserve) + zone->fallback_reserve--; + +} + /* * The "priority" of VM scanning is how much of the queues we will scan in one * go. A value of 12 for DEF_PRIORITY implies that we will scan 1/4096th of the @@ -473,6 +538,9 @@ extern struct pglist_data contig_page_da #if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS #error Allocator MAX_ORDER exceeds SECTION_SIZE #endif +#if ((SECTION_SIZE_BITS - MAX_ORDER) * BITS_PER_ALLOC) > 64 +#error free_area_usemap is not big enough +#endif struct page; struct mem_section { @@ -485,6 +553,7 @@ struct mem_section { * before using it wrong. */ unsigned long section_mem_map; + u64 free_area_usemap; }; extern struct mem_section mem_section[NR_MEM_SECTIONS]; @@ -536,6 +605,17 @@ static inline struct mem_section *__pfn_ return __nr_to_section(pfn_to_section_nr(pfn)); } +static inline unsigned long *pfn_to_usemap(struct zone *zone, unsigned long pfn) +{ + return &__pfn_to_section(pfn)->free_area_usemap; +} + +static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) +{ + pfn &= (PAGES_PER_SECTION-1); + return (int)((pfn >> (MAX_ORDER-1)) * BITS_PER_RCLM_TYPE); +} + #define pfn_to_page(pfn) \ ({ \ unsigned long __pfn = (pfn); \ @@ -572,6 +652,15 @@ static inline int pfn_valid(unsigned lon void sparse_init(void); #else #define sparse_init() do {} while (0) +static inline unsigned long *pfn_to_usemap(struct zone *zone, unsigned long pfn) +{ + return (zone->free_area_usemap); +} +static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn) +{ + pfn = pfn - zone->zone_start_pfn; + return (int)((pfn >> (MAX_ORDER-1)) * BITS_PER_RCLM_TYPE); +} #endif /* CONFIG_SPARSEMEM */ #ifdef CONFIG_NODES_SPAN_OTHER_NODES diff -rup -X /usr/src/patchset-0.5/bin//dontdiff linux-2.6.13-rc3-mhp1-01_gfp_flags/mm/page_alloc.c linux-2.6.13-rc3-mhp1-02_more_defines/mm/page_alloc.c --- linux-2.6.13-rc3-mhp1-01_gfp_flags/mm/page_alloc.c 2005-07-13 05:46:46.000000000 +0100 +++ linux-2.6.13-rc3-mhp1-02_more_defines/mm/page_alloc.c 2005-07-18 12:27:09.000000000 +0100 @@ -65,6 +65,20 @@ EXPORT_SYMBOL(totalram_pages); EXPORT_SYMBOL(nr_swap_pages); /* + * fallback_allocs contains the fallback types for low memory conditions + * where the preferred alloction type if not available. + */ +int fallback_allocs[RCLM_TYPES][RCLM_TYPES+1] = { + {RCLM_NORCLM, RCLM_FALLBACK, RCLM_KERN, RCLM_USER, -1}, + {RCLM_KERN, RCLM_FALLBACK, RCLM_NORCLM, RCLM_USER, -1}, + {RCLM_USER, RCLM_FALLBACK, RCLM_NORCLM, RCLM_KERN, -1}, + {RCLM_FALLBACK, RCLM_NORCLM, RCLM_KERN, RCLM_USER, -1} +}; +static char *type_names[RCLM_TYPES] = { "Kernnel Unreclaimable", + "Kernel Reclaimable", + "User Reclaimable", "Fallback"}; + +/* * Used by page_zone() to look up the address of the struct zone whose * id is encoded in the upper bits of page->flags */