diff options
| author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-11-28 17:56:10 +0100 | 
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-11-28 17:56:10 +0100 | 
| commit | 9d1566e1f36b5167731372d2dfea97dbb4c43edf (patch) | |
| tree | 7eff84e5fd2c5758bb932d9e48ba1a5e43a80cad /mm/vmscan.c | |
| parent | 907140462eb511f3d98aa89c0665da1b618d3545 (diff) | |
| parent | b7b275e60bcd5f89771e865a8239325f86d9927d (diff) | |
Merge 6.1-rc7 into usb-next
We need the USB fixes in here as well.
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'mm/vmscan.c')
| -rw-r--r-- | mm/vmscan.c | 72 | 
1 files changed, 54 insertions, 18 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 04d8b88e5216..026199c047e0 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2514,8 +2514,20 @@ static unsigned long shrink_inactive_list(unsigned long nr_to_scan,  	 * the flushers simply cannot keep up with the allocation  	 * rate. Nudge the flusher threads in case they are asleep.  	 */ -	if (stat.nr_unqueued_dirty == nr_taken) +	if (stat.nr_unqueued_dirty == nr_taken) {  		wakeup_flusher_threads(WB_REASON_VMSCAN); +		/* +		 * For cgroupv1 dirty throttling is achieved by waking up +		 * the kernel flusher here and later waiting on folios +		 * which are in writeback to finish (see shrink_folio_list()). +		 * +		 * Flusher may not be able to issue writeback quickly +		 * enough for cgroupv1 writeback throttling to work +		 * on a large system. +		 */ +		if (!writeback_throttling_sane(sc)) +			reclaim_throttle(pgdat, VMSCAN_THROTTLE_WRITEBACK); +	}  	sc->nr.dirty += stat.nr_dirty;  	sc->nr.congested += stat.nr_congested; @@ -4971,10 +4983,13 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap  	int scanned;  	int reclaimed;  	LIST_HEAD(list); +	LIST_HEAD(clean);  	struct folio *folio; +	struct folio *next;  	enum vm_event_item item;  	struct reclaim_stat stat;  	struct lru_gen_mm_walk *walk; +	bool skip_retry = false;  	struct mem_cgroup *memcg = lruvec_memcg(lruvec);  	struct pglist_data *pgdat = lruvec_pgdat(lruvec); @@ -4991,20 +5006,37 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap  	if (list_empty(&list))  		return scanned; - +retry:  	reclaimed = shrink_folio_list(&list, pgdat, sc, &stat, false); +	sc->nr_reclaimed += reclaimed; -	list_for_each_entry(folio, &list, lru) { -		/* restore LRU_REFS_FLAGS cleared by isolate_folio() */ -		if (folio_test_workingset(folio)) -			folio_set_referenced(folio); +	list_for_each_entry_safe_reverse(folio, next, &list, lru) { +		if (!folio_evictable(folio)) { +			list_del(&folio->lru); +			folio_putback_lru(folio); +			continue; +		} -		/* don't add rejected pages to the oldest generation */  		if (folio_test_reclaim(folio) && -		    (folio_test_dirty(folio) || folio_test_writeback(folio))) -			folio_clear_active(folio); -		else -			folio_set_active(folio); +		    (folio_test_dirty(folio) || folio_test_writeback(folio))) { +			/* restore LRU_REFS_FLAGS cleared by isolate_folio() */ +			if (folio_test_workingset(folio)) +				folio_set_referenced(folio); +			continue; +		} + +		if (skip_retry || folio_test_active(folio) || folio_test_referenced(folio) || +		    folio_mapped(folio) || folio_test_locked(folio) || +		    folio_test_dirty(folio) || folio_test_writeback(folio)) { +			/* don't add rejected folios to the oldest generation */ +			set_mask_bits(&folio->flags, LRU_REFS_MASK | LRU_REFS_FLAGS, +				      BIT(PG_active)); +			continue; +		} + +		/* retry folios that may have missed folio_rotate_reclaimable() */ +		list_move(&folio->lru, &clean); +		sc->nr_scanned -= folio_nr_pages(folio);  	}  	spin_lock_irq(&lruvec->lru_lock); @@ -5026,7 +5058,13 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap  	mem_cgroup_uncharge_list(&list);  	free_unref_page_list(&list); -	sc->nr_reclaimed += reclaimed; +	INIT_LIST_HEAD(&list); +	list_splice_init(&clean, &list); + +	if (!list_empty(&list)) { +		skip_retry = true; +		goto retry; +	}  	if (need_swapping && type == LRU_GEN_ANON)  		*need_swapping = true; @@ -5844,8 +5882,8 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)  	enum lru_list lru;  	unsigned long nr_reclaimed = 0;  	unsigned long nr_to_reclaim = sc->nr_to_reclaim; +	bool proportional_reclaim;  	struct blk_plug plug; -	bool scan_adjusted;  	if (lru_gen_enabled()) {  		lru_gen_shrink_lruvec(lruvec, sc); @@ -5868,8 +5906,8 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)  	 * abort proportional reclaim if either the file or anon lru has already  	 * dropped to zero at the first pass.  	 */ -	scan_adjusted = (!cgroup_reclaim(sc) && !current_is_kswapd() && -			 sc->priority == DEF_PRIORITY); +	proportional_reclaim = (!cgroup_reclaim(sc) && !current_is_kswapd() && +				sc->priority == DEF_PRIORITY);  	blk_start_plug(&plug);  	while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] || @@ -5889,7 +5927,7 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)  		cond_resched(); -		if (nr_reclaimed < nr_to_reclaim || scan_adjusted) +		if (nr_reclaimed < nr_to_reclaim || proportional_reclaim)  			continue;  		/* @@ -5940,8 +5978,6 @@ static void shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)  		nr_scanned = targets[lru] - nr[lru];  		nr[lru] = targets[lru] * (100 - percentage) / 100;  		nr[lru] -= min(nr[lru], nr_scanned); - -		scan_adjusted = true;  	}  	blk_finish_plug(&plug);  	sc->nr_reclaimed += nr_reclaimed;  | 
