diff options
Diffstat (limited to 'mm/vmscan.c')
| -rw-r--r-- | mm/vmscan.c | 58 | 
1 files changed, 37 insertions, 21 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index 1080209a568b..6f13394b112e 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1423,7 +1423,7 @@ static int __remove_mapping(struct address_space *mapping, struct folio *folio,  	}  	if (folio_test_swapcache(folio)) { -		swp_entry_t swap = folio_swap_entry(folio); +		swp_entry_t swap = folio->swap;  		if (reclaimed && !mapping_exiting(mapping))  			shadow = workingset_eviction(folio, target_memcg); @@ -2064,7 +2064,7 @@ retry:  		 * (refcount == 1) it can be freed.  Otherwise, leave  		 * the folio on the LRU so it is swappable.  		 */ -		if (folio_has_private(folio)) { +		if (folio_needs_release(folio)) {  			if (!filemap_release_folio(folio, sc->gfp_mask))  				goto activate_locked;  			if (!mapping && folio_ref_count(folio) == 1) { @@ -2729,9 +2729,9 @@ static void shrink_active_list(unsigned long nr_to_scan,  		}  		if (unlikely(buffer_heads_over_limit)) { -			if (folio_test_private(folio) && folio_trylock(folio)) { -				if (folio_test_private(folio)) -					filemap_release_folio(folio, 0); +			if (folio_needs_release(folio) && +			    folio_trylock(folio)) { +				filemap_release_folio(folio, 0);  				folio_unlock(folio);  			}  		} @@ -4284,6 +4284,7 @@ static void walk_mm(struct lruvec *lruvec, struct mm_struct *mm, struct lru_gen_  	static const struct mm_walk_ops mm_walk_ops = {  		.test_walk = should_skip_vma,  		.p4d_entry = walk_pud_range, +		.walk_lock = PGWALK_RDLOCK,  	};  	int err; @@ -4439,7 +4440,7 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan)  	int prev, next;  	int type, zone;  	struct lru_gen_folio *lrugen = &lruvec->lrugen; - +restart:  	spin_lock_irq(&lruvec->lru_lock);  	VM_WARN_ON_ONCE(!seq_is_valid(lruvec)); @@ -4450,11 +4451,12 @@ static void inc_max_seq(struct lruvec *lruvec, bool can_swap, bool force_scan)  		VM_WARN_ON_ONCE(!force_scan && (type == LRU_GEN_FILE || can_swap)); -		while (!inc_min_seq(lruvec, type, can_swap)) { -			spin_unlock_irq(&lruvec->lru_lock); -			cond_resched(); -			spin_lock_irq(&lruvec->lru_lock); -		} +		if (inc_min_seq(lruvec, type, can_swap)) +			continue; + +		spin_unlock_irq(&lruvec->lru_lock); +		cond_resched(); +		goto restart;  	}  	/* @@ -4655,6 +4657,7 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw)  	pte_t *pte = pvmw->pte;  	unsigned long addr = pvmw->address;  	struct folio *folio = pfn_folio(pvmw->pfn); +	bool can_swap = !folio_is_file_lru(folio);  	struct mem_cgroup *memcg = folio_memcg(folio);  	struct pglist_data *pgdat = folio_pgdat(folio);  	struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat); @@ -4703,7 +4706,7 @@ void lru_gen_look_around(struct page_vma_mapped_walk *pvmw)  		if (!pte_young(ptent))  			continue; -		folio = get_pfn_folio(pfn, memcg, pgdat, !walk || walk->can_swap); +		folio = get_pfn_folio(pfn, memcg, pgdat, can_swap);  		if (!folio)  			continue; @@ -4853,16 +4856,17 @@ void lru_gen_release_memcg(struct mem_cgroup *memcg)  		spin_lock_irq(&pgdat->memcg_lru.lock); -		VM_WARN_ON_ONCE(hlist_nulls_unhashed(&lruvec->lrugen.list)); +		if (hlist_nulls_unhashed(&lruvec->lrugen.list)) +			goto unlock;  		gen = lruvec->lrugen.gen; -		hlist_nulls_del_rcu(&lruvec->lrugen.list); +		hlist_nulls_del_init_rcu(&lruvec->lrugen.list);  		pgdat->memcg_lru.nr_memcgs[gen]--;  		if (!pgdat->memcg_lru.nr_memcgs[gen] && gen == get_memcg_gen(pgdat->memcg_lru.seq))  			WRITE_ONCE(pgdat->memcg_lru.seq, pgdat->memcg_lru.seq + 1); - +unlock:  		spin_unlock_irq(&pgdat->memcg_lru.lock);  	}  } @@ -4889,7 +4893,8 @@ static int lru_gen_memcg_seg(struct lruvec *lruvec)   *                          the eviction   ******************************************************************************/ -static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx) +static bool sort_folio(struct lruvec *lruvec, struct folio *folio, struct scan_control *sc, +		       int tier_idx)  {  	bool success;  	int gen = folio_lru_gen(folio); @@ -4939,6 +4944,13 @@ static bool sort_folio(struct lruvec *lruvec, struct folio *folio, int tier_idx)  		return true;  	} +	/* ineligible */ +	if (zone > sc->reclaim_idx || skip_cma(folio, sc)) { +		gen = folio_inc_gen(lruvec, folio, false); +		list_move_tail(&folio->lru, &lrugen->folios[gen][type][zone]); +		return true; +	} +  	/* waiting for writeback */  	if (folio_test_locked(folio) || folio_test_writeback(folio) ||  	    (type == LRU_GEN_FILE && folio_test_dirty(folio))) { @@ -4987,7 +4999,8 @@ static bool isolate_folio(struct lruvec *lruvec, struct folio *folio, struct sca  static int scan_folios(struct lruvec *lruvec, struct scan_control *sc,  		       int type, int tier, struct list_head *list)  { -	int gen, zone; +	int i; +	int gen;  	enum vm_event_item item;  	int sorted = 0;  	int scanned = 0; @@ -5003,9 +5016,10 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc,  	gen = lru_gen_from_seq(lrugen->min_seq[type]); -	for (zone = sc->reclaim_idx; zone >= 0; zone--) { +	for (i = MAX_NR_ZONES; i > 0; i--) {  		LIST_HEAD(moved);  		int skipped = 0; +		int zone = (sc->reclaim_idx + i) % MAX_NR_ZONES;  		struct list_head *head = &lrugen->folios[gen][type][zone];  		while (!list_empty(head)) { @@ -5019,7 +5033,7 @@ static int scan_folios(struct lruvec *lruvec, struct scan_control *sc,  			scanned += delta; -			if (sort_folio(lruvec, folio, tier)) +			if (sort_folio(lruvec, folio, sc, tier))  				sorted += delta;  			else if (isolate_folio(lruvec, folio, sc)) {  				list_add(&folio->lru, list); @@ -5434,8 +5448,10 @@ restart:  	rcu_read_lock();  	hlist_nulls_for_each_entry_rcu(lrugen, pos, &pgdat->memcg_lru.fifo[gen][bin], list) { -		if (op) +		if (op) {  			lru_gen_rotate_memcg(lruvec, op); +			op = 0; +		}  		mem_cgroup_put(memcg); @@ -5443,7 +5459,7 @@ restart:  		memcg = lruvec_memcg(lruvec);  		if (!mem_cgroup_tryget(memcg)) { -			op = 0; +			lru_gen_release_memcg(memcg);  			memcg = NULL;  			continue;  		}  | 
