fs/btrfs/block-group.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
The function clear_incompat_bg_bits() currently uses
list_for_each_entry_rcu() to iterate over the fs_info->space_info list.
However, inside the loop, it calls down_read(&sinfo->groups_sem).
Since down_read() is a blocking operation that can sleep, calling it
inside an implied RCU read-side critical section is illegal and can
trigger "scheduling while atomic" errors or lockdep warnings.
As established in commit 728049050012 ("btrfs: kill the RCU protection
for fs_info->space_info"), the space_info list is initialized upon mount
and destroyed during unmount. It does not change during the runtime of
the filesystem, making RCU protection unnecessary.
Fix this by switching to the standard list_for_each_entry() iterator,
which safely allows blocking operations like semaphore acquisition within
the loop.
Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
---
fs/btrfs/block-group.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 08b14449fabe..d2cb26f130eb 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -1011,7 +1011,7 @@ static void clear_incompat_bg_bits(struct btrfs_fs_info *fs_info, u64 flags)
struct list_head *head = &fs_info->space_info;
struct btrfs_space_info *sinfo;
- list_for_each_entry_rcu(sinfo, head, list) {
+ list_for_each_entry(sinfo, head, list) {
down_read(&sinfo->groups_sem);
if (!list_empty(&sinfo->block_groups[BTRFS_RAID_RAID5]))
found_raid56 = true;
--
2.25.1
On Thu, Jan 15, 2026 at 02:38:26PM +0000, Jiasheng Jiang wrote:
> The function clear_incompat_bg_bits() currently uses
> list_for_each_entry_rcu() to iterate over the fs_info->space_info list.
> However, inside the loop, it calls down_read(&sinfo->groups_sem).
>
> Since down_read() is a blocking operation that can sleep, calling it
> inside an implied RCU read-side critical section is illegal and can
> trigger "scheduling while atomic" errors or lockdep warnings.
Since we aren't actually in an rcu critical section this isn't really
the case. You did say "implied" but that is kind of hiding a lot of
meaning for a quick read. And the suggestion of hitting a scheduling
while atomic warning *is* wrong and misleading.
The debug warning this will really trigger is __list_check_rcu()
calling rcu_read_lock_any_held() if CONFIG_PROVE_RCU_LIST is enabled.
>
> As established in commit 728049050012 ("btrfs: kill the RCU protection
> for fs_info->space_info"), the space_info list is initialized upon mount
> and destroyed during unmount. It does not change during the runtime of
> the filesystem, making RCU protection unnecessary.
>
> Fix this by switching to the standard list_for_each_entry() iterator,
> which safely allows blocking operations like semaphore acquisition within
> the loop.
Please rephrase the commit message to indicate that the problem is the
unnecessary/misleading usage of the _rcu variant since we are not
in an rcu read critical section, rather than focusing on the semaphore,
which is a code smell but not actually wrong.
In general, my advice to you for your contributions going forward is to
focus on the specific improvement your fix results in, ideally with a
demonstration that it truly happens, as opposed to theoretical issues
with the code that may or may not actually be realized.
So in this case, for example, you would point out that the code hits the
CONFIG_PROVE_RCU_LIST warning and show the dmesg snippet. That also
has the positive side effect of improving reviewer confidence that you
are fully understanding and validating your changes.
Thanks,
Boris
>
> Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
> ---
> fs/btrfs/block-group.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
> index 08b14449fabe..d2cb26f130eb 100644
> --- a/fs/btrfs/block-group.c
> +++ b/fs/btrfs/block-group.c
> @@ -1011,7 +1011,7 @@ static void clear_incompat_bg_bits(struct btrfs_fs_info *fs_info, u64 flags)
> struct list_head *head = &fs_info->space_info;
> struct btrfs_space_info *sinfo;
>
> - list_for_each_entry_rcu(sinfo, head, list) {
> + list_for_each_entry(sinfo, head, list) {
> down_read(&sinfo->groups_sem);
> if (!list_empty(&sinfo->block_groups[BTRFS_RAID_RAID5]))
> found_raid56 = true;
> --
> 2.25.1
>
The function clear_incompat_bg_bits() currently uses
list_for_each_entry_rcu() to iterate over the fs_info->space_info list
without holding the RCU read lock.
When CONFIG_PROVE_RCU_LIST is enabled, this triggers a false positive
lockdep warning because the internal check inside the RCU iterator fails:
WARNING: suspicious RCU usage
-----------------------------
fs/btrfs/block-group.c:1014 suspicious rcu_dereference_check() usage!
other info that might help us debug this:
rcu_scheduler_active = 2, debug_locks = 1
1 lock held by ...:
#0: ... (sb_internal_sem){.+.+}-{0:0}, at: start_transaction+0x...
As established in commit 728049050012 ("btrfs: kill the RCU protection
for fs_info->space_info"), the space_info list is stable (initialized
upon mount and destroyed during unmount). RCU protection is unnecessary.
Fix this by switching to the standard list_for_each_entry() iterator,
which silences the warning.
Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
---
fs/btrfs/block-group.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 08b14449fabe..d2cb26f130eb 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -1011,7 +1011,7 @@ static void clear_incompat_bg_bits(struct btrfs_fs_info *fs_info, u64 flags)
struct list_head *head = &fs_info->space_info;
struct btrfs_space_info *sinfo;
- list_for_each_entry_rcu(sinfo, head, list) {
+ list_for_each_entry(sinfo, head, list) {
down_read(&sinfo->groups_sem);
if (!list_empty(&sinfo->block_groups[BTRFS_RAID_RAID5]))
found_raid56 = true;
--
2.25.1
On Fri, Jan 16, 2026 at 04:02:56PM +0000, Jiasheng Jiang wrote:
> The function clear_incompat_bg_bits() currently uses
> list_for_each_entry_rcu() to iterate over the fs_info->space_info list
> without holding the RCU read lock.
>
> When CONFIG_PROVE_RCU_LIST is enabled, this triggers a false positive
> lockdep warning because the internal check inside the RCU iterator fails:
>
> WARNING: suspicious RCU usage
> -----------------------------
> fs/btrfs/block-group.c:1014 suspicious rcu_dereference_check() usage!
>
> other info that might help us debug this:
>
> rcu_scheduler_active = 2, debug_locks = 1
> 1 lock held by ...:
> #0: ... (sb_internal_sem){.+.+}-{0:0}, at: start_transaction+0x...
>
> As established in commit 728049050012 ("btrfs: kill the RCU protection
> for fs_info->space_info"), the space_info list is stable (initialized
> upon mount and destroyed during unmount). RCU protection is unnecessary.
>
> Fix this by switching to the standard list_for_each_entry() iterator,
> which silences the warning.
>
This version looks good to me, thanks.
Reviewed-by: Boris Burkov <boris@bur.io>
> Signed-off-by: Jiasheng Jiang <jiashengjiangcool@gmail.com>
> ---
> fs/btrfs/block-group.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
> index 08b14449fabe..d2cb26f130eb 100644
> --- a/fs/btrfs/block-group.c
> +++ b/fs/btrfs/block-group.c
> @@ -1011,7 +1011,7 @@ static void clear_incompat_bg_bits(struct btrfs_fs_info *fs_info, u64 flags)
> struct list_head *head = &fs_info->space_info;
> struct btrfs_space_info *sinfo;
>
> - list_for_each_entry_rcu(sinfo, head, list) {
> + list_for_each_entry(sinfo, head, list) {
> down_read(&sinfo->groups_sem);
> if (!list_empty(&sinfo->block_groups[BTRFS_RAID_RAID5]))
> found_raid56 = true;
> --
> 2.25.1
>
© 2016 - 2026 Red Hat, Inc.