net/mlx4_en: Fix mixed PFC and Global pause user control requests
[pandora-kernel.git] / mm / vmscan.c
index 1e4ee1a..4de949b 100644 (file)
@@ -1085,6 +1085,7 @@ int __isolate_lru_page(struct page *page, isolate_mode_t mode, int file)
 
                if (PageDirty(page)) {
                        struct address_space *mapping;
+                       bool migrate_dirty;
 
                        /* ISOLATE_CLEAN means only clean pages */
                        if (mode & ISOLATE_CLEAN)
@@ -1093,10 +1094,19 @@ int __isolate_lru_page(struct page *page, isolate_mode_t mode, int file)
                        /*
                         * Only pages without mappings or that have a
                         * ->migratepage callback are possible to migrate
-                        * without blocking
+                        * without blocking. However, we can be racing with
+                        * truncation so it's necessary to lock the page
+                        * to stabilise the mapping as truncation holds
+                        * the page lock until after the page is removed
+                        * from the page cache.
                         */
+                       if (!trylock_page(page))
+                               return ret;
+
                        mapping = page_mapping(page);
-                       if (mapping && !mapping->a_ops->migratepage)
+                       migrate_dirty = mapping && mapping->a_ops->migratepage;
+                       unlock_page(page);
+                       if (!migrate_dirty)
                                return ret;
                }
        }
@@ -2492,19 +2502,6 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *mem_cont,
 }
 #endif
 
-static bool zone_balanced(struct zone *zone, int order,
-                         unsigned long balance_gap, int classzone_idx)
-{
-       if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone) +
-                                   balance_gap, classzone_idx, 0))
-               return false;
-
-       if (COMPACTION_BUILD && order && !compaction_suitable(zone, order))
-               return false;
-
-       return true;
-}
-
 /*
  * pgdat_balanced is used when checking if a node is balanced for high-order
  * allocations. Only zones that meet watermarks and are in a zone allowed
@@ -2564,7 +2561,8 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,
                        continue;
                }
 
-               if (!zone_balanced(zone, order, 0, i))
+               if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone),
+                                                       i, 0))
                        all_zones_ok = false;
                else
                        balanced += zone->present_pages;
@@ -2667,7 +2665,8 @@ loop_again:
                                shrink_active_list(SWAP_CLUSTER_MAX, zone,
                                                        &sc, priority, 0);
 
-                       if (!zone_balanced(zone, order, 0, 0)) {
+                       if (!zone_watermark_ok_safe(zone, order,
+                                       high_wmark_pages(zone), 0, 0)) {
                                end_zone = i;
                                break;
                        } else {
@@ -2728,8 +2727,9 @@ loop_again:
                                (zone->present_pages +
                                        KSWAPD_ZONE_BALANCE_GAP_RATIO-1) /
                                KSWAPD_ZONE_BALANCE_GAP_RATIO);
-                       if (!zone_balanced(zone, order,
-                                          balance_gap, end_zone)) {
+                       if (!zone_watermark_ok_safe(zone, order,
+                                       high_wmark_pages(zone) + balance_gap,
+                                       end_zone, 0)) {
                                shrink_zone(priority, zone, &sc);
 
                                reclaim_state->reclaimed_slab = 0;
@@ -2756,7 +2756,8 @@ loop_again:
                                continue;
                        }
 
-                       if (!zone_balanced(zone, order, 0, end_zone)) {
+                       if (!zone_watermark_ok_safe(zone, order,
+                                       high_wmark_pages(zone), end_zone, 0)) {
                                all_zones_ok = 0;
                                /*
                                 * We are still under min water mark.  This
@@ -3025,7 +3026,10 @@ static int kswapd(void *p)
                }
        }
 
+       tsk->flags &= ~(PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD);
        current->reclaim_state = NULL;
+       lockdep_clear_current_reclaim_state();
+
        return 0;
 }