|
@@ -1717,26 +1717,6 @@ static unsigned long shrink_list(enum lru_list lru, unsigned long nr_to_scan,
|
|
|
return shrink_inactive_list(nr_to_scan, zone, sc, priority, file);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Smallish @nr_to_scan's are deposited in @nr_saved_scan,
|
|
|
- * until we collected @swap_cluster_max pages to scan.
|
|
|
- */
|
|
|
-static unsigned long nr_scan_try_batch(unsigned long nr_to_scan,
|
|
|
- unsigned long *nr_saved_scan)
|
|
|
-{
|
|
|
- unsigned long nr;
|
|
|
-
|
|
|
- *nr_saved_scan += nr_to_scan;
|
|
|
- nr = *nr_saved_scan;
|
|
|
-
|
|
|
- if (nr >= SWAP_CLUSTER_MAX)
|
|
|
- *nr_saved_scan = 0;
|
|
|
- else
|
|
|
- nr = 0;
|
|
|
-
|
|
|
- return nr;
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* Determine how aggressively the anon and file LRU lists should be
|
|
|
* scanned. The relative value of each set of LRU lists is determined
|
|
@@ -1755,6 +1735,22 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
|
|
|
u64 fraction[2], denominator;
|
|
|
enum lru_list l;
|
|
|
int noswap = 0;
|
|
|
+ int force_scan = 0;
|
|
|
+
|
|
|
+
|
|
|
+ anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
|
|
|
+ zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON);
|
|
|
+ file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) +
|
|
|
+ zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE);
|
|
|
+
|
|
|
+ if (((anon + file) >> priority) < SWAP_CLUSTER_MAX) {
|
|
|
+ /* kswapd does zone balancing and need to scan this zone */
|
|
|
+ if (scanning_global_lru(sc) && current_is_kswapd())
|
|
|
+ force_scan = 1;
|
|
|
+ /* memcg may have small limit and need to avoid priority drop */
|
|
|
+ if (!scanning_global_lru(sc))
|
|
|
+ force_scan = 1;
|
|
|
+ }
|
|
|
|
|
|
/* If we have no swap space, do not bother scanning anon pages. */
|
|
|
if (!sc->may_swap || (nr_swap_pages <= 0)) {
|
|
@@ -1765,11 +1761,6 @@ static void get_scan_count(struct zone *zone, struct scan_control *sc,
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
|
- anon = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_ANON) +
|
|
|
- zone_nr_lru_pages(zone, sc, LRU_INACTIVE_ANON);
|
|
|
- file = zone_nr_lru_pages(zone, sc, LRU_ACTIVE_FILE) +
|
|
|
- zone_nr_lru_pages(zone, sc, LRU_INACTIVE_FILE);
|
|
|
-
|
|
|
if (scanning_global_lru(sc)) {
|
|
|
free = zone_page_state(zone, NR_FREE_PAGES);
|
|
|
/* If we have very few page cache pages,
|
|
@@ -1836,8 +1827,23 @@ out:
|
|
|
scan >>= priority;
|
|
|
scan = div64_u64(scan * fraction[file], denominator);
|
|
|
}
|
|
|
- nr[l] = nr_scan_try_batch(scan,
|
|
|
- &reclaim_stat->nr_saved_scan[l]);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If zone is small or memcg is small, nr[l] can be 0.
|
|
|
+ * This results no-scan on this priority and priority drop down.
|
|
|
+ * For global direct reclaim, it can visit next zone and tend
|
|
|
+ * not to have problems. For global kswapd, it's for zone
|
|
|
+ * balancing and it need to scan a small amounts. When using
|
|
|
+ * memcg, priority drop can cause big latency. So, it's better
|
|
|
+ * to scan small amount. See may_noscan above.
|
|
|
+ */
|
|
|
+ if (!scan && force_scan) {
|
|
|
+ if (file)
|
|
|
+ scan = SWAP_CLUSTER_MAX;
|
|
|
+ else if (!noswap)
|
|
|
+ scan = SWAP_CLUSTER_MAX;
|
|
|
+ }
|
|
|
+ nr[l] = scan;
|
|
|
}
|
|
|
}
|
|
|
|