[Deepin-Kernel-SIG] [linux 6.6.y] [Upstream] mm/list_lru: Split list_lru lock into per-cgroup scope - #2026
Conversation
Reviewer's GuideMake zswap reclaim and list_lru fully memcg-aware, switching zswap pool LRU management from a manual list + spinlock to the generic list_lru infrastructure, updating memcg list_lru reparenting/allocation, and fixing a swap cache recursion hazard during zswap-triggered reclaim. Sequence diagram for memcg-aware zswap reclaim and swap cache recursion protectionsequenceDiagram
participant Task as task
participant ZS as zswap_store
participant SM as shrink_memcg
participant LL as list_lru_walk_one
participant CB as shrink_memcg_cb
participant WB as zswap_writeback_entry
participant SC as __read_swap_cache_async
Task->>ZS: zswap_store(folio)
ZS->>ZS: get_obj_cgroup_from_folio(folio)
ZS->>ZS: obj_cgroup_may_zswap(objcg)?
alt objcg not allowed
ZS->>ZS: get_mem_cgroup_from_objcg(objcg)
ZS->>SM: shrink_memcg(memcg)
SM->>SM: zswap_pool_current_get()
SM->>LL: list_lru_walk_one(pool->list_lru, nid, memcg, shrink_memcg_cb)
LL-->>CB: shrink_memcg_cb(item, lru_one, lock, arg)
CB->>WB: zswap_writeback_entry(entry, tree)
WB->>SC: __read_swap_cache_async(swpentry, GFP_KERNEL, mpol, NO_INTERLEAVE_INDEX, &page_was_allocated, true)
SC-->>WB: page or error
WB-->>CB: writeback_result
CB-->>LL: LRU_REMOVED_RETRY or LRU_RETRY
SM-->>ZS: ret (0 or error)
end
ZS-->>Task: store result / reject
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In the !CONFIG_MEMCG_KMEM path, the new list_lru_from_memcg() helper still takes an int parameter but is now called with a struct mem_cgroup * in list_lru_add/list_lru_del, which will cause unsafe pointer-to-int coercions; consider aligning the prototype and call sites to avoid type mismatches in non-memcg-kmem builds.
- The new shrink_memcg() path is invoked from zswap_store() when obj_cgroup_may_zswap() fails; it would be useful to double-check that this reclaim-on-store behavior cannot lead to unexpected reentrancy or long latencies in hot paths, e.g. by guarding against nested zswap reclaim calls or imposing tighter bounds on the reclaim work done synchronously.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the !CONFIG_MEMCG_KMEM path, the new list_lru_from_memcg() helper still takes an int parameter but is now called with a struct mem_cgroup * in list_lru_add/list_lru_del, which will cause unsafe pointer-to-int coercions; consider aligning the prototype and call sites to avoid type mismatches in non-memcg-kmem builds.
- The new shrink_memcg() path is invoked from zswap_store() when obj_cgroup_may_zswap() fails; it would be useful to double-check that this reclaim-on-store behavior cannot lead to unexpected reentrancy or long latencies in hot paths, e.g. by guarding against nested zswap reclaim calls or imposing tighter bounds on the reclaim work done synchronously.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
There was a problem hiding this comment.
Pull request overview
This PR backports mainline MM changes to make zswap’s reclaim and accounting memcg-aware by integrating zswap entries with the generic list_lru infrastructure, while also updating core list_lru memcg/reparenting logic and tightening swap-cache behavior to avoid recursion hazards.
Changes:
- Convert zswap’s per-pool LRU to
list_lruwith memcg-aware accounting and implement memcg round-robin reclaim. - Rework
list_lrumemcg integration/reparenting and update workingset shadow shrinker initialization to the newer shrinker/list_lru helpers. - Extend
__read_swap_cache_async()with a “skip if exists” mode to prevent recursive wait/lock scenarios during zswap-triggered reclaim.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| mm/zswap.c | Switches zswap LRU to list_lru, adds memcg-aware reclaim and memcg offline cleanup integration. |
| mm/workingset.c | Migrates workingset shadow shrinker init to dynamically allocated shrinker + new list_lru init helper. |
| mm/swap.h | Extends __read_swap_cache_async() signature to add skip_if_exists. |
| mm/swap_state.c | Implements the skip_if_exists behavior to avoid recursive wait/lock behavior. |
| mm/memcontrol.c | Hooks zswap memcg offline cleanup into memcg offline sequence. |
| mm/list_lru.c | Refactors list_lru memcg lookup/reparenting/allocation and lockdep plumbing. |
| include/linux/zswap.h | Exposes zswap memcg offline cleanup API. |
| include/linux/memcontrol.h | Provides get_mem_cgroup_from_objcg() (and stub when !MEMCG). |
| include/linux/list_lru.h | Adjusts list_lru init APIs and adds memcg+lockdep key helper. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| static inline struct list_lru_one * | ||
| list_lru_from_memcg(struct list_lru *lru, int nid, int idx) | ||
| { | ||
| return &lru->node[nid].lru; | ||
| } |
| if (writeback_result) { | ||
| zswap_reject_reclaim_fail++; | ||
| zswap_lru_putback(&entry->pool->list_lru, entry); | ||
| ret = LRU_RETRY; | ||
| goto put_unlock; |
| void zswap_invalidate(int type, pgoff_t offset); | ||
| void zswap_swapon(int type); | ||
| void zswap_swapoff(int type); | ||
| void zswap_memcg_offline_cleanup(struct mem_cgroup *memcg); |
ab5c512 to
fc0c4bf
Compare
mainline inclusion from mainline-v6.8-rc1 category: performance Currently, we only have a single global LRU for zswap. This makes it impossible to perform worload-specific shrinking - an memcg cannot determine which pages in the pool it owns, and often ends up writing pages from other memcgs. This issue has been previously observed in practice and mitigated by simply disabling memcg-initiated shrinking: https://lore.kernel.org/all/20230530232435.3097106-1-nphamcs@gmail.com/T/#u This patch fully resolves the issue by replacing the global zswap LRU with memcg- and NUMA-specific LRUs, and modify the reclaim logic: a) When a store attempt hits an memcg limit, it now triggers a synchronous reclaim attempt that, if successful, allows the new hotter page to be accepted by zswap. b) If the store attempt instead hits the global zswap limit, it will trigger an asynchronous reclaim attempt, in which an memcg is selected for reclaim in a round-robin-like fashion. [nphamcs@gmail.com: use correct function for the onlineness check, use mem_cgroup_iter_break()] Link: https://lkml.kernel.org/r/20231205195419.2563217-1-nphamcs@gmail.com [nphamcs@gmail.com: drop the pool's reference at the end of the writeback step] Link: https://lkml.kernel.org/r/20231206030627.4155634-1-nphamcs@gmail.com Link: https://lkml.kernel.org/r/20231130194023.4102148-4-nphamcs@gmail.com Signed-off-by: Domenico Cerasuolo <cerasuolodomenico@gmail.com> Co-developed-by: Nhat Pham <nphamcs@gmail.com> Signed-off-by: Nhat Pham <nphamcs@gmail.com> Tested-by: Bagas Sanjaya <bagasdotme@gmail.com> Cc: Chris Li <chrisl@kernel.org> Cc: Dan Streetman <ddstreet@ieee.org> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@kernel.org> Cc: Muchun Song <muchun.song@linux.dev> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Seth Jennings <sjenning@redhat.com> Cc: Shakeel Butt <shakeelb@google.com> Cc: Shuah Khan <shuah@kernel.org> Cc: Vitaly Wool <vitaly.wool@konsulko.com> Cc: Yosry Ahmed <yosryahmed@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Conflicts: mm/zswap.c [call to zswap_memcg_offline_cleanup() in mem_cgroup_css_offline(), but mm/memcontrol.c does not include linux/zswap.h where the function is declared, causing: mm/memcontrol.c:5654:9: error: implicit declaration of function 'zswap_memcg_offline_cleanup' [-Werror=implicit-function-declaration] Upstream gets the declaration transitively: include/linux/mmzone.h includes linux/zswap.h since commit b5ba474 ("zswap: shrink zswap pool based on memory pressure"), which is not (yet) backported to this branch. Add the include directly, matching what upstream achieves via mmzone.h.] (cherry picked from commit a65b0e7) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.7-rc1 category: performance Use new APIs to dynamically allocate the mm-shadow shrinker. Link: https://lkml.kernel.org/r/20230911094444.68966-20-zhengqi.arch@bytedance.com Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com> Acked-by: Muchun Song <songmuchun@bytedance.com> Cc: Abhinav Kumar <quic_abhinavk@quicinc.com> Cc: Alasdair Kergon <agk@redhat.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Cc: Andreas Dilger <adilger.kernel@dilger.ca> Cc: Andreas Gruenbacher <agruenba@redhat.com> Cc: Anna Schumaker <anna@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Bob Peterson <rpeterso@redhat.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Carlos Llamas <cmllamas@google.com> Cc: Chandan Babu R <chandan.babu@oracle.com> Cc: Chao Yu <chao@kernel.org> Cc: Chris Mason <clm@fb.com> Cc: Christian Brauner <brauner@kernel.org> Cc: Christian Koenig <christian.koenig@amd.com> Cc: Chuck Lever <cel@kernel.org> Cc: Coly Li <colyli@suse.de> Cc: Dai Ngo <Dai.Ngo@oracle.com> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: "Darrick J. Wong" <djwong@kernel.org> Cc: Dave Chinner <david@fromorbit.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: David Airlie <airlied@gmail.com> Cc: David Hildenbrand <david@redhat.com> Cc: David Sterba <dsterba@suse.com> Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Cc: Gao Xiang <hsiangkao@linux.alibaba.com> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Huang Rui <ray.huang@amd.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jaegeuk Kim <jaegeuk@kernel.org> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Jan Kara <jack@suse.cz> Cc: Jason Wang <jasowang@redhat.com> Cc: Jeff Layton <jlayton@kernel.org> Cc: Jeffle Xu <jefflexu@linux.alibaba.com> Cc: Joel Fernandes (Google) <joel@joelfernandes.org> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Josef Bacik <josef@toxicpanda.com> Cc: Juergen Gross <jgross@suse.com> Cc: Kent Overstreet <kent.overstreet@gmail.com> Cc: Kirill Tkhai <tkhai@ya.ru> Cc: Marijn Suijten <marijn.suijten@somainline.org> Cc: "Michael S. Tsirkin" <mst@redhat.com> Cc: Mike Snitzer <snitzer@kernel.org> Cc: Minchan Kim <minchan@kernel.org> Cc: Nadav Amit <namit@vmware.com> Cc: Neil Brown <neilb@suse.de> Cc: Oleksandr Tyshchenko <oleksandr_tyshchenko@epam.com> Cc: Olga Kornievskaia <kolga@netapp.com> Cc: Paul E. McKenney <paulmck@kernel.org> Cc: Richard Weinberger <richard@nod.at> Cc: Rob Clark <robdclark@gmail.com> Cc: Rob Herring <robh@kernel.org> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Sean Paul <sean@poorly.run> Cc: Sergey Senozhatsky <senozhatsky@chromium.org> Cc: Song Liu <song@kernel.org> Cc: Stefano Stabellini <sstabellini@kernel.org> Cc: Steven Price <steven.price@arm.com> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Tomeu Vizoso <tomeu.vizoso@collabora.com> Cc: Tom Talpey <tom@talpey.com> Cc: Trond Myklebust <trond.myklebust@hammerspace.com> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: Xuan Zhuo <xuanzhuo@linux.alibaba.com> Cc: Yue Hu <huyue2@coolpad.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit 219c666) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.9-rc1 category: performance commit a02b8bf upstream. list_lru_init_key() isn't used by anyone, remove it to clean up. Link: https://lkml.kernel.org/r/20231228062715.338672-2-haifeng.xu@shopee.com Signed-off-by: Haifeng Xu <haifeng.xu@shopee.com> Acked-by: Roman Gushchin <roman.gushchin@linux.dev> Cc: Johannes Weiner <hannes@cmpxchg.org> Cc: Michal Hocko <mhocko@kernel.org> Cc: Shakeel Butt <shakeelb@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.13-rc1 category: performance commit 3f28bbe upstream. Patch series "mm/list_lru: Split list_lru lock into per-cgroup scope". When LOCKDEP is not enabled, lock_class_key is an empty struct that is never used. But the list_lru initialization function still takes a placeholder pointer as parameter, and the compiler cannot optimize it because the function is not static and exported. Remove this parameter and move it inside the list_lru struct. Only use it when LOCKDEP is enabled. Kernel builds with LOCKDEP will be slightly larger, while !LOCKDEP builds without it will be slightly smaller (the common case). Link: https://lkml.kernel.org/r/20241104175257.60853-1-ryncsn@gmail.com Link: https://lkml.kernel.org/r/20241104175257.60853-2-ryncsn@gmail.com Signed-off-by: Kairui Song <kasong@tencent.com> Acked-by: Shakeel Butt <shakeel.butt@linux.dev> 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: Waiman Long <longman@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.13-rc1 category: performance commit 78c0ed0 upstream. It's no longer used by any module, just remove it. Link: https://lkml.kernel.org/r/20241104175257.60853-3-ryncsn@gmail.com Signed-off-by: Kairui Song <kasong@tencent.com> Reviewed-by: Muchun Song <muchun.song@linux.dev> Acked-by: Shakeel Butt <shakeel.butt@linux.dev> 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: Qi Zheng <zhengqi.arch@bytedance.com> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Waiman Long <longman@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.13-rc1 category: performance commit 8d42abb upstream. No feature change, just change of code structure and fix comment. The list lrus are not empty until memcg_reparent_list_lru_node() calls are all done, so the comments in memcg_offline_kmem were slightly inaccurate. Link: https://lkml.kernel.org/r/20241104175257.60853-4-ryncsn@gmail.com Signed-off-by: Kairui Song <kasong@tencent.com> Reviewed-by: Muchun Song <muchun.song@linux.dev> Acked-by: Shakeel Butt <shakeel.butt@linux.dev> 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: Qi Zheng <zhengqi.arch@bytedance.com> Cc: Roman Gushchin <roman.gushchin@linux.dev> Cc: Waiman Long <longman@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.13-rc1 category: performance commit 28e9802 upstream. Currently, there is a lot of code for detecting reparent racing using kmemcg_id as the synchronization flag. And an intermediate table is required to record and compare the kmemcg_id. We can simplify this by just checking the cgroup css status, skip if cgroup is being offlined. On the reparenting side, ensure no more allocation is on going and no further allocation will occur by using the XArray lock as barrier. Combined with a O(n^2) top-down walk for the allocation, we get rid of the intermediate table allocation completely. Despite being O(n^2), it should be actually faster because it's not practical to have a very deep cgroup level, and in most cases the parent cgroup should have been allocated already. This also avoided changing kmemcg_id before reparenting, making cgroups have a stable index for list_lru_memcg. After this change it's possible that a dying cgroup will see a NULL value in XArray corresponding to the kmemcg_id, because the kmemcg_id will point to an empty slot. In such case, just fallback to use its parent. As a result the code is simpler, following test also showed a very slight performance gain (12 test runs): prepare() { mkdir /tmp/test-fs modprobe brd rd_nr=1 rd_size=16777216 mkfs.xfs -f /dev/ram0 mount -t xfs /dev/ram0 /tmp/test-fs for i in $(seq 10000); do seq 8000 > "/tmp/test-fs/$i" done mkdir -p /sys/fs/cgroup/system.slice/bench/test/1 echo +memory > /sys/fs/cgroup/system.slice/bench/cgroup.subtree_control echo +memory > /sys/fs/cgroup/system.slice/bench/test/cgroup.subtree_control echo +memory > /sys/fs/cgroup/system.slice/bench/test/1/cgroup.subtree_control echo 768M > /sys/fs/cgroup/system.slice/bench/memory.max } do_test() { read_worker() { mkdir -p "/sys/fs/cgroup/system.slice/bench/test/1/$1" echo $BASHPID > "/sys/fs/cgroup/system.slice/bench/test/1/$1/cgroup.procs" read -r __TMP < "/tmp/test-fs/$1"; } read_in_all() { for i in $(seq 10000); do read_worker "$i" & done; wait } echo 3 > /proc/sys/vm/drop_caches time read_in_all for i in $(seq 1 10000); do rmdir "/sys/fs/cgroup/system.slice/bench/test/1/$i" &>/dev/null done } Before: real 0m3.498s user 0m11.037s sys 0m35.872s real 1m33.860s user 0m11.593s sys 3m1.169s real 1m31.883s user 0m11.265s sys 2m59.198s real 1m32.394s user 0m11.294s sys 3m1.616s real 1m31.017s user 0m11.379s sys 3m1.349s real 1m31.931s user 0m11.295s sys 2m59.863s real 1m32.758s user 0m11.254s sys 2m59.538s real 1m35.198s user 0m11.145s sys 3m1.123s real 1m30.531s user 0m11.393s sys 2m58.089s real 1m31.142s user 0m11.333s sys 3m0.549s After: real 0m3.489s user 0m10.943s sys 0m36.036s real 1m10.893s user 0m11.495s sys 2m38.545s real 1m29.129s user 0m11.382s sys 3m1.601s real 1m29.944s user 0m11.494s sys 3m1.575s real 1m31.208s user 0m11.451s sys 2m59.693s real 1m25.944s user 0m11.327s sys 2m56.394s real 1m28.599s user 0m11.312s sys 3m0.162s real 1m26.746s user 0m11.538s sys 2m55.462s real 1m30.668s user 0m11.475s sys 3m2.075s real 1m29.258s user 0m11.292s sys 3m0.780s Which is slightly faster in real time. Link: https://lkml.kernel.org/r/20241104175257.60853-5-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> Conflicts: mm/list_lru.c mm/zswap.c [mm/list_lru: fix !CONFIG_MEMCG_KMEM build for list_lru_from_memcg() Commit 2e60fe3 ("mm/list_lru: simplify reparenting and initial allocation") added a !CONFIG_MEMCG fallback stub: list_lru_from_memcg(struct list_lru *lru, int nid, int idx) but all callers pass a struct mem_cgroup pointer. With CONFIG_MEMCG_KMEM disabled this fails to build: mm/list_lru.c:117:51: error: passing argument 3 of 'list_lru_from_memcg' makes integer from pointer without a cast [-Werror=int-conversion] Make the stub take struct mem_cgroup * like its CONFIG_MEMCG_KMEM counterpart, so both variants share one signature. Same end state as upstream commit fb56fdf ("mm/list_lru: split the lock to per-cgroup scope"), which incidentally resolved the same mismatch.] Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
mainline inclusion from mainline-v6.8-rc4 category: bugfix In the per-memcg LRU universe, LRU removal uses entry->objcg to determine which list count needs to be decreased. Drop the objcg reference after updating the LRU, to fix a possible use-after-free. Link: https://lkml.kernel.org/r/20240130013438.565167-1-hannes@cmpxchg.org Fixes: a65b0e7 ("zswap: make shrinking memcg-aware") Signed-off-by: Johannes Weiner <hannes@cmpxchg.org> Acked-by: Yosry Ahmed <yosryahmed@google.com> Reviewed-by: Nhat Pham <nphamcs@gmail.com> Reviewed-by: Chengming Zhou <zhouchengming@bytedance.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit 2e601e1) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
fc0c4bf to
b52c223
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
include/linux/zswap.h:18
- include/linux/zswap.h now declares zswap_memcg_offline_cleanup(struct mem_cgroup *), but this header doesn’t declare/forward-declare struct mem_cgroup or include <linux/memcontrol.h>. This breaks compilation for includers like fs/proc/meminfo.c and mm/page_io.c that include <linux/zswap.h> without pulling in memcontrol definitions (unknown type name ‘struct mem_cgroup’). Add a forward declaration to keep the header self-contained.
void zswap_memcg_offline_cleanup(struct mem_cgroup *memcg);
mm/zswap.c:394
- zswap_lru_putback() calls list_lru_putback() after dropping the list_lru walk lock. However, list_lru_putback() currently uses list_lru_from_memcg_idx() and does not fall back to a parent memcg when the per-memcg list has been erased during memcg offlining/reparenting (xa_load can return NULL). That can race with memcg offline (memcg_reparent_list_lrus() erases the xarray entry), leading to a NULL dereference when trying to put an isolated entry back. Consider updating list_lru_putback() (mm/list_lru.c) to use the new list_lru_from_memcg() helper (parent fallback) or otherwise guarantee a non-NULL list during offlining.
rcu_read_lock();
memcg = mem_cgroup_from_entry(entry);
spin_lock(lock);
/* we cannot use list_lru_add here, because it increments node's lru count */
list_lru_putback(list_lru, &entry->lru, nid, memcg);
Commits(8):
mm: zswap: fix objcg use-after-free in entry destruction
mm/list_lru: simplify reparenting and initial allocation
mm/list_lru: code clean up for reparenting
mm/list_lru: don't export list_lru_add
mm/list_lru: don't pass unnecessary key parameters
mm: list_lru: remove unused macro list_lru_init_key()
mm: workingset: dynamically allocate the mm-shadow shrinker
zswap: make shrinking memcg-aware
Link: https://lore.kernel.org/all/20241104175257.60853-1-ryncsn@gmail.com/T/#u
From: Kairui Song kasong@tencent.com
Currently, every list_lru has a per-node lock that protects adding,
deletion, isolation, and reparenting of all list_lru_one instances
belonging to this list_lru on this node. This lock contention is heavy
when multiple cgroups modify the same list_lru.
This can be alleviated by splitting the lock into per-cgroup scope.
To achieve this, this series reworked and optimized the reparenting
process step by step, making it possible to have a stable list_lru_one,
and making it possible to pin the list_lru_one. Then split the lock
into per-cgroup scope.
The result is ~15% performance gain for simple multi-cgroup tar test
of small files, and reduced LOC. See PATCH 5/6 for test details.
V2: https://lore.kernel.org/linux-mm/20240925171020.32142-1-ryncsn@gmail.com/
Updates from V2:
[Dan Carpenter, Naresh Kamboju]
https://lore.kernel.org/linux-mm/62a65418-2393-40ec-b462-151605a5efcf@stanley.mountain/
[Applied to "mm/list_lru: split the lock to per-cgroup scope"]
https://lore.kernel.org/linux-mm/CAMgjq7D_OA=vYf5SnNnKXjppPFhDqsbYF--6=cOayKiadxuwrQ@mail.gmail.com/
V1: https://lore.kernel.org/linux-mm/20240624175313.47329-1-ryncsn@gmail.com/
Updates from V1:
Song]
Kairui Song (6):
mm/list_lru: don't pass unnecessary key parameters
mm/list_lru: don't export list_lru_add
mm/list_lru: code clean up for reparenting
mm/list_lru: simplify reparenting and initial allocation
mm/list_lru: split the lock to per-cgroup scope
mm/list_lru: simplify the list_lru walk callback function
drivers/android/binder_alloc.c | 8 +-
drivers/android/binder_alloc.h | 2 +-
fs/dcache.c | 4 +-
fs/gfs2/quota.c | 2 +-
fs/inode.c | 5 +-
fs/nfs/nfs42xattr.c | 4 +-
fs/nfsd/filecache.c | 5 +-
fs/xfs/xfs_buf.c | 2 -
fs/xfs/xfs_qm.c | 6 +-
include/linux/list_lru.h | 26 ++-
mm/list_lru.c | 383 ++++++++++++++++-----------------
mm/memcontrol.c | 10 +-
mm/workingset.c | 20 +-
mm/zswap.c | 12 +-
14 files changed, 241 insertions(+), 248 deletions(-)
--
2.47.0
Summary by Sourcery
Integrate memcg-aware list_lru support into zswap and core MM infrastructure to enable cgroup-aware zswap reclaim and robust handling of memcg offlining and swap cache recursion.
New Features:
Bug Fixes:
Enhancements: