Skip to contentSkip to conversation

bcache patches for 4.20

PATCH Applied Coly Li 2 participants 20 messages Oct 8, 2018

Subsystems (3)
lore
Share & tools
lore

Coly Li

author
#0 lore raw

cover bcache patches for 4.20

Hi Jens,

Here are patches for Linux 4.20. In this run we don't have big changes, most of the patches for fixes or code cleanup.

Ben Peddell resends a patch which had no response for a while, I pick it for this version. Our new developer Dongbo Cao contributes a bug fix to avoid kernel panic for too small cache set size, with other code cleanup changes. Shenghui and me have several code cleanup and minor fixes, and Junhui again contributes helpful fixes for several real bugs.

Please pull them for 4.20 merge window. Thanks in advance.

Coly Li
---

Ben Peddell (1):
bcache: Populate writeback_rate_minimum attribute

Coly Li (3):
bcache: use REQ_PRIO to indicate bio for metadata
bcache: fix typo in code comments of closure_return_with_destructor()
bcache: replace hard coded number with BUCKET_GC_GEN_MAX

Dongbo Cao (3):
bcache: remove useless parameter of bch_debug_init()
bcache: split combined if-condition code into separate ones
bcache: panic fix for making cache device

Shenghui Wang (4):
bcache: account size of buckets used in uuid write to

    ca->meta_sectors_written

bcache: recal cached_dev_sectors on detach
bcache: remove unused bch_passthrough_cache
bcache: use MAX_CACHES_PER_SET instead of magic number 8 in
__bch_bucket_alloc_set

Tang Junhui (4):
bcache: trace missed reading by cache_missed
bcache: fix ioctl in flash device
bcache: correct dirty data statistics
bcache: fix miss key refill->end in writeback

 drivers/md/bcache/alloc.c   |   2 +-
 drivers/md/bcache/bcache.h  |   2 +-
 drivers/md/bcache/btree.c   |   2 +-
 drivers/md/bcache/closure.h |   3 +-
 drivers/md/bcache/debug.c   |   2 +-
 drivers/md/bcache/extents.c |   2 +-
 drivers/md/bcache/request.c |   9 ++-
 drivers/md/bcache/request.h |   2 +-
 drivers/md/bcache/super.c   | 113 +++++++++++++++++++++++++++++-------
 drivers/md/bcache/sysfs.c   |   2 +
 10 files changed, 109 insertions(+), 30 deletions(-)
Signature · 1 line
2.19.0
author
#1 lore raw

PATCH 1/15 bcache: account size of buckets used in uuid write to ca->meta_sectors_written

From: Shenghui Wang <[email protected]>

UUIDs are considered as metadata. __uuid_write should add the number of buckets (in sectors) written to disk to ca->meta_sectors_written. Currently only 1 bucket is used in uuid write.

Steps to test:
1) create a fresh backing device and a fresh cache device separately. The backing device didn't attach to any cache set.
2) cd /sys/block/<cache device>/bcache
cat metadata_written // record the output value
cat bucket_size
3) attach the backing device to cache set
4) cat metadata_written
The output value is almost the same as the value in step 2 before the change.
After the change, the value is bigger about 1 bucket size.

---
 drivers/md/bcache/super.c | 5 +++++
 1 file changed, 5 insertions(+)
