|
@@ -53,12 +53,15 @@ LIST_HEAD(bch_cache_sets);
|
|
|
static LIST_HEAD(uncached_devices);
|
|
|
|
|
|
static int bcache_major;
|
|
|
-static DEFINE_IDA(bcache_minor);
|
|
|
+static DEFINE_IDA(bcache_device_idx);
|
|
|
static wait_queue_head_t unregister_wait;
|
|
|
struct workqueue_struct *bcache_wq;
|
|
|
|
|
|
#define BTREE_MAX_PAGES (256 * 1024 / PAGE_SIZE)
|
|
|
-#define BCACHE_MINORS 16 /* partition support */
|
|
|
+/* limitation of partitions number on single bcache device */
|
|
|
+#define BCACHE_MINORS 128
|
|
|
+/* limitation of bcache devices number on single system */
|
|
|
+#define BCACHE_DEVICE_IDX_MAX ((1U << MINORBITS)/BCACHE_MINORS)
|
|
|
|
|
|
/* Superblock */
|
|
|
|
|
@@ -721,6 +724,16 @@ static void bcache_device_attach(struct bcache_device *d, struct cache_set *c,
|
|
|
closure_get(&c->caching);
|
|
|
}
|
|
|
|
|
|
+static inline int first_minor_to_idx(int first_minor)
|
|
|
+{
|
|
|
+ return (first_minor/BCACHE_MINORS);
|
|
|
+}
|
|
|
+
|
|
|
+static inline int idx_to_first_minor(int idx)
|
|
|
+{
|
|
|
+ return (idx * BCACHE_MINORS);
|
|
|
+}
|
|
|
+
|
|
|
static void bcache_device_free(struct bcache_device *d)
|
|
|
{
|
|
|
lockdep_assert_held(&bch_register_lock);
|
|
@@ -734,7 +747,8 @@ static void bcache_device_free(struct bcache_device *d)
|
|
|
if (d->disk && d->disk->queue)
|
|
|
blk_cleanup_queue(d->disk->queue);
|
|
|
if (d->disk) {
|
|
|
- ida_simple_remove(&bcache_minor, d->disk->first_minor);
|
|
|
+ ida_simple_remove(&bcache_device_idx,
|
|
|
+ first_minor_to_idx(d->disk->first_minor));
|
|
|
put_disk(d->disk);
|
|
|
}
|
|
|
|
|
@@ -751,7 +765,7 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
|
|
|
{
|
|
|
struct request_queue *q;
|
|
|
size_t n;
|
|
|
- int minor;
|
|
|
+ int idx;
|
|
|
|
|
|
if (!d->stripe_size)
|
|
|
d->stripe_size = 1 << 31;
|
|
@@ -776,25 +790,24 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
|
|
|
if (!d->full_dirty_stripes)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- minor = ida_simple_get(&bcache_minor, 0, MINORMASK + 1, GFP_KERNEL);
|
|
|
- if (minor < 0)
|
|
|
- return minor;
|
|
|
-
|
|
|
- minor *= BCACHE_MINORS;
|
|
|
+ idx = ida_simple_get(&bcache_device_idx, 0,
|
|
|
+ BCACHE_DEVICE_IDX_MAX, GFP_KERNEL);
|
|
|
+ if (idx < 0)
|
|
|
+ return idx;
|
|
|
|
|
|
if (!(d->bio_split = bioset_create(4, offsetof(struct bbio, bio),
|
|
|
BIOSET_NEED_BVECS |
|
|
|
BIOSET_NEED_RESCUER)) ||
|
|
|
!(d->disk = alloc_disk(BCACHE_MINORS))) {
|
|
|
- ida_simple_remove(&bcache_minor, minor);
|
|
|
+ ida_simple_remove(&bcache_device_idx, idx);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
set_capacity(d->disk, sectors);
|
|
|
- snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", minor);
|
|
|
+ snprintf(d->disk->disk_name, DISK_NAME_LEN, "bcache%i", idx);
|
|
|
|
|
|
d->disk->major = bcache_major;
|
|
|
- d->disk->first_minor = minor;
|
|
|
+ d->disk->first_minor = idx_to_first_minor(idx);
|
|
|
d->disk->fops = &bcache_ops;
|
|
|
d->disk->private_data = d;
|
|
|
|