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: No space left on device [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 | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 214a384dc1d7..d4b3ab078ad3 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1581,13 +1581,32 @@ 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; + struct bcache_device *d; 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); + + /* + * Although 10% of buckets are forced to reserve, it should + * be able to meet the needs of gc and btree node allocation. + * But the remaining buckets are not necessarily allocatable + * free buckets. Because some of the buckets might be cached + * dirty data. At the same time, the space that has been + * allocated to other flash devices must be considered. + */ + for (u = c->uuids; u < c->uuids + c->nr_uuids && sectors > 0; u++) { + if (!(d = c->devices[u - c->uuids])) + continue; + sectors -= min(UUID_FLASH_ONLY(u) ? u->sectors : + bcache_dev_sectors_dirty(d), sectors); + } + return sectors; } int bch_flash_dev_create(struct cache_set *c, uint64_t size) @@ -1612,6 +1631,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 -ENOSPC; + } bch_uuid_write(c); -- 2.17.1