drivers/md/bcache/super.c +5 -0
index 94c756c66bd7..448e531e8c2d 100644
@@ -417,6 +417,7 @@ static int __uuid_write(struct cache_set *c)
 {
 	BKEY_PADDED(key) k;
 	struct closure cl;
+	struct cache *ca;
 
 	closure_init_stack(&cl);
 	lockdep_assert_held(&bch_register_lock);
@@ -428,6 +429,10 @@ static int __uuid_write(struct cache_set *c)
 	uuid_io(c, REQ_OP_WRITE, 0, &k.key, &cl);
 	closure_sync(&cl);
 
+	/* Only one bucket used for uuid write */
+	ca = PTR_CACHE(c, &k.key, 0);
+	atomic_long_add(ca->sb.bucket_size, &ca->meta_sectors_written);
+
 	bkey_copy(&c->uuid_bucket, &k.key);
 	bkey_put(c, &k.key);
 	return 0;
Signature · 1 line
2.19.0
author
#2 lore raw

PATCH 2/15 bcache: trace missed reading by cache_missed

In reply to Coly Li

From: Tang Junhui <[email protected]>

Missed reading IOs are identified by s->cache_missed, not the s->cache_miss, so in trace_bcache_read() using trace_bcache_read to identify whether the IO is missed or not.

---
 drivers/md/bcache/request.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/bcache/request.c +1 -1
index 51be355a3309..4946d486f734 100644
@@ -850,7 +850,7 @@ static void cached_dev_read_done_bh(struct closure *cl)
 
 	bch_mark_cache_accounting(s->iop.c, s->d,
 				  !s->cache_missed, s->iop.bypass);
-	trace_bcache_read(s->orig_bio, !s->cache_miss, s->iop.bypass);
+	trace_bcache_read(s->orig_bio, !s->cache_missed, s->iop.bypass);
 
 	if (s->iop.status)
 		continue_at_nobarrier(cl, cached_dev_read_error, bcache_wq);
Signature · 1 line
2.19.0
author
#3 lore raw

PATCH 3/15 bcache: use REQ_PRIO to indicate bio for metadata

In reply to Coly Li

In cached_dev_cache_miss() and check_should_bypass(), REQ_META is used to check whether a bio is for metadata request. REQ_META is used for blktrace, the correct REQ_ flag should be REQ_PRIO. This flag means the bio should be prior to other bio, and frequently be used to indicate metadata io in file system code.

This patch replaces REQ_META with correct flag REQ_PRIO.

CC Adam Manzanares because he explains to me what REQ_PRIO is for.

Cc Adam Manzanares <[email protected]>
---
 drivers/md/bcache/request.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/bcache/request.c +2 -2
index 4946d486f734..ee15fb039fd0 100644
@@ -395,7 +395,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio)
 	 * unless the read-ahead request is for metadata (eg, for gfs2).
 	 */
 	if (bio->bi_opf & (REQ_RAHEAD|REQ_BACKGROUND) &&
-	    !(bio->bi_opf & REQ_META))
+	    !(bio->bi_opf & REQ_PRIO))
 		goto skip;
 
 	if (bio->bi_iter.bi_sector & (c->sb.block_size - 1) ||
@@ -877,7 +877,7 @@ static int cached_dev_cache_miss(struct btree *b, struct search *s,
 	}
 
 	if (!(bio->bi_opf & REQ_RAHEAD) &&
-	    !(bio->bi_opf & REQ_META) &&
+	    !(bio->bi_opf & REQ_PRIO) &&
 	    s->iop.c->gc_stats.in_use < CUTOFF_CACHE_READA)
 		reada = min_t(sector_t, dc->readahead >> 9,
 			      get_capacity(bio->bi_disk) - bio_end_sector(bio));
Signature · 1 line
2.19.0
author
#4 lore raw

PATCH 4/15 bcache: fix ioctl in flash device

In reply to Coly Li

From: Tang Junhui <[email protected]>

When doing ioctl in flash device, it will call ioctl_dev() in super.c, then we should not to get cached device since flash only device has no backend device. This patch just move the jugement dc->io_disable to cached_dev_ioctl() to make ioctl in flash device correctly.

Fixes 0f0709e6bfc3c ("bcache: stop bcache device when backing device is offline")
---
 drivers/md/bcache/request.c | 3 +++
 drivers/md/bcache/super.c   | 4 ----
 2 files changed, 3 insertions(+), 4 deletions(-)
drivers/md/bcache/request.c +3 -0
index ee15fb039fd0..3bf35914bb57 100644
@@ -1218,6 +1218,9 @@ static int cached_dev_ioctl(struct bcache_device *d, fmode_t mode,
 {
 	struct cached_dev *dc = container_of(d, struct cached_dev, disk);
 
+	if (dc->io_disable)
+		return -EIO;
+
 	return __blkdev_driver_ioctl(dc->bdev, mode, cmd, arg);
 }
 
drivers/md/bcache/super.c +0 -4
index 448e531e8c2d..a99af19d2f91 100644
@@ -647,10 +647,6 @@ static int ioctl_dev(struct block_device *b, fmode_t mode,
 		     unsigned int cmd, unsigned long arg)
 {
 	struct bcache_device *d = b->bd_disk->private_data;
-	struct cached_dev *dc = container_of(d, struct cached_dev, disk);
-
-	if (dc->io_disable)
-		return -EIO;
 
 	return d->ioctl(d, mode, cmd, arg);
 }
Signature · 1 line
2.19.0
author
#5 lore raw

PATCH 5/15 bcache: fix typo in code comments of closure_return_with_destructor()

In reply to Coly Li

The code comments of closure_return_with_destructor() in closure.h makrs function name as closure_return(). This patch fixes this type with the correct name - closure_return_with_destructor.

---
 drivers/md/bcache/closure.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/md/bcache/closure.h +2 -1
index eca0d496b686..c88cdc4ae4ec 100644
@@ -345,7 +345,8 @@ do {									\
 } while (0)
 
 /**
- * closure_return - finish execution of a closure, with destructor
+ * closure_return_with_destructor - finish execution of a closure,
+ *				    with destructor
  *
  * Works like closure_return(), except @destructor will be called when all
  * outstanding refs on @cl have been dropped; @destructor may be used to safely
Signature · 1 line
2.19.0
author
#6 lore raw

PATCH 6/15 bcache: correct dirty data statistics

In reply to Coly Li

From: Tang Junhui <[email protected]>

When bcache device is clean, dirty keys may still exist after journal replay, so we need to count these dirty keys even device in clean status, otherwise after writeback, the amount of dirty data would be incorrect.

---
 drivers/md/bcache/super.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/md/bcache/super.c +2 -1
index a99af19d2f91..4989c7d4d4d0 100644
@@ -1152,11 +1152,12 @@ int bch_cached_dev_attach(struct cached_dev *dc, struct cache_set *c,
 	}
 
 	if (BDEV_STATE(&dc->sb) == BDEV_STATE_DIRTY) {
-		bch_sectors_dirty_init(&dc->disk);
 		atomic_set(&dc->has_dirty, 1);
 		bch_writeback_queue(dc);
 	}
 
+	bch_sectors_dirty_init(&dc->disk);
+
 	bch_cached_dev_run(dc);
 	bcache_device_link(&dc->disk, c, "bdev");
 	atomic_inc(&c->attached_dev_nr);
Signature · 1 line
2.19.0
author
#7 lore raw

PATCH 7/15 bcache: Populate writeback_rate_minimum attribute

In reply to Coly Li

From: Ben Peddell <[email protected]>

Forgot to include the maintainers with my first email.

Somewhere between Michael Lyle's original
"bcache: PI controller for writeback rate V2" patch dated 07 Sep 2017 and 1d316e6 bcache: implement PI controller for writeback rate, the mapping of the writeback_rate_minimum attribute was dropped.

Re-add the missing sysfs writeback_rate_minimum attribute mapping to "allow the user to specify a minimum rate at which dirty blocks are retired."

Fixes 1d316e6 bcache: implement PI controller for writeback rate
---
 drivers/md/bcache/sysfs.c | 2 ++
 1 file changed, 2 insertions(+)
drivers/md/bcache/sysfs.c +2 -0
index 150cf4f4cf74..26f035a0c5b9 100644
@@ -285,6 +285,7 @@ STORE(__cached_dev)
 			    1, WRITEBACK_RATE_UPDATE_SECS_MAX);
 	d_strtoul(writeback_rate_i_term_inverse);
 	d_strtoul_nonzero(writeback_rate_p_term_inverse);
+	d_strtoul_nonzero(writeback_rate_minimum);
 
 	sysfs_strtoul_clamp(io_error_limit, dc->error_limit, 0, INT_MAX);
 
@@ -412,6 +413,7 @@ static struct attribute *bch_cached_dev_files[] = {
 	&sysfs_writeback_rate_update_seconds,
 	&sysfs_writeback_rate_i_term_inverse,
 	&sysfs_writeback_rate_p_term_inverse,
+	&sysfs_writeback_rate_minimum,
 	&sysfs_writeback_rate_debug,
 	&sysfs_errors,
 	&sysfs_io_error_limit,
Signature · 1 line
2.19.0
maintainer
#8 lore raw

Re: [PATCH 07/15] bcache: Populate writeback_rate_minimum attribute

Quoted 9 lines · Coly Li

From: Ben Peddell <[email protected]>

Forgot to include the maintainers with my first email.

Somewhere between Michael Lyle's original
"bcache: PI controller for writeback rate V2" patch dated 07 Sep 2017 and 1d316e6 bcache: implement PI controller for writeback rate, the mapping of the writeback_rate_minimum attribute was dropped.

Quoted 5 lines

Re-add the missing sysfs writeback_rate_minimum attribute mapping to "allow the user to specify a minimum rate at which dirty blocks are retired."

Fixes 1d316e6 bcache: implement PI controller for writeback rate

Remember to use the correct format for the Fixes line.

Signature · 1 line
Jens Axboe
author
#9 lore raw

Re: [PATCH 07/15] bcache: Populate writeback_rate_minimum attribute

Quoted 10 lines · Jens Axboe
Quoted 9 lines · Coly Li

From: Ben Peddell <[email protected]>

Forgot to include the maintainers with my first email.

Somewhere between Michael Lyle's original
"bcache: PI controller for writeback rate V2" patch dated 07 Sep 2017 and 1d316e6 bcache: implement PI controller for writeback rate, the mapping of the writeback_rate_minimum attribute was dropped.

Quoted 8 lines
Quoted 5 lines

Re-add the missing sysfs writeback_rate_minimum attribute mapping to "allow the user to specify a minimum rate at which dirty blocks are retired."

Fixes 1d316e6 bcache: implement PI controller for writeback rate

Remember to use the correct format for the Fixes line.

Hi Jens,

This is my fault, it slips from my eyes. I'd like to resend a fixed up version to you.

BTW, now I only use checkpatches.pl to check patch format, do you use extra scripts as format checking hooks ?

Thanks.

Coly Li

maintainer
#10 lore raw

Re: [PATCH 07/15] bcache: Populate writeback_rate_minimum attribute

Quoted 17 lines · Coly Li
Quoted 16 lines · Jens Axboe
Quoted 14 lines · Coly Li

From: Ben Peddell <[email protected]>

Forgot to include the maintainers with my first email.

Somewhere between Michael Lyle's original
"bcache: PI controller for writeback rate V2" patch dated 07 Sep 2017 and 1d316e6 bcache: implement PI controller for writeback rate, the mapping of the writeback_rate_minimum attribute was dropped.

Re-add the missing sysfs writeback_rate_minimum attribute mapping to "allow the user to specify a minimum rate at which dirty blocks are retired."

Fixes 1d316e6 bcache: implement PI controller for writeback rate
Quoted 7 lines
Quoted 2 lines

Remember to use the correct format for the Fixes line.

Hi Jens,

This is my fault, it slips from my eyes. I'd like to resend a fixed up version to you.

I fixed it up when I applied it.

Quoted 2 lines

BTW, now I only use checkpatches.pl to check patch format, do you use extra scripts as format checking hooks ?

I don't use checkpatch, I just use my eye balls :-)

Signature · 1 line
Jens Axboe
author
#11 lore raw

PATCH 8/15 bcache: fix miss key refill->end in writeback

In reply to Coly Li

From: Tang Junhui <[email protected]>

refill->end record the last key of writeback, for example, at the first time, keys (1,128K) to (1,1024K) are flush to the backend device, but the end key (1,1024K) is not included, since the bellow code:

	if (bkey_cmp(k, refill->end) >= 0) {
		ret = MAP_DONE;
		goto out;
	}

And in the next time when we refill writeback keybuf again, we searched key start from (1,1024K), and got a key bigger than it, so the key (1,1024K) missed.
This patch modify the above code, and let the end key to be included to the writeback key buffer.

---
 drivers/md/bcache/btree.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/bcache/btree.c +1 -1
index e7d4817681f2..3f4211b5cd33 100644
@@ -2434,7 +2434,7 @@ static int refill_keybuf_fn(struct btree_op *op, struct btree *b,
 	struct keybuf *buf = refill->buf;
 	int ret = MAP_CONTINUE;
 
-	if (bkey_cmp(k, refill->end) >= 0) {
+	if (bkey_cmp(k, refill->end) > 0) {
 		ret = MAP_DONE;
 		goto out;
 	}
Signature · 1 line
2.19.0
author
#12 lore raw

PATCH 9/15 bcache: recal cached_dev_sectors on detach

In reply to Coly Li

From: Shenghui Wang <[email protected]>

Recal cached_dev_sectors on cached_dev detached, as recal done on cached_dev attached.

Update the cached_dev_sectors before bcache_device_detach called as bcache_device_detach will set bcache_device->c to NULL.

---
 drivers/md/bcache/super.c | 1 +
 1 file changed, 1 insertion(+)
drivers/md/bcache/super.c +1 -0
index 4989c7d4d4d0..dc392a485269 100644
@@ -1008,6 +1008,7 @@ static void cached_dev_detach_finish(struct work_struct *w)
 	bch_write_bdev_super(dc, &cl);
 	closure_sync(&cl);
 
+	calc_cached_dev_sectors(dc->disk.c);
 	bcache_device_detach(&dc->disk);
 	list_move(&dc->list, &uncached_devices);
 
Signature · 1 line
2.19.0
author
#13 lore raw

PATCH 10/15 bcache: remove unused bch_passthrough_cache

In reply to Coly Li

From: Shenghui Wang <[email protected]>

struct kmem_cache *bch_passthrough_cache is not used in bcache code. Remove it.

---
 drivers/md/bcache/request.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/bcache/request.h +1 -1
index aa055cfeb099..721bf336ed1a 100644
@@ -39,6 +39,6 @@ void bch_data_insert(struct closure *cl);
 void bch_cached_dev_request_init(struct cached_dev *dc);
 void bch_flash_dev_request_init(struct bcache_device *d);
 
-extern struct kmem_cache *bch_search_cache, *bch_passthrough_cache;
+extern struct kmem_cache *bch_search_cache;
 
 #endif /* _BCACHE_REQUEST_H_ */
Signature · 1 line
2.19.0
author
#14 lore raw

PATCH 11/15 bcache: remove useless parameter of bch_debug_init()

In reply to Coly Li

From: Dongbo Cao <[email protected]>

Parameter "struct kobject *kobj" in bch_debug_init() is useless, remove it in this patch.

---
 drivers/md/bcache/bcache.h | 2 +-
 drivers/md/bcache/debug.c  | 2 +-
 drivers/md/bcache/super.c  | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
drivers/md/bcache/bcache.h +1 -1
index 83504dd8100a..5cfa1ec1b7a1 100644
@@ -1003,7 +1003,7 @@ void bch_open_buckets_free(struct cache_set *c);
 int bch_cache_allocator_start(struct cache *ca);
 
 void bch_debug_exit(void);
-void bch_debug_init(struct kobject *kobj);
+void bch_debug_init(void);
 void bch_request_exit(void);
 int bch_request_init(void);
 
drivers/md/bcache/debug.c +1 -1
index 06da66b2488a..8f448b9c96a1 100644
@@ -253,7 +253,7 @@ void bch_debug_exit(void)
 		debugfs_remove_recursive(bcache_debug);
 }
 
-void __init bch_debug_init(struct kobject *kobj)
+void __init bch_debug_init(void)
 {
 	/*
 	 * it is unnecessary to check return value of
drivers/md/bcache/super.c +1 -1
index dc392a485269..719686ea5e27 100644
@@ -2381,7 +2381,7 @@ static int __init bcache_init(void)
 	    sysfs_create_files(bcache_kobj, files))
 		goto err;
 
-	bch_debug_init(bcache_kobj);
+	bch_debug_init();
 	closure_debug_init();
 
 	return 0;
Signature · 1 line
2.19.0
author
#15 lore raw

PATCH 12/15 bcache: replace hard coded number with BUCKET_GC_GEN_MAX

In reply to Coly Li

In extents.c:bch_extent_bad(), number 96 is used as parameter to call btree_bug_on(). The purpose is to check whether stale gen value exceeds BUCKET_GC_GEN_MAX, so it is better to use macro BUCKET_GC_GEN_MAX to make the code more understandable.

---
 drivers/md/bcache/extents.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/bcache/extents.c +1 -1
index c809724e6571..956004366699 100644
@@ -553,7 +553,7 @@ static bool bch_extent_bad(struct btree_keys *bk, const struct bkey *k)
 	for (i = 0; i < KEY_PTRS(k); i++) {
 		stale = ptr_stale(b->c, k, i);
 
-		btree_bug_on(stale > 96, b,
+		btree_bug_on(stale > BUCKET_GC_GEN_MAX, b,
 			     "key too stale: %i, need_gc %u",
 			     stale, b->c->need_gc);
 
Signature · 1 line
2.19.0
author
#16 lore raw

PATCH 13/15 bcache: use MAX_CACHES_PER_SET instead of magic number 8 in __bch_bucket_alloc_set

In reply to Coly Li

From: Shenghui Wang <[email protected]>

Current cache_set has MAX_CACHES_PER_SET caches most, and the macro is used for
"

	struct cache *cache_by_alloc[MAX_CACHES_PER_SET];

"
in the define of struct cache_set.

Use MAX_CACHES_PER_SET instead of magic number 8 in __bch_bucket_alloc_set.

---
 drivers/md/bcache/alloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/bcache/alloc.c +1 -1
index 7a28232d868b..5002838ea476 100644
@@ -484,7 +484,7 @@ int __bch_bucket_alloc_set(struct cache_set *c, unsigned int reserve,
 	int i;
 
 	lockdep_assert_held(&c->bucket_lock);
-	BUG_ON(!n || n > c->caches_loaded || n > 8);
+	BUG_ON(!n || n > c->caches_loaded || n > MAX_CACHES_PER_SET);
 
 	bkey_init(k);
 
Signature · 1 line
2.19.0
author
#17 lore raw

PATCH 14/15 bcache: split combined if-condition code into separate ones

In reply to Coly Li

From: Dongbo Cao <[email protected]>

Split the combined '||' statements in if() check, to make the code easier for debug.

---
 drivers/md/bcache/super.c | 90 +++++++++++++++++++++++++++++++++------
 1 file changed, 76 insertions(+), 14 deletions(-)
drivers/md/bcache/super.c +76 -14
index 719686ea5e27..2a362a7ba995 100644
@@ -2051,6 +2051,8 @@ static int cache_alloc(struct cache *ca)
 	size_t free;
 	size_t btree_buckets;
 	struct bucket *b;
+	int ret = -ENOMEM;
+	const char *err = NULL;
 
 	__module_get(THIS_MODULE);
 	kobject_init(&ca->kobj, &bch_cache_ktype);
@@ -2069,26 +2071,86 @@ static int cache_alloc(struct cache *ca)
 	btree_buckets = ca->sb.njournal_buckets ?: 8;
 	free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
 
-	if (!init_fifo(&ca->free[RESERVE_BTREE], btree_buckets, GFP_KERNEL) ||
-	    !init_fifo_exact(&ca->free[RESERVE_PRIO], prio_buckets(ca), GFP_KERNEL) ||
-	    !init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL) ||
-	    !init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL) ||
-	    !init_fifo(&ca->free_inc,	free << 2, GFP_KERNEL) ||
-	    !init_heap(&ca->heap,	free << 3, GFP_KERNEL) ||
-	    !(ca->buckets	= vzalloc(array_size(sizeof(struct bucket),
-						     ca->sb.nbuckets))) ||
-	    !(ca->prio_buckets	= kzalloc(array3_size(sizeof(uint64_t),
-						      prio_buckets(ca), 2),
-					  GFP_KERNEL)) ||
-	    !(ca->disk_buckets	= alloc_bucket_pages(GFP_KERNEL, ca)))
-		return -ENOMEM;
+	if (!init_fifo(&ca->free[RESERVE_BTREE], btree_buckets,
+						GFP_KERNEL)) {
+		err = "ca->free[RESERVE_BTREE] alloc failed";
+		goto err_btree_alloc;
+	}
+
+	if (!init_fifo_exact(&ca->free[RESERVE_PRIO], prio_buckets(ca),
+							GFP_KERNEL)) {
+		err = "ca->free[RESERVE_PRIO] alloc failed";
+		goto err_prio_alloc;
+	}
+
+	if (!init_fifo(&ca->free[RESERVE_MOVINGGC], free, GFP_KERNEL)) {
+		err = "ca->free[RESERVE_MOVINGGC] alloc failed";
+		goto err_movinggc_alloc;
+	}
+
+	if (!init_fifo(&ca->free[RESERVE_NONE], free, GFP_KERNEL)) {
+		err = "ca->free[RESERVE_NONE] alloc failed";
+		goto err_none_alloc;
+	}
+
+	if (!init_fifo(&ca->free_inc, free << 2, GFP_KERNEL)) {
+		err = "ca->free_inc alloc failed";
+		goto err_free_inc_alloc;
+	}
+
+	if (!init_heap(&ca->heap, free << 3, GFP_KERNEL)) {
+		err = "ca->heap alloc failed";
+		goto err_heap_alloc;
+	}
+
+	ca->buckets = vzalloc(array_size(sizeof(struct bucket),
+			      ca->sb.nbuckets));
+	if (!ca->buckets) {
+		err = "ca->buckets alloc failed";
+		goto err_buckets_alloc;
+	}
+
+	ca->prio_buckets = kzalloc(array3_size(sizeof(uint64_t),
+				   prio_buckets(ca), 2),
+				   GFP_KERNEL);
+	if (!ca->prio_buckets) {
+		err = "ca->prio_buckets alloc failed";
+		goto err_prio_buckets_alloc;
+	}
+
+	ca->disk_buckets = alloc_bucket_pages(GFP_KERNEL, ca);
+	if (!ca->disk_buckets) {
+		err = "ca->disk_buckets alloc failed";
+		goto err_disk_buckets_alloc;
+	}
 
 	ca->prio_last_buckets = ca->prio_buckets + prio_buckets(ca);
 
 	for_each_bucket(b, ca)
 		atomic_set(&b->pin, 0);
-
 	return 0;
+
+err_disk_buckets_alloc:
+	kfree(ca->prio_buckets);
+err_prio_buckets_alloc:
+	vfree(ca->buckets);
+err_buckets_alloc:
+	free_heap(&ca->heap);
+err_heap_alloc:
+	free_fifo(&ca->free_inc);
+err_free_inc_alloc:
+	free_fifo(&ca->free[RESERVE_NONE]);
+err_none_alloc:
+	free_fifo(&ca->free[RESERVE_MOVINGGC]);
+err_movinggc_alloc:
+	free_fifo(&ca->free[RESERVE_PRIO]);
+err_prio_alloc:
+	free_fifo(&ca->free[RESERVE_BTREE]);
+err_btree_alloc:
+	module_put(THIS_MODULE);
+	if (err)
+		pr_notice("error %s: %s", ca->cache_dev_name, err);
+	return ret;
 }
 
 static int register_cache(struct cache_sb *sb, struct page *sb_page,
Signature · 1 line
2.19.0
author
#18 lore raw

PATCH 15/15 bcache: panic fix for making cache device

In reply to Coly Li

From: Dongbo Cao <[email protected]>

when the nbuckets of cache device is smaller than 1024, making cache device will trigger BUG_ON in kernel, add a condition to avoid this.

---
 drivers/md/bcache/super.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/md/bcache/super.c +8 -0
index 2a362a7ba995..563f75686100 100644
@@ -2070,6 +2070,11 @@ static int cache_alloc(struct cache *ca)
 	 */
 	btree_buckets = ca->sb.njournal_buckets ?: 8;
 	free = roundup_pow_of_two(ca->sb.nbuckets) >> 10;
+	if (!free) {
+		ret = -EPERM;
+		err = "ca->sb.nbuckets is too small";
+		goto err_free;
+	}
 
 	if (!init_fifo(&ca->free[RESERVE_BTREE], btree_buckets,
 						GFP_KERNEL)) {
@@ -2147,6 +2152,7 @@ static int cache_alloc(struct cache *ca)
 err_prio_alloc:
 	free_fifo(&ca->free[RESERVE_BTREE]);
 err_btree_alloc:
+err_free:
 	module_put(THIS_MODULE);
 	if (err)
 		pr_notice("error %s: %s", ca->cache_dev_name, err);
@@ -2176,6 +2182,8 @@ static int register_cache(struct cache_sb *sb, struct page *sb_page,
 		blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 		if (ret == -ENOMEM)
 			err = "cache_alloc(): -ENOMEM";
+		else if (ret == -EPERM)
+			err = "cache_alloc(): cache device is too small";
 		else
 			err = "cache_alloc(): unknown error";
 		goto err;
Signature · 1 line
2.19.0
maintainer Applied
#19 lore raw
In reply to Coly Li
Quoted 5 lines · Coly Li

Hi Jens,

Here are patches for Linux 4.20. In this run we don't have big changes, most of the patches for fixes or code cleanup.

Quoted 7 lines

Ben Peddell resends a patch which had no response for a while, I pick it for this version. Our new developer Dongbo Cao contributes a bug fix to avoid kernel panic for too small cache set size, with other code cleanup changes. Shenghui and me have several code cleanup and minor fixes, and Junhui again contributes helpful fixes for several real bugs.

Please pull them for 4.20 merge window. Thanks in advance.

Applied, thanks.

Signature · 1 line
Jens Axboe