Linux bcache driver list
 help / color / mirror / Atom feed
* [PATCH RESEND v2] bcache: convert bch_register_lock to rw_semaphore
@ 2026-07-06 13:04 Qiliang Yuan
  2026-07-07  8:29 ` kernel test robot
  0 siblings, 1 reply; 2+ messages in thread
From: Qiliang Yuan @ 2026-07-06 13:04 UTC (permalink / raw)
  To: Coly Li, Kent Overstreet
  Cc: Coly Li, linux-bcache, linux-kernel, Qiliang Yuan, Jing Wu

Refactor the global bch_register_lock from a mutex to an rw_semaphore to
reduce lock contention and hung tasks (State D) during large-scale bcache
device registration and concurrent sysfs access.

The core change converts the mutex to an rw_semaphore with the following
locking strategy:
- Read lock (down_read): sysfs show (read) operations that only inspect
  state. These can now run concurrently with each other.
- Write lock (down_write): all sysfs store (write) operations, device
  registration/unregistration, attach/detach, reboot, and other paths
  that modify bcache state. These retain exclusive access.

This approach allows concurrent sysfs reads (the most frequent
operations) while maintaining exclusive access for state modifications.

Representative call trace from production logs:
[  243.082130] INFO: task bcache_cache_se:3496 blocked for more than 121 seconds.
[  243.130817] Call trace:
[  243.134161]  __switch_to+0x7c/0xbc
[  243.138461]  __schedule+0x338/0x6f0
[  243.142847]  schedule+0x50/0xe0
[  243.146884]  schedule_preempt_disabled+0x18/0x24
[  243.152400]  __mutex_lock.constprop.0+0x1d4/0x5ec
[  243.158002]  __mutex_lock_slowpath+0x1c/0x30
[  243.163170]  mutex_lock+0x50/0x60
[  243.167397]  bch_cache_set_store+0x40/0x80 [bcache]

Co-developed-by: Qiliang Yuan <yuanql9@chinatelecom.cn>
Signed-off-by: Qiliang Yuan <yuanql9@chinatelecom.cn>
Signed-off-by: Jing Wu <realwujing@gmail.com>
---
Refactor the global bch_register_lock from a mutex to an rw_semaphore to
reduce lock contention and hung tasks (State D) during large-scale bcache
device registration and concurrent sysfs access.

No code changes since v2. Resending for review since v2 has not received
any feedback yet; v2 already addressed the regression Coly pointed out
in v1 (race window in run_cache_set() between up_read()/down_write()).
---
V1 -> V2:
- Remove downgrade_write()/up_read()/down_write() lock manipulation in
  run_cache_set() to eliminate race window during partial initialization
  that could lead to use-after-free if unregister is triggered between
  up_read() and down_write(). Keep write lock held throughout instead.
  (Coly)
- Simplify all sysfs store wrappers to unconditionally use down_write()
  instead of per-attribute read/write lock selection, which was fragile
  and could miss newly added attributes.
- Fix STORE_LOCKED macro to use down_write()/up_write() for store
  operations (was incorrectly using down_read()/up_read()).
- Expand bch_flash_dev store from STORE_LOCKED macro to explicit
  wrapper with down_write() and bcache_is_reboot check.
- Fix whitespace indentation in bcache_init() error path.
- Note on KABI: bch_register_lock is a module-internal global variable
  with no EXPORT_SYMBOL in the entire bcache driver. Changing its type
  from struct mutex to struct rw_semaphore does not affect the kernel
  ABI, as the symbol is never exported to other modules.

v1: https://lore.kernel.org/r/20260318-wujing-bcache-v1-1-f0b9aaf3f81d@gmail.com
---
 drivers/md/bcache/bcache.h  |  2 +-
 drivers/md/bcache/request.c | 18 ++++++-------
 drivers/md/bcache/super.c   | 64 +++++++++++++++++++++----------------------
 drivers/md/bcache/sysfs.c   | 66 ++++++++++++++++++++++++++++++++++++++++-----
 drivers/md/bcache/sysfs.h   |  8 +++---
 5 files changed, 105 insertions(+), 53 deletions(-)

diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index ec9ff97150812..544f514376016 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -1012,7 +1012,7 @@ void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent);
 extern struct workqueue_struct *bcache_wq;
 extern struct workqueue_struct *bch_journal_wq;
 extern struct workqueue_struct *bch_flush_wq;
-extern struct mutex bch_register_lock;
+extern struct rw_semaphore bch_register_lock;
 extern struct list_head bch_cache_sets;
 
 extern const struct kobj_type bch_cached_dev_ktype;
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index 3fa3b13a410f4..b39c127c4751b 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -1135,15 +1135,15 @@ static void quit_max_writeback_rate(struct cache_set *c,
 	struct cached_dev *dc;
 
 	/*
-	 * mutex bch_register_lock may compete with other parallel requesters,
-	 * or attach/detach operations on other backing device. Waiting to
-	 * the mutex lock may increase I/O request latency for seconds or more.
-	 * To avoid such situation, if mutext_trylock() failed, only writeback
-	 * rate of current cached device is set to 1, and __update_write_back()
-	 * will decide writeback rate of other cached devices (remember now
-	 * c->idle_counter is 0 already).
+	 * rw_semaphore bch_register_lock may compete with other parallel
+	 * requesters, or attach/detach operations on other backing device.
+	 * Waiting to the semaphore lock may increase I/O request latency
+	 * for seconds or more. To avoid such situation, if down_write_trylock()
+	 * failed, only writeback rate of current cached device is set to 1,
+	 * and __update_write_back() will decide writeback rate of other
+	 * cached devices (remember now c->idle_counter is 0 already).
 	 */
-	if (mutex_trylock(&bch_register_lock)) {
+	if (down_write_trylock(&bch_register_lock)) {
 		for (i = 0; i < c->devices_max_used; i++) {
 			if (!c->devices[i])
 				continue;
@@ -1160,7 +1160,7 @@ static void quit_max_writeback_rate(struct cache_set *c,
 			 */
 			atomic_long_set(&dc->writeback_rate.rate, 1);
 		}
-		mutex_unlock(&bch_register_lock);
+		up_write(&bch_register_lock);
 	} else
 		atomic_long_set(&this_dc->writeback_rate.rate, 1);
 }
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 97d9adb0bf96b..87cbb0750ca8b 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -40,7 +40,7 @@ static const char invalid_uuid[] = {
 };
 
 static struct kobject *bcache_kobj;
-struct mutex bch_register_lock;
+struct rw_semaphore bch_register_lock;
 bool bcache_is_reboot;
 LIST_HEAD(bch_cache_sets);
 static LIST_HEAD(uncached_devices);
@@ -1155,7 +1155,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
 		dc->writeback_thread = NULL;
 	}
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 
 	bcache_device_detach(&dc->disk);
 	list_move(&dc->list, &uncached_devices);
@@ -1164,7 +1164,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
 	clear_bit(BCACHE_DEV_DETACHING, &dc->disk.flags);
 	clear_bit(BCACHE_DEV_UNLINK_DONE, &dc->disk.flags);
 
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	pr_info("Caching disabled for %pg\n", dc->bdev);
 
@@ -1362,7 +1362,7 @@ static CLOSURE_CALLBACK(cached_dev_free)
 	if (!IS_ERR_OR_NULL(dc->status_update_thread))
 		kthread_stop(dc->status_update_thread);
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 
 	if (atomic_read(&dc->running)) {
 		bd_unlink_disk_holder(dc->bdev, dc->disk.disk);
@@ -1371,7 +1371,7 @@ static CLOSURE_CALLBACK(cached_dev_free)
 	bcache_device_free(&dc->disk);
 	list_del(&dc->list);
 
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	/*
 	 * Wait for any pending sb_write to complete before free.
@@ -1397,9 +1397,9 @@ static CLOSURE_CALLBACK(cached_dev_flush)
 	closure_type(dc, struct cached_dev, disk.cl);
 	struct bcache_device *d = &dc->disk;
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 	bcache_device_unlink(d);
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	bch_cache_accounting_destroy(&dc->accounting);
 	kobject_del(&d->kobj);
@@ -1512,12 +1512,12 @@ static CLOSURE_CALLBACK(flash_dev_free)
 {
 	closure_type(d, struct bcache_device, cl);
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 	atomic_long_sub(bcache_dev_sectors_dirty(d),
 			&d->c->flash_dev_dirty_sectors);
 	del_gendisk(d->disk);
 	bcache_device_free(d);
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 	kobject_put(&d->kobj);
 }
 
@@ -1525,9 +1525,9 @@ static CLOSURE_CALLBACK(flash_dev_flush)
 {
 	closure_type(d, struct bcache_device, cl);
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 	bcache_device_unlink(d);
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 	kobject_del(&d->kobj);
 	continue_at(cl, flash_dev_free, system_percpu_wq);
 }
@@ -1689,7 +1689,7 @@ static CLOSURE_CALLBACK(cache_set_free)
 	bch_btree_cache_free(c);
 	bch_journal_free(c);
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 	bch_bset_sort_state_free(&c->sort);
 	free_pages((unsigned long) c->uuids, ilog2(meta_bucket_pages(&c->cache->sb)));
 
@@ -1710,7 +1710,7 @@ static CLOSURE_CALLBACK(cache_set_free)
 	kfree(c->devices);
 
 	list_del(&c->list);
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	pr_info("Cache set %pU unregistered\n", c->set_uuid);
 	wake_up(&unregister_wait);
@@ -1828,7 +1828,7 @@ static CLOSURE_CALLBACK(__cache_set_unregister)
 	struct bcache_device *d;
 	size_t i;
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 
 	for (i = 0; i < c->devices_max_used; i++) {
 		d = c->devices[i];
@@ -1846,7 +1846,7 @@ static CLOSURE_CALLBACK(__cache_set_unregister)
 		}
 	}
 
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	continue_at(cl, cache_set_flush, system_percpu_wq);
 }
@@ -2424,9 +2424,9 @@ static int register_cache(struct cache_sb *sb, struct cache_sb_disk *sb_disk,
 		goto out;
 	}
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 	err = register_cache_set(ca);
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	if (err) {
 		ret = -ENODEV;
@@ -2501,11 +2501,11 @@ static void register_bdev_worker(struct work_struct *work)
 	struct async_reg_args *args =
 		container_of(work, struct async_reg_args, reg_work.work);
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 	if (register_bdev(args->sb, args->sb_disk, args->bdev_file,
 			  args->holder) < 0)
 		fail = true;
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	if (fail)
 		pr_info("error %s: fail to register backing device\n",
@@ -2620,13 +2620,13 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
 		if (ret == -EBUSY) {
 			dev_t dev;
 
-			mutex_lock(&bch_register_lock);
+			down_write(&bch_register_lock);
 			if (lookup_bdev(strim(path), &dev) == 0 &&
 			    bch_is_open(dev))
 				err = "device already registered";
 			else
 				err = "device busy";
-			mutex_unlock(&bch_register_lock);
+			up_write(&bch_register_lock);
 			if (attr == &ksysfs_register_quiet) {
 				quiet = true;
 				ret = size;
@@ -2659,9 +2659,9 @@ static ssize_t register_bcache(struct kobject *k, struct kobj_attribute *attr,
 	}
 
 	if (SB_IS_BDEV(sb)) {
-		mutex_lock(&bch_register_lock);
+		down_write(&bch_register_lock);
 		ret = register_bdev(sb, sb_disk, bdev_file, holder);
-		mutex_unlock(&bch_register_lock);
+		up_write(&bch_register_lock);
 		/* blkdev_put() will be called in cached_dev_free() */
 		if (ret < 0)
 			goto out_free_sb;
@@ -2715,7 +2715,7 @@ static ssize_t bch_pending_bdevs_cleanup(struct kobject *k,
 	struct pdev *pdev, *tpdev;
 	struct cache_set *c, *tc;
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
 	list_for_each_entry_safe(dc, tdc, &uncached_devices, list) {
 		pdev = kmalloc_obj(struct pdev);
 		if (!pdev)
@@ -2736,7 +2736,7 @@ static ssize_t bch_pending_bdevs_cleanup(struct kobject *k,
 			}
 		}
 	}
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
 
 	list_for_each_entry_safe(pdev, tpdev, &pending_devs, list) {
 		pr_info("delete pdev %p\n", pdev);
@@ -2763,7 +2763,7 @@ static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
 		struct cache_set *c, *tc;
 		struct cached_dev *dc, *tdc;
 
-		mutex_lock(&bch_register_lock);
+		down_write(&bch_register_lock);
 
 		if (bcache_is_reboot)
 			goto out;
@@ -2780,7 +2780,7 @@ static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
 		    list_empty(&uncached_devices))
 			goto out;
 
-		mutex_unlock(&bch_register_lock);
+		up_write(&bch_register_lock);
 
 		pr_info("Stopping all devices:\n");
 
@@ -2815,7 +2815,7 @@ static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
 		while (1) {
 			long timeout = start + 10 * HZ - jiffies;
 
-			mutex_lock(&bch_register_lock);
+			down_write(&bch_register_lock);
 			stopped = list_empty(&bch_cache_sets) &&
 				list_empty(&uncached_devices);
 
@@ -2825,7 +2825,7 @@ static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
 			prepare_to_wait(&unregister_wait, &wait,
 					TASK_UNINTERRUPTIBLE);
 
-			mutex_unlock(&bch_register_lock);
+			up_write(&bch_register_lock);
 			schedule_timeout(timeout);
 		}
 
@@ -2836,7 +2836,7 @@ static int bcache_reboot(struct notifier_block *n, unsigned long code, void *x)
 		else
 			pr_notice("Timeout waiting for devices to be closed\n");
 out:
-		mutex_unlock(&bch_register_lock);
+		up_write(&bch_register_lock);
 	}
 
 	return NOTIFY_DONE;
@@ -2864,7 +2864,6 @@ static void bcache_exit(void)
 	if (bcache_major)
 		unregister_blkdev(bcache_major, "bcache");
 	unregister_reboot_notifier(&reboot);
-	mutex_destroy(&bch_register_lock);
 }
 
 /* Check and fixup module parameters */
@@ -2904,14 +2903,13 @@ static int __init bcache_init(void)
 
 	check_module_parameters();
 
-	mutex_init(&bch_register_lock);
+	init_rwsem(&bch_register_lock);
 	init_waitqueue_head(&unregister_wait);
 	register_reboot_notifier(&reboot);
 
 	bcache_major = register_blkdev(0, "bcache");
 	if (bcache_major < 0) {
 		unregister_reboot_notifier(&reboot);
-		mutex_destroy(&bch_register_lock);
 		return bcache_major;
 	}
 
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index cfac56caa8047..553c15667a2d4 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -285,7 +285,26 @@ SHOW(__bch_cached_dev)
 #undef var
 	return 0;
 }
-SHOW_LOCKED(bch_cached_dev)
+SHOW(bch_cached_dev)
+{
+	struct cached_dev *dc = container_of(kobj, struct cached_dev,
+					     disk.kobj);
+	ssize_t ret;
+
+	/*
+	 * Statistics attributes like dirty_data read atomic variables and
+	 * can be shown without holding the global bch_register_lock.
+	 */
+	if (attr == &sysfs_dirty_data ||
+	    attr == &sysfs_writeback_rate_debug)
+		return __bch_cached_dev_show(kobj, attr, buf);
+
+	down_read(&bch_register_lock);
+	ret = __bch_cached_dev_show(kobj, attr, buf);
+	up_read(&bch_register_lock);
+
+	return ret;
+}
 
 STORE(__cached_dev)
 {
@@ -462,7 +481,8 @@ STORE(bch_cached_dev)
 	if (bcache_is_reboot)
 		return -EBUSY;
 
-	mutex_lock(&bch_register_lock);
+	down_write(&bch_register_lock);
+
 	size = __cached_dev_store(kobj, attr, buf, size);
 
 	if (attr == &sysfs_writeback_running) {
@@ -495,7 +515,8 @@ STORE(bch_cached_dev)
 			schedule_delayed_work(&dc->writeback_rate_update,
 				      dc->writeback_rate_update_seconds * HZ);
 
-	mutex_unlock(&bch_register_lock);
+	up_write(&bch_register_lock);
+
 	return size;
 }
 
@@ -598,7 +619,18 @@ STORE(__bch_flash_dev)
 
 	return size;
 }
-STORE_LOCKED(bch_flash_dev)
+STORE(bch_flash_dev)
+{
+	/* no user space access if system is rebooting */
+	if (bcache_is_reboot)
+		return -EBUSY;
+
+	down_write(&bch_register_lock);
+	size = __bch_flash_dev_store(kobj, attr, buf, size);
+	up_write(&bch_register_lock);
+
+	return size;
+}
 
 static struct attribute *bch_flash_dev_attrs[] = {
 	&sysfs_unregister,
@@ -806,7 +838,16 @@ SHOW(__bch_cache_set)
 
 	return 0;
 }
-SHOW_LOCKED(bch_cache_set)
+SHOW(bch_cache_set)
+{
+	ssize_t ret;
+
+	down_read(&bch_register_lock);
+	ret = __bch_cache_set_show(kobj, attr, buf);
+	up_read(&bch_register_lock);
+
+	return ret;
+}
 
 STORE(__bch_cache_set)
 {
@@ -927,7 +968,20 @@ STORE(__bch_cache_set)
 
 	return size;
 }
-STORE_LOCKED(bch_cache_set)
+STORE(bch_cache_set)
+{
+	ssize_t ret;
+
+	/* no user space access if system is rebooting */
+	if (bcache_is_reboot)
+		return -EBUSY;
+
+	down_write(&bch_register_lock);
+	ret = __bch_cache_set_store(kobj, attr, buf, size);
+	up_write(&bch_register_lock);
+
+	return ret;
+}
 
 SHOW(bch_cache_set_internal)
 {
diff --git a/drivers/md/bcache/sysfs.h b/drivers/md/bcache/sysfs.h
index 65b8bd975ab1e..d897325677d57 100644
--- a/drivers/md/bcache/sysfs.h
+++ b/drivers/md/bcache/sysfs.h
@@ -24,9 +24,9 @@ static ssize_t fn ## _store(struct kobject *kobj, struct attribute *attr,\
 SHOW(fn)								\
 {									\
 	ssize_t ret;							\
-	mutex_lock(&bch_register_lock);					\
+	down_read(&bch_register_lock);					\
 	ret = __ ## fn ## _show(kobj, attr, buf);			\
-	mutex_unlock(&bch_register_lock);				\
+	up_read(&bch_register_lock);				\
 	return ret;							\
 }
 
@@ -34,9 +34,9 @@ SHOW(fn)								\
 STORE(fn)								\
 {									\
 	ssize_t ret;							\
-	mutex_lock(&bch_register_lock);					\
+	down_write(&bch_register_lock);					\
 	ret = __ ## fn ## _store(kobj, attr, buf, size);		\
-	mutex_unlock(&bch_register_lock);				\
+	up_write(&bch_register_lock);				\
 	return ret;							\
 }
 

---
base-commit: 502d801f0ab03e4f32f9a33d203154ce84887921
change-id: 20260706-feat-bcache-30e964a17dd2

Best regards,
-- 
Jing Wu <realwujing@gmail.com>


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH RESEND v2] bcache: convert bch_register_lock to rw_semaphore
  2026-07-06 13:04 [PATCH RESEND v2] bcache: convert bch_register_lock to rw_semaphore Qiliang Yuan
@ 2026-07-07  8:29 ` kernel test robot
  0 siblings, 0 replies; 2+ messages in thread
