lightnvm: pblk: fix min size for page mempool
authorJavier González <javier@cnexlabs.com>
Fri, 13 Oct 2017 12:46:06 +0000 (14:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Dec 2017 09:10:37 +0000 (10:10 +0100)
[ Upstream commit bd432417681a224d9fa4a9d43be7d4edc82135b2 ]

pblk uses an internal page mempool for allocating pages on internal
bios. The main two users of this memory pool are partial reads (reads
with some sectors in cache and some on media) and padded writes, which
need to add dummy pages to an existing bio already containing valid
data (and with a large enough bioset allocated). In both cases, the
maximum number of pages per bio is defined by the maximum number of
physical sectors supported by the underlying device.

This patch fixes a bad mempool allocation, where the min_nr of elements
on the pool was fixed (to 16), which is lower than the maximum number
of sectors supported by NVMe (as of the time for this patch). Instead,
use the maximum number of allowed sectors reported by the device.

Reported-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Javier González <javier@cnexlabs.com>
Signed-off-by: Matias Bjørling <m@bjorling.me>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Sasha Levin <alexander.levin@verizon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/lightnvm/pblk-core.c
drivers/lightnvm/pblk-init.c
drivers/lightnvm/pblk-read.c
drivers/lightnvm/pblk.h

index 81501644fb158be8731773379714cd6ebfbca6fc..bb3e9d5d427609b265f9ed9256a7e40f4a6793ab 100644 (file)
@@ -193,7 +193,7 @@ void pblk_bio_free_pages(struct pblk *pblk, struct bio *bio, int off,
        bio_advance(bio, off * PBLK_EXPOSED_PAGE_SIZE);
        for (i = off; i < nr_pages + off; i++) {
                bv = bio->bi_io_vec[i];
-               mempool_free(bv.bv_page, pblk->page_pool);
+               mempool_free(bv.bv_page, pblk->page_bio_pool);
        }
 }
 
@@ -205,14 +205,14 @@ int pblk_bio_add_pages(struct pblk *pblk, struct bio *bio, gfp_t flags,
        int i, ret;
 
        for (i = 0; i < nr_pages; i++) {
-               page = mempool_alloc(pblk->page_pool, flags);
+               page = mempool_alloc(pblk->page_bio_pool, flags);
                if (!page)
                        goto err;
 
                ret = bio_add_pc_page(q, bio, page, PBLK_EXPOSED_PAGE_SIZE, 0);
                if (ret != PBLK_EXPOSED_PAGE_SIZE) {
                        pr_err("pblk: could not add page to bio\n");
-                       mempool_free(page, pblk->page_pool);
+                       mempool_free(page, pblk->page_bio_pool);
                        goto err;
                }
        }
index 39de6121f46ea2af081520b26b30b35bafe4716e..1b75675ee67b82f39887e836bcc22829c4cafdc6 100644 (file)
@@ -132,7 +132,6 @@ static int pblk_rwb_init(struct pblk *pblk)
 }
 
 /* Minimum pages needed within a lun */
-#define PAGE_POOL_SIZE 16
 #define ADDR_POOL_SIZE 64
 
 static int pblk_set_ppaf(struct pblk *pblk)
@@ -247,14 +246,16 @@ static int pblk_core_init(struct pblk *pblk)
        if (pblk_init_global_caches(pblk))
                return -ENOMEM;
 
-       pblk->page_pool = mempool_create_page_pool(PAGE_POOL_SIZE, 0);
-       if (!pblk->page_pool)
+       /* internal bios can be at most the sectors signaled by the device. */
+       pblk->page_bio_pool = mempool_create_page_pool(nvm_max_phys_sects(dev),
+                                                                       0);
+       if (!pblk->page_bio_pool)
                return -ENOMEM;
 
        pblk->line_ws_pool = mempool_create_slab_pool(PBLK_WS_POOL_SIZE,
                                                        pblk_blk_ws_cache);
        if (!pblk->line_ws_pool)
-               goto free_page_pool;
+               goto free_page_bio_pool;
 
        pblk->rec_pool = mempool_create_slab_pool(geo->nr_luns, pblk_rec_cache);
        if (!pblk->rec_pool)
@@ -309,8 +310,8 @@ free_rec_pool:
        mempool_destroy(pblk->rec_pool);
 free_blk_ws_pool:
        mempool_destroy(pblk->line_ws_pool);
-free_page_pool:
-       mempool_destroy(pblk->page_pool);
+free_page_bio_pool:
+       mempool_destroy(pblk->page_bio_pool);
        return -ENOMEM;
 }
 
@@ -322,7 +323,7 @@ static void pblk_core_free(struct pblk *pblk)
        if (pblk->bb_wq)
                destroy_workqueue(pblk->bb_wq);
 
-       mempool_destroy(pblk->page_pool);
+       mempool_destroy(pblk->page_bio_pool);
        mempool_destroy(pblk->line_ws_pool);
        mempool_destroy(pblk->rec_pool);
        mempool_destroy(pblk->g_rq_pool);
index ee8efb55b330762399c880f6ab876e5cccdcae45..402c732f0970ae45ea7b7a2cad36fcbaa40d299f 100644 (file)
@@ -238,7 +238,7 @@ static int pblk_fill_partial_read_bio(struct pblk *pblk, struct nvm_rq *rqd,
                kunmap_atomic(src_p);
                kunmap_atomic(dst_p);
 
-               mempool_free(src_bv.bv_page, pblk->page_pool);
+               mempool_free(src_bv.bv_page, pblk->page_bio_pool);
 
                hole = find_next_zero_bit(read_bitmap, nr_secs, hole + 1);
        } while (hole < nr_secs);
index 67e623bd5c2df1f69fecd084def0d793da7eab7c..053164deb0721fac30dd550adce1ad16ecacf2ef 100644 (file)
@@ -618,7 +618,7 @@ struct pblk {
 
        struct list_head compl_list;
 
-       mempool_t *page_pool;
+       mempool_t *page_bio_pool;
        mempool_t *line_ws_pool;
        mempool_t *rec_pool;
        mempool_t *g_rq_pool;