diff mbox series

[v3,12/16] bcache: handle btree node memory allocation properly for bucket size > 8MB

Message ID 20200715143015.14957-13-colyli@suse.de (mailing list archive)
State New, archived
Headers show
Series bcache: extend bucket size to 32bit width | expand

Commit Message

Coly Li July 15, 2020, 2:30 p.m. UTC
From: Coly Li <colyli@suse.de>

Currently the bcache internal btree node occupies a whole bucket. When
loading the btree node from cache device into memory, mca_data_alloc()
will call bch_btree_keys_alloc() to allocate memory for the whole bucket
size, ilog2(b->c->btree_pages) is send to bch_btree_keys_alloc() as the
parameter 'page_order'.

c->btree_pages is set as bucket_pages() in bch_cache_set_alloc(), for
bucket size > 8MB, ilog2(b->c->btree_pages) is 12 for 4KB page size. By
default the maximum page order __get_free_pages() accepts is MAX_ORDER
(11), in this condition bch_btree_keys_alloc() will always fail.

Because of other over-page-order allocation failure fails the cache
device registration, such btree node allocation failure wasn't observed
during runtime. After other blocking page allocation failures for bucket
size > 8MB, this btree node allocation issue may trigger potentical risk
e.g. infinite dead-loop to retry btree node allocation after failure.

This patch fixes the potential problem by setting c->btree_pages to
meta_bucket_pages() in bch_cache_set_alloc(). In the condition that
bucket size > 8MB, meta_bucket_pages() will always return a number which
won't exceed the maximum page order of the buddy allocator.

Signed-off-by: Coly Li <colyli@suse.de>
---
 drivers/md/bcache/super.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Hannes Reinecke July 16, 2020, 6:08 a.m. UTC | #1
On 7/15/20 4:30 PM, colyli@suse.de wrote:
> From: Coly Li <colyli@suse.de>
> 
> Currently the bcache internal btree node occupies a whole bucket. When
> loading the btree node from cache device into memory, mca_data_alloc()
> will call bch_btree_keys_alloc() to allocate memory for the whole bucket
> size, ilog2(b->c->btree_pages) is send to bch_btree_keys_alloc() as the
> parameter 'page_order'.
> 
> c->btree_pages is set as bucket_pages() in bch_cache_set_alloc(), for
> bucket size > 8MB, ilog2(b->c->btree_pages) is 12 for 4KB page size. By
> default the maximum page order __get_free_pages() accepts is MAX_ORDER
> (11), in this condition bch_btree_keys_alloc() will always fail.
> 
> Because of other over-page-order allocation failure fails the cache
> device registration, such btree node allocation failure wasn't observed
> during runtime. After other blocking page allocation failures for bucket
> size > 8MB, this btree node allocation issue may trigger potentical risk
> e.g. infinite dead-loop to retry btree node allocation after failure.
> 
> This patch fixes the potential problem by setting c->btree_pages to
> meta_bucket_pages() in bch_cache_set_alloc(). In the condition that
> bucket size > 8MB, meta_bucket_pages() will always return a number which
> won't exceed the maximum page order of the buddy allocator.
> 
> Signed-off-by: Coly Li <colyli@suse.de>
> ---
>   drivers/md/bcache/super.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
> index b1d8388ef57d..02901d0ae8e2 100644
> --- a/drivers/md/bcache/super.c
> +++ b/drivers/md/bcache/super.c
> @@ -1867,7 +1867,7 @@ struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
>   	c->nr_uuids		= meta_bucket_bytes(&c->sb) / sizeof(struct uuid_entry);
>   	c->devices_max_used	= 0;
>   	atomic_set(&c->attached_dev_nr, 0);
> -	c->btree_pages		= bucket_pages(c);
> +	c->btree_pages		= meta_bucket_pages(&c->sb);
>   	if (c->btree_pages > BTREE_MAX_PAGES)
>   		c->btree_pages = max_t(int, c->btree_pages / 4,
>   				       BTREE_MAX_PAGES);
> 
Reviewed-by: Hannes Reinecke <hare@suse.de>

Cheers,

Hannes
diff mbox series

Patch

diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index b1d8388ef57d..02901d0ae8e2 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1867,7 +1867,7 @@  struct cache_set *bch_cache_set_alloc(struct cache_sb *sb)
 	c->nr_uuids		= meta_bucket_bytes(&c->sb) / sizeof(struct uuid_entry);
 	c->devices_max_used	= 0;
 	atomic_set(&c->attached_dev_nr, 0);
-	c->btree_pages		= bucket_pages(c);
+	c->btree_pages		= meta_bucket_pages(&c->sb);
 	if (c->btree_pages > BTREE_MAX_PAGES)
 		c->btree_pages = max_t(int, c->btree_pages / 4,
 				       BTREE_MAX_PAGES);