mm/shrinker: do not hold RCU lock in shrinker_debugfs_count_show()
Subsystems (2)
PATCH 1/1 mm/shrinker: do not hold RCU lock in shrinker_debugfs_count_show()
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show() invokes the ->count_objects() callback under rcu_read_lock(). The zswap callback flushes memcg stats via css_rstat_flush(), which may sleep, so it must not run under RCU.
The RCU lock is not needed here. mem_cgroup_iter() takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or by mem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free() removes the debugfs entries via debugfs_remove_recursive(), which waits for in-flight readers to drain, before call_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.
Drop the rcu_read_lock()/rcu_read_unlock().
--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)
mm/shrinker_debug.c +0 -4
@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)if (!count_per_node)return -ENOMEM ; -rcu_read_lock (); - memcg_aware = shrinker->flags &SHRINKER_MEMCG_AWARE ; memcg =mem_cgroup_iter (NULL ,NULL ,NULL );
@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v) } }while ((memcg =mem_cgroup_iter (NULL , memcg,NULL )) !=NULL ); -rcu_read_unlock (); -kfree (count_per_node);return ret; }
Signature · 1 line
2.53.0-Meta
Quoted 24 lines · On Wed, 10 Jun 2026 16:20:48 -0700 Shakeel Butt <[email protected]> wrote:
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.
Quoted 1 line
Drop the rcu_read_lock()/rcu_read_unlock().
All make sense to me, thank you for the nice description and the fix!
Quoted 6 lines
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>
Thanks,
SJ
[...]
Quoted 26 lines · On Wed, 10 Jun 2026 17:22:51 -0700 SeongJae Park <[email protected]> wrote:
Quoted 24 lines · On Wed, 10 Jun 2026 16:20:48 -0700 Shakeel Butt <[email protected]> wrote:
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.
Quoted 6 lines
Quoted 1 line
Drop the rcu_read_lock()/rcu_read_unlock().
All make sense to me, thank you for the nice description and the fix!
Quoted 2 lines
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")
Forgot asking this, sorry. Are you intentionally not adding Cc: stable@ here? I think the user impact is arguably minor enough to not Cc-ing stable@, but just thought it would be good to make the intention clear.
Quoted 6 lines
Quoted 4 lines
Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>Reviewed-by SeongJae Park <[email protected]>
Thanks,
SJ
[...]
Quoted 30 lines · SeongJae Park
Quoted 28 lines · On Wed, 10 Jun 2026 17:22:51 -0700 SeongJae Park <[email protected]> wrote:
Quoted 25 lines · On Wed, 10 Jun 2026 16:20:48 -0700 Shakeel Butt <[email protected]> wrote:
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Quoted 9 lines
Quoted 4 lines
All make sense to me, thank you for the nice description and the fix!
Quoted 2 lines
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Forgot asking this, sorry. Are you intentionally not adding Cc: stable@ here? I think the user impact is arguably minor enough to not Cc-ing stable@, but just thought it would be good to make the intention clear.
Haha I was just being lazy to think through if this should be CCed to stable or not and letting others/reviewers do that for me :P
Quoted 6 lines
Quoted 6 lines
Quoted 4 lines
Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>Reviewed-by SeongJae Park <[email protected]>
Thanks.
Quoted 26 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Quoted 9 lines
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)
LGTM, so:
Thanks!
Quoted 49 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)mm/shrinker_debug.c +0
-2@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)if (!count_per_node)return -ENOMEM ; -rcu_read_lock (); - memcg_aware = shrinker->flags &SHRINKER_MEMCG_AWARE ; memcg =mem_cgroup_iter (NULL ,NULL ,NULL );
mm/shrinker_debug.c static int shrinker_debugfs_count_show(struct seq_file *m, void *v) · line 91
Quoted 8 lines
mm/shrinker_debug.c +0
-2@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v) } }while ((memcg =mem_cgroup_iter (NULL , memcg,NULL )) !=NULL ); -rcu_read_unlock (); -kfree (count_per_node);return ret; }
Thanks for the fix!
Zenghui
Quoted 25 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.
Quoted 7 lines
Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>
Too fast :)
Quoted 28 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.
Quoted 7 lines
Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>
Thanks.
Quoted 24 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.
Quoted 7 lines
Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>
Quoted 60 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)mm/shrinker_debug.c +0
-4@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)if (!count_per_node)return -ENOMEM ; -rcu_read_lock (); - memcg_aware = shrinker->flags &SHRINKER_MEMCG_AWARE ; memcg =mem_cgroup_iter (NULL ,NULL ,NULL );@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v) } }while ((memcg =mem_cgroup_iter (NULL , memcg,NULL )) !=NULL ); -rcu_read_unlock (); -kfree (count_per_node);return ret; }Signature · 1 line
2.53.0-Meta
Quoted 53 lines · Nick Huang
Quoted 52 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)mm/shrinker_debug.c +0
-2@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)if (!count_per_node)return -ENOMEM ; -rcu_read_lock (); - memcg_aware = shrinker->flags &SHRINKER_MEMCG_AWARE ; memcg =mem_cgroup_iter (NULL ,NULL ,NULL );@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v) } }while ((memcg =mem_cgroup_iter (NULL , memcg,NULL )) !=NULL );
Quoted 9 lines
Quoted 8 lines
mm/shrinker_debug.c +0
-2-rcu_read_unlock (); -kfree (count_per_node);return ret; }Signature · 1 line
2.53.0-MetaReviewed-by Nick Huang <[email protected]>
Sorry, but what exactly did you review here? In the past you were sending AI slop:
https://lore.kernel.org/all/aeNGbNyPxJssnkbO@lucifer/
Not even properly following the process.
https://lore.kernel.org/all/[email protected]/
https://lore.kernel.org/all/?q=f%3Asef1548%40gmail.com
Why suddenly reviewing MM patches?
Best regards,
Krzysztof
Quoted 71 lines · Krzysztof Kozlowski
Quoted 53 lines · Nick Huang
Quoted 52 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)mm/shrinker_debug.c +0
-2@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)if (!count_per_node)return -ENOMEM ; -rcu_read_lock (); - memcg_aware = shrinker->flags &SHRINKER_MEMCG_AWARE ; memcg =mem_cgroup_iter (NULL ,NULL ,NULL );@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v) } }while ((memcg =mem_cgroup_iter (NULL , memcg,NULL )) !=NULL );Quoted 9 lines
Quoted 8 lines
mm/shrinker_debug.c +0
-2-rcu_read_unlock (); -kfree (count_per_node);return ret; }Signature · 1 line
2.53.0-MetaReviewed-by Nick Huang <[email protected]>Sorry, but what exactly did you review here? In the past you were sending AI slop:
https://lore.kernel.org/all/aeNGbNyPxJssnkbO@lucifer/Not even properly following the process.
https://lore.kernel.org/all/[email protected]/
Quoted 6 lines
https://lore.kernel.org/all/?q=f%3Asef1548%40gmail.com
Why suddenly reviewing MM patches?
Best regards,
Krzysztof
Hi Krzysztof
I saw this patch on the mailing list and was interested in the RCU issue, so I looked at the related code. I checked that removing the outer RCU read-side critical section doesn't break the memcg lifetime, since mem_cgroup_iter() returns the memcg with a CSS reference held.
I should have explained what I checked instead of just adding a Reviewed-by.
Thanks for pointing that out.
Regards,
Nick Huang
Quoted 79 lines · Nick Huang
Quoted 71 lines · Krzysztof Kozlowski
Quoted 53 lines · Nick Huang
Quoted 52 lines · Shakeel Butt
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)mm/shrinker_debug.c +0
-2@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)if (!count_per_node)return -ENOMEM ; -rcu_read_lock (); - memcg_aware = shrinker->flags &SHRINKER_MEMCG_AWARE ; memcg =mem_cgroup_iter (NULL ,NULL ,NULL );@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v) } }while ((memcg =mem_cgroup_iter (NULL , memcg,NULL )) !=NULL );Quoted 9 lines
Quoted 8 lines
mm/shrinker_debug.c +0
-2-rcu_read_unlock (); -kfree (count_per_node);return ret; }Signature · 1 line
2.53.0-MetaReviewed-by Nick Huang <[email protected]>Sorry, but what exactly did you review here? In the past you were sending AI slop:
https://lore.kernel.org/all/aeNGbNyPxJssnkbO@lucifer/Not even properly following the process.
https://lore.kernel.org/all/[email protected]/Quoted 6 lines
https://lore.kernel.org/all/?q=f%3Asef1548%40gmail.com
Why suddenly reviewing MM patches?
Best regards,
Krzysztof
Quoted 7 lines
Hi Krzysztof
I saw this patch on the mailing list and was interested in the RCU issue, so I looked at the related code. I checked that removing the outer RCU read-side critical section doesn't break the memcg lifetime, since
mem_cgroup_iter()returns the memcg with a CSS reference held.
I should have explained what I checked instead of just adding a Reviewed-by.
Thanks for pointing that out.
After all the maintainers already provided a review...
Best regards,
Krzysztof
Krzysztof Kozlowski <[email protected]> 於 2026年8月25日週二 下午9:56寫道:
Quoted 89 lines · Nick Huang
Quoted 79 lines · Krzysztof Kozlowski
Quoted 71 lines · Nick Huang
Quoted 53 lines · Shakeel Butt
Quoted 52 lines
Reading the debugfs "count" file of a memcg-aware shrinker can sleep inside an RCU read-side critical section:
BUG: sleeping function called from invalid context at kernel/cgroup/rstat.c:421 RCU nest depth: 1, expected: 0 css_rstat_flush mem_cgroup_flush_stats zswap_shrinker_count shrinker_debugfs_count_show
shrinker_debugfs_count_show()invokes the ->count_objects() callback underrcu_read_lock(). The zswap callback flushes memcg stats viacss_rstat_flush(), which may sleep, so it must not run under RCU.The RCU lock is not needed here.
mem_cgroup_iter()takes RCU internally and returns a memcg holding a css reference (dropped on the next iteration or bymem_cgroup_iter_break()), so the memcg stays alive without it. The shrinker is kept alive by the open debugfs file:shrinker_free()removes the debugfs entries viadebugfs_remove_recursive(), which waits for in-flight readers to drain, beforecall_rcu(..., shrinker_free_rcu_cb). The sibling "scan" handler already invokes the sleeping ->scan_objects() callback with no RCU section.Drop the rcu_read_lock()/rcu_read_unlock().
Fixes 5035ebc644ae ("mm: shrinkers: introduce debugfs interface for memory shrinkers")Reported-by Zenghui Yu <[email protected]>Suggested-by Nhat Pham <[email protected]>Signed-off-by Shakeel Butt <[email protected]>--- mm/shrinker_debug.c | 4 ---- 1 file changed, 4 deletions(-)mm/shrinker_debug.c +0
-2@@ -57,8 +57,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v)if (!count_per_node)return -ENOMEM ; -rcu_read_lock (); - memcg_aware = shrinker->flags &SHRINKER_MEMCG_AWARE ; memcg =mem_cgroup_iter (NULL ,NULL ,NULL );@@ -88,8 +86,6 @@ static int shrinker_debugfs_count_show(struct seq_file *m, void *v) } }while ((memcg =mem_cgroup_iter (NULL , memcg,NULL )) !=NULL );Quoted 9 lines
Quoted 8 lines
mm/shrinker_debug.c +0
-3-rcu_read_unlock (); -kfree (count_per_node);return ret; } --2.53.0-Meta
Reviewed-by Nick Huang <[email protected]>Sorry, but what exactly did you review here? In the past you were sending AI slop:
https://lore.kernel.org/all/aeNGbNyPxJssnkbO@lucifer/Not even properly following the process.
https://lore.kernel.org/all/[email protected]/Quoted 6 lines
https://lore.kernel.org/all/?q=f%3Asef1548%40gmail.com
Why suddenly reviewing MM patches?
Best regards,
KrzysztofQuoted 7 lines
Hi Krzysztof
I saw this patch on the mailing list and was interested in the RCU issue, so I looked at the related code. I checked that removing the outer RCU read-side critical section doesn't break the memcg lifetime, since
mem_cgroup_iter()returns the memcg with a CSS reference held.
I should have explained what I checked instead of just adding a Reviewed-by.
Thanks for pointing that out.
Quoted 4 lines
After all the maintainers already provided a review...
Best regards,
Krzysztof
Hi Krzysztof
Sorry, I misread it and didn't realize that the maintainers had already reviewed it.
Thanks for pointing that out, and thanks for taking the time to respond.
Signature · 2 lines
Regards, Nick Huang