diff options
Diffstat (limited to 'drivers/md/bcache/super.c')
| -rw-r--r-- | drivers/md/bcache/super.c | 32 | 
1 files changed, 28 insertions, 4 deletions
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index dbfa1c38e85e..8c73f0c7f28a 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -10,6 +10,7 @@  #include "btree.h"  #include "debug.h"  #include "request.h" +#include "writeback.h"  #include <linux/blkdev.h>  #include <linux/buffer_head.h> @@ -744,13 +745,35 @@ static void bcache_device_free(struct bcache_device *d)  		mempool_destroy(d->unaligned_bvec);  	if (d->bio_split)  		bioset_free(d->bio_split); +	if (is_vmalloc_addr(d->stripe_sectors_dirty)) +		vfree(d->stripe_sectors_dirty); +	else +		kfree(d->stripe_sectors_dirty);  	closure_debug_destroy(&d->cl);  } -static int bcache_device_init(struct bcache_device *d, unsigned block_size) +static int bcache_device_init(struct bcache_device *d, unsigned block_size, +			      sector_t sectors)  {  	struct request_queue *q; +	size_t n; + +	if (!d->stripe_size_bits) +		d->stripe_size_bits = 31; + +	d->nr_stripes = round_up(sectors, 1 << d->stripe_size_bits) >> +		d->stripe_size_bits; + +	if (!d->nr_stripes || d->nr_stripes > SIZE_MAX / sizeof(atomic_t)) +		return -ENOMEM; + +	n = d->nr_stripes * sizeof(atomic_t); +	d->stripe_sectors_dirty = n < PAGE_SIZE << 6 +		? kzalloc(n, GFP_KERNEL) +		: vzalloc(n); +	if (!d->stripe_sectors_dirty) +		return -ENOMEM;  	if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio))) ||  	    !(d->unaligned_bvec = mempool_create_kmalloc_pool(1, @@ -760,6 +783,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size)  	    !(q = blk_alloc_queue(GFP_KERNEL)))  		return -ENOMEM; +	set_capacity(d->disk, sectors);  	snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", bcache_minor);  	d->disk->major		= bcache_major; @@ -1047,7 +1071,8 @@ static int cached_dev_init(struct cached_dev *dc, unsigned block_size)  		hlist_add_head(&io->hash, dc->io_hash + RECENT_IO);  	} -	ret = bcache_device_init(&dc->disk, block_size); +	ret = bcache_device_init(&dc->disk, block_size, +			 dc->bdev->bd_part->nr_sects - dc->sb.data_offset);  	if (ret)  		return ret; @@ -1146,11 +1171,10 @@ static int flash_dev_run(struct cache_set *c, struct uuid_entry *u)  	kobject_init(&d->kobj, &bch_flash_dev_ktype); -	if (bcache_device_init(d, block_bytes(c))) +	if (bcache_device_init(d, block_bytes(c), u->sectors))  		goto err;  	bcache_device_attach(d, c, u - c->uuids); -	set_capacity(d->disk, u->sectors);  	bch_flash_dev_request_init(d);  	add_disk(d->disk);  | 
