Index: 2.6.13-joel2/include/linux/mmzone.h
===================================================================
--- 2.6.13-joel2.orig/include/linux/mmzone.h 2005-09-13 14:54:17.%N -0500
+++ 2.6.13-joel2/include/linux/mmzone.h 2005-09-19 16:26:18.%N -0500
@@ -21,6 +21,21 @@
#define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER
#endif
+/*
+ * 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 18
+#define BITS_PER_RCLM_TYPE 2
+
+#define BITS_PER_ALLOC_TYPE 2
+
struct free_area {
struct list_head free_list;
unsigned long nr_free;
@@ -137,7 +152,45 @@ struct zone {
* free areas of different sizes
*/
spinlock_t lock;
+ /*
+ * 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_ALLOC_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,17 @@ 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 +537,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 +552,7 @@ struct mem_section {
* before using it wrong.
*/
unsigned long section_mem_map;
+ DECLARE_BITMAP(free_area_usemap,64);
};
extern struct mem_section mem_section[NR_MEM_SECTIONS];
@@ -536,6 +604,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[0];
+}
+
+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 +651,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