default 0 if BASE_FULL
        default 1 if !BASE_FULL
 
+config PAGE_GROUP_BY_MOBILITY
+       bool "Group pages based on their mobility in the page allocator"
+       def_bool y
+       help
+         The standard allocator will fragment memory over time which means
+         that high order allocations will fail even if kswapd is running. If
+         this option is set, the allocator will try and group page types
+         based on their ability to migrate or reclaim. This is a best effort
+         attempt at lowering fragmentation which a few workloads care about.
+         The loss is a more complex allocator that may perform slower. If
+         you are interested in working with large pages, say Y and set
+         /proc/sys/vm/min_free_bytes to 16374. Otherwise say N
+
 menuconfig MODULES
        bool "Enable loadable module support"
        help
 
 EXPORT_SYMBOL(nr_node_ids);
 #endif
 
+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
 static inline int get_pageblock_migratetype(struct page *page)
 {
        return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
        return ((gfp_flags & __GFP_MOVABLE) != 0);
 }
 
+#else
+static inline int get_pageblock_migratetype(struct page *page)
+{
+       return MIGRATE_UNMOVABLE;
+}
+
+static void set_pageblock_migratetype(struct page *page, int migratetype)
+{
+}
+
+static inline int gfpflags_to_migratetype(gfp_t gfp_flags)
+{
+       return MIGRATE_UNMOVABLE;
+}
+#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
+
 #ifdef CONFIG_DEBUG_VM
 static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
 {
        return 0;
 }
 
+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
 /*
  * This array describes the order lists are fallen back to when
  * the free lists for the desirable migrate type are depleted
 
        return NULL;
 }
+#else
+static struct page *__rmqueue_fallback(struct zone *zone, int order,
+                                               int start_migratetype)
+{
+       return NULL;
+}
+#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
 
 /* 
  * Do the hard work of removing an element from the buddy allocator.
                        if (unlikely(!pcp->count))
                                goto failed;
                }
+
+#ifdef CONFIG_PAGE_GROUP_BY_MOBILITY
                /* Find a page of the appropriate migrate type */
-               list_for_each_entry(page, &pcp->list, lru) {
-                       if (page_private(page) == migratetype) {
-                               list_del(&page->lru);
-                               pcp->count--;
+               list_for_each_entry(page, &pcp->list, lru)
+                       if (page_private(page) == migratetype)
                                break;
-                       }
-               }
 
-               /*
-                * Check if a page of the appropriate migrate type
-                * was found. If not, allocate more to the pcp list
-                */
-               if (&page->lru == &pcp->list) {
+               /* Allocate more to the pcp list if necessary */
+               if (unlikely(&page->lru == &pcp->list)) {
                        pcp->count += rmqueue_bulk(zone, 0,
                                        pcp->batch, &pcp->list, migratetype);
                        page = list_entry(pcp->list.next, struct page, lru);
-                       VM_BUG_ON(page_private(page) != migratetype);
-                       list_del(&page->lru);
-                       pcp->count--;
                }
+#else
+               page = list_entry(pcp->list.next, struct page, lru);
+#endif /* CONFIG_PAGE_GROUP_BY_MOBILITY */
+
+               list_del(&page->lru);
+               pcp->count--;
        } else {
                spin_lock_irqsave(&zone->lock, flags);
                page = __rmqueue(zone, order, migratetype);