diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index ea37a4342334..3283f5db1217 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -367,6 +367,11 @@ enum objext_flags { static inline bool folio_memcg_kmem(struct folio *folio); +void do_traversal_all_lruvec(int (*callback)(struct mem_cgroup *memcg, + struct lruvec *lruvec, + void *private), + void *private); + /* * After the initialization objcg->memcg is always pointing at * a valid memcg, but can be atomically swapped to the parent memcg. diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 43ca0b458eb9..ddaba40255bb 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1271,6 +1271,34 @@ struct lruvec *folio_lruvec_lock_irqsave(struct folio *folio, return lruvec; } +void do_traversal_all_lruvec(int (*callback)(struct mem_cgroup *memcg, + struct lruvec *lruvec, + void *private), + void *private) +{ + pg_data_t *pgdat; + int ret; + + for_each_online_pgdat(pgdat) { + struct mem_cgroup *memcg = NULL; + + memcg = mem_cgroup_iter(NULL, NULL, NULL); + do { + struct lruvec *lruvec = mem_cgroup_lruvec(memcg, pgdat); + + ret = callback(memcg, lruvec, private); + if (ret) { + mem_cgroup_iter_break(NULL, memcg); + break; + } + + memcg = mem_cgroup_iter(NULL, memcg, NULL); + } while (memcg); + } +} +EXPORT_SYMBOL_GPL(do_traversal_all_lruvec); + + /** * mem_cgroup_update_lru_size - account for adding or removing an lru page * @lruvec: mem_cgroup per zone lru vector