Skip to content

Commit

Permalink
lightnvm: pblk: fix crash in pblk_end_partial_read due to multipage b…
Browse files Browse the repository at this point in the history
…vecs

The introduction of multipage bio vectors broke pblk's partial read
logic due to it not being prepared for multipage bio vectors.

Use bio vector iterators instead of direct bio vector indexing.

Fixes: 07173c3 ("block: enable multipage bvecs")
Reported-by: Klaus Jensen <klaus.jensen@cnexlabs.com>
Signed-off-by: Hans Holmberg <hans.holmberg@cnexlabs.com>
Updated description.
Signed-off-by: Matias Bjørling <mb@lightnvm.io>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
  • Loading branch information
Hans Holmberg authored and Jens Axboe committed Apr 10, 2019
1 parent eb3afb7 commit b2b3a70
Showing 1 changed file with 28 additions and 22 deletions.
50 changes: 28 additions & 22 deletions drivers/lightnvm/pblk-read.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,14 +231,14 @@ static void pblk_end_partial_read(struct nvm_rq *rqd)
struct pblk_sec_meta *meta;
struct bio *new_bio = rqd->bio;
struct bio *bio = pr_ctx->orig_bio;
struct bio_vec src_bv, dst_bv;
void *meta_list = rqd->meta_list;
int bio_init_idx = pr_ctx->bio_init_idx;
unsigned long *read_bitmap = pr_ctx->bitmap;
struct bvec_iter orig_iter = BVEC_ITER_ALL_INIT;
struct bvec_iter new_iter = BVEC_ITER_ALL_INIT;
int nr_secs = pr_ctx->orig_nr_secs;
int nr_holes = nr_secs - bitmap_weight(read_bitmap, nr_secs);
void *src_p, *dst_p;
int hole, i;
int bit, i;

if (unlikely(nr_holes == 1)) {
struct ppa_addr ppa;
Expand All @@ -257,33 +257,39 @@ static void pblk_end_partial_read(struct nvm_rq *rqd)

/* Fill the holes in the original bio */
i = 0;
hole = find_first_zero_bit(read_bitmap, nr_secs);
do {
struct pblk_line *line;
for (bit = 0; bit < nr_secs; bit++) {
if (!test_bit(bit, read_bitmap)) {
struct bio_vec dst_bv, src_bv;
struct pblk_line *line;

line = pblk_ppa_to_line(pblk, rqd->ppa_list[i]);
kref_put(&line->ref, pblk_line_put);
line = pblk_ppa_to_line(pblk, rqd->ppa_list[i]);
kref_put(&line->ref, pblk_line_put);

meta = pblk_get_meta(pblk, meta_list, hole);
meta->lba = cpu_to_le64(pr_ctx->lba_list_media[i]);
meta = pblk_get_meta(pblk, meta_list, bit);
meta->lba = cpu_to_le64(pr_ctx->lba_list_media[i]);

src_bv = new_bio->bi_io_vec[i++];
dst_bv = bio->bi_io_vec[bio_init_idx + hole];
dst_bv = bio_iter_iovec(bio, orig_iter);
src_bv = bio_iter_iovec(new_bio, new_iter);

src_p = kmap_atomic(src_bv.bv_page);
dst_p = kmap_atomic(dst_bv.bv_page);
src_p = kmap_atomic(src_bv.bv_page);
dst_p = kmap_atomic(dst_bv.bv_page);

memcpy(dst_p + dst_bv.bv_offset,
src_p + src_bv.bv_offset,
PBLK_EXPOSED_PAGE_SIZE);
memcpy(dst_p + dst_bv.bv_offset,
src_p + src_bv.bv_offset,
PBLK_EXPOSED_PAGE_SIZE);

kunmap_atomic(src_p);
kunmap_atomic(dst_p);
kunmap_atomic(src_p);
kunmap_atomic(dst_p);

mempool_free(src_bv.bv_page, &pblk->page_bio_pool);
flush_dcache_page(dst_bv.bv_page);
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);
bio_advance_iter(new_bio, &new_iter,
PBLK_EXPOSED_PAGE_SIZE);
i++;
}
bio_advance_iter(bio, &orig_iter, PBLK_EXPOSED_PAGE_SIZE);
}

bio_put(new_bio);
kfree(pr_ctx);
Expand Down

0 comments on commit b2b3a70

Please sign in to comment.