From: mingzhe <mingzhe.zou@xxxxxxxxxxxx> Currently, size is specified and not checked when creating a flash device. This will cause a problem, IO maybe hang when creating a flash device with the actual size of the device. ``` if (attr == &sysfs_flash_vol_create) { int r; uint64_t v; strtoi_h_or_return(buf, v); r = bch_flash_dev_create(c, v); if (r) return r; } ``` Because the flash device needs some space for superblock, journal and btree. If the size of data reaches the available size, the new IO cannot allocate space and will hang. At this time, the gc thread will be started frequently. Even more unreasonable, we can create flash devices larger than actual size. ``` [root@zou ~]# echo 2G > /sys/block/vdb/bcache/set/flash_vol_create [root@zou ~]# lsblk /dev/vdb NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vdb 252:16 0 1G 0 disk └─bcache0 251:0 0 2G 0 disk ``` This patch will limit the size of flash device, reserving a portion of available size for the btree, available ratio can be modified by macro. ``` [root@zou ~]# echo 2G > /sys/block/vdb/bcache/set/flash_vol_create [root@zou ~]# lsblk /dev/vdb NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT vdb 252:16 0 1G 0 disk └─bcache0 251:0 0 900M 0 disk ``` Signed-off-by: mingzhe <mingzhe.zou@xxxxxxxxxxxx> --- drivers/md/bcache/bcache.h | 1 + drivers/md/bcache/super.c | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h index 2acda9cea0f9..f4436229cd83 100644 --- a/drivers/md/bcache/bcache.h +++ b/drivers/md/bcache/bcache.h @@ -525,6 +525,7 @@ struct cache_set { struct cache *cache; +#define FLASH_DEV_AVAILABLE_RATIO 90 struct bcache_device **devices; unsigned int devices_max_used; atomic_t attached_dev_nr; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index ba3909bb6bea..214a384dc1d7 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1579,6 +1579,17 @@ static int flash_devs_run(struct cache_set *c) return ret; } +static inline sector_t flash_dev_max_sectors(struct cache_set *c) +{ + 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); +} + int bch_flash_dev_create(struct cache_set *c, uint64_t size) { struct uuid_entry *u; @@ -1600,7 +1611,7 @@ int bch_flash_dev_create(struct cache_set *c, uint64_t size) u->first_reg = u->last_reg = cpu_to_le32((u32)ktime_get_real_seconds()); SET_UUID_FLASH_ONLY(u, 1); - u->sectors = size >> 9; + u->sectors = min(flash_dev_max_sectors(c), size >> 9); bch_uuid_write(c); -- 2.17.1