162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/mm/swap.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * This file contains the default values for the operation of the 1062306a36Sopenharmony_ci * Linux VM subsystem. Fine-tuning documentation can be found in 1162306a36Sopenharmony_ci * Documentation/admin-guide/sysctl/vm.rst. 1262306a36Sopenharmony_ci * Started 18.12.91 1362306a36Sopenharmony_ci * Swap aging added 23.2.95, Stephen Tweedie. 1462306a36Sopenharmony_ci * Buffermem limits added 12.3.98, Rik van Riel. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <linux/mm.h> 1862306a36Sopenharmony_ci#include <linux/sched.h> 1962306a36Sopenharmony_ci#include <linux/kernel_stat.h> 2062306a36Sopenharmony_ci#include <linux/swap.h> 2162306a36Sopenharmony_ci#include <linux/mman.h> 2262306a36Sopenharmony_ci#include <linux/pagemap.h> 2362306a36Sopenharmony_ci#include <linux/pagevec.h> 2462306a36Sopenharmony_ci#include <linux/init.h> 2562306a36Sopenharmony_ci#include <linux/export.h> 2662306a36Sopenharmony_ci#include <linux/mm_inline.h> 2762306a36Sopenharmony_ci#include <linux/percpu_counter.h> 2862306a36Sopenharmony_ci#include <linux/memremap.h> 2962306a36Sopenharmony_ci#include <linux/percpu.h> 3062306a36Sopenharmony_ci#include <linux/cpu.h> 3162306a36Sopenharmony_ci#include <linux/notifier.h> 3262306a36Sopenharmony_ci#include <linux/backing-dev.h> 3362306a36Sopenharmony_ci#include <linux/memcontrol.h> 3462306a36Sopenharmony_ci#include <linux/gfp.h> 3562306a36Sopenharmony_ci#include <linux/uio.h> 3662306a36Sopenharmony_ci#include <linux/hugetlb.h> 3762306a36Sopenharmony_ci#include <linux/page_idle.h> 3862306a36Sopenharmony_ci#include <linux/local_lock.h> 3962306a36Sopenharmony_ci#include <linux/buffer_head.h> 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#include "internal.h" 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define CREATE_TRACE_POINTS 4462306a36Sopenharmony_ci#include <trace/events/pagemap.h> 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* How many pages do we try to swap or page in/out together? As a power of 2 */ 4762306a36Sopenharmony_ciint page_cluster; 4862306a36Sopenharmony_ciconst int page_cluster_max = 31; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* Protecting only lru_rotate.fbatch which requires disabling interrupts */ 5162306a36Sopenharmony_cistruct lru_rotate { 5262306a36Sopenharmony_ci local_lock_t lock; 5362306a36Sopenharmony_ci struct folio_batch fbatch; 5462306a36Sopenharmony_ci}; 5562306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct lru_rotate, lru_rotate) = { 5662306a36Sopenharmony_ci .lock = INIT_LOCAL_LOCK(lock), 5762306a36Sopenharmony_ci}; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* 6062306a36Sopenharmony_ci * The following folio batches are grouped together because they are protected 6162306a36Sopenharmony_ci * by disabling preemption (and interrupts remain enabled). 6262306a36Sopenharmony_ci */ 6362306a36Sopenharmony_cistruct cpu_fbatches { 6462306a36Sopenharmony_ci local_lock_t lock; 6562306a36Sopenharmony_ci struct folio_batch lru_add; 6662306a36Sopenharmony_ci struct folio_batch lru_deactivate_file; 6762306a36Sopenharmony_ci struct folio_batch lru_deactivate; 6862306a36Sopenharmony_ci struct folio_batch lru_lazyfree; 6962306a36Sopenharmony_ci#ifdef CONFIG_SMP 7062306a36Sopenharmony_ci struct folio_batch activate; 7162306a36Sopenharmony_ci#endif 7262306a36Sopenharmony_ci}; 7362306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct cpu_fbatches, cpu_fbatches) = { 7462306a36Sopenharmony_ci .lock = INIT_LOCAL_LOCK(lock), 7562306a36Sopenharmony_ci}; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* 7862306a36Sopenharmony_ci * This path almost never happens for VM activity - pages are normally freed 7962306a36Sopenharmony_ci * in batches. But it gets used by networking - and for compound pages. 8062306a36Sopenharmony_ci */ 8162306a36Sopenharmony_cistatic void __page_cache_release(struct folio *folio) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci if (folio_test_lru(folio)) { 8462306a36Sopenharmony_ci struct lruvec *lruvec; 8562306a36Sopenharmony_ci unsigned long flags; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci lruvec = folio_lruvec_lock_irqsave(folio, &flags); 8862306a36Sopenharmony_ci lruvec_del_folio(lruvec, folio); 8962306a36Sopenharmony_ci __folio_clear_lru_flags(folio); 9062306a36Sopenharmony_ci unlock_page_lruvec_irqrestore(lruvec, flags); 9162306a36Sopenharmony_ci } 9262306a36Sopenharmony_ci /* See comment on folio_test_mlocked in release_pages() */ 9362306a36Sopenharmony_ci if (unlikely(folio_test_mlocked(folio))) { 9462306a36Sopenharmony_ci long nr_pages = folio_nr_pages(folio); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci __folio_clear_mlocked(folio); 9762306a36Sopenharmony_ci zone_stat_mod_folio(folio, NR_MLOCK, -nr_pages); 9862306a36Sopenharmony_ci count_vm_events(UNEVICTABLE_PGCLEARED, nr_pages); 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic void __folio_put_small(struct folio *folio) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci __page_cache_release(folio); 10562306a36Sopenharmony_ci mem_cgroup_uncharge(folio); 10662306a36Sopenharmony_ci free_unref_page(&folio->page, 0); 10762306a36Sopenharmony_ci} 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistatic void __folio_put_large(struct folio *folio) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci /* 11262306a36Sopenharmony_ci * __page_cache_release() is supposed to be called for thp, not for 11362306a36Sopenharmony_ci * hugetlb. This is because hugetlb page does never have PageLRU set 11462306a36Sopenharmony_ci * (it's never listed to any LRU lists) and no memcg routines should 11562306a36Sopenharmony_ci * be called for hugetlb (it has a separate hugetlb_cgroup.) 11662306a36Sopenharmony_ci */ 11762306a36Sopenharmony_ci if (!folio_test_hugetlb(folio)) 11862306a36Sopenharmony_ci __page_cache_release(folio); 11962306a36Sopenharmony_ci destroy_large_folio(folio); 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_civoid __folio_put(struct folio *folio) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci if (unlikely(folio_is_zone_device(folio))) 12562306a36Sopenharmony_ci free_zone_device_page(&folio->page); 12662306a36Sopenharmony_ci else if (unlikely(folio_test_large(folio))) 12762306a36Sopenharmony_ci __folio_put_large(folio); 12862306a36Sopenharmony_ci else 12962306a36Sopenharmony_ci __folio_put_small(folio); 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ciEXPORT_SYMBOL(__folio_put); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/** 13462306a36Sopenharmony_ci * put_pages_list() - release a list of pages 13562306a36Sopenharmony_ci * @pages: list of pages threaded on page->lru 13662306a36Sopenharmony_ci * 13762306a36Sopenharmony_ci * Release a list of pages which are strung together on page.lru. 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_civoid put_pages_list(struct list_head *pages) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci struct folio *folio, *next; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci list_for_each_entry_safe(folio, next, pages, lru) { 14462306a36Sopenharmony_ci if (!folio_put_testzero(folio)) { 14562306a36Sopenharmony_ci list_del(&folio->lru); 14662306a36Sopenharmony_ci continue; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci if (folio_test_large(folio)) { 14962306a36Sopenharmony_ci list_del(&folio->lru); 15062306a36Sopenharmony_ci __folio_put_large(folio); 15162306a36Sopenharmony_ci continue; 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci /* LRU flag must be clear because it's passed using the lru */ 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci free_unref_page_list(pages); 15762306a36Sopenharmony_ci INIT_LIST_HEAD(pages); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ciEXPORT_SYMBOL(put_pages_list); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_citypedef void (*move_fn_t)(struct lruvec *lruvec, struct folio *folio); 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_cistatic void lru_add_fn(struct lruvec *lruvec, struct folio *folio) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci int was_unevictable = folio_test_clear_unevictable(folio); 16662306a36Sopenharmony_ci long nr_pages = folio_nr_pages(folio); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci /* 17162306a36Sopenharmony_ci * Is an smp_mb__after_atomic() still required here, before 17262306a36Sopenharmony_ci * folio_evictable() tests the mlocked flag, to rule out the possibility 17362306a36Sopenharmony_ci * of stranding an evictable folio on an unevictable LRU? I think 17462306a36Sopenharmony_ci * not, because __munlock_folio() only clears the mlocked flag 17562306a36Sopenharmony_ci * while the LRU lock is held. 17662306a36Sopenharmony_ci * 17762306a36Sopenharmony_ci * (That is not true of __page_cache_release(), and not necessarily 17862306a36Sopenharmony_ci * true of release_pages(): but those only clear the mlocked flag after 17962306a36Sopenharmony_ci * folio_put_testzero() has excluded any other users of the folio.) 18062306a36Sopenharmony_ci */ 18162306a36Sopenharmony_ci if (folio_evictable(folio)) { 18262306a36Sopenharmony_ci if (was_unevictable) 18362306a36Sopenharmony_ci __count_vm_events(UNEVICTABLE_PGRESCUED, nr_pages); 18462306a36Sopenharmony_ci } else { 18562306a36Sopenharmony_ci folio_clear_active(folio); 18662306a36Sopenharmony_ci folio_set_unevictable(folio); 18762306a36Sopenharmony_ci /* 18862306a36Sopenharmony_ci * folio->mlock_count = !!folio_test_mlocked(folio)? 18962306a36Sopenharmony_ci * But that leaves __mlock_folio() in doubt whether another 19062306a36Sopenharmony_ci * actor has already counted the mlock or not. Err on the 19162306a36Sopenharmony_ci * safe side, underestimate, let page reclaim fix it, rather 19262306a36Sopenharmony_ci * than leaving a page on the unevictable LRU indefinitely. 19362306a36Sopenharmony_ci */ 19462306a36Sopenharmony_ci folio->mlock_count = 0; 19562306a36Sopenharmony_ci if (!was_unevictable) 19662306a36Sopenharmony_ci __count_vm_events(UNEVICTABLE_PGCULLED, nr_pages); 19762306a36Sopenharmony_ci } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci lruvec_add_folio(lruvec, folio); 20062306a36Sopenharmony_ci trace_mm_lru_insertion(folio); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_cistatic void folio_batch_move_lru(struct folio_batch *fbatch, move_fn_t move_fn) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci int i; 20662306a36Sopenharmony_ci struct lruvec *lruvec = NULL; 20762306a36Sopenharmony_ci unsigned long flags = 0; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci for (i = 0; i < folio_batch_count(fbatch); i++) { 21062306a36Sopenharmony_ci struct folio *folio = fbatch->folios[i]; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci /* block memcg migration while the folio moves between lru */ 21362306a36Sopenharmony_ci if (move_fn != lru_add_fn && !folio_test_clear_lru(folio)) 21462306a36Sopenharmony_ci continue; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci lruvec = folio_lruvec_relock_irqsave(folio, lruvec, &flags); 21762306a36Sopenharmony_ci move_fn(lruvec, folio); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci folio_set_lru(folio); 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (lruvec) 22362306a36Sopenharmony_ci unlock_page_lruvec_irqrestore(lruvec, flags); 22462306a36Sopenharmony_ci folios_put(fbatch->folios, folio_batch_count(fbatch)); 22562306a36Sopenharmony_ci folio_batch_reinit(fbatch); 22662306a36Sopenharmony_ci} 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_cistatic void folio_batch_add_and_move(struct folio_batch *fbatch, 22962306a36Sopenharmony_ci struct folio *folio, move_fn_t move_fn) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci if (folio_batch_add(fbatch, folio) && !folio_test_large(folio) && 23262306a36Sopenharmony_ci !lru_cache_disabled()) 23362306a36Sopenharmony_ci return; 23462306a36Sopenharmony_ci folio_batch_move_lru(fbatch, move_fn); 23562306a36Sopenharmony_ci} 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_cistatic void lru_move_tail_fn(struct lruvec *lruvec, struct folio *folio) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci if (!folio_test_unevictable(folio)) { 24062306a36Sopenharmony_ci lruvec_del_folio(lruvec, folio); 24162306a36Sopenharmony_ci folio_clear_active(folio); 24262306a36Sopenharmony_ci lruvec_add_folio_tail(lruvec, folio); 24362306a36Sopenharmony_ci __count_vm_events(PGROTATED, folio_nr_pages(folio)); 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci/* 24862306a36Sopenharmony_ci * Writeback is about to end against a folio which has been marked for 24962306a36Sopenharmony_ci * immediate reclaim. If it still appears to be reclaimable, move it 25062306a36Sopenharmony_ci * to the tail of the inactive list. 25162306a36Sopenharmony_ci * 25262306a36Sopenharmony_ci * folio_rotate_reclaimable() must disable IRQs, to prevent nasty races. 25362306a36Sopenharmony_ci */ 25462306a36Sopenharmony_civoid folio_rotate_reclaimable(struct folio *folio) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci if (!folio_test_locked(folio) && !folio_test_dirty(folio) && 25762306a36Sopenharmony_ci !folio_test_unevictable(folio) && folio_test_lru(folio)) { 25862306a36Sopenharmony_ci struct folio_batch *fbatch; 25962306a36Sopenharmony_ci unsigned long flags; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci folio_get(folio); 26262306a36Sopenharmony_ci local_lock_irqsave(&lru_rotate.lock, flags); 26362306a36Sopenharmony_ci fbatch = this_cpu_ptr(&lru_rotate.fbatch); 26462306a36Sopenharmony_ci folio_batch_add_and_move(fbatch, folio, lru_move_tail_fn); 26562306a36Sopenharmony_ci local_unlock_irqrestore(&lru_rotate.lock, flags); 26662306a36Sopenharmony_ci } 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_civoid lru_note_cost(struct lruvec *lruvec, bool file, 27062306a36Sopenharmony_ci unsigned int nr_io, unsigned int nr_rotated) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci unsigned long cost; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci /* 27562306a36Sopenharmony_ci * Reflect the relative cost of incurring IO and spending CPU 27662306a36Sopenharmony_ci * time on rotations. This doesn't attempt to make a precise 27762306a36Sopenharmony_ci * comparison, it just says: if reloads are about comparable 27862306a36Sopenharmony_ci * between the LRU lists, or rotations are overwhelmingly 27962306a36Sopenharmony_ci * different between them, adjust scan balance for CPU work. 28062306a36Sopenharmony_ci */ 28162306a36Sopenharmony_ci cost = nr_io * SWAP_CLUSTER_MAX + nr_rotated; 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci do { 28462306a36Sopenharmony_ci unsigned long lrusize; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* 28762306a36Sopenharmony_ci * Hold lruvec->lru_lock is safe here, since 28862306a36Sopenharmony_ci * 1) The pinned lruvec in reclaim, or 28962306a36Sopenharmony_ci * 2) From a pre-LRU page during refault (which also holds the 29062306a36Sopenharmony_ci * rcu lock, so would be safe even if the page was on the LRU 29162306a36Sopenharmony_ci * and could move simultaneously to a new lruvec). 29262306a36Sopenharmony_ci */ 29362306a36Sopenharmony_ci spin_lock_irq(&lruvec->lru_lock); 29462306a36Sopenharmony_ci /* Record cost event */ 29562306a36Sopenharmony_ci if (file) 29662306a36Sopenharmony_ci lruvec->file_cost += cost; 29762306a36Sopenharmony_ci else 29862306a36Sopenharmony_ci lruvec->anon_cost += cost; 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* 30162306a36Sopenharmony_ci * Decay previous events 30262306a36Sopenharmony_ci * 30362306a36Sopenharmony_ci * Because workloads change over time (and to avoid 30462306a36Sopenharmony_ci * overflow) we keep these statistics as a floating 30562306a36Sopenharmony_ci * average, which ends up weighing recent refaults 30662306a36Sopenharmony_ci * more than old ones. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci lrusize = lruvec_page_state(lruvec, NR_INACTIVE_ANON) + 30962306a36Sopenharmony_ci lruvec_page_state(lruvec, NR_ACTIVE_ANON) + 31062306a36Sopenharmony_ci lruvec_page_state(lruvec, NR_INACTIVE_FILE) + 31162306a36Sopenharmony_ci lruvec_page_state(lruvec, NR_ACTIVE_FILE); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (lruvec->file_cost + lruvec->anon_cost > lrusize / 4) { 31462306a36Sopenharmony_ci lruvec->file_cost /= 2; 31562306a36Sopenharmony_ci lruvec->anon_cost /= 2; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci spin_unlock_irq(&lruvec->lru_lock); 31862306a36Sopenharmony_ci } while ((lruvec = parent_lruvec(lruvec))); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_civoid lru_note_cost_refault(struct folio *folio) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci#ifdef CONFIG_HYPERHOLD_FILE_LRU 32462306a36Sopenharmony_ci if (page_is_file_lru(folio_page(folio, 0))) { 32562306a36Sopenharmony_ci lru_note_cost(&(folio_pgdat(folio)->__lruvec), 1, folio_nr_pages(folio), 0); 32662306a36Sopenharmony_ci return; 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci#endif 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci lru_note_cost(folio_lruvec(folio), folio_is_file_lru(folio), 33162306a36Sopenharmony_ci folio_nr_pages(folio), 0); 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_cistatic void folio_activate_fn(struct lruvec *lruvec, struct folio *folio) 33562306a36Sopenharmony_ci{ 33662306a36Sopenharmony_ci if (!folio_test_active(folio) && !folio_test_unevictable(folio)) { 33762306a36Sopenharmony_ci long nr_pages = folio_nr_pages(folio); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci lruvec_del_folio(lruvec, folio); 34062306a36Sopenharmony_ci folio_set_active(folio); 34162306a36Sopenharmony_ci lruvec_add_folio(lruvec, folio); 34262306a36Sopenharmony_ci trace_mm_lru_activate(folio); 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci __count_vm_events(PGACTIVATE, nr_pages); 34562306a36Sopenharmony_ci __count_memcg_events(lruvec_memcg(lruvec), PGACTIVATE, 34662306a36Sopenharmony_ci nr_pages); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci#ifdef CONFIG_SMP 35162306a36Sopenharmony_cistatic void folio_activate_drain(int cpu) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci struct folio_batch *fbatch = &per_cpu(cpu_fbatches.activate, cpu); 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci if (folio_batch_count(fbatch)) 35662306a36Sopenharmony_ci folio_batch_move_lru(fbatch, folio_activate_fn); 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_civoid folio_activate(struct folio *folio) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci if (folio_test_lru(folio) && !folio_test_active(folio) && 36262306a36Sopenharmony_ci !folio_test_unevictable(folio)) { 36362306a36Sopenharmony_ci struct folio_batch *fbatch; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci folio_get(folio); 36662306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 36762306a36Sopenharmony_ci fbatch = this_cpu_ptr(&cpu_fbatches.activate); 36862306a36Sopenharmony_ci folio_batch_add_and_move(fbatch, folio, folio_activate_fn); 36962306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 37062306a36Sopenharmony_ci } 37162306a36Sopenharmony_ci} 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci#else 37462306a36Sopenharmony_cistatic inline void folio_activate_drain(int cpu) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci} 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_civoid folio_activate(struct folio *folio) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci struct lruvec *lruvec; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (folio_test_clear_lru(folio)) { 38362306a36Sopenharmony_ci lruvec = folio_lruvec_lock_irq(folio); 38462306a36Sopenharmony_ci folio_activate_fn(lruvec, folio); 38562306a36Sopenharmony_ci unlock_page_lruvec_irq(lruvec); 38662306a36Sopenharmony_ci folio_set_lru(folio); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci#endif 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic void __lru_cache_activate_folio(struct folio *folio) 39262306a36Sopenharmony_ci{ 39362306a36Sopenharmony_ci struct folio_batch *fbatch; 39462306a36Sopenharmony_ci int i; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 39762306a36Sopenharmony_ci fbatch = this_cpu_ptr(&cpu_fbatches.lru_add); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci /* 40062306a36Sopenharmony_ci * Search backwards on the optimistic assumption that the folio being 40162306a36Sopenharmony_ci * activated has just been added to this batch. Note that only 40262306a36Sopenharmony_ci * the local batch is examined as a !LRU folio could be in the 40362306a36Sopenharmony_ci * process of being released, reclaimed, migrated or on a remote 40462306a36Sopenharmony_ci * batch that is currently being drained. Furthermore, marking 40562306a36Sopenharmony_ci * a remote batch's folio active potentially hits a race where 40662306a36Sopenharmony_ci * a folio is marked active just after it is added to the inactive 40762306a36Sopenharmony_ci * list causing accounting errors and BUG_ON checks to trigger. 40862306a36Sopenharmony_ci */ 40962306a36Sopenharmony_ci for (i = folio_batch_count(fbatch) - 1; i >= 0; i--) { 41062306a36Sopenharmony_ci struct folio *batch_folio = fbatch->folios[i]; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (batch_folio == folio) { 41362306a36Sopenharmony_ci folio_set_active(folio); 41462306a36Sopenharmony_ci break; 41562306a36Sopenharmony_ci } 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci#ifdef CONFIG_LRU_GEN 42262306a36Sopenharmony_cistatic void folio_inc_refs(struct folio *folio) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci unsigned long new_flags, old_flags = READ_ONCE(folio->flags); 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci if (folio_test_unevictable(folio)) 42762306a36Sopenharmony_ci return; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci if (!folio_test_referenced(folio)) { 43062306a36Sopenharmony_ci folio_set_referenced(folio); 43162306a36Sopenharmony_ci return; 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_ci if (!folio_test_workingset(folio)) { 43562306a36Sopenharmony_ci folio_set_workingset(folio); 43662306a36Sopenharmony_ci return; 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci /* see the comment on MAX_NR_TIERS */ 44062306a36Sopenharmony_ci do { 44162306a36Sopenharmony_ci new_flags = old_flags & LRU_REFS_MASK; 44262306a36Sopenharmony_ci if (new_flags == LRU_REFS_MASK) 44362306a36Sopenharmony_ci break; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci new_flags += BIT(LRU_REFS_PGOFF); 44662306a36Sopenharmony_ci new_flags |= old_flags & ~LRU_REFS_MASK; 44762306a36Sopenharmony_ci } while (!try_cmpxchg(&folio->flags, &old_flags, new_flags)); 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci#else 45062306a36Sopenharmony_cistatic void folio_inc_refs(struct folio *folio) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci#endif /* CONFIG_LRU_GEN */ 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci/* 45662306a36Sopenharmony_ci * Mark a page as having seen activity. 45762306a36Sopenharmony_ci * 45862306a36Sopenharmony_ci * inactive,unreferenced -> inactive,referenced 45962306a36Sopenharmony_ci * inactive,referenced -> active,unreferenced 46062306a36Sopenharmony_ci * active,unreferenced -> active,referenced 46162306a36Sopenharmony_ci * 46262306a36Sopenharmony_ci * When a newly allocated page is not yet visible, so safe for non-atomic ops, 46362306a36Sopenharmony_ci * __SetPageReferenced(page) may be substituted for mark_page_accessed(page). 46462306a36Sopenharmony_ci */ 46562306a36Sopenharmony_civoid folio_mark_accessed(struct folio *folio) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci if (lru_gen_enabled()) { 46862306a36Sopenharmony_ci folio_inc_refs(folio); 46962306a36Sopenharmony_ci return; 47062306a36Sopenharmony_ci } 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (!folio_test_referenced(folio)) { 47362306a36Sopenharmony_ci folio_set_referenced(folio); 47462306a36Sopenharmony_ci } else if (folio_test_unevictable(folio)) { 47562306a36Sopenharmony_ci /* 47662306a36Sopenharmony_ci * Unevictable pages are on the "LRU_UNEVICTABLE" list. But, 47762306a36Sopenharmony_ci * this list is never rotated or maintained, so marking an 47862306a36Sopenharmony_ci * unevictable page accessed has no effect. 47962306a36Sopenharmony_ci */ 48062306a36Sopenharmony_ci } else if (!folio_test_active(folio)) { 48162306a36Sopenharmony_ci /* 48262306a36Sopenharmony_ci * If the folio is on the LRU, queue it for activation via 48362306a36Sopenharmony_ci * cpu_fbatches.activate. Otherwise, assume the folio is in a 48462306a36Sopenharmony_ci * folio_batch, mark it active and it'll be moved to the active 48562306a36Sopenharmony_ci * LRU on the next drain. 48662306a36Sopenharmony_ci */ 48762306a36Sopenharmony_ci if (folio_test_lru(folio)) 48862306a36Sopenharmony_ci folio_activate(folio); 48962306a36Sopenharmony_ci else 49062306a36Sopenharmony_ci __lru_cache_activate_folio(folio); 49162306a36Sopenharmony_ci folio_clear_referenced(folio); 49262306a36Sopenharmony_ci workingset_activation(folio); 49362306a36Sopenharmony_ci } 49462306a36Sopenharmony_ci if (folio_test_idle(folio)) 49562306a36Sopenharmony_ci folio_clear_idle(folio); 49662306a36Sopenharmony_ci} 49762306a36Sopenharmony_ciEXPORT_SYMBOL(folio_mark_accessed); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci/** 50062306a36Sopenharmony_ci * folio_add_lru - Add a folio to an LRU list. 50162306a36Sopenharmony_ci * @folio: The folio to be added to the LRU. 50262306a36Sopenharmony_ci * 50362306a36Sopenharmony_ci * Queue the folio for addition to the LRU. The decision on whether 50462306a36Sopenharmony_ci * to add the page to the [in]active [file|anon] list is deferred until the 50562306a36Sopenharmony_ci * folio_batch is drained. This gives a chance for the caller of folio_add_lru() 50662306a36Sopenharmony_ci * have the folio added to the active list using folio_mark_accessed(). 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_civoid folio_add_lru(struct folio *folio) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci struct folio_batch *fbatch; 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci VM_BUG_ON_FOLIO(folio_test_active(folio) && 51362306a36Sopenharmony_ci folio_test_unevictable(folio), folio); 51462306a36Sopenharmony_ci VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci /* see the comment in lru_gen_add_folio() */ 51762306a36Sopenharmony_ci if (lru_gen_enabled() && !folio_test_unevictable(folio) && 51862306a36Sopenharmony_ci lru_gen_in_fault() && !(current->flags & PF_MEMALLOC)) 51962306a36Sopenharmony_ci folio_set_active(folio); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci folio_get(folio); 52262306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 52362306a36Sopenharmony_ci fbatch = this_cpu_ptr(&cpu_fbatches.lru_add); 52462306a36Sopenharmony_ci folio_batch_add_and_move(fbatch, folio, lru_add_fn); 52562306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ciEXPORT_SYMBOL(folio_add_lru); 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci/** 53062306a36Sopenharmony_ci * folio_add_lru_vma() - Add a folio to the appropate LRU list for this VMA. 53162306a36Sopenharmony_ci * @folio: The folio to be added to the LRU. 53262306a36Sopenharmony_ci * @vma: VMA in which the folio is mapped. 53362306a36Sopenharmony_ci * 53462306a36Sopenharmony_ci * If the VMA is mlocked, @folio is added to the unevictable list. 53562306a36Sopenharmony_ci * Otherwise, it is treated the same way as folio_add_lru(). 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_civoid folio_add_lru_vma(struct folio *folio, struct vm_area_struct *vma) 53862306a36Sopenharmony_ci{ 53962306a36Sopenharmony_ci VM_BUG_ON_FOLIO(folio_test_lru(folio), folio); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (unlikely((vma->vm_flags & (VM_LOCKED | VM_SPECIAL)) == VM_LOCKED)) 54262306a36Sopenharmony_ci mlock_new_folio(folio); 54362306a36Sopenharmony_ci else 54462306a36Sopenharmony_ci folio_add_lru(folio); 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci/* 54862306a36Sopenharmony_ci * If the folio cannot be invalidated, it is moved to the 54962306a36Sopenharmony_ci * inactive list to speed up its reclaim. It is moved to the 55062306a36Sopenharmony_ci * head of the list, rather than the tail, to give the flusher 55162306a36Sopenharmony_ci * threads some time to write it out, as this is much more 55262306a36Sopenharmony_ci * effective than the single-page writeout from reclaim. 55362306a36Sopenharmony_ci * 55462306a36Sopenharmony_ci * If the folio isn't mapped and dirty/writeback, the folio 55562306a36Sopenharmony_ci * could be reclaimed asap using the reclaim flag. 55662306a36Sopenharmony_ci * 55762306a36Sopenharmony_ci * 1. active, mapped folio -> none 55862306a36Sopenharmony_ci * 2. active, dirty/writeback folio -> inactive, head, reclaim 55962306a36Sopenharmony_ci * 3. inactive, mapped folio -> none 56062306a36Sopenharmony_ci * 4. inactive, dirty/writeback folio -> inactive, head, reclaim 56162306a36Sopenharmony_ci * 5. inactive, clean -> inactive, tail 56262306a36Sopenharmony_ci * 6. Others -> none 56362306a36Sopenharmony_ci * 56462306a36Sopenharmony_ci * In 4, it moves to the head of the inactive list so the folio is 56562306a36Sopenharmony_ci * written out by flusher threads as this is much more efficient 56662306a36Sopenharmony_ci * than the single-page writeout from reclaim. 56762306a36Sopenharmony_ci */ 56862306a36Sopenharmony_cistatic void lru_deactivate_file_fn(struct lruvec *lruvec, struct folio *folio) 56962306a36Sopenharmony_ci{ 57062306a36Sopenharmony_ci bool active = folio_test_active(folio); 57162306a36Sopenharmony_ci long nr_pages = folio_nr_pages(folio); 57262306a36Sopenharmony_ci 57362306a36Sopenharmony_ci if (folio_test_unevictable(folio)) 57462306a36Sopenharmony_ci return; 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci /* Some processes are using the folio */ 57762306a36Sopenharmony_ci if (folio_mapped(folio)) 57862306a36Sopenharmony_ci return; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci lruvec_del_folio(lruvec, folio); 58162306a36Sopenharmony_ci folio_clear_active(folio); 58262306a36Sopenharmony_ci folio_clear_referenced(folio); 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci if (folio_test_writeback(folio) || folio_test_dirty(folio)) { 58562306a36Sopenharmony_ci /* 58662306a36Sopenharmony_ci * Setting the reclaim flag could race with 58762306a36Sopenharmony_ci * folio_end_writeback() and confuse readahead. But the 58862306a36Sopenharmony_ci * race window is _really_ small and it's not a critical 58962306a36Sopenharmony_ci * problem. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci lruvec_add_folio(lruvec, folio); 59262306a36Sopenharmony_ci folio_set_reclaim(folio); 59362306a36Sopenharmony_ci } else { 59462306a36Sopenharmony_ci /* 59562306a36Sopenharmony_ci * The folio's writeback ended while it was in the batch. 59662306a36Sopenharmony_ci * We move that folio to the tail of the inactive list. 59762306a36Sopenharmony_ci */ 59862306a36Sopenharmony_ci lruvec_add_folio_tail(lruvec, folio); 59962306a36Sopenharmony_ci __count_vm_events(PGROTATED, nr_pages); 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci if (active) { 60362306a36Sopenharmony_ci __count_vm_events(PGDEACTIVATE, nr_pages); 60462306a36Sopenharmony_ci __count_memcg_events(lruvec_memcg(lruvec), PGDEACTIVATE, 60562306a36Sopenharmony_ci nr_pages); 60662306a36Sopenharmony_ci } 60762306a36Sopenharmony_ci} 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic void lru_deactivate_fn(struct lruvec *lruvec, struct folio *folio) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci if (!folio_test_unevictable(folio) && (folio_test_active(folio) || lru_gen_enabled())) { 61262306a36Sopenharmony_ci long nr_pages = folio_nr_pages(folio); 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci lruvec_del_folio(lruvec, folio); 61562306a36Sopenharmony_ci folio_clear_active(folio); 61662306a36Sopenharmony_ci folio_clear_referenced(folio); 61762306a36Sopenharmony_ci lruvec_add_folio(lruvec, folio); 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci __count_vm_events(PGDEACTIVATE, nr_pages); 62062306a36Sopenharmony_ci __count_memcg_events(lruvec_memcg(lruvec), PGDEACTIVATE, 62162306a36Sopenharmony_ci nr_pages); 62262306a36Sopenharmony_ci } 62362306a36Sopenharmony_ci} 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_cistatic void lru_lazyfree_fn(struct lruvec *lruvec, struct folio *folio) 62662306a36Sopenharmony_ci{ 62762306a36Sopenharmony_ci if (folio_test_anon(folio) && folio_test_swapbacked(folio) && 62862306a36Sopenharmony_ci !folio_test_swapcache(folio) && !folio_test_unevictable(folio)) { 62962306a36Sopenharmony_ci long nr_pages = folio_nr_pages(folio); 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci lruvec_del_folio(lruvec, folio); 63262306a36Sopenharmony_ci folio_clear_active(folio); 63362306a36Sopenharmony_ci folio_clear_referenced(folio); 63462306a36Sopenharmony_ci /* 63562306a36Sopenharmony_ci * Lazyfree folios are clean anonymous folios. They have 63662306a36Sopenharmony_ci * the swapbacked flag cleared, to distinguish them from normal 63762306a36Sopenharmony_ci * anonymous folios 63862306a36Sopenharmony_ci */ 63962306a36Sopenharmony_ci folio_clear_swapbacked(folio); 64062306a36Sopenharmony_ci lruvec_add_folio(lruvec, folio); 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci __count_vm_events(PGLAZYFREE, nr_pages); 64362306a36Sopenharmony_ci __count_memcg_events(lruvec_memcg(lruvec), PGLAZYFREE, 64462306a36Sopenharmony_ci nr_pages); 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci/* 64962306a36Sopenharmony_ci * Drain pages out of the cpu's folio_batch. 65062306a36Sopenharmony_ci * Either "cpu" is the current CPU, and preemption has already been 65162306a36Sopenharmony_ci * disabled; or "cpu" is being hot-unplugged, and is already dead. 65262306a36Sopenharmony_ci */ 65362306a36Sopenharmony_civoid lru_add_drain_cpu(int cpu) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci struct cpu_fbatches *fbatches = &per_cpu(cpu_fbatches, cpu); 65662306a36Sopenharmony_ci struct folio_batch *fbatch = &fbatches->lru_add; 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci if (folio_batch_count(fbatch)) 65962306a36Sopenharmony_ci folio_batch_move_lru(fbatch, lru_add_fn); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci fbatch = &per_cpu(lru_rotate.fbatch, cpu); 66262306a36Sopenharmony_ci /* Disabling interrupts below acts as a compiler barrier. */ 66362306a36Sopenharmony_ci if (data_race(folio_batch_count(fbatch))) { 66462306a36Sopenharmony_ci unsigned long flags; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci /* No harm done if a racing interrupt already did this */ 66762306a36Sopenharmony_ci local_lock_irqsave(&lru_rotate.lock, flags); 66862306a36Sopenharmony_ci folio_batch_move_lru(fbatch, lru_move_tail_fn); 66962306a36Sopenharmony_ci local_unlock_irqrestore(&lru_rotate.lock, flags); 67062306a36Sopenharmony_ci } 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci fbatch = &fbatches->lru_deactivate_file; 67362306a36Sopenharmony_ci if (folio_batch_count(fbatch)) 67462306a36Sopenharmony_ci folio_batch_move_lru(fbatch, lru_deactivate_file_fn); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci fbatch = &fbatches->lru_deactivate; 67762306a36Sopenharmony_ci if (folio_batch_count(fbatch)) 67862306a36Sopenharmony_ci folio_batch_move_lru(fbatch, lru_deactivate_fn); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci fbatch = &fbatches->lru_lazyfree; 68162306a36Sopenharmony_ci if (folio_batch_count(fbatch)) 68262306a36Sopenharmony_ci folio_batch_move_lru(fbatch, lru_lazyfree_fn); 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci folio_activate_drain(cpu); 68562306a36Sopenharmony_ci} 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci/** 68862306a36Sopenharmony_ci * deactivate_file_folio() - Deactivate a file folio. 68962306a36Sopenharmony_ci * @folio: Folio to deactivate. 69062306a36Sopenharmony_ci * 69162306a36Sopenharmony_ci * This function hints to the VM that @folio is a good reclaim candidate, 69262306a36Sopenharmony_ci * for example if its invalidation fails due to the folio being dirty 69362306a36Sopenharmony_ci * or under writeback. 69462306a36Sopenharmony_ci * 69562306a36Sopenharmony_ci * Context: Caller holds a reference on the folio. 69662306a36Sopenharmony_ci */ 69762306a36Sopenharmony_civoid deactivate_file_folio(struct folio *folio) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci struct folio_batch *fbatch; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* Deactivating an unevictable folio will not accelerate reclaim */ 70262306a36Sopenharmony_ci if (folio_test_unevictable(folio)) 70362306a36Sopenharmony_ci return; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci folio_get(folio); 70662306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 70762306a36Sopenharmony_ci fbatch = this_cpu_ptr(&cpu_fbatches.lru_deactivate_file); 70862306a36Sopenharmony_ci folio_batch_add_and_move(fbatch, folio, lru_deactivate_file_fn); 70962306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci/* 71362306a36Sopenharmony_ci * folio_deactivate - deactivate a folio 71462306a36Sopenharmony_ci * @folio: folio to deactivate 71562306a36Sopenharmony_ci * 71662306a36Sopenharmony_ci * folio_deactivate() moves @folio to the inactive list if @folio was on the 71762306a36Sopenharmony_ci * active list and was not unevictable. This is done to accelerate the 71862306a36Sopenharmony_ci * reclaim of @folio. 71962306a36Sopenharmony_ci */ 72062306a36Sopenharmony_civoid folio_deactivate(struct folio *folio) 72162306a36Sopenharmony_ci{ 72262306a36Sopenharmony_ci if (folio_test_lru(folio) && !folio_test_unevictable(folio) && 72362306a36Sopenharmony_ci (folio_test_active(folio) || lru_gen_enabled())) { 72462306a36Sopenharmony_ci struct folio_batch *fbatch; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci folio_get(folio); 72762306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 72862306a36Sopenharmony_ci fbatch = this_cpu_ptr(&cpu_fbatches.lru_deactivate); 72962306a36Sopenharmony_ci folio_batch_add_and_move(fbatch, folio, lru_deactivate_fn); 73062306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci} 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci/** 73562306a36Sopenharmony_ci * folio_mark_lazyfree - make an anon folio lazyfree 73662306a36Sopenharmony_ci * @folio: folio to deactivate 73762306a36Sopenharmony_ci * 73862306a36Sopenharmony_ci * folio_mark_lazyfree() moves @folio to the inactive file list. 73962306a36Sopenharmony_ci * This is done to accelerate the reclaim of @folio. 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_civoid folio_mark_lazyfree(struct folio *folio) 74262306a36Sopenharmony_ci{ 74362306a36Sopenharmony_ci if (folio_test_lru(folio) && folio_test_anon(folio) && 74462306a36Sopenharmony_ci folio_test_swapbacked(folio) && !folio_test_swapcache(folio) && 74562306a36Sopenharmony_ci !folio_test_unevictable(folio)) { 74662306a36Sopenharmony_ci struct folio_batch *fbatch; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci folio_get(folio); 74962306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 75062306a36Sopenharmony_ci fbatch = this_cpu_ptr(&cpu_fbatches.lru_lazyfree); 75162306a36Sopenharmony_ci folio_batch_add_and_move(fbatch, folio, lru_lazyfree_fn); 75262306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci} 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_civoid lru_add_drain(void) 75762306a36Sopenharmony_ci{ 75862306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 75962306a36Sopenharmony_ci lru_add_drain_cpu(smp_processor_id()); 76062306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 76162306a36Sopenharmony_ci mlock_drain_local(); 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/* 76562306a36Sopenharmony_ci * It's called from per-cpu workqueue context in SMP case so 76662306a36Sopenharmony_ci * lru_add_drain_cpu and invalidate_bh_lrus_cpu should run on 76762306a36Sopenharmony_ci * the same cpu. It shouldn't be a problem in !SMP case since 76862306a36Sopenharmony_ci * the core is only one and the locks will disable preemption. 76962306a36Sopenharmony_ci */ 77062306a36Sopenharmony_cistatic void lru_add_and_bh_lrus_drain(void) 77162306a36Sopenharmony_ci{ 77262306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 77362306a36Sopenharmony_ci lru_add_drain_cpu(smp_processor_id()); 77462306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 77562306a36Sopenharmony_ci invalidate_bh_lrus_cpu(); 77662306a36Sopenharmony_ci mlock_drain_local(); 77762306a36Sopenharmony_ci} 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_civoid lru_add_drain_cpu_zone(struct zone *zone) 78062306a36Sopenharmony_ci{ 78162306a36Sopenharmony_ci local_lock(&cpu_fbatches.lock); 78262306a36Sopenharmony_ci lru_add_drain_cpu(smp_processor_id()); 78362306a36Sopenharmony_ci drain_local_pages(zone); 78462306a36Sopenharmony_ci local_unlock(&cpu_fbatches.lock); 78562306a36Sopenharmony_ci mlock_drain_local(); 78662306a36Sopenharmony_ci} 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci#ifdef CONFIG_SMP 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cistatic DEFINE_PER_CPU(struct work_struct, lru_add_drain_work); 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic void lru_add_drain_per_cpu(struct work_struct *dummy) 79362306a36Sopenharmony_ci{ 79462306a36Sopenharmony_ci lru_add_and_bh_lrus_drain(); 79562306a36Sopenharmony_ci} 79662306a36Sopenharmony_ci 79762306a36Sopenharmony_cistatic bool cpu_needs_drain(unsigned int cpu) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct cpu_fbatches *fbatches = &per_cpu(cpu_fbatches, cpu); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ci /* Check these in order of likelihood that they're not zero */ 80262306a36Sopenharmony_ci return folio_batch_count(&fbatches->lru_add) || 80362306a36Sopenharmony_ci data_race(folio_batch_count(&per_cpu(lru_rotate.fbatch, cpu))) || 80462306a36Sopenharmony_ci folio_batch_count(&fbatches->lru_deactivate_file) || 80562306a36Sopenharmony_ci folio_batch_count(&fbatches->lru_deactivate) || 80662306a36Sopenharmony_ci folio_batch_count(&fbatches->lru_lazyfree) || 80762306a36Sopenharmony_ci folio_batch_count(&fbatches->activate) || 80862306a36Sopenharmony_ci need_mlock_drain(cpu) || 80962306a36Sopenharmony_ci has_bh_in_lru(cpu, NULL); 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci/* 81362306a36Sopenharmony_ci * Doesn't need any cpu hotplug locking because we do rely on per-cpu 81462306a36Sopenharmony_ci * kworkers being shut down before our page_alloc_cpu_dead callback is 81562306a36Sopenharmony_ci * executed on the offlined cpu. 81662306a36Sopenharmony_ci * Calling this function with cpu hotplug locks held can actually lead 81762306a36Sopenharmony_ci * to obscure indirect dependencies via WQ context. 81862306a36Sopenharmony_ci */ 81962306a36Sopenharmony_cistatic inline void __lru_add_drain_all(bool force_all_cpus) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci /* 82262306a36Sopenharmony_ci * lru_drain_gen - Global pages generation number 82362306a36Sopenharmony_ci * 82462306a36Sopenharmony_ci * (A) Definition: global lru_drain_gen = x implies that all generations 82562306a36Sopenharmony_ci * 0 < n <= x are already *scheduled* for draining. 82662306a36Sopenharmony_ci * 82762306a36Sopenharmony_ci * This is an optimization for the highly-contended use case where a 82862306a36Sopenharmony_ci * user space workload keeps constantly generating a flow of pages for 82962306a36Sopenharmony_ci * each CPU. 83062306a36Sopenharmony_ci */ 83162306a36Sopenharmony_ci static unsigned int lru_drain_gen; 83262306a36Sopenharmony_ci static struct cpumask has_work; 83362306a36Sopenharmony_ci static DEFINE_MUTEX(lock); 83462306a36Sopenharmony_ci unsigned cpu, this_gen; 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci /* 83762306a36Sopenharmony_ci * Make sure nobody triggers this path before mm_percpu_wq is fully 83862306a36Sopenharmony_ci * initialized. 83962306a36Sopenharmony_ci */ 84062306a36Sopenharmony_ci if (WARN_ON(!mm_percpu_wq)) 84162306a36Sopenharmony_ci return; 84262306a36Sopenharmony_ci 84362306a36Sopenharmony_ci /* 84462306a36Sopenharmony_ci * Guarantee folio_batch counter stores visible by this CPU 84562306a36Sopenharmony_ci * are visible to other CPUs before loading the current drain 84662306a36Sopenharmony_ci * generation. 84762306a36Sopenharmony_ci */ 84862306a36Sopenharmony_ci smp_mb(); 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci /* 85162306a36Sopenharmony_ci * (B) Locally cache global LRU draining generation number 85262306a36Sopenharmony_ci * 85362306a36Sopenharmony_ci * The read barrier ensures that the counter is loaded before the mutex 85462306a36Sopenharmony_ci * is taken. It pairs with smp_mb() inside the mutex critical section 85562306a36Sopenharmony_ci * at (D). 85662306a36Sopenharmony_ci */ 85762306a36Sopenharmony_ci this_gen = smp_load_acquire(&lru_drain_gen); 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_ci mutex_lock(&lock); 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci /* 86262306a36Sopenharmony_ci * (C) Exit the draining operation if a newer generation, from another 86362306a36Sopenharmony_ci * lru_add_drain_all(), was already scheduled for draining. Check (A). 86462306a36Sopenharmony_ci */ 86562306a36Sopenharmony_ci if (unlikely(this_gen != lru_drain_gen && !force_all_cpus)) 86662306a36Sopenharmony_ci goto done; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci /* 86962306a36Sopenharmony_ci * (D) Increment global generation number 87062306a36Sopenharmony_ci * 87162306a36Sopenharmony_ci * Pairs with smp_load_acquire() at (B), outside of the critical 87262306a36Sopenharmony_ci * section. Use a full memory barrier to guarantee that the 87362306a36Sopenharmony_ci * new global drain generation number is stored before loading 87462306a36Sopenharmony_ci * folio_batch counters. 87562306a36Sopenharmony_ci * 87662306a36Sopenharmony_ci * This pairing must be done here, before the for_each_online_cpu loop 87762306a36Sopenharmony_ci * below which drains the page vectors. 87862306a36Sopenharmony_ci * 87962306a36Sopenharmony_ci * Let x, y, and z represent some system CPU numbers, where x < y < z. 88062306a36Sopenharmony_ci * Assume CPU #z is in the middle of the for_each_online_cpu loop 88162306a36Sopenharmony_ci * below and has already reached CPU #y's per-cpu data. CPU #x comes 88262306a36Sopenharmony_ci * along, adds some pages to its per-cpu vectors, then calls 88362306a36Sopenharmony_ci * lru_add_drain_all(). 88462306a36Sopenharmony_ci * 88562306a36Sopenharmony_ci * If the paired barrier is done at any later step, e.g. after the 88662306a36Sopenharmony_ci * loop, CPU #x will just exit at (C) and miss flushing out all of its 88762306a36Sopenharmony_ci * added pages. 88862306a36Sopenharmony_ci */ 88962306a36Sopenharmony_ci WRITE_ONCE(lru_drain_gen, lru_drain_gen + 1); 89062306a36Sopenharmony_ci smp_mb(); 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci cpumask_clear(&has_work); 89362306a36Sopenharmony_ci for_each_online_cpu(cpu) { 89462306a36Sopenharmony_ci struct work_struct *work = &per_cpu(lru_add_drain_work, cpu); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci if (cpu_needs_drain(cpu)) { 89762306a36Sopenharmony_ci INIT_WORK(work, lru_add_drain_per_cpu); 89862306a36Sopenharmony_ci queue_work_on(cpu, mm_percpu_wq, work); 89962306a36Sopenharmony_ci __cpumask_set_cpu(cpu, &has_work); 90062306a36Sopenharmony_ci } 90162306a36Sopenharmony_ci } 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci for_each_cpu(cpu, &has_work) 90462306a36Sopenharmony_ci flush_work(&per_cpu(lru_add_drain_work, cpu)); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_cidone: 90762306a36Sopenharmony_ci mutex_unlock(&lock); 90862306a36Sopenharmony_ci} 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_civoid lru_add_drain_all(void) 91162306a36Sopenharmony_ci{ 91262306a36Sopenharmony_ci __lru_add_drain_all(false); 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci#else 91562306a36Sopenharmony_civoid lru_add_drain_all(void) 91662306a36Sopenharmony_ci{ 91762306a36Sopenharmony_ci lru_add_drain(); 91862306a36Sopenharmony_ci} 91962306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ciatomic_t lru_disable_count = ATOMIC_INIT(0); 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci/* 92462306a36Sopenharmony_ci * lru_cache_disable() needs to be called before we start compiling 92562306a36Sopenharmony_ci * a list of pages to be migrated using isolate_lru_page(). 92662306a36Sopenharmony_ci * It drains pages on LRU cache and then disable on all cpus until 92762306a36Sopenharmony_ci * lru_cache_enable is called. 92862306a36Sopenharmony_ci * 92962306a36Sopenharmony_ci * Must be paired with a call to lru_cache_enable(). 93062306a36Sopenharmony_ci */ 93162306a36Sopenharmony_civoid lru_cache_disable(void) 93262306a36Sopenharmony_ci{ 93362306a36Sopenharmony_ci atomic_inc(&lru_disable_count); 93462306a36Sopenharmony_ci /* 93562306a36Sopenharmony_ci * Readers of lru_disable_count are protected by either disabling 93662306a36Sopenharmony_ci * preemption or rcu_read_lock: 93762306a36Sopenharmony_ci * 93862306a36Sopenharmony_ci * preempt_disable, local_irq_disable [bh_lru_lock()] 93962306a36Sopenharmony_ci * rcu_read_lock [rt_spin_lock CONFIG_PREEMPT_RT] 94062306a36Sopenharmony_ci * preempt_disable [local_lock !CONFIG_PREEMPT_RT] 94162306a36Sopenharmony_ci * 94262306a36Sopenharmony_ci * Since v5.1 kernel, synchronize_rcu() is guaranteed to wait on 94362306a36Sopenharmony_ci * preempt_disable() regions of code. So any CPU which sees 94462306a36Sopenharmony_ci * lru_disable_count = 0 will have exited the critical 94562306a36Sopenharmony_ci * section when synchronize_rcu() returns. 94662306a36Sopenharmony_ci */ 94762306a36Sopenharmony_ci synchronize_rcu_expedited(); 94862306a36Sopenharmony_ci#ifdef CONFIG_SMP 94962306a36Sopenharmony_ci __lru_add_drain_all(true); 95062306a36Sopenharmony_ci#else 95162306a36Sopenharmony_ci lru_add_and_bh_lrus_drain(); 95262306a36Sopenharmony_ci#endif 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci/** 95662306a36Sopenharmony_ci * release_pages - batched put_page() 95762306a36Sopenharmony_ci * @arg: array of pages to release 95862306a36Sopenharmony_ci * @nr: number of pages 95962306a36Sopenharmony_ci * 96062306a36Sopenharmony_ci * Decrement the reference count on all the pages in @arg. If it 96162306a36Sopenharmony_ci * fell to zero, remove the page from the LRU and free it. 96262306a36Sopenharmony_ci * 96362306a36Sopenharmony_ci * Note that the argument can be an array of pages, encoded pages, 96462306a36Sopenharmony_ci * or folio pointers. We ignore any encoded bits, and turn any of 96562306a36Sopenharmony_ci * them into just a folio that gets free'd. 96662306a36Sopenharmony_ci */ 96762306a36Sopenharmony_civoid release_pages(release_pages_arg arg, int nr) 96862306a36Sopenharmony_ci{ 96962306a36Sopenharmony_ci int i; 97062306a36Sopenharmony_ci struct encoded_page **encoded = arg.encoded_pages; 97162306a36Sopenharmony_ci LIST_HEAD(pages_to_free); 97262306a36Sopenharmony_ci struct lruvec *lruvec = NULL; 97362306a36Sopenharmony_ci unsigned long flags = 0; 97462306a36Sopenharmony_ci unsigned int lock_batch; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci for (i = 0; i < nr; i++) { 97762306a36Sopenharmony_ci struct folio *folio; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci /* Turn any of the argument types into a folio */ 98062306a36Sopenharmony_ci folio = page_folio(encoded_page_ptr(encoded[i])); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci /* 98362306a36Sopenharmony_ci * Make sure the IRQ-safe lock-holding time does not get 98462306a36Sopenharmony_ci * excessive with a continuous string of pages from the 98562306a36Sopenharmony_ci * same lruvec. The lock is held only if lruvec != NULL. 98662306a36Sopenharmony_ci */ 98762306a36Sopenharmony_ci if (lruvec && ++lock_batch == SWAP_CLUSTER_MAX) { 98862306a36Sopenharmony_ci unlock_page_lruvec_irqrestore(lruvec, flags); 98962306a36Sopenharmony_ci lruvec = NULL; 99062306a36Sopenharmony_ci } 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci if (is_huge_zero_page(&folio->page)) 99362306a36Sopenharmony_ci continue; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci if (folio_is_zone_device(folio)) { 99662306a36Sopenharmony_ci if (lruvec) { 99762306a36Sopenharmony_ci unlock_page_lruvec_irqrestore(lruvec, flags); 99862306a36Sopenharmony_ci lruvec = NULL; 99962306a36Sopenharmony_ci } 100062306a36Sopenharmony_ci if (put_devmap_managed_page(&folio->page)) 100162306a36Sopenharmony_ci continue; 100262306a36Sopenharmony_ci if (folio_put_testzero(folio)) 100362306a36Sopenharmony_ci free_zone_device_page(&folio->page); 100462306a36Sopenharmony_ci continue; 100562306a36Sopenharmony_ci } 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci if (!folio_put_testzero(folio)) 100862306a36Sopenharmony_ci continue; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci if (folio_test_large(folio)) { 101162306a36Sopenharmony_ci if (lruvec) { 101262306a36Sopenharmony_ci unlock_page_lruvec_irqrestore(lruvec, flags); 101362306a36Sopenharmony_ci lruvec = NULL; 101462306a36Sopenharmony_ci } 101562306a36Sopenharmony_ci __folio_put_large(folio); 101662306a36Sopenharmony_ci continue; 101762306a36Sopenharmony_ci } 101862306a36Sopenharmony_ci 101962306a36Sopenharmony_ci if (folio_test_lru(folio)) { 102062306a36Sopenharmony_ci struct lruvec *prev_lruvec = lruvec; 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci lruvec = folio_lruvec_relock_irqsave(folio, lruvec, 102362306a36Sopenharmony_ci &flags); 102462306a36Sopenharmony_ci if (prev_lruvec != lruvec) 102562306a36Sopenharmony_ci lock_batch = 0; 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci lruvec_del_folio(lruvec, folio); 102862306a36Sopenharmony_ci __folio_clear_lru_flags(folio); 102962306a36Sopenharmony_ci } 103062306a36Sopenharmony_ci 103162306a36Sopenharmony_ci /* 103262306a36Sopenharmony_ci * In rare cases, when truncation or holepunching raced with 103362306a36Sopenharmony_ci * munlock after VM_LOCKED was cleared, Mlocked may still be 103462306a36Sopenharmony_ci * found set here. This does not indicate a problem, unless 103562306a36Sopenharmony_ci * "unevictable_pgs_cleared" appears worryingly large. 103662306a36Sopenharmony_ci */ 103762306a36Sopenharmony_ci if (unlikely(folio_test_mlocked(folio))) { 103862306a36Sopenharmony_ci __folio_clear_mlocked(folio); 103962306a36Sopenharmony_ci zone_stat_sub_folio(folio, NR_MLOCK); 104062306a36Sopenharmony_ci count_vm_event(UNEVICTABLE_PGCLEARED); 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci list_add(&folio->lru, &pages_to_free); 104462306a36Sopenharmony_ci } 104562306a36Sopenharmony_ci if (lruvec) 104662306a36Sopenharmony_ci unlock_page_lruvec_irqrestore(lruvec, flags); 104762306a36Sopenharmony_ci 104862306a36Sopenharmony_ci mem_cgroup_uncharge_list(&pages_to_free); 104962306a36Sopenharmony_ci free_unref_page_list(&pages_to_free); 105062306a36Sopenharmony_ci} 105162306a36Sopenharmony_ciEXPORT_SYMBOL(release_pages); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci/* 105462306a36Sopenharmony_ci * The folios which we're about to release may be in the deferred lru-addition 105562306a36Sopenharmony_ci * queues. That would prevent them from really being freed right now. That's 105662306a36Sopenharmony_ci * OK from a correctness point of view but is inefficient - those folios may be 105762306a36Sopenharmony_ci * cache-warm and we want to give them back to the page allocator ASAP. 105862306a36Sopenharmony_ci * 105962306a36Sopenharmony_ci * So __folio_batch_release() will drain those queues here. 106062306a36Sopenharmony_ci * folio_batch_move_lru() calls folios_put() directly to avoid 106162306a36Sopenharmony_ci * mutual recursion. 106262306a36Sopenharmony_ci */ 106362306a36Sopenharmony_civoid __folio_batch_release(struct folio_batch *fbatch) 106462306a36Sopenharmony_ci{ 106562306a36Sopenharmony_ci if (!fbatch->percpu_pvec_drained) { 106662306a36Sopenharmony_ci lru_add_drain(); 106762306a36Sopenharmony_ci fbatch->percpu_pvec_drained = true; 106862306a36Sopenharmony_ci } 106962306a36Sopenharmony_ci release_pages(fbatch->folios, folio_batch_count(fbatch)); 107062306a36Sopenharmony_ci folio_batch_reinit(fbatch); 107162306a36Sopenharmony_ci} 107262306a36Sopenharmony_ciEXPORT_SYMBOL(__folio_batch_release); 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci/** 107562306a36Sopenharmony_ci * folio_batch_remove_exceptionals() - Prune non-folios from a batch. 107662306a36Sopenharmony_ci * @fbatch: The batch to prune 107762306a36Sopenharmony_ci * 107862306a36Sopenharmony_ci * find_get_entries() fills a batch with both folios and shadow/swap/DAX 107962306a36Sopenharmony_ci * entries. This function prunes all the non-folio entries from @fbatch 108062306a36Sopenharmony_ci * without leaving holes, so that it can be passed on to folio-only batch 108162306a36Sopenharmony_ci * operations. 108262306a36Sopenharmony_ci */ 108362306a36Sopenharmony_civoid folio_batch_remove_exceptionals(struct folio_batch *fbatch) 108462306a36Sopenharmony_ci{ 108562306a36Sopenharmony_ci unsigned int i, j; 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci for (i = 0, j = 0; i < folio_batch_count(fbatch); i++) { 108862306a36Sopenharmony_ci struct folio *folio = fbatch->folios[i]; 108962306a36Sopenharmony_ci if (!xa_is_value(folio)) 109062306a36Sopenharmony_ci fbatch->folios[j++] = folio; 109162306a36Sopenharmony_ci } 109262306a36Sopenharmony_ci fbatch->nr = j; 109362306a36Sopenharmony_ci} 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci/* 109662306a36Sopenharmony_ci * Perform any setup for the swap system 109762306a36Sopenharmony_ci */ 109862306a36Sopenharmony_civoid __init swap_setup(void) 109962306a36Sopenharmony_ci{ 110062306a36Sopenharmony_ci unsigned long megs = totalram_pages() >> (20 - PAGE_SHIFT); 110162306a36Sopenharmony_ci 110262306a36Sopenharmony_ci /* Use a smaller cluster for small-memory machines */ 110362306a36Sopenharmony_ci if (megs < 16) 110462306a36Sopenharmony_ci page_cluster = 2; 110562306a36Sopenharmony_ci else 110662306a36Sopenharmony_ci page_cluster = 3; 110762306a36Sopenharmony_ci /* 110862306a36Sopenharmony_ci * Right now other parts of the system means that we 110962306a36Sopenharmony_ci * _really_ don't want to cluster much more 111062306a36Sopenharmony_ci */ 111162306a36Sopenharmony_ci} 1112