Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/workingset: Convert workingset_refault() to take a folio

This nets us 178 bytes of savings from removing calls to compound_head.
The three callers all grow a little, but each of them will be converted
to use folios soon, so that's fine.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Howells <dhowells@redhat.com>
Acked-by: Vlastimil Babka <vbabka@suse.cz>

+31 -35
+2 -2
include/linux/swap.h
··· 329 329 /* linux/mm/workingset.c */ 330 330 void workingset_age_nonresident(struct lruvec *lruvec, unsigned long nr_pages); 331 331 void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg); 332 - void workingset_refault(struct page *page, void *shadow); 332 + void workingset_refault(struct folio *folio, void *shadow); 333 333 void workingset_activation(struct folio *folio); 334 334 335 335 /* Only track the nodes of mappings with shadow entries */ ··· 350 350 /* linux/mm/swap.c */ 351 351 extern void lru_note_cost(struct lruvec *lruvec, bool file, 352 352 unsigned int nr_pages); 353 - extern void lru_note_cost_page(struct page *); 353 + extern void lru_note_cost_folio(struct folio *); 354 354 extern void lru_cache_add(struct page *); 355 355 void mark_page_accessed(struct page *); 356 356 void folio_mark_accessed(struct folio *);
-6
include/linux/vmstat.h
··· 597 597 598 598 #endif /* CONFIG_MEMCG */ 599 599 600 - static inline void inc_lruvec_state(struct lruvec *lruvec, 601 - enum node_stat_item idx) 602 - { 603 - mod_lruvec_state(lruvec, idx, 1); 604 - } 605 - 606 600 static inline void __inc_lruvec_page_state(struct page *page, 607 601 enum node_stat_item idx) 608 602 {
+1 -1
mm/filemap.c
··· 998 998 */ 999 999 WARN_ON_ONCE(PageActive(page)); 1000 1000 if (!(gfp_mask & __GFP_WRITE) && shadow) 1001 - workingset_refault(page, shadow); 1001 + workingset_refault(page_folio(page), shadow); 1002 1002 lru_cache_add(page); 1003 1003 } 1004 1004 return ret;
+2 -1
mm/memory.c
··· 3539 3539 3540 3540 shadow = get_shadow_from_swap_cache(entry); 3541 3541 if (shadow) 3542 - workingset_refault(page, shadow); 3542 + workingset_refault(page_folio(page), 3543 + shadow); 3543 3544 3544 3545 lru_cache_add(page); 3545 3546
+3 -4
mm/swap.c
··· 293 293 } while ((lruvec = parent_lruvec(lruvec))); 294 294 } 295 295 296 - void lru_note_cost_page(struct page *page) 296 + void lru_note_cost_folio(struct folio *folio) 297 297 { 298 - struct folio *folio = page_folio(page); 299 - lru_note_cost(folio_lruvec(folio), 300 - page_is_file_lru(page), thp_nr_pages(page)); 298 + lru_note_cost(folio_lruvec(folio), folio_is_file_lru(folio), 299 + folio_nr_pages(folio)); 301 300 } 302 301 303 302 static void __folio_activate(struct folio *folio, struct lruvec *lruvec)
+1 -1
mm/swap_state.c
··· 498 498 mem_cgroup_swapin_uncharge_swap(entry); 499 499 500 500 if (shadow) 501 - workingset_refault(page, shadow); 501 + workingset_refault(page_folio(page), shadow); 502 502 503 503 /* Caller will initiate read into locked page */ 504 504 lru_cache_add(page);
+22 -20
mm/workingset.c
··· 273 273 } 274 274 275 275 /** 276 - * workingset_refault - evaluate the refault of a previously evicted page 277 - * @page: the freshly allocated replacement page 278 - * @shadow: shadow entry of the evicted page 276 + * workingset_refault - Evaluate the refault of a previously evicted folio. 277 + * @folio: The freshly allocated replacement folio. 278 + * @shadow: Shadow entry of the evicted folio. 279 279 * 280 280 * Calculates and evaluates the refault distance of the previously 281 - * evicted page in the context of the node and the memcg whose memory 281 + * evicted folio in the context of the node and the memcg whose memory 282 282 * pressure caused the eviction. 283 283 */ 284 - void workingset_refault(struct page *page, void *shadow) 284 + void workingset_refault(struct folio *folio, void *shadow) 285 285 { 286 - bool file = page_is_file_lru(page); 286 + bool file = folio_is_file_lru(folio); 287 287 struct mem_cgroup *eviction_memcg; 288 288 struct lruvec *eviction_lruvec; 289 289 unsigned long refault_distance; ··· 295 295 unsigned long refault; 296 296 bool workingset; 297 297 int memcgid; 298 + long nr; 298 299 299 300 unpack_shadow(shadow, &memcgid, &pgdat, &eviction, &workingset); 300 301 301 302 rcu_read_lock(); 302 303 /* 303 304 * Look up the memcg associated with the stored ID. It might 304 - * have been deleted since the page's eviction. 305 + * have been deleted since the folio's eviction. 305 306 * 306 307 * Note that in rare events the ID could have been recycled 307 - * for a new cgroup that refaults a shared page. This is 308 + * for a new cgroup that refaults a shared folio. This is 308 309 * impossible to tell from the available data. However, this 309 310 * should be a rare and limited disturbance, and activations 310 311 * are always speculative anyway. Ultimately, it's the aging ··· 341 340 refault_distance = (refault - eviction) & EVICTION_MASK; 342 341 343 342 /* 344 - * The activation decision for this page is made at the level 343 + * The activation decision for this folio is made at the level 345 344 * where the eviction occurred, as that is where the LRU order 346 - * during page reclaim is being determined. 345 + * during folio reclaim is being determined. 347 346 * 348 - * However, the cgroup that will own the page is the one that 347 + * However, the cgroup that will own the folio is the one that 349 348 * is actually experiencing the refault event. 350 349 */ 351 - memcg = page_memcg(page); 350 + nr = folio_nr_pages(folio); 351 + memcg = folio_memcg(folio); 352 352 lruvec = mem_cgroup_lruvec(memcg, pgdat); 353 353 354 - inc_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file); 354 + mod_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + file, nr); 355 355 356 356 mem_cgroup_flush_stats(); 357 357 /* ··· 378 376 if (refault_distance > workingset_size) 379 377 goto out; 380 378 381 - SetPageActive(page); 382 - workingset_age_nonresident(lruvec, thp_nr_pages(page)); 383 - inc_lruvec_state(lruvec, WORKINGSET_ACTIVATE_BASE + file); 379 + folio_set_active(folio); 380 + workingset_age_nonresident(lruvec, nr); 381 + mod_lruvec_state(lruvec, WORKINGSET_ACTIVATE_BASE + file, nr); 384 382 385 - /* Page was active prior to eviction */ 383 + /* Folio was active prior to eviction */ 386 384 if (workingset) { 387 - SetPageWorkingset(page); 385 + folio_set_workingset(folio); 388 386 /* XXX: Move to lru_cache_add() when it supports new vs putback */ 389 - lru_note_cost_page(page); 390 - inc_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + file); 387 + lru_note_cost_folio(folio); 388 + mod_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + file, nr); 391 389 } 392 390 out: 393 391 rcu_read_unlock();