Skip to content

[Deepin-Kernel-SIG] [linux 7.2.y] mm/list_lru: don't copy stale shrinker id from non-memcg-aware shrinkers - #2127

Merged
opsiff merged 1 commit into
deepin-community:linux-7.2.yfrom
opsiff:linux-7.2.y-2026-09-07-patch-2
Sep 7, 2026
Merged

[Deepin-Kernel-SIG] [linux 7.2.y] mm/list_lru: don't copy stale shrinker id from non-memcg-aware shrinkers#2127
opsiff merged 1 commit into
deepin-community:linux-7.2.yfrom
opsiff:linux-7.2.y-2026-09-07-patch-2

Conversation

@opsiff

@opsiff opsiff commented Sep 7, 2026

Copy link
Copy Markdown
Member

maillist inclusion
category: bugfix

With cgroup.memory=nokmem, shrinker_memcg_alloc() fails with -ENOSYS for shrinkers without SHRINKER_NONSLAB, and shrinker_alloc() falls back to a non-memcg-aware shrinker. On this fallback path, shrinker->id is never assigned and keeps 0 from kzalloc(), which is a valid id belonging to whichever memcg-aware shrinker registers first.

__list_lru_init() copies shrinker->id unconditionally, so every list_lru backed by such a fallback shrinker (thp-deferred_split, zswap-shrinker, workingset shadow nodes, superblock lrus, ...) ends up with lru->shrinker_id == 0 instead of -1.

Under nokmem the list_lru collapses to the shared per-node lists, but __list_lru_add() still calls set_shrinker_bit() against the memcg of the added object. Most list_lru users are unaffected because their objects resolve to a NULL memcg without kmem accounting, but the THP deferred split queue holds user folios, which are charged regardless of nokmem. Since no memcg-aware shrinker can register under nokmem, shrinker_nr_max stays 0 and every memcg's shrinker_info has map_nr_max == 0, so the first folio added by khugepaged triggers on every boot:

WARNING: mm/shrinker.c:212 at set_shrinker_bit+0x99/0xa0

On systems where a SHRINKER_NONSLAB shrinker (btrfs, xfs) did register and expand the maps, there is no warning; instead bit 0 is set spuriously for an unrelated shrinker.

shrinker->id is only meaningful while SHRINKER_MEMCG_AWARE is set, and all readers inside mm/shrinker.c already check the flag before using the id. Make __list_lru_init() do the same and fall back to -1, so set_shrinker_bit() is never reached with a bogus id. The stale shrinker->id itself is left as is; cleaning that up is a separate topic.

Fixes: 0337520 ("mm: do not allocate shrinker info with cgroup.memory=nokmem")

Summary by Sourcery

Bug Fixes:

  • Prevent list LRU instances from using an unassigned shrinker ID when shrinkers fall back to non-memcg-aware operation, avoiding invalid shrinker-bit updates and warnings with cgroup.memory=nokmem.

maillist inclusion
category: bugfix

With cgroup.memory=nokmem, shrinker_memcg_alloc() fails with -ENOSYS
for shrinkers without SHRINKER_NONSLAB, and shrinker_alloc() falls
back to a non-memcg-aware shrinker.  On this fallback path,
shrinker->id is never assigned and keeps 0 from kzalloc(), which is a
valid id belonging to whichever memcg-aware shrinker registers first.

__list_lru_init() copies shrinker->id unconditionally, so every
list_lru backed by such a fallback shrinker (thp-deferred_split,
zswap-shrinker, workingset shadow nodes, superblock lrus, ...) ends
up with lru->shrinker_id == 0 instead of -1.

Under nokmem the list_lru collapses to the shared per-node lists, but
__list_lru_add() still calls set_shrinker_bit() against the memcg of
the added object.  Most list_lru users are unaffected because their
objects resolve to a NULL memcg without kmem accounting, but the THP
deferred split queue holds user folios, which are charged regardless
of nokmem.  Since no memcg-aware shrinker can register under nokmem,
shrinker_nr_max stays 0 and every memcg's shrinker_info has
map_nr_max == 0, so the first folio added by khugepaged triggers on
every boot:

  WARNING: mm/shrinker.c:212 at set_shrinker_bit+0x99/0xa0

On systems where a SHRINKER_NONSLAB shrinker (btrfs, xfs) did register
and expand the maps, there is no warning; instead bit 0 is set
spuriously for an unrelated shrinker.

shrinker->id is only meaningful while SHRINKER_MEMCG_AWARE is set,
and all readers inside mm/shrinker.c already check the flag before
using the id.  Make __list_lru_init() do the same and fall back to -1,
so set_shrinker_bit() is never reached with a bogus id.  The stale
shrinker->id itself is left as is; cleaning that up is a separate
topic.

Fixes: 0337520 ("mm: do not allocate shrinker info with cgroup.memory=nokmem")
Signed-off-by: Qinyun Tan <qinyuntan@linux.alibaba.com>
Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
@sourcery-ai

sourcery-ai Bot commented Sep 7, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Fixes list_lru initialization so non-memcg-aware shrinkers do not propagate an unassigned shrinker ID, preventing warnings and spurious shrinker bits under cgroup.memory=nokmem.

Flow diagram for safe list_lru shrinker ID initialization

flowchart TD
    A["__list_lru_init()"] --> B{"shrinker exists and SHRINKER_MEMCG_AWARE is set?"}
    B -->|Yes| C["lru->shrinker_id = shrinker->id"]
    B -->|No| D["lru->shrinker_id = -1"]
    D --> E["__list_lru_add() avoids set_shrinker_bit() with stale ID"]
    C --> F["Use valid memcg-aware shrinker ID"]
Loading

File-Level Changes

Change Details Files
Guard list_lru shrinker ID propagation on memcg-awareness to prevent stale IDs from reaching shrinker bit updates.
  • Only copy shrinker->id when SHRINKER_MEMCG_AWARE is set.
  • Initialize non-memcg-aware or absent shrinker IDs to -1, including nokmem fallback paths.
  • Document the stale-ID scenario and its effect on set_shrinker_bit().
mm/list_lru.c

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from opsiff. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@opsiff
opsiff merged commit 3aad40c into deepin-community:linux-7.2.y Sep 7, 2026
8 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants