1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2a38e4082SDave Chinner /* 3a38e4082SDave Chinner * Copyright (c) 2013 Red Hat, Inc. and Parallels Inc. All rights reserved. 4a38e4082SDave Chinner * Authors: David Chinner and Glauber Costa 5a38e4082SDave Chinner * 6a38e4082SDave Chinner * Generic LRU infrastructure 7a38e4082SDave Chinner */ 8a38e4082SDave Chinner #ifndef _LRU_LIST_H 9a38e4082SDave Chinner #define _LRU_LIST_H 10a38e4082SDave Chinner 11a38e4082SDave Chinner #include <linux/list.h> 123b1d58a4SDave Chinner #include <linux/nodemask.h> 13503c358cSVladimir Davydov #include <linux/shrinker.h> 14bbca91ccSMuchun Song #include <linux/xarray.h> 15a38e4082SDave Chinner 1660d3fd32SVladimir Davydov struct mem_cgroup; 1760d3fd32SVladimir Davydov 18a38e4082SDave Chinner /* list_lru_walk_cb has to always return one of those */ 19a38e4082SDave Chinner enum lru_status { 20a38e4082SDave Chinner LRU_REMOVED, /* item removed from list */ 21449dd698SJohannes Weiner LRU_REMOVED_RETRY, /* item removed, but lock has been 22449dd698SJohannes Weiner dropped and reacquired */ 23a38e4082SDave Chinner LRU_ROTATE, /* item referenced, give another pass */ 24a38e4082SDave Chinner LRU_SKIP, /* item cannot be locked, skip */ 25a38e4082SDave Chinner LRU_RETRY, /* item not freeable. May drop the lock 26a38e4082SDave Chinner internally, but has to return locked. */ 27b49547adSChengming Zhou LRU_STOP, /* stop lru list walking. May drop the lock 28b49547adSChengming Zhou internally, but has to return locked. */ 29a38e4082SDave Chinner }; 30a38e4082SDave Chinner 3160d3fd32SVladimir Davydov struct list_lru_one { 32a38e4082SDave Chinner struct list_head list; 332788cf0cSVladimir Davydov /* may become negative during memcg reparenting */ 34a38e4082SDave Chinner long nr_items; 35*fb56fdf8SKairui Song /* protects all fields above */ 36*fb56fdf8SKairui Song spinlock_t lock; 3760d3fd32SVladimir Davydov }; 3860d3fd32SVladimir Davydov 39d7011070SMuchun Song struct list_lru_memcg { 405abc1e37SMuchun Song struct rcu_head rcu; 416a6b7b77SMuchun Song /* array of per cgroup per node lists, indexed by node id */ 425abc1e37SMuchun Song struct list_lru_one node[]; 436a6b7b77SMuchun Song }; 446a6b7b77SMuchun Song 4560d3fd32SVladimir Davydov struct list_lru_node { 4660d3fd32SVladimir Davydov /* global list, used for the root cgroup in cgroup aware lrus */ 4760d3fd32SVladimir Davydov struct list_lru_one lru; 48*fb56fdf8SKairui Song atomic_long_t nr_items; 493b1d58a4SDave Chinner } ____cacheline_aligned_in_smp; 503b1d58a4SDave Chinner 513b1d58a4SDave Chinner struct list_lru { 525ca302c8SGlauber Costa struct list_lru_node *node; 533a3b7fecSJohannes Weiner #ifdef CONFIG_MEMCG 54c0a5b560SVladimir Davydov struct list_head list; 55c92e8e10SKirill Tkhai int shrinker_id; 563e858996SJiri Slaby bool memcg_aware; 57bbca91ccSMuchun Song struct xarray xa; 58c0a5b560SVladimir Davydov #endif 593f28bbe5SKairui Song #ifdef CONFIG_LOCKDEP 603f28bbe5SKairui Song struct lock_class_key *key; 613f28bbe5SKairui Song #endif 62a38e4082SDave Chinner }; 63a38e4082SDave Chinner 645ca302c8SGlauber Costa void list_lru_destroy(struct list_lru *lru); 6560d3fd32SVladimir Davydov int __list_lru_init(struct list_lru *lru, bool memcg_aware, 663f28bbe5SKairui Song struct shrinker *shrinker); 6760d3fd32SVladimir Davydov 68c92e8e10SKirill Tkhai #define list_lru_init(lru) \ 693f28bbe5SKairui Song __list_lru_init((lru), false, NULL) 70c92e8e10SKirill Tkhai #define list_lru_init_memcg(lru, shrinker) \ 713f28bbe5SKairui Song __list_lru_init((lru), true, shrinker) 723f28bbe5SKairui Song 733f28bbe5SKairui Song static inline int list_lru_init_memcg_key(struct list_lru *lru, struct shrinker *shrinker, 743f28bbe5SKairui Song struct lock_class_key *key) 753f28bbe5SKairui Song { 763f28bbe5SKairui Song #ifdef CONFIG_LOCKDEP 773f28bbe5SKairui Song lru->key = key; 783f28bbe5SKairui Song #endif 793f28bbe5SKairui Song return list_lru_init_memcg(lru, shrinker); 803f28bbe5SKairui Song } 8160d3fd32SVladimir Davydov 8288f2ef73SMuchun Song int memcg_list_lru_alloc(struct mem_cgroup *memcg, struct list_lru *lru, 8388f2ef73SMuchun Song gfp_t gfp); 841f391eb2SMuchun Song void memcg_reparent_list_lrus(struct mem_cgroup *memcg, struct mem_cgroup *parent); 85a38e4082SDave Chinner 86a38e4082SDave Chinner /** 87a38e4082SDave Chinner * list_lru_add: add an element to the lru list's tail 887679e140SAndy Shevchenko * @lru: the lru pointer 89a38e4082SDave Chinner * @item: the item to be added. 900a97c01cSNhat Pham * @nid: the node id of the sublist to add the item to. 910a97c01cSNhat Pham * @memcg: the cgroup of the sublist to add the item to. 92a38e4082SDave Chinner * 93a38e4082SDave Chinner * If the element is already part of a list, this function returns doing 94a38e4082SDave Chinner * nothing. Therefore the caller does not need to keep state about whether or 95a38e4082SDave Chinner * not the element already belongs in the list and is allowed to lazy update 96a38e4082SDave Chinner * it. Note however that this is valid for *a* list, not *this* list. If 97a38e4082SDave Chinner * the caller organize itself in a way that elements can be in more than 98a38e4082SDave Chinner * one type of list, it is up to the caller to fully remove the item from 99a38e4082SDave Chinner * the previous list (with list_lru_del() for instance) before moving it 1007679e140SAndy Shevchenko * to @lru. 101a38e4082SDave Chinner * 1027679e140SAndy Shevchenko * Return: true if the list was updated, false otherwise 103a38e4082SDave Chinner */ 1040a97c01cSNhat Pham bool list_lru_add(struct list_lru *lru, struct list_head *item, int nid, 1050a97c01cSNhat Pham struct mem_cgroup *memcg); 106a38e4082SDave Chinner 107a38e4082SDave Chinner /** 1080a97c01cSNhat Pham * list_lru_add_obj: add an element to the lru list's tail 1090a97c01cSNhat Pham * @lru: the lru pointer 1100a97c01cSNhat Pham * @item: the item to be added. 1110a97c01cSNhat Pham * 1120a97c01cSNhat Pham * This function is similar to list_lru_add(), but the NUMA node and the 1130a97c01cSNhat Pham * memcg of the sublist is determined by @item list_head. This assumption is 1140a97c01cSNhat Pham * valid for slab objects LRU such as dentries, inodes, etc. 1150a97c01cSNhat Pham * 1160a97c01cSNhat Pham * Return value: true if the list was updated, false otherwise 1170a97c01cSNhat Pham */ 1180a97c01cSNhat Pham bool list_lru_add_obj(struct list_lru *lru, struct list_head *item); 1190a97c01cSNhat Pham 1200a97c01cSNhat Pham /** 1210a97c01cSNhat Pham * list_lru_del: delete an element from the lru list 1227679e140SAndy Shevchenko * @lru: the lru pointer 123a38e4082SDave Chinner * @item: the item to be deleted. 1240a97c01cSNhat Pham * @nid: the node id of the sublist to delete the item from. 1250a97c01cSNhat Pham * @memcg: the cgroup of the sublist to delete the item from. 126a38e4082SDave Chinner * 1277679e140SAndy Shevchenko * This function works analogously as list_lru_add() in terms of list 128a38e4082SDave Chinner * manipulation. The comments about an element already pertaining to 1297679e140SAndy Shevchenko * a list are also valid for list_lru_del(). 130a38e4082SDave Chinner * 1317679e140SAndy Shevchenko * Return: true if the list was updated, false otherwise 132a38e4082SDave Chinner */ 1330a97c01cSNhat Pham bool list_lru_del(struct list_lru *lru, struct list_head *item, int nid, 1340a97c01cSNhat Pham struct mem_cgroup *memcg); 1350a97c01cSNhat Pham 1360a97c01cSNhat Pham /** 1370a97c01cSNhat Pham * list_lru_del_obj: delete an element from the lru list 1380a97c01cSNhat Pham * @lru: the lru pointer 1390a97c01cSNhat Pham * @item: the item to be deleted. 1400a97c01cSNhat Pham * 1410a97c01cSNhat Pham * This function is similar to list_lru_del(), but the NUMA node and the 1420a97c01cSNhat Pham * memcg of the sublist is determined by @item list_head. This assumption is 1430a97c01cSNhat Pham * valid for slab objects LRU such as dentries, inodes, etc. 1440a97c01cSNhat Pham * 1450a97c01cSNhat Pham * Return value: true if the list was updated, false otherwise. 1460a97c01cSNhat Pham */ 1470a97c01cSNhat Pham bool list_lru_del_obj(struct list_lru *lru, struct list_head *item); 148a38e4082SDave Chinner 149a38e4082SDave Chinner /** 15060d3fd32SVladimir Davydov * list_lru_count_one: return the number of objects currently held by @lru 151a38e4082SDave Chinner * @lru: the lru pointer. 1526a4f496fSGlauber Costa * @nid: the node id to count from. 15360d3fd32SVladimir Davydov * @memcg: the cgroup to count from. 154a38e4082SDave Chinner * 1557679e140SAndy Shevchenko * There is no guarantee that the list is not updated while the count is being 1567679e140SAndy Shevchenko * computed. Callers that want such a guarantee need to provide an outer lock. 1577679e140SAndy Shevchenko * 1587679e140SAndy Shevchenko * Return: 0 for empty lists, otherwise the number of objects 1597679e140SAndy Shevchenko * currently held by @lru. 160a38e4082SDave Chinner */ 16160d3fd32SVladimir Davydov unsigned long list_lru_count_one(struct list_lru *lru, 16260d3fd32SVladimir Davydov int nid, struct mem_cgroup *memcg); 1636a4f496fSGlauber Costa unsigned long list_lru_count_node(struct list_lru *lru, int nid); 164503c358cSVladimir Davydov 165503c358cSVladimir Davydov static inline unsigned long list_lru_shrink_count(struct list_lru *lru, 166503c358cSVladimir Davydov struct shrink_control *sc) 167503c358cSVladimir Davydov { 16860d3fd32SVladimir Davydov return list_lru_count_one(lru, sc->nid, sc->memcg); 169503c358cSVladimir Davydov } 170503c358cSVladimir Davydov 1716a4f496fSGlauber Costa static inline unsigned long list_lru_count(struct list_lru *lru) 1726a4f496fSGlauber Costa { 1736a4f496fSGlauber Costa long count = 0; 1746a4f496fSGlauber Costa int nid; 1756a4f496fSGlauber Costa 176ff0b67efSVladimir Davydov for_each_node_state(nid, N_NORMAL_MEMORY) 1776a4f496fSGlauber Costa count += list_lru_count_node(lru, nid); 1786a4f496fSGlauber Costa 1796a4f496fSGlauber Costa return count; 1806a4f496fSGlauber Costa } 181a38e4082SDave Chinner 1823f97b163SVladimir Davydov void list_lru_isolate(struct list_lru_one *list, struct list_head *item); 1833f97b163SVladimir Davydov void list_lru_isolate_move(struct list_lru_one *list, struct list_head *item, 1843f97b163SVladimir Davydov struct list_head *head); 1853f97b163SVladimir Davydov 1863f97b163SVladimir Davydov typedef enum lru_status (*list_lru_walk_cb)(struct list_head *item, 1873f97b163SVladimir Davydov struct list_lru_one *list, spinlock_t *lock, void *cb_arg); 1883f97b163SVladimir Davydov 189a38e4082SDave Chinner /** 1907679e140SAndy Shevchenko * list_lru_walk_one: walk a @lru, isolating and disposing freeable items. 191a38e4082SDave Chinner * @lru: the lru pointer. 1926a4f496fSGlauber Costa * @nid: the node id to scan from. 19360d3fd32SVladimir Davydov * @memcg: the cgroup to scan from. 19406c88398SZhen Lei * @isolate: callback function that is responsible for deciding what to do with 195a38e4082SDave Chinner * the item currently being scanned 196a38e4082SDave Chinner * @cb_arg: opaque type that will be passed to @isolate 197a38e4082SDave Chinner * @nr_to_walk: how many items to scan. 198a38e4082SDave Chinner * 1997679e140SAndy Shevchenko * This function will scan all elements in a particular @lru, calling the 200a38e4082SDave Chinner * @isolate callback for each of those items, along with the current list 201a38e4082SDave Chinner * spinlock and a caller-provided opaque. The @isolate callback can choose to 202a38e4082SDave Chinner * drop the lock internally, but *must* return with the lock held. The callback 2037679e140SAndy Shevchenko * will return an enum lru_status telling the @lru infrastructure what to 204a38e4082SDave Chinner * do with the object being scanned. 205a38e4082SDave Chinner * 2067679e140SAndy Shevchenko * Please note that @nr_to_walk does not mean how many objects will be freed, 207a38e4082SDave Chinner * just how many objects will be scanned. 208a38e4082SDave Chinner * 2097679e140SAndy Shevchenko * Return: the number of objects effectively removed from the LRU. 210a38e4082SDave Chinner */ 21160d3fd32SVladimir Davydov unsigned long list_lru_walk_one(struct list_lru *lru, 21260d3fd32SVladimir Davydov int nid, struct mem_cgroup *memcg, 21360d3fd32SVladimir Davydov list_lru_walk_cb isolate, void *cb_arg, 21460d3fd32SVladimir Davydov unsigned long *nr_to_walk); 2156b51e881SSebastian Andrzej Siewior /** 2167679e140SAndy Shevchenko * list_lru_walk_one_irq: walk a @lru, isolating and disposing freeable items. 2176b51e881SSebastian Andrzej Siewior * @lru: the lru pointer. 2186b51e881SSebastian Andrzej Siewior * @nid: the node id to scan from. 2196b51e881SSebastian Andrzej Siewior * @memcg: the cgroup to scan from. 22006c88398SZhen Lei * @isolate: callback function that is responsible for deciding what to do with 2216b51e881SSebastian Andrzej Siewior * the item currently being scanned 2226b51e881SSebastian Andrzej Siewior * @cb_arg: opaque type that will be passed to @isolate 2236b51e881SSebastian Andrzej Siewior * @nr_to_walk: how many items to scan. 2246b51e881SSebastian Andrzej Siewior * 2257679e140SAndy Shevchenko * Same as list_lru_walk_one() except that the spinlock is acquired with 2266b51e881SSebastian Andrzej Siewior * spin_lock_irq(). 2276b51e881SSebastian Andrzej Siewior */ 2286b51e881SSebastian Andrzej Siewior unsigned long list_lru_walk_one_irq(struct list_lru *lru, 2296b51e881SSebastian Andrzej Siewior int nid, struct mem_cgroup *memcg, 2306b51e881SSebastian Andrzej Siewior list_lru_walk_cb isolate, void *cb_arg, 2316b51e881SSebastian Andrzej Siewior unsigned long *nr_to_walk); 2326a4f496fSGlauber Costa unsigned long list_lru_walk_node(struct list_lru *lru, int nid, 2336a4f496fSGlauber Costa list_lru_walk_cb isolate, void *cb_arg, 2346a4f496fSGlauber Costa unsigned long *nr_to_walk); 2356a4f496fSGlauber Costa 2366a4f496fSGlauber Costa static inline unsigned long 237503c358cSVladimir Davydov list_lru_shrink_walk(struct list_lru *lru, struct shrink_control *sc, 238503c358cSVladimir Davydov list_lru_walk_cb isolate, void *cb_arg) 239503c358cSVladimir Davydov { 24060d3fd32SVladimir Davydov return list_lru_walk_one(lru, sc->nid, sc->memcg, isolate, cb_arg, 241503c358cSVladimir Davydov &sc->nr_to_scan); 242503c358cSVladimir Davydov } 243503c358cSVladimir Davydov 244503c358cSVladimir Davydov static inline unsigned long 2456b51e881SSebastian Andrzej Siewior list_lru_shrink_walk_irq(struct list_lru *lru, struct shrink_control *sc, 2466b51e881SSebastian Andrzej Siewior list_lru_walk_cb isolate, void *cb_arg) 2476b51e881SSebastian Andrzej Siewior { 2486b51e881SSebastian Andrzej Siewior return list_lru_walk_one_irq(lru, sc->nid, sc->memcg, isolate, cb_arg, 2496b51e881SSebastian Andrzej Siewior &sc->nr_to_scan); 2506b51e881SSebastian Andrzej Siewior } 2516b51e881SSebastian Andrzej Siewior 2526b51e881SSebastian Andrzej Siewior static inline unsigned long 2536a4f496fSGlauber Costa list_lru_walk(struct list_lru *lru, list_lru_walk_cb isolate, 2546a4f496fSGlauber Costa void *cb_arg, unsigned long nr_to_walk) 2556a4f496fSGlauber Costa { 2566a4f496fSGlauber Costa long isolated = 0; 2576a4f496fSGlauber Costa int nid; 2586a4f496fSGlauber Costa 259ff0b67efSVladimir Davydov for_each_node_state(nid, N_NORMAL_MEMORY) { 2606a4f496fSGlauber Costa isolated += list_lru_walk_node(lru, nid, isolate, 2616a4f496fSGlauber Costa cb_arg, &nr_to_walk); 2626a4f496fSGlauber Costa if (nr_to_walk <= 0) 2636a4f496fSGlauber Costa break; 2646a4f496fSGlauber Costa } 2656a4f496fSGlauber Costa return isolated; 2666a4f496fSGlauber Costa } 267a38e4082SDave Chinner #endif /* _LRU_LIST_H */ 268