Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lightnvm: pblk: advance bio according to lba index

When a lba either hits the cache or corresponds to an empty entry in the
L2P table, we need to advance the bio according to the position in which
the lba is located. Otherwise, we will copy data in the wrong page, thus
causing data corruption for the application.

In case of a cache hit, we assumed that bio->bi_iter.bi_idx would
contain the correct index, but this is no necessarily true. Instead, use
the local bio advance counter and iterator. This guarantees that lbas
hitting the cache are copied into the right bv_page.

In case of an empty L2P entry, we omitted to advance the bio. In the
cases when the same I/O also contains a cache hit, data corresponding
to this lba will be copied to the wrong bv_page. Fix this by advancing
the bio as we do in the case of a cache hit.

Fixes: a4bd217b4326 lightnvm: physical block device (pblk) target

Signed-off-by: Javier González <javier@javigon.com>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Javier González and committed by
Jens Axboe
75cb8e93 5a60f4b6

+19 -10
+2 -2
drivers/lightnvm/pblk-rb.c
··· 657 657 * be directed to disk. 658 658 */ 659 659 int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba, 660 - struct ppa_addr ppa, int bio_iter) 660 + struct ppa_addr ppa, int bio_iter, bool advanced_bio) 661 661 { 662 662 struct pblk *pblk = container_of(rb, struct pblk, rwb); 663 663 struct pblk_rb_entry *entry; ··· 694 694 * filled with data from the cache). If part of the data resides on the 695 695 * media, we will read later on 696 696 */ 697 - if (unlikely(!bio->bi_iter.bi_idx)) 697 + if (unlikely(!advanced_bio)) 698 698 bio_advance(bio, bio_iter * PBLK_EXPOSED_PAGE_SIZE); 699 699 700 700 data = bio_data(bio);
+16 -7
drivers/lightnvm/pblk-read.c
··· 26 26 */ 27 27 static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio, 28 28 sector_t lba, struct ppa_addr ppa, 29 - int bio_iter) 29 + int bio_iter, bool advanced_bio) 30 30 { 31 31 #ifdef CONFIG_NVM_DEBUG 32 32 /* Callers must ensure that the ppa points to a cache address */ ··· 34 34 BUG_ON(!pblk_addr_in_cache(ppa)); 35 35 #endif 36 36 37 - return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa, bio_iter); 37 + return pblk_rb_copy_to_bio(&pblk->rwb, bio, lba, ppa, 38 + bio_iter, advanced_bio); 38 39 } 39 40 40 41 static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd, ··· 45 44 struct ppa_addr ppas[PBLK_MAX_REQ_ADDRS]; 46 45 sector_t blba = pblk_get_lba(bio); 47 46 int nr_secs = rqd->nr_ppas; 48 - int advanced_bio = 0; 47 + bool advanced_bio = false; 49 48 int i, j = 0; 50 49 51 50 /* logic error: lba out-of-bounds. Ignore read request */ ··· 63 62 retry: 64 63 if (pblk_ppa_empty(p)) { 65 64 WARN_ON(test_and_set_bit(i, read_bitmap)); 66 - continue; 65 + 66 + if (unlikely(!advanced_bio)) { 67 + bio_advance(bio, (i) * PBLK_EXPOSED_PAGE_SIZE); 68 + advanced_bio = true; 69 + } 70 + 71 + goto next; 67 72 } 68 73 69 74 /* Try to read from write buffer. The address is later checked 70 75 * on the write buffer to prevent retrieving overwritten data. 71 76 */ 72 77 if (pblk_addr_in_cache(p)) { 73 - if (!pblk_read_from_cache(pblk, bio, lba, p, i)) { 78 + if (!pblk_read_from_cache(pblk, bio, lba, p, i, 79 + advanced_bio)) { 74 80 pblk_lookup_l2p_seq(pblk, &p, lba, 1); 75 81 goto retry; 76 82 } 77 83 WARN_ON(test_and_set_bit(i, read_bitmap)); 78 - advanced_bio = 1; 84 + advanced_bio = true; 79 85 #ifdef CONFIG_NVM_DEBUG 80 86 atomic_long_inc(&pblk->cache_reads); 81 87 #endif ··· 91 83 rqd->ppa_list[j++] = p; 92 84 } 93 85 86 + next: 94 87 if (advanced_bio) 95 88 bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE); 96 89 } ··· 291 282 * write buffer to prevent retrieving overwritten data. 292 283 */ 293 284 if (pblk_addr_in_cache(ppa)) { 294 - if (!pblk_read_from_cache(pblk, bio, lba, ppa, 0)) { 285 + if (!pblk_read_from_cache(pblk, bio, lba, ppa, 0, 1)) { 295 286 pblk_lookup_l2p_seq(pblk, &ppa, lba, 1); 296 287 goto retry; 297 288 }
+1 -1
drivers/lightnvm/pblk.h
··· 670 670 struct list_head *list, 671 671 unsigned int max); 672 672 int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba, 673 - struct ppa_addr ppa, int bio_iter); 673 + struct ppa_addr ppa, int bio_iter, bool advanced_bio); 674 674 unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries); 675 675 676 676 unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags);