#define ALLOC_HARDER           0x10 /* try to alloc harder */
 #define ALLOC_HIGH             0x20 /* __GFP_HIGH set */
 #define ALLOC_CPUSET           0x40 /* check for correct cpuset */
+#define ALLOC_PFMEMALLOC       0x80 /* Caller has PF_MEMALLOC set */
 
 #ifdef CONFIG_FAIL_PAGE_ALLOC
 
        } else if (unlikely(rt_task(current)) && !in_interrupt())
                alloc_flags |= ALLOC_HARDER;
 
-       if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) {
-               if (!in_interrupt() &&
-                   ((current->flags & PF_MEMALLOC) ||
-                    unlikely(test_thread_flag(TIF_MEMDIE))))
+       if ((current->flags & PF_MEMALLOC) ||
+                       unlikely(test_thread_flag(TIF_MEMDIE))) {
+               alloc_flags |= ALLOC_PFMEMALLOC;
+
+               if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt())
                        alloc_flags |= ALLOC_NO_WATERMARKS;
        }
 
        return alloc_flags;
 }
 
+bool gfp_pfmemalloc_allowed(gfp_t gfp_mask)
+{
+       return !!(gfp_to_alloc_flags(gfp_mask) & ALLOC_PFMEMALLOC);
+}
+
 static inline struct page *
 __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
        struct zonelist *zonelist, enum zone_type high_zoneidx,
        warn_alloc_failed(gfp_mask, order, NULL);
        return page;
 got_pg:
+       /*
+        * page->pfmemalloc is set when the caller had PFMEMALLOC set or is
+        * been OOM killed. The expectation is that the caller is taking
+        * steps that will free more memory. The caller should avoid the
+        * page being used for !PFMEMALLOC purposes.
+        */
+       page->pfmemalloc = !!(alloc_flags & ALLOC_PFMEMALLOC);
+
        if (kmemcheck_enabled)
                kmemcheck_pagealloc_alloc(page, order, gfp_mask);
-       return page;
 
+       return page;
 }
 
 /*
                page = __alloc_pages_slowpath(gfp_mask, order,
                                zonelist, high_zoneidx, nodemask,
                                preferred_zone, migratetype);
+       else
+               page->pfmemalloc = false;
 
        trace_mm_page_alloc(page, order, gfp_mask, migratetype);
 
 
 
 #include <trace/events/kmem.h>
 
+#include       "internal.h"
+
 /*
  * DEBUG       - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON.
  *               0 for faster, smaller code (especially in the critical paths).
 #define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN
 #endif
 
+/*
+ * true if a page was allocated from pfmemalloc reserves for network-based
+ * swap
+ */
+static bool pfmemalloc_active __read_mostly;
+
 /* Legal flag mask for kmem_cache_create(). */
 #if DEBUG
 # define CREATE_MASK   (SLAB_RED_ZONE | \
                         * Must have this definition in here for the proper
                         * alignment of array_cache. Also simplifies accessing
                         * the entries.
+                        *
+                        * Entries should not be directly dereferenced as
+                        * entries belonging to slabs marked pfmemalloc will
+                        * have the lower bits set SLAB_OBJ_PFMEMALLOC
                         */
 };
 
+#define SLAB_OBJ_PFMEMALLOC    1
+static inline bool is_obj_pfmemalloc(void *objp)
+{
+       return (unsigned long)objp & SLAB_OBJ_PFMEMALLOC;
+}
+
+static inline void set_obj_pfmemalloc(void **objp)
+{
+       *objp = (void *)((unsigned long)*objp | SLAB_OBJ_PFMEMALLOC);
+       return;
+}
+
+static inline void clear_obj_pfmemalloc(void **objp)
+{
+       *objp = (void *)((unsigned long)*objp & ~SLAB_OBJ_PFMEMALLOC);
+}
+
 /*
  * bootstrap: The caches do not work without cpuarrays anymore, but the
  * cpuarrays are allocated from the generic caches...
        return nc;
 }
 
+static inline bool is_slab_pfmemalloc(struct slab *slabp)
+{
+       struct page *page = virt_to_page(slabp->s_mem);
+
+       return PageSlabPfmemalloc(page);
+}
+
+/* Clears pfmemalloc_active if no slabs have pfmalloc set */
+static void recheck_pfmemalloc_active(struct kmem_cache *cachep,
+                                               struct array_cache *ac)
+{
+       struct kmem_list3 *l3 = cachep->nodelists[numa_mem_id()];
+       struct slab *slabp;
+       unsigned long flags;
+
+       if (!pfmemalloc_active)
+               return;
+
+       spin_lock_irqsave(&l3->list_lock, flags);
+       list_for_each_entry(slabp, &l3->slabs_full, list)
+               if (is_slab_pfmemalloc(slabp))
+                       goto out;
+
+       list_for_each_entry(slabp, &l3->slabs_partial, list)
+               if (is_slab_pfmemalloc(slabp))
+                       goto out;
+
+       list_for_each_entry(slabp, &l3->slabs_free, list)
+               if (is_slab_pfmemalloc(slabp))
+                       goto out;
+
+       pfmemalloc_active = false;
+out:
+       spin_unlock_irqrestore(&l3->list_lock, flags);
+}
+
+static void *ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
+                                               gfp_t flags, bool force_refill)
+{
+       int i;
+       void *objp = ac->entry[--ac->avail];
+
+       /* Ensure the caller is allowed to use objects from PFMEMALLOC slab */
+       if (unlikely(is_obj_pfmemalloc(objp))) {
+               struct kmem_list3 *l3;
+
+               if (gfp_pfmemalloc_allowed(flags)) {
+                       clear_obj_pfmemalloc(&objp);
+                       return objp;
+               }
+
+               /* The caller cannot use PFMEMALLOC objects, find another one */
+               for (i = 1; i < ac->avail; i++) {
+                       /* If a !PFMEMALLOC object is found, swap them */
+                       if (!is_obj_pfmemalloc(ac->entry[i])) {
+                               objp = ac->entry[i];
+                               ac->entry[i] = ac->entry[ac->avail];
+                               ac->entry[ac->avail] = objp;
+                               return objp;
+                       }
+               }
+
+               /*
+                * If there are empty slabs on the slabs_free list and we are
+                * being forced to refill the cache, mark this one !pfmemalloc.
+                */
+               l3 = cachep->nodelists[numa_mem_id()];
+               if (!list_empty(&l3->slabs_free) && force_refill) {
+                       struct slab *slabp = virt_to_slab(objp);
+                       ClearPageSlabPfmemalloc(virt_to_page(slabp->s_mem));
+                       clear_obj_pfmemalloc(&objp);
+                       recheck_pfmemalloc_active(cachep, ac);
+                       return objp;
+               }
+
+               /* No !PFMEMALLOC objects available */
+               ac->avail++;
+               objp = NULL;
+       }
+
+       return objp;
+}
+
+static void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac,
+                                                               void *objp)
+{
+       if (unlikely(pfmemalloc_active)) {
+               /* Some pfmemalloc slabs exist, check if this is one */
+               struct page *page = virt_to_page(objp);
+               if (PageSlabPfmemalloc(page))
+                       set_obj_pfmemalloc(&objp);
+       }
+
+       ac->entry[ac->avail++] = objp;
+}
+
 /*
  * Transfer objects in one arraycache to another.
  * Locking must be handled by the caller.
                        STATS_INC_ACOVERFLOW(cachep);
                        __drain_alien_cache(cachep, alien, nodeid);
                }
-               alien->entry[alien->avail++] = objp;
+               ac_put_obj(cachep, alien, objp);
                spin_unlock(&alien->lock);
        } else {
                spin_lock(&(cachep->nodelists[nodeid])->list_lock);
                return NULL;
        }
 
+       /* Record if ALLOC_PFMEMALLOC was set when allocating the slab */
+       if (unlikely(page->pfmemalloc))
+               pfmemalloc_active = true;
+
        nr_pages = (1 << cachep->gfporder);
        if (cachep->flags & SLAB_RECLAIM_ACCOUNT)
                add_zone_page_state(page_zone(page),
        else
                add_zone_page_state(page_zone(page),
                        NR_SLAB_UNRECLAIMABLE, nr_pages);
-       for (i = 0; i < nr_pages; i++)
+       for (i = 0; i < nr_pages; i++) {
                __SetPageSlab(page + i);
 
+               if (page->pfmemalloc)
+                       SetPageSlabPfmemalloc(page + i);
+       }
+
        if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) {
                kmemcheck_alloc_shadow(page, cachep->gfporder, flags, nodeid);
 
                                NR_SLAB_UNRECLAIMABLE, nr_freed);
        while (i--) {
                BUG_ON(!PageSlab(page));
+               __ClearPageSlabPfmemalloc(page);
                __ClearPageSlab(page);
                page++;
        }
 #define check_slabp(x,y) do { } while(0)
 #endif
 
-static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags)
+static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags,
+                                                       bool force_refill)
 {
        int batchcount;
        struct kmem_list3 *l3;
        struct array_cache *ac;
        int node;
 
-retry:
        check_irq_off();
        node = numa_mem_id();
+       if (unlikely(force_refill))
+               goto force_grow;
+retry:
        ac = cpu_cache_get(cachep);
        batchcount = ac->batchcount;
        if (!ac->touched && batchcount > BATCHREFILL_LIMIT) {
                        STATS_INC_ACTIVE(cachep);
                        STATS_SET_HIGH(cachep);
 
-                       ac->entry[ac->avail++] = slab_get_obj(cachep, slabp,
-                                                           node);
+                       ac_put_obj(cachep, ac, slab_get_obj(cachep, slabp,
+                                                                       node));
                }
                check_slabp(cachep, slabp);
 
 
        if (unlikely(!ac->avail)) {
                int x;
+force_grow:
                x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL);
 
                /* cache_grow can reenable interrupts, then ac could change. */
                ac = cpu_cache_get(cachep);
-               if (!x && ac->avail == 0)       /* no objects in sight? abort */
+
+               /* no objects in sight? abort */
+               if (!x && (ac->avail == 0 || force_refill))
                        return NULL;
 
                if (!ac->avail)         /* objects refilled by interrupt? */
                        goto retry;
        }
        ac->touched = 1;
-       return ac->entry[--ac->avail];
+
+       return ac_get_obj(cachep, ac, flags, force_refill);
 }
 
 static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep,
 {
        void *objp;
        struct array_cache *ac;
+       bool force_refill = false;
 
        check_irq_off();
 
        ac = cpu_cache_get(cachep);
        if (likely(ac->avail)) {
-               STATS_INC_ALLOCHIT(cachep);
                ac->touched = 1;
-               objp = ac->entry[--ac->avail];
-       } else {
-               STATS_INC_ALLOCMISS(cachep);
-               objp = cache_alloc_refill(cachep, flags);
+               objp = ac_get_obj(cachep, ac, flags, false);
+
                /*
-                * the 'ac' may be updated by cache_alloc_refill(),
-                * and kmemleak_erase() requires its correct value.
+                * Allow for the possibility all avail objects are not allowed
+                * by the current flags
                 */
-               ac = cpu_cache_get(cachep);
+               if (objp) {
+                       STATS_INC_ALLOCHIT(cachep);
+                       goto out;
+               }
+               force_refill = true;
        }
+
+       STATS_INC_ALLOCMISS(cachep);
+       objp = cache_alloc_refill(cachep, flags, force_refill);
+       /*
+        * the 'ac' may be updated by cache_alloc_refill(),
+        * and kmemleak_erase() requires its correct value.
+        */
+       ac = cpu_cache_get(cachep);
+
+out:
        /*
         * To avoid a false negative, if an object that is in one of the
         * per-CPU caches is leaked, we need to make sure kmemleak doesn't
        struct kmem_list3 *l3;
 
        for (i = 0; i < nr_objects; i++) {
-               void *objp = objpp[i];
+               void *objp;
                struct slab *slabp;
 
+               clear_obj_pfmemalloc(&objpp[i]);
+               objp = objpp[i];
+
                slabp = virt_to_slab(objp);
                l3 = cachep->nodelists[node];
                list_del(&slabp->list);
                cache_flusharray(cachep, ac);
        }
 
-       ac->entry[ac->avail++] = objp;
+       ac_put_obj(cachep, ac, objp);
 }
 
 /**