Skip to content

Commit 75cb8e9

Browse files
Javier Gonzálezaxboe
authored andcommitted
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: a4bd217 lightnvm: physical block device (pblk) target Signed-off-by: Javier González <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 5a60f4b commit 75cb8e9

File tree

3 files changed

+19
-10
lines changed

3 files changed

+19
-10
lines changed

drivers/lightnvm/pblk-rb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ unsigned int pblk_rb_read_to_bio(struct pblk_rb *rb, struct nvm_rq *rqd,
657657
* be directed to disk.
658658
*/
659659
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)
661661
{
662662
struct pblk *pblk = container_of(rb, struct pblk, rwb);
663663
struct pblk_rb_entry *entry;
@@ -694,7 +694,7 @@ int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba,
694694
* filled with data from the cache). If part of the data resides on the
695695
* media, we will read later on
696696
*/
697-
if (unlikely(!bio->bi_iter.bi_idx))
697+
if (unlikely(!advanced_bio))
698698
bio_advance(bio, bio_iter * PBLK_EXPOSED_PAGE_SIZE);
699699

700700
data = bio_data(bio);

drivers/lightnvm/pblk-read.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,16 @@
2626
*/
2727
static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio,
2828
sector_t lba, struct ppa_addr ppa,
29-
int bio_iter)
29+
int bio_iter, bool advanced_bio)
3030
{
3131
#ifdef CONFIG_NVM_DEBUG
3232
/* Callers must ensure that the ppa points to a cache address */
3333
BUG_ON(pblk_ppa_empty(ppa));
3434
BUG_ON(!pblk_addr_in_cache(ppa));
3535
#endif
3636

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);
3839
}
3940

4041
static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
@@ -44,7 +45,7 @@ static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
4445
struct ppa_addr ppas[PBLK_MAX_REQ_ADDRS];
4546
sector_t blba = pblk_get_lba(bio);
4647
int nr_secs = rqd->nr_ppas;
47-
int advanced_bio = 0;
48+
bool advanced_bio = false;
4849
int i, j = 0;
4950

5051
/* logic error: lba out-of-bounds. Ignore read request */
@@ -62,19 +63,26 @@ static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
6263
retry:
6364
if (pblk_ppa_empty(p)) {
6465
WARN_ON(test_and_set_bit(i, read_bitmap));
65-
continue;
66+
67+
if (unlikely(!advanced_bio)) {
68+
bio_advance(bio, (i) * PBLK_EXPOSED_PAGE_SIZE);
69+
advanced_bio = true;
70+
}
71+
72+
goto next;
6673
}
6774

6875
/* Try to read from write buffer. The address is later checked
6976
* on the write buffer to prevent retrieving overwritten data.
7077
*/
7178
if (pblk_addr_in_cache(p)) {
72-
if (!pblk_read_from_cache(pblk, bio, lba, p, i)) {
79+
if (!pblk_read_from_cache(pblk, bio, lba, p, i,
80+
advanced_bio)) {
7381
pblk_lookup_l2p_seq(pblk, &p, lba, 1);
7482
goto retry;
7583
}
7684
WARN_ON(test_and_set_bit(i, read_bitmap));
77-
advanced_bio = 1;
85+
advanced_bio = true;
7886
#ifdef CONFIG_NVM_DEBUG
7987
atomic_long_inc(&pblk->cache_reads);
8088
#endif
@@ -83,6 +91,7 @@ static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd,
8391
rqd->ppa_list[j++] = p;
8492
}
8593

94+
next:
8695
if (advanced_bio)
8796
bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE);
8897
}
@@ -282,7 +291,7 @@ static void pblk_read_rq(struct pblk *pblk, struct nvm_rq *rqd,
282291
* write buffer to prevent retrieving overwritten data.
283292
*/
284293
if (pblk_addr_in_cache(ppa)) {
285-
if (!pblk_read_from_cache(pblk, bio, lba, ppa, 0)) {
294+
if (!pblk_read_from_cache(pblk, bio, lba, ppa, 0, 1)) {
286295
pblk_lookup_l2p_seq(pblk, &ppa, lba, 1);
287296
goto retry;
288297
}

drivers/lightnvm/pblk.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ unsigned int pblk_rb_read_to_bio_list(struct pblk_rb *rb, struct bio *bio,
670670
struct list_head *list,
671671
unsigned int max);
672672
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);
674674
unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries);
675675

676676
unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags);

0 commit comments

Comments
 (0)