Merge tag 'nfsd-4.8' of git://linux-nfs.org/~bfields/linux
[cascardo/linux.git] / mm / compaction.c
index cd93ea2..9affb29 100644 (file)
@@ -331,7 +331,7 @@ static bool compact_trylock_irqsave(spinlock_t *lock, unsigned long *flags,
 {
        if (cc->mode == MIGRATE_ASYNC) {
                if (!spin_trylock_irqsave(lock, *flags)) {
-                       cc->contended = COMPACT_CONTENDED_LOCK;
+                       cc->contended = true;
                        return false;
                }
        } else {
@@ -365,13 +365,13 @@ static bool compact_unlock_should_abort(spinlock_t *lock,
        }
 
        if (fatal_signal_pending(current)) {
-               cc->contended = COMPACT_CONTENDED_SCHED;
+               cc->contended = true;
                return true;
        }
 
        if (need_resched()) {
                if (cc->mode == MIGRATE_ASYNC) {
-                       cc->contended = COMPACT_CONTENDED_SCHED;
+                       cc->contended = true;
                        return true;
                }
                cond_resched();
@@ -394,7 +394,7 @@ static inline bool compact_should_abort(struct compact_control *cc)
        /* async compaction aborts if contended */
        if (need_resched()) {
                if (cc->mode == MIGRATE_ASYNC) {
-                       cc->contended = COMPACT_CONTENDED_SCHED;
+                       cc->contended = true;
                        return true;
                }
 
@@ -1200,7 +1200,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
        struct page *page;
        const isolate_mode_t isolate_mode =
                (sysctl_compact_unevictable_allowed ? ISOLATE_UNEVICTABLE : 0) |
-               (cc->mode == MIGRATE_ASYNC ? ISOLATE_ASYNC_MIGRATE : 0);
+               (cc->mode != MIGRATE_SYNC ? ISOLATE_ASYNC_MIGRATE : 0);
 
        /*
         * Start at where we last stopped, or beginning of the zone as
@@ -1438,11 +1438,6 @@ bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
 {
        struct zone *zone;
        struct zoneref *z;
-       pg_data_t *last_pgdat = NULL;
-
-       /* Do not retry compaction for zone-constrained allocations */
-       if (ac->high_zoneidx < ZONE_NORMAL)
-               return false;
 
        /*
         * Make sure at least one zone would pass __compaction_suitable if we continue
@@ -1453,27 +1448,14 @@ bool compaction_zonelist_suitable(struct alloc_context *ac, int order,
                unsigned long available;
                enum compact_result compact_result;
 
-               if (last_pgdat == zone->zone_pgdat)
-                       continue;
-
-               /*
-                * This over-estimates the number of pages available for
-                * reclaim/compaction but walking the LRU would take too
-                * long. The consequences are that compaction may retry
-                * longer than it should for a zone-constrained allocation
-                * request.
-                */
-               last_pgdat = zone->zone_pgdat;
-               available = pgdat_reclaimable_pages(zone->zone_pgdat) / order;
-
                /*
                 * Do not consider all the reclaimable memory because we do not
                 * want to trash just for a single high order allocation which
                 * is even not guaranteed to appear even if __compaction_suitable
                 * is happy about the watermark check.
                 */
+               available = zone_reclaimable_pages(zone) / order;
                available += zone_page_state_snapshot(zone, NR_FREE_PAGES);
-               available = min(zone->managed_pages, available);
                compact_result = __compaction_suitable(zone, order, alloc_flags,
                                ac_classzone_idx(ac), available);
                if (compact_result != COMPACT_SKIPPED &&
@@ -1637,14 +1619,11 @@ out:
        trace_mm_compaction_end(start_pfn, cc->migrate_pfn,
                                cc->free_pfn, end_pfn, sync, ret);
 
-       if (ret == COMPACT_CONTENDED)
-               ret = COMPACT_PARTIAL;
-
        return ret;
 }
 
 static enum compact_result compact_zone_order(struct zone *zone, int order,
-               gfp_t gfp_mask, enum migrate_mode mode, int *contended,
+               gfp_t gfp_mask, enum compact_priority prio,
                unsigned int alloc_flags, int classzone_idx)
 {
        enum compact_result ret;
@@ -1654,7 +1633,8 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
                .order = order,
                .gfp_mask = gfp_mask,
                .zone = zone,
-               .mode = mode,
+               .mode = (prio == COMPACT_PRIO_ASYNC) ?
+                                       MIGRATE_ASYNC : MIGRATE_SYNC_LIGHT,
                .alloc_flags = alloc_flags,
                .classzone_idx = classzone_idx,
                .direct_compaction = true,
@@ -1667,7 +1647,6 @@ static enum compact_result compact_zone_order(struct zone *zone, int order,
        VM_BUG_ON(!list_empty(&cc.freepages));
        VM_BUG_ON(!list_empty(&cc.migratepages));
 
-       *contended = cc.contended;
        return ret;
 }
 
@@ -1680,50 +1659,38 @@ int sysctl_extfrag_threshold = 500;
  * @alloc_flags: The allocation flags of the current allocation
  * @ac: The context of current allocation
  * @mode: The migration mode for async, sync light, or sync migration
- * @contended: Return value that determines if compaction was aborted due to
- *            need_resched() or lock contention
  *
  * This is the main entry point for direct page compaction.
  */
 enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
                unsigned int alloc_flags, const struct alloc_context *ac,
-               enum migrate_mode mode, int *contended)
+               enum compact_priority prio)
 {
        int may_enter_fs = gfp_mask & __GFP_FS;
        int may_perform_io = gfp_mask & __GFP_IO;
        struct zoneref *z;
        struct zone *zone;
        enum compact_result rc = COMPACT_SKIPPED;
-       int all_zones_contended = COMPACT_CONTENDED_LOCK; /* init for &= op */
-
-       *contended = COMPACT_CONTENDED_NONE;
 
        /* Check if the GFP flags allow compaction */
        if (!may_enter_fs || !may_perform_io)
                return COMPACT_SKIPPED;
 
-       trace_mm_compaction_try_to_compact_pages(order, gfp_mask, mode);
+       trace_mm_compaction_try_to_compact_pages(order, gfp_mask, prio);
 
        /* Compact each zone in the list */
        for_each_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
                                                                ac->nodemask) {
                enum compact_result status;
-               int zone_contended;
 
                if (compaction_deferred(zone, order)) {
                        rc = max_t(enum compact_result, COMPACT_DEFERRED, rc);
                        continue;
                }
 
-               status = compact_zone_order(zone, order, gfp_mask, mode,
-                               &zone_contended, alloc_flags,
-                               ac_classzone_idx(ac));
+               status = compact_zone_order(zone, order, gfp_mask, prio,
+                                       alloc_flags, ac_classzone_idx(ac));
                rc = max(status, rc);
-               /*
-                * It takes at least one zone that wasn't lock contended
-                * to clear all_zones_contended.
-                */
-               all_zones_contended &= zone_contended;
 
                /* If a normal allocation would succeed, stop compacting */
                if (zone_watermark_ok(zone, order, low_wmark_pages(zone),
@@ -1735,59 +1702,29 @@ enum compact_result try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
                         * succeeds in this zone.
                         */
                        compaction_defer_reset(zone, order, false);
-                       /*
-                        * It is possible that async compaction aborted due to
-                        * need_resched() and the watermarks were ok thanks to
-                        * somebody else freeing memory. The allocation can
-                        * however still fail so we better signal the
-                        * need_resched() contention anyway (this will not
-                        * prevent the allocation attempt).
-                        */
-                       if (zone_contended == COMPACT_CONTENDED_SCHED)
-                               *contended = COMPACT_CONTENDED_SCHED;
 
-                       goto break_loop;
+                       break;
                }
 
-               if (mode != MIGRATE_ASYNC && (status == COMPACT_COMPLETE ||
-                                       status == COMPACT_PARTIAL_SKIPPED)) {
+               if (prio != COMPACT_PRIO_ASYNC && (status == COMPACT_COMPLETE ||
+                                       status == COMPACT_PARTIAL_SKIPPED))
                        /*
                         * We think that allocation won't succeed in this zone
                         * so we defer compaction there. If it ends up
                         * succeeding after all, it will be reset.
                         */
                        defer_compaction(zone, order);
-               }
 
                /*
                 * We might have stopped compacting due to need_resched() in
                 * async compaction, or due to a fatal signal detected. In that
-                * case do not try further zones and signal need_resched()
-                * contention.
-                */
-               if ((zone_contended == COMPACT_CONTENDED_SCHED)
-                                       || fatal_signal_pending(current)) {
-                       *contended = COMPACT_CONTENDED_SCHED;
-                       goto break_loop;
-               }
-
-               continue;
-break_loop:
-               /*
-                * We might not have tried all the zones, so  be conservative
-                * and assume they are not all lock contended.
+                * case do not try further zones
                 */
-               all_zones_contended = 0;
-               break;
+               if ((prio == COMPACT_PRIO_ASYNC && need_resched())
+                                       || fatal_signal_pending(current))
+                       break;
        }
 
-       /*
-        * If at least one zone wasn't deferred or skipped, we report if all
-        * zones that were tried were lock contended.
-        */
-       if (rc > COMPACT_INACTIVE && all_zones_contended)
-               *contended = COMPACT_CONTENDED_LOCK;
-
        return rc;
 }