> 2022年9月14日 14:06,mingzhe.zou@xxxxxxxxxxxx 写道: > > From: mingzhe <mingzhe.zou@xxxxxxxxxxxx> > > Bcache allows multiple flash devices to be created on the same cache. > We can create multiple flash devices, and the total size larger than > cache device's actual size. > ``` > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > [root@zou ~]# echo 50G > /sys/block/vdd/bcache/set/flash_vol_create > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > └─bcache1 251:128 0 50G 0 disk > [root@zou ~]# echo 50G > /sys/block/vdd/bcache/set/flash_vol_create > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > ├─bcache2 251:256 0 50G 0 disk > └─bcache1 251:128 0 50G 0 disk > [root@zou ~]# echo 50G > /sys/block/vdd/bcache/set/flash_vol_create > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > ├─bcache3 251:256 0 50G 0 disk > ├─bcache2 251:256 0 50G 0 disk > └─bcache1 251:128 0 50G 0 disk > ``` > > This patch will limit the total size of multi-flash device, until no > free space to create a new flash device with an error. > ``` > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > [root@zou ~]# echo 50G > /sys/block/vdd/bcache/set/flash_vol_create > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > └─bcache1 251:128 0 50G 0 disk > [root@zou ~]# echo 50G > /sys/block/vdd/bcache/set/flash_vol_create > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > ├─bcache2 251:256 0 39.9G 0 disk > └─bcache1 251:128 0 50G 0 disk > [root@zou ~]# echo 50G > /sys/block/vdd/bcache/set/flash_vol_create > -bash: echo: write error: Invalid argument > [root@zou ~]# lsblk /dev/vdd > NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT > vdd 252:48 0 100G 0 disk > ├─bcache2 251:256 0 39.9G 0 disk > └─bcache1 251:128 0 50G 0 disk > ``` > > Signed-off-by: mingzhe <mingzhe.zou@xxxxxxxxxxxx> > --- > drivers/md/bcache/super.c | 13 ++++++++++++- > 1 file changed, 12 insertions(+), 1 deletion(-) > > diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c > index 214a384dc1d7..e019cfd793eb 100644 > --- a/drivers/md/bcache/super.c > +++ b/drivers/md/bcache/super.c > @@ -1581,13 +1581,20 @@ static int flash_devs_run(struct cache_set *c) > > static inline sector_t flash_dev_max_sectors(struct cache_set *c) > { > + sector_t sectors; > + struct uuid_entry *u; > size_t avail_nbuckets; > struct cache *ca = c->cache; > size_t first_bucket = ca->sb.first_bucket; > size_t njournal_buckets = ca->sb.njournal_buckets; > > avail_nbuckets = c->nbuckets - first_bucket - njournal_buckets; > - return bucket_to_sector(c, avail_nbuckets / 100 * FLASH_DEV_AVAILABLE_RATIO); > + sectors = bucket_to_sector(c, avail_nbuckets / 100 * FLASH_DEV_AVAILABLE_RATIO); > + > + for (u = c->uuids; u < c->uuids + c->nr_uuids && sectors > 0; u++) > + if (UUID_FLASH_ONLY(u)) > + sectors -= min(u->sectors, sectors); > + return sectors; The value returned from flash_dev_max_sectors() is the buckets number which not allocated to flash devices. But it might not always be the allocable free buckets for new flash device. Because some of the buckets might be allocated to btree nodes, or cached dirty data. Although these space might be shrunk eventually, we should always avoid to use up all the free buckets. Therefore, the exact free bucket amount should be calculated —-- no cheap method to do it. There is a variable cache_set->avail_nbuckets for current available buckets, but it is updated after gc accomplished and not a updated-in-time value. So this value is always <= real available buckets. That is to say, if the creating flash device size < (cache_set->avail_nbuckets - reserved_buckets), the creation failed but there might be enough free buckets for the creating flash device. This is very probably to happen because cache_set->avail_nbuckets is not refreshed frequently. > } > > int bch_flash_dev_create(struct cache_set *c, uint64_t size) > @@ -1612,6 +1619,10 @@ int bch_flash_dev_create(struct cache_set *c, uint64_t size) > > SET_UUID_FLASH_ONLY(u, 1); > u->sectors = min(flash_dev_max_sectors(c), size >> 9); > + if (!u->sectors) { > + pr_err("Can't create volume, no free space"); > + return -EINVAL; > + } The idea is cool. But current code doesn’t solve the target problem, and I don’t have better solution in my brain yet... Thanks. Coly Li > > bch_uuid_write(c); > > -- > 2.17.1 >