public inbox for linux-btrfs@vger.kernel.org
 help / color / mirror / Atom feed
From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
To: linux-btrfs@vger.kernel.org
Cc: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Subject: [PATCH] btrfs: zoned: take rcu_read_lock before dereferencing device->name
Date: Fri, 27 Feb 2026 12:50:51 +0100	[thread overview]
Message-ID: <20260227115051.136255-1-johannes.thumshirn@wdc.com> (raw)

When mounting a zoned filesystem with lockdep enabled, the following splat
is emitted:

 =============================
 WARNING: suspicious RCU usage
 7.0.0-rc1+ #351 Not tainted
 -----------------------------
 fs/btrfs/zoned.c:594 suspicious rcu_dereference_check() usage!

 other info that might help us debug this:

 rcu_scheduler_active = 2, debug_locks = 1
 3 locks held by mount/459:
  #0: ffff8881014dec78 (&fc->uapi_mutex){+.+.}-{4:4}, at: __do_sys_fsconfig+0x2ae/0x680
  #1: ffff888101ddd0e8 (&type->s_umount_key#31/1){+.+.}-{4:4}, at: alloc_super+0xc0/0x3e0
  #2: ffff888101e294e0 (&fs_devs->device_list_mutex){+.+.}-{4:4}, at: btrfs_get_dev_zone_info_all_devices+0x45/0x90

 stack backtrace:
 CPU: 2 UID: 0 PID: 459 Comm: mount Not tainted 7.0.0-rc1+ #351 PREEMPT(full)
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-9.fc43 06/10/2025
 Call Trace:
  <TASK>
  dump_stack_lvl+0x5b/0x80
  lockdep_rcu_suspicious.cold+0x4e/0xa3
  btrfs_get_dev_zone_info+0x434/0x9d0
  btrfs_get_dev_zone_info_all_devices+0x62/0x90
  open_ctree+0xcd2/0x1677
  btrfs_get_tree.cold+0xfc/0x1e3
  ? rcu_is_watching+0x18/0x50
  vfs_get_tree+0x28/0xb0
  __do_sys_fsconfig+0x324/0x680
  do_syscall_64+0x92/0x4f0
  entry_SYSCALL_64_after_hwframe+0x76/0x7e
 RIP: 0033:0x7f88d294c40e
 Code: 73 01 c3 48 8b 0d f2 29 0f 00 f7 d8 64 89 01 48 83 c8 ff c3 0f 1f 84 00 00 00 00 00 f3 0f 1e fa 49 89 ca b8 af 01 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d c2 29 0f 00 f7 d8 64 89 01 48
 RSP: 002b:00007ffd642d05e8 EFLAGS: 00000246 ORIG_RAX: 00000000000001af
 RAX: ffffffffffffffda RBX: 000055c860d48b10 RCX: 00007f88d294c40e
 RDX: 0000000000000000 RSI: 0000000000000006 RDI: 0000000000000003
 RBP: 00007ffd642d0730 R08: 0000000000000000 R09: 0000000000000000
 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
 R13: 000055c860d49c40 R14: 00007f88d2acca60 R15: 000055c860d49d08
  </TASK>
 BTRFS info (device vda): host-managed zoned block device /dev/vda, 64 zones of 268435456 bytes
 BTRFS info (device vda): zoned mode enabled with zone size 268435456
 BTRFS info (device vda): checking UUID tree

Fix it by holding the rc_read_lock before calling into rcu_dereference()
to dereference the rcu protected device->name pointer.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
---
 fs/btrfs/zoned.c | 24 ++++++++++++++++++++----
 1 file changed, 20 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index ab330ec957bc..e69a05f492a6 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 
+#include "linux/rcupdate.h"
 #include <linux/bitops.h>
 #include <linux/slab.h>
 #include <linux/blkdev.h>
