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

mm/list_lru: simplify the list_lru walk callback function

Now isolation no longer takes the list_lru global node lock, only use the
per-cgroup lock instead. And this lock is inside the list_lru_one being
walked, no longer needed to pass the lock explicitly.

Link: https://lkml.kernel.org/r/20241104175257.60853-7-ryncsn@gmail.com
Signed-off-by: Kairui Song <kasong@tencent.com>
Cc: Chengming Zhou <zhouchengming@bytedance.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Qi Zheng <zhengqi.arch@bytedance.com>
Cc: Roman Gushchin <roman.gushchin@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Waiman Long <longman@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Kairui Song and committed by
Andrew Morton
da0c0251 fb56fdf8

+25 -33
+3 -4
drivers/android/binder_alloc.c
··· 1047 1047 /** 1048 1048 * binder_alloc_free_page() - shrinker callback to free pages 1049 1049 * @item: item to free 1050 - * @lock: lock protecting the item 1050 + * @lru: list_lru instance of the item 1051 1051 * @cb_arg: callback argument 1052 1052 * 1053 1053 * Called from list_lru_walk() in binder_shrink_scan() to free ··· 1055 1055 */ 1056 1056 enum lru_status binder_alloc_free_page(struct list_head *item, 1057 1057 struct list_lru_one *lru, 1058 - spinlock_t *lock, 1059 1058 void *cb_arg) 1060 - __must_hold(lock) 1059 + __must_hold(&lru->lock) 1061 1060 { 1062 1061 struct binder_lru_page *page = container_of(item, typeof(*page), lru); 1063 1062 struct binder_alloc *alloc = page->alloc; ··· 1091 1092 1092 1093 list_lru_isolate(lru, item); 1093 1094 spin_unlock(&alloc->lock); 1094 - spin_unlock(lock); 1095 + spin_unlock(&lru->lock); 1095 1096 1096 1097 if (vma) { 1097 1098 trace_binder_unmap_user_start(alloc, index);
+1 -1
drivers/android/binder_alloc.h
··· 118 118 #endif 119 119 enum lru_status binder_alloc_free_page(struct list_head *item, 120 120 struct list_lru_one *lru, 121 - spinlock_t *lock, void *cb_arg); 121 + void *cb_arg); 122 122 struct binder_buffer *binder_alloc_new_buf(struct binder_alloc *alloc, 123 123 size_t data_size, 124 124 size_t offsets_size,
+2 -2
fs/dcache.c
··· 1089 1089 } 1090 1090 1091 1091 static enum lru_status dentry_lru_isolate(struct list_head *item, 1092 - struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) 1092 + struct list_lru_one *lru, void *arg) 1093 1093 { 1094 1094 struct list_head *freeable = arg; 1095 1095 struct dentry *dentry = container_of(item, struct dentry, d_lru); ··· 1170 1170 } 1171 1171 1172 1172 static enum lru_status dentry_lru_isolate_shrink(struct list_head *item, 1173 - struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) 1173 + struct list_lru_one *lru, void *arg) 1174 1174 { 1175 1175 struct list_head *freeable = arg; 1176 1176 struct dentry *dentry = container_of(item, struct dentry, d_lru);
+1 -1
fs/gfs2/quota.c
··· 149 149 150 150 151 151 static enum lru_status gfs2_qd_isolate(struct list_head *item, 152 - struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) 152 + struct list_lru_one *lru, void *arg) 153 153 { 154 154 struct list_head *dispose = arg; 155 155 struct gfs2_quota_data *qd =
+2 -2
fs/inode.c
··· 881 881 * with this flag set because they are the inodes that are out of order. 882 882 */ 883 883 static enum lru_status inode_lru_isolate(struct list_head *item, 884 - struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) 884 + struct list_lru_one *lru, void *arg) 885 885 { 886 886 struct list_head *freeable = arg; 887 887 struct inode *inode = container_of(item, struct inode, i_lru); ··· 923 923 if (inode_has_buffers(inode) || !mapping_empty(&inode->i_data)) { 924 924 inode_pin_lru_isolating(inode); 925 925 spin_unlock(&inode->i_lock); 926 - spin_unlock(lru_lock); 926 + spin_unlock(&lru->lock); 927 927 if (remove_inode_buffers(inode)) { 928 928 unsigned long reap; 929 929 reap = invalidate_mapping_pages(&inode->i_data, 0, -1);
+2 -2
fs/nfs/nfs42xattr.c
··· 802 802 803 803 static enum lru_status 804 804 cache_lru_isolate(struct list_head *item, 805 - struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) 805 + struct list_lru_one *lru, void *arg) 806 806 { 807 807 struct list_head *dispose = arg; 808 808 struct inode *inode; ··· 867 867 868 868 static enum lru_status 869 869 entry_lru_isolate(struct list_head *item, 870 - struct list_lru_one *lru, spinlock_t *lru_lock, void *arg) 870 + struct list_lru_one *lru, void *arg) 871 871 { 872 872 struct list_head *dispose = arg; 873 873 struct nfs4_xattr_bucket *bucket;
+1 -4
fs/nfsd/filecache.c
··· 487 487 * nfsd_file_lru_cb - Examine an entry on the LRU list 488 488 * @item: LRU entry to examine 489 489 * @lru: controlling LRU 490 - * @lock: LRU list lock (unused) 491 490 * @arg: dispose list 492 491 * 493 492 * Return values: ··· 496 497 */ 497 498 static enum lru_status 498 499 nfsd_file_lru_cb(struct list_head *item, struct list_lru_one *lru, 499 - spinlock_t *lock, void *arg) 500 - __releases(lock) 501 - __acquires(lock) 500 + void *arg) 502 501 { 503 502 struct list_head *head = arg; 504 503 struct nfsd_file *nf = list_entry(item, struct nfsd_file, nf_lru);
-2
fs/xfs/xfs_buf.c
··· 1857 1857 xfs_buftarg_drain_rele( 1858 1858 struct list_head *item, 1859 1859 struct list_lru_one *lru, 1860 - spinlock_t *lru_lock, 1861 1860 void *arg) 1862 1861 1863 1862 { ··· 1955 1956 xfs_buftarg_isolate( 1956 1957 struct list_head *item, 1957 1958 struct list_lru_one *lru, 1958 - spinlock_t *lru_lock, 1959 1959 void *arg) 1960 1960 { 1961 1961 struct xfs_buf *bp = container_of(item, struct xfs_buf, b_lru);
+2 -3
fs/xfs/xfs_qm.c
··· 412 412 xfs_qm_dquot_isolate( 413 413 struct list_head *item, 414 414 struct list_lru_one *lru, 415 - spinlock_t *lru_lock, 416 415 void *arg) 417 - __releases(lru_lock) __acquires(lru_lock) 416 + __releases(&lru->lock) __acquires(&lru->lock) 418 417 { 419 418 struct xfs_dquot *dqp = container_of(item, 420 419 struct xfs_dquot, q_lru); ··· 459 460 trace_xfs_dqreclaim_dirty(dqp); 460 461 461 462 /* we have to drop the LRU lock to flush the dquot */ 462 - spin_unlock(lru_lock); 463 + spin_unlock(&lru->lock); 463 464 464 465 error = xfs_qm_dqflush(dqp, &bp); 465 466 if (error)
+1 -1
include/linux/list_lru.h
··· 184 184 struct list_head *head); 185 185 186 186 typedef enum lru_status (*list_lru_walk_cb)(struct list_head *item, 187 - struct list_lru_one *list, spinlock_t *lock, void *cb_arg); 187 + struct list_lru_one *list, void *cb_arg); 188 188 189 189 /** 190 190 * list_lru_walk_one: walk a @lru, isolating and disposing freeable items.
+1 -1
mm/list_lru.c
··· 298 298 break; 299 299 --*nr_to_walk; 300 300 301 - ret = isolate(item, l, &l->lock, cb_arg); 301 + ret = isolate(item, l, cb_arg); 302 302 switch (ret) { 303 303 /* 304 304 * LRU_RETRY, LRU_REMOVED_RETRY and LRU_STOP will drop the lru
+7 -8
mm/workingset.c
··· 702 702 703 703 static enum lru_status shadow_lru_isolate(struct list_head *item, 704 704 struct list_lru_one *lru, 705 - spinlock_t *lru_lock, 706 - void *arg) __must_hold(lru_lock) 705 + void *arg) __must_hold(lru->lock) 707 706 { 708 707 struct xa_node *node = container_of(item, struct xa_node, private_list); 709 708 struct address_space *mapping; ··· 711 712 /* 712 713 * Page cache insertions and deletions synchronously maintain 713 714 * the shadow node LRU under the i_pages lock and the 714 - * lru_lock. Because the page cache tree is emptied before 715 - * the inode can be destroyed, holding the lru_lock pins any 715 + * &lru->lock. Because the page cache tree is emptied before 716 + * the inode can be destroyed, holding the &lru->lock pins any 716 717 * address_space that has nodes on the LRU. 717 718 * 718 719 * We can then safely transition to the i_pages lock to 719 720 * pin only the address_space of the particular node we want 720 - * to reclaim, take the node off-LRU, and drop the lru_lock. 721 + * to reclaim, take the node off-LRU, and drop the &lru->lock. 721 722 */ 722 723 723 724 mapping = container_of(node->array, struct address_space, i_pages); 724 725 725 726 /* Coming from the list, invert the lock order */ 726 727 if (!xa_trylock(&mapping->i_pages)) { 727 - spin_unlock_irq(lru_lock); 728 + spin_unlock_irq(&lru->lock); 728 729 ret = LRU_RETRY; 729 730 goto out; 730 731 } ··· 733 734 if (mapping->host != NULL) { 734 735 if (!spin_trylock(&mapping->host->i_lock)) { 735 736 xa_unlock(&mapping->i_pages); 736 - spin_unlock_irq(lru_lock); 737 + spin_unlock_irq(&lru->lock); 737 738 ret = LRU_RETRY; 738 739 goto out; 739 740 } ··· 742 743 list_lru_isolate(lru, item); 743 744 __dec_node_page_state(virt_to_page(node), WORKINGSET_NODES); 744 745 745 - spin_unlock(lru_lock); 746 + spin_unlock(&lru->lock); 746 747 747 748 /* 748 749 * The nodes should only contain one or more shadow entries,
+2 -2
mm/zswap.c
··· 1102 1102 * for reclaim by this ratio. 1103 1103 */ 1104 1104 static enum lru_status shrink_memcg_cb(struct list_head *item, struct list_lru_one *l, 1105 - spinlock_t *lock, void *arg) 1105 + void *arg) 1106 1106 { 1107 1107 struct zswap_entry *entry = container_of(item, struct zswap_entry, lru); 1108 1108 bool *encountered_page_in_swapcache = (bool *)arg; ··· 1158 1158 * It's safe to drop the lock here because we return either 1159 1159 * LRU_REMOVED_RETRY or LRU_RETRY. 1160 1160 */ 1161 - spin_unlock(lock); 1161 + spin_unlock(&l->lock); 1162 1162 1163 1163 writeback_result = zswap_writeback_entry(entry, swpentry); 1164 1164