[PATCH] block/bcache: introduce bioset_resize() and use it in bcac=
From: Shida Zhang
Date: Wed Jan 21 2026 - 06:32:06 EST
Subsystems using bio_sets currently have their reserve pool sizes fixed at
initialization. In some scenarios, such as high-load storage environments o=
r
memory-constrained systems, it is beneficial to adjust these emergency
reserves dynamically without tearing down the entire bioset.
Introduce bioset_resize() to allow the resizing of the bio_pool, bvec_pool,
within an existing bio_set.
Additionally, update bcache to expose this functionality. A new sysfs
attribute 'detached_pool_size' is added to bcache devices, allowing users
to tune the emergency reserve for detached bios based on production
workloads.
Signed-off-by: Shida Zhang <zhangshida@xxxxxxxxxx>
---
block/bio.c | 30 ++++++++++++++++++++++++++++++
drivers/md/bcache/sysfs.c | 34 ++++++++++++++++++++++++++++++++++
include/linux/bio.h | 1 +
3 files changed, 65 insertions(+)
diff --git a/block/bio.c b/block/bio.c
index e726c0e280a..8c80325e616 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1857,6 +1857,36 @@ int bioset_init(struct bio_set *bs,
}
EXPORT_SYMBOL(bioset_init);
+/**
+ * bioset_resize - resize a bio_set's reserve pools
+ * @bs: bio_set to resize
+ * @pool_size: new number of elements in the reserve pool
+ *
+ * Description:
+ * Resizes the pre-allocated elements in a bio_set. This allows a subsy=
stem
+ * to increase or decrease its emergency reserves dynamically.
+ *
+ * Return:
+ * 0 on success, -ENOMEM on failure.
+ */
+int bioset_resize(struct bio_set *bs, unsigned int pool_size)
+{
+ int ret;
+
+ ret =3D mempool_resize(&bs->bio_pool, pool_size);
+ if (ret)
+ return ret;
+
+ if (bs->bvec_pool.pool_data) {
+ ret =3D mempool_resize(&bs->bvec_pool, pool_size);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(bioset_resize);
+
static int __init init_bio(void)
{
int i;
diff --git a/drivers/md/bcache/sysfs.c b/drivers/md/bcache/sysfs.c
index 72f38e5b6f5..de63c04dafe 100644
--- a/drivers/md/bcache/sysfs.c
+++ b/drivers/md/bcache/sysfs.c
@@ -16,6 +16,7 @@
#include <linux/blkdev.h>
#include <linux/sort.h>
#include <linux/sched/clock.h>
+#include <linux/bio.h>
extern bool bcache_is_reboot;
@@ -150,6 +151,8 @@ rw_attribute(copy_gc_enabled);
rw_attribute(idle_max_writeback_rate);
rw_attribute(gc_after_writeback);
rw_attribute(size);
+rw_attribute(detached_pool_size);
+
static ssize_t bch_snprint_string_list(char *buf,
size_t size,
@@ -167,6 +170,30 @@ static ssize_t bch_snprint_string_list(char *buf,
return out - buf;
}
+SHOW(bch_detached_pool_size)
+{
+ struct bcache_device *d =3D container_of(kobj, struct bcache_device, kobj=
);
+
+ return scnprintf(buf, PAGE_SIZE, "%u\n", d->bio_detached.bio_pool.min_nr)=
;
+}
+
+STORE(bch_detached_pool_size)
+{
+ struct bcache_device *d =3D container_of(kobj, struct bcache_device, kobj=
);
+ unsigned int v;
+ int ret;
+
+ /* Bcache STORE macro uses 'size', not 'count' */
+ if (kstrtouint(buf, 10, &v) || v < 1)
+ return -EINVAL;
+
+ ret =3D bioset_resize(&d->bio_detached, v);
+ if (ret)
+ return ret;
+
+ return size;
+}
+
SHOW(__bch_cached_dev)
{
struct cached_dev *dc =3D container_of(kobj, struct cached_dev,
@@ -282,6 +309,9 @@ SHOW(__bch_cached_dev)
return strlen(buf);
}
+ if (attr =3D=3D &sysfs_detached_pool_size)
+ return bch_detached_pool_size_show(kobj, attr, buf);
+
#undef var
return 0;
}
@@ -450,6 +480,9 @@ STORE(__cached_dev)
if (attr =3D=3D &sysfs_stop)
bcache_device_stop(&dc->disk);
+ if (attr =3D=3D &sysfs_detached_pool_size)
+ return bch_detached_pool_size_store(kobj, attr, buf, size);
+
return size;
}
@@ -540,6 +573,7 @@ static struct attribute *bch_cached_dev_attrs[] =3D {
#endif
&sysfs_backing_dev_name,
&sysfs_backing_dev_uuid,
+ &sysfs_detached_pool_size,
NULL
};
ATTRIBUTE_GROUPS(bch_cached_dev);
diff --git a/include/linux/bio.h b/include/linux/bio.h
index c75a9b3672a..2d8a657000c 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -354,6 +354,7 @@ enum {
extern int bioset_init(struct bio_set *, unsigned int, unsigned int,
int flags);
extern void bioset_exit(struct bio_set *);
extern int biovec_init_pool(mempool_t *pool, int pool_entries);
+int bioset_resize(struct bio_set *bs, unsigned int pool_size);
struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_=
vecs,
blk_opf_t opf, gfp_t gfp_mask,
--=20
2.34.1