@@ -401,17 +402,22 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
 
 	/* We reject devices with a zone size larger than 8GB */
 	if (zone_info->zone_size > BTRFS_MAX_ZONE_SIZE) {
-		btrfs_err(fs_info,
-		"zoned: %s: zone size %llu larger than supported maximum %llu",
-				 rcu_dereference(device->name),
-				 zone_info->zone_size, BTRFS_MAX_ZONE_SIZE);
+		rcu_read_lock();
+		btrfs_err(
+			fs_info,
+			"zoned: %s: zone size %llu larger than supported maximum %llu",
+			rcu_dereference(device->name), zone_info->zone_size,
+			BTRFS_MAX_ZONE_SIZE);
+		rcu_read_unlock();
 		ret = -EINVAL;
 		goto out;
 	} else if (zone_info->zone_size < BTRFS_MIN_ZONE_SIZE) {
+		rcu_read_lock();
 		btrfs_err(fs_info,
 		"zoned: %s: zone size %llu smaller than supported minimum %u",
 				 rcu_dereference(device->name),
 				 zone_info->zone_size, BTRFS_MIN_ZONE_SIZE);
+		rcu_read_unlock();
 		ret = -EINVAL;
 		goto out;
 	}
@@ -427,10 +433,12 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
 	if (!max_active_zones && zone_info->nr_zones > BTRFS_DEFAULT_MAX_ACTIVE_ZONES)
 		max_active_zones = BTRFS_DEFAULT_MAX_ACTIVE_ZONES;
 	if (max_active_zones && max_active_zones < BTRFS_MIN_ACTIVE_ZONES) {
+		rcu_read_lock();
 		btrfs_err(fs_info,
 "zoned: %s: max active zones %u is too small, need at least %u active zones",
 				 rcu_dereference(device->name), max_active_zones,
 				 BTRFS_MIN_ACTIVE_ZONES);
+		rcu_read_unlock();
 		ret = -EINVAL;
 		goto out;
 	}
@@ -469,9 +477,11 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
 		zone_info->zone_cache = vcalloc(zone_info->nr_zones,
 						sizeof(struct blk_zone));
 		if (!zone_info->zone_cache) {
+			rcu_read_lock();
 			btrfs_err(device->fs_info,
 				"zoned: failed to allocate zone cache for %s",
 				rcu_dereference(device->name));
+			rcu_read_unlock();
 			ret = -ENOMEM;
 			goto out;
 		}
@@ -507,10 +517,12 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
 	}
 
 	if (unlikely(nreported != zone_info->nr_zones)) {
+		rcu_read_lock();
 		btrfs_err(device->fs_info,
 				 "inconsistent number of zones on %s (%u/%u)",
 				 rcu_dereference(device->name), nreported,
 				 zone_info->nr_zones);
+		rcu_read_unlock();
 		ret = -EIO;
 		goto out;
 	}
@@ -522,10 +534,12 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
 				zone_info->max_active_zones = 0;
 				goto validate;
 			}
+			rcu_read_lock();
 			btrfs_err(device->fs_info,
 			"zoned: %u active zones on %s exceeds max_active_zones %u",
 					 nactive, rcu_dereference(device->name),
 					 max_active_zones);
+			rcu_read_unlock();
 			ret = -EIO;
 			goto out;
 		}
@@ -591,10 +605,12 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device, bool populate_cache)
 		emulated = "emulated ";
 	}
 
+	rcu_read_lock();
 	btrfs_info(fs_info,
 		"%s block device %s, %u %szones of %llu bytes",
 		model, rcu_dereference(device->name), zone_info->nr_zones,
 		emulated, zone_info->zone_size);
+	rcu_read_unlock();
 
 	return 0;
 
-- 
2.53.0


             reply	other threads:[~2026-02-27 11:50 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-27 11:50 Johannes Thumshirn [this message]
2026-02-27 12:07 ` [PATCH] btrfs: zoned: take rcu_read_lock before dereferencing device->name Filipe Manana
2026-02-27 12:10   ` Johannes Thumshirn

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260227115051.136255-1-johannes.thumshirn@wdc.com \
    --to=johannes.thumshirn@wdc.com \
    --cc=linux-btrfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox