summaryrefslogtreecommitdiffstats
path: root/drivers/lightnvm
diff options
context:
space:
mode:
authorJavier González <jg@lightnvm.io>2017-07-28 09:13:16 -0400
committerJens Axboe <axboe@kernel.dk>2017-07-28 10:06:00 -0400
commit75cb8e939cf30ebdfffd9b28566d8aead95138a8 (patch)
tree867ba4c5211487b1aa5907302054efc7bead8ec4 /drivers/lightnvm
parent5a60f4b6da95b91d17425923fa61e1844af0aff0 (diff)
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>
Diffstat (limited to 'drivers/lightnvm')
-rw-r--r--drivers/lightnvm/pblk-rb.c4
-rw-r--r--drivers/lightnvm/pblk-read.c23
-rw-r--r--drivers/lightnvm/pblk.h2
3 files changed, 19 insertions, 10 deletions
diff --git a/drivers/lightnvm/pblk-rb.c b/drivers/lightnvm/pblk-rb.c
index 5ecc154f6831..9bc32578a766 100644
--- a/drivers/lightnvm/pblk-rb.c
+++ b/drivers/lightnvm/pblk-rb.c
@@ -657,7 +657,7 @@ try:
657 * be directed to disk. 657 * be directed to disk.
658 */ 658 */
659int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba, 659int 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 struct pblk *pblk = container_of(rb, struct pblk, rwb); 662 struct pblk *pblk = container_of(rb, struct pblk, rwb);
663 struct pblk_rb_entry *entry; 663 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,
694 * filled with data from the cache). If part of the data resides on the 694 * filled with data from the cache). If part of the data resides on the
695 * media, we will read later on 695 * media, we will read later on
696 */ 696 */
697 if (unlikely(!bio->bi_iter.bi_idx)) 697 if (unlikely(!advanced_bio))
698 bio_advance(bio, bio_iter * PBLK_EXPOSED_PAGE_SIZE); 698 bio_advance(bio, bio_iter * PBLK_EXPOSED_PAGE_SIZE);
699 699
700 data = bio_data(bio); 700 data = bio_data(bio);
diff --git a/drivers/lightnvm/pblk-read.c b/drivers/lightnvm/pblk-read.c
index 4e5c48f3de62..d682e89e6493 100644
--- a/drivers/lightnvm/pblk-read.c
+++ b/drivers/lightnvm/pblk-read.c
@@ -26,7 +26,7 @@
26 */ 26 */
27static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio, 27static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio,
28 sector_t lba, struct ppa_addr ppa, 28 sector_t lba, struct ppa_addr ppa,
29 int bio_iter) 29 int bio_iter, bool advanced_bio)
30{ 30{
31#ifdef CONFIG_NVM_DEBUG 31#ifdef CONFIG_NVM_DEBUG
32 /* Callers must ensure that the ppa points to a cache address */ 32 /* Callers must ensure that the ppa points to a cache address */
@@ -34,7 +34,8 @@ static int pblk_read_from_cache(struct pblk *pblk, struct bio *bio,
34 BUG_ON(!pblk_addr_in_cache(ppa)); 34 BUG_ON(!pblk_addr_in_cache(ppa));
35#endif 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
40static void pblk_read_ppalist_rq(struct pblk *pblk, struct nvm_rq *rqd, 41static 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,
44 struct ppa_addr ppas[PBLK_MAX_REQ_ADDRS]; 45 struct ppa_addr ppas[PBLK_MAX_REQ_ADDRS];
45 sector_t blba = pblk_get_lba(bio); 46 sector_t blba = pblk_get_lba(bio);
46 int nr_secs = rqd->nr_ppas; 47 int nr_secs = rqd->nr_ppas;
47 int advanced_bio = 0; 48 bool advanced_bio = false;
48 int i, j = 0; 49 int i, j = 0;
49 50
50 /* logic error: lba out-of-bounds. Ignore read request */ 51 /* 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,
62retry: 63retry:
63 if (pblk_ppa_empty(p)) { 64 if (pblk_ppa_empty(p)) {
64 WARN_ON(test_and_set_bit(i, read_bitmap)); 65 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;
66 } 73 }
67 74
68 /* Try to read from write buffer. The address is later checked 75 /* Try to read from write buffer. The address is later checked
69 * on the write buffer to prevent retrieving overwritten data. 76 * on the write buffer to prevent retrieving overwritten data.
70 */ 77 */
71 if (pblk_addr_in_cache(p)) { 78 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)) {
73 pblk_lookup_l2p_seq(pblk, &p, lba, 1); 81 pblk_lookup_l2p_seq(pblk, &p, lba, 1);
74 goto retry; 82 goto retry;
75 } 83 }
76 WARN_ON(test_and_set_bit(i, read_bitmap)); 84 WARN_ON(test_and_set_bit(i, read_bitmap));
77 advanced_bio = 1; 85 advanced_bio = true;
78#ifdef CONFIG_NVM_DEBUG 86#ifdef CONFIG_NVM_DEBUG
79 atomic_long_inc(&pblk->cache_reads); 87 atomic_long_inc(&pblk->cache_reads);
80#endif 88#endif
@@ -83,6 +91,7 @@ retry:
83 rqd->ppa_list[j++] = p; 91 rqd->ppa_list[j++] = p;
84 } 92 }
85 93
94next:
86 if (advanced_bio) 95 if (advanced_bio)
87 bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE); 96 bio_advance(bio, PBLK_EXPOSED_PAGE_SIZE);
88 } 97 }
@@ -282,7 +291,7 @@ retry:
282 * write buffer to prevent retrieving overwritten data. 291 * write buffer to prevent retrieving overwritten data.
283 */ 292 */
284 if (pblk_addr_in_cache(ppa)) { 293 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)) {
286 pblk_lookup_l2p_seq(pblk, &ppa, lba, 1); 295 pblk_lookup_l2p_seq(pblk, &ppa, lba, 1);
287 goto retry; 296 goto retry;
288 } 297 }
diff --git a/drivers/lightnvm/pblk.h b/drivers/lightnvm/pblk.h
index 0c5692cc2f60..67e623bd5c2d 100644
--- a/drivers/lightnvm/pblk.h
+++ b/drivers/lightnvm/pblk.h
@@ -670,7 +670,7 @@ unsigned int pblk_rb_read_to_bio_list(struct pblk_rb *rb, struct bio *bio,
670 struct list_head *list, 670 struct list_head *list,
671 unsigned int max); 671 unsigned int max);
672int pblk_rb_copy_to_bio(struct pblk_rb *rb, struct bio *bio, sector_t lba, 672int 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);
674unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries); 674unsigned int pblk_rb_read_commit(struct pblk_rb *rb, unsigned int entries);
675 675
676unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags); 676unsigned int pblk_rb_sync_init(struct pblk_rb *rb, unsigned long *flags);