Group short-lived and reclaimable kernel allocations
[sfrench/cifs-2.6.git] / include / linux / mmzone.h
index 4e5627379b0935b306261d7c9666786fa5357f24..4721e9aa3ced3d1d53ba54a1901651f30ff368d8 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/seqlock.h>
 #include <linux/nodemask.h>
+#include <linux/pageblock-flags.h>
 #include <asm/atomic.h>
 #include <asm/page.h>
 
  */
 #define PAGE_ALLOC_COSTLY_ORDER 3
 
+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
+#define MIGRATE_UNMOVABLE     0
+#define MIGRATE_RECLAIMABLE   1
+#define MIGRATE_MOVABLE       2
+#define MIGRATE_TYPES         3
+#else
+#define MIGRATE_UNMOVABLE     0
+#define MIGRATE_UNRECLAIMABLE 0
+#define MIGRATE_MOVABLE       0
+#define MIGRATE_TYPES         1
+#endif
+
+#define for_each_migratetype_order(order, type) \
+       for (order = 0; order < MAX_ORDER; order++) \
+               for (type = 0; type < MIGRATE_TYPES; type++)
+
 struct free_area {
-       struct list_head        free_list;
+       struct list_head        free_list[MIGRATE_TYPES];
        unsigned long           nr_free;
 };
 
@@ -222,6 +239,14 @@ struct zone {
 #endif
        struct free_area        free_area[MAX_ORDER];
 
+#ifndef CONFIG_SPARSEMEM
+       /*
+        * Flags for a MAX_ORDER_NR_PAGES block. See pageblock-flags.h.
+        * In SPARSEMEM, this map is stored in struct mem_section
+        */
+       unsigned long           *pageblock_flags;
+#endif /* CONFIG_SPARSEMEM */
+
 
        ZONE_PADDING(_pad1_)
 
@@ -324,6 +349,17 @@ struct zone {
 #define MAX_ZONES_PER_ZONELIST (MAX_NUMNODES * MAX_NR_ZONES)
 
 #ifdef CONFIG_NUMA
+
+/*
+ * The NUMA zonelists are doubled becausse we need zonelists that restrict the
+ * allocations to a single node for GFP_THISNODE.
+ *
+ * [0 .. MAX_NR_ZONES -1]              : Zonelists with fallback
+ * [MAZ_NR_ZONES ... MAZ_ZONELISTS -1]  : No fallback (GFP_THISNODE)
+ */
+#define MAX_ZONELISTS (2 * MAX_NR_ZONES)
+
+
 /*
  * We cache key information from each zonelist for smaller cache
  * footprint when scanning for free pages in get_page_from_freelist().
@@ -389,6 +425,7 @@ struct zonelist_cache {
        unsigned long last_full_zap;            /* when last zap'd (jiffies) */
 };
 #else
+#define MAX_ZONELISTS MAX_NR_ZONES
 struct zonelist_cache;
 #endif
 
@@ -455,7 +492,7 @@ extern struct page *mem_map;
 struct bootmem_data;
 typedef struct pglist_data {
        struct zone node_zones[MAX_NR_ZONES];
-       struct zonelist node_zonelists[MAX_NR_ZONES];
+       struct zonelist node_zonelists[MAX_ZONELISTS];
        int nr_zones;
 #ifdef CONFIG_FLAT_NODE_MEM_MAP
        struct page *node_mem_map;
@@ -708,6 +745,9 @@ extern struct zone *next_zone(struct zone *zone);
 #define PAGES_PER_SECTION       (1UL << PFN_SECTION_SHIFT)
 #define PAGE_SECTION_MASK      (~(PAGES_PER_SECTION-1))
 
+#define SECTION_BLOCKFLAGS_BITS \
+               ((SECTION_SIZE_BITS - (MAX_ORDER-1)) * NR_PAGEBLOCK_BITS)
+
 #if (MAX_ORDER - 1 + PAGE_SHIFT) > SECTION_SIZE_BITS
 #error Allocator MAX_ORDER exceeds SECTION_SIZE
 #endif
@@ -727,6 +767,7 @@ struct mem_section {
         * before using it wrong.
         */
        unsigned long section_mem_map;
+       DECLARE_BITMAP(pageblock_flags, SECTION_BLOCKFLAGS_BITS);
 };
 
 #ifdef CONFIG_SPARSEMEM_EXTREME
@@ -771,12 +812,17 @@ static inline struct page *__section_mem_map_addr(struct mem_section *section)
        return (struct page *)map;
 }
 
-static inline int valid_section(struct mem_section *section)
+static inline int present_section(struct mem_section *section)
 {
        return (section && (section->section_mem_map & SECTION_MARKED_PRESENT));
 }
 
-static inline int section_has_mem_map(struct mem_section *section)
+static inline int present_section_nr(unsigned long nr)
+{
+       return present_section(__nr_to_section(nr));
+}
+
+static inline int valid_section(struct mem_section *section)
 {
        return (section && (section->section_mem_map & SECTION_HAS_MEM_MAP));
 }
@@ -798,6 +844,13 @@ static inline int pfn_valid(unsigned long pfn)
        return valid_section(__nr_to_section(pfn_to_section_nr(pfn)));
 }
 
+static inline int pfn_present(unsigned long pfn)
+{
+       if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+               return 0;
+       return present_section(__nr_to_section(pfn_to_section_nr(pfn)));
+}
+
 /*
  * These are _only_ used during initialisation, therefore they
  * can use __initdata ...  They could have names to indicate