From: kernel test robot @ 2026-07-07  8:29 UTC (permalink / raw)
  To: Qiliang Yuan, Coly Li, Kent Overstreet
  Cc: oe-kbuild-all, linux-bcache, linux-kernel, Qiliang Yuan, Jing Wu

Hi Qiliang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 502d801f0ab03e4f32f9a33d203154ce84887921]

url:    https://github.com/intel-lab-lkp/linux/commits/Qiliang-Yuan/bcache-convert-bch_register_lock-to-rw_semaphore/20260706-212031
base:   502d801f0ab03e4f32f9a33d203154ce84887921
patch link:    https://lore.kernel.org/r/20260706-feat-bcache-v2-1-70a4b6e246c0%40gmail.com
patch subject: [PATCH RESEND v2] bcache: convert bch_register_lock to rw_semaphore
config: arc-allmodconfig (https://download.01.org/0day-ci/archive/20260707/202607071617.e4elNFQN-lkp@intel.com/config)
compiler: arc-linux-gcc (GCC) 16.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260707/202607071617.e4elNFQN-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202607071617.e4elNFQN-lkp@intel.com/

All warnings (new ones prefixed by >>):

   drivers/md/bcache/sysfs.c: In function 'bch_cached_dev_show':
>> drivers/md/bcache/sysfs.c:290:28: warning: unused variable 'dc' [-Wunused-variable]
     290 |         struct cached_dev *dc = container_of(kobj, struct cached_dev,
         |                            ^~


vim +/dc +290 drivers/md/bcache/sysfs.c

   178	
   179		if (attr == &sysfs_cache_mode)
   180			return bch_snprint_string_list(buf, PAGE_SIZE,
   181						       bch_cache_modes,
   182						       BDEV_CACHE_MODE(&dc->sb));
   183	
   184		if (attr == &sysfs_readahead_cache_policy)
   185			return bch_snprint_string_list(buf, PAGE_SIZE,
   186						      bch_reada_cache_policies,
   187						      dc->cache_readahead_policy);
   188	
   189		if (attr == &sysfs_stop_when_cache_set_failed)
   190			return bch_snprint_string_list(buf, PAGE_SIZE,
   191						       bch_stop_on_failure_modes,
   192						       dc->stop_when_cache_set_failed);
   193	
   194	
   195		sysfs_printf(data_csum,		"%i", dc->disk.data_csum);
   196		var_printf(verify,		"%i");
   197		var_printf(bypass_torture_test,	"%i");
   198		var_printf(writeback_metadata,	"%i");
   199		var_printf(writeback_running,	"%i");
   200		var_printf(writeback_consider_fragment,	"%i");
   201		var_print(writeback_delay);
   202		var_print(writeback_percent);
   203		sysfs_hprint(writeback_rate,
   204			     wb ? atomic_long_read(&dc->writeback_rate.rate) << 9 : 0);
   205		sysfs_printf(io_errors,		"%i", atomic_read(&dc->io_errors));
   206		sysfs_printf(io_error_limit,	"%i", dc->error_limit);
   207		sysfs_printf(io_disable,	"%i", dc->io_disable);
   208		var_print(writeback_rate_update_seconds);
   209		var_print(writeback_rate_i_term_inverse);
   210		var_print(writeback_rate_p_term_inverse);
   211		var_print(writeback_rate_fp_term_low);
   212		var_print(writeback_rate_fp_term_mid);
   213		var_print(writeback_rate_fp_term_high);
   214		var_print(writeback_rate_minimum);
   215	
   216		if (attr == &sysfs_writeback_rate_debug) {
   217			char rate[20];
   218			char dirty[20];
   219			char target[20];
   220			char proportional[20];
   221			char integral[20];
   222			char change[20];
   223			s64 next_io;
   224	
   225			/*
   226			 * Except for dirty and target, other values should
   227			 * be 0 if writeback is not running.
   228			 */
   229			bch_hprint(rate,
   230				   wb ? atomic_long_read(&dc->writeback_rate.rate) << 9
   231				      : 0);
   232			bch_hprint(dirty, bcache_dev_sectors_dirty(&dc->disk) << 9);
   233			bch_hprint(target, dc->writeback_rate_target << 9);
   234			bch_hprint(proportional,
   235				   wb ? dc->writeback_rate_proportional << 9 : 0);
   236			bch_hprint(integral,
   237				   wb ? dc->writeback_rate_integral_scaled << 9 : 0);
   238			bch_hprint(change, wb ? dc->writeback_rate_change << 9 : 0);
   239			next_io = wb ? div64_s64(dc->writeback_rate.next-local_clock(),
   240						 NSEC_PER_MSEC) : 0;
   241	
   242			return sprintf(buf,
   243				       "rate:\t\t%s/sec\n"
   244				       "dirty:\t\t%s\n"
   245				       "target:\t\t%s\n"
   246				       "proportional:\t%s\n"
   247				       "integral:\t%s\n"
   248				       "change:\t\t%s/sec\n"
   249				       "next io:\t%llims\n",
   250				       rate, dirty, target, proportional,
   251				       integral, change, next_io);
   252		}
   253	
   254		sysfs_hprint(dirty_data,
   255			     bcache_dev_sectors_dirty(&dc->disk) << 9);
   256	
   257		sysfs_hprint(stripe_size,	 ((uint64_t)dc->disk.stripe_size) << 9);
   258		var_printf(partial_stripes_expensive,	"%u");
   259	
   260		var_hprint(sequential_cutoff);
   261	
   262		sysfs_print(running,		atomic_read(&dc->running));
   263		sysfs_print(state,		states[BDEV_STATE(&dc->sb)]);
   264	
   265		if (attr == &sysfs_label) {
   266			memcpy(buf, dc->sb.label, SB_LABEL_SIZE);
   267			buf[SB_LABEL_SIZE + 1] = '\0';
   268			strcat(buf, "\n");
   269			return strlen(buf);
   270		}
   271	
   272		if (attr == &sysfs_backing_dev_name) {
   273			snprintf(buf, BDEVNAME_SIZE + 1, "%pg", dc->bdev);
   274			strcat(buf, "\n");
   275			return strlen(buf);
   276		}
   277	
   278		if (attr == &sysfs_backing_dev_uuid) {
   279			/* convert binary uuid into 36-byte string plus '\0' */
   280			snprintf(buf, 36+1, "%pU", dc->sb.uuid);
   281			strcat(buf, "\n");
   282			return strlen(buf);
   283		}
   284	
   285	#undef var
   286		return 0;
   287	}
   288	SHOW(bch_cached_dev)
   289	{
 > 290		struct cached_dev *dc = container_of(kobj, struct cached_dev,
   291						     disk.kobj);
   292		ssize_t ret;
   293	
   294		/*
   295		 * Statistics attributes like dirty_data read atomic variables and
   296		 * can be shown without holding the global bch_register_lock.
   297		 */
   298		if (attr == &sysfs_dirty_data ||
   299		    attr == &sysfs_writeback_rate_debug)
   300			return __bch_cached_dev_show(kobj, attr, buf);
   301	
   302		down_read(&bch_register_lock);
   303		ret = __bch_cached_dev_show(kobj, attr, buf);
   304		up_read(&bch_register_lock);
   305	
   306		return ret;
   307	}
   308	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-07  8:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 13:04 [PATCH RESEND v2] bcache: convert bch_register_lock to rw_semaphore Qiliang Yuan
2026-07-07  8:29 ` kernel test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox