diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2014-01-21 23:32:05 -0500 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2014-01-21 23:32:05 -0500 |
commit | 5837c80e870bc3b12ac6a98cdc9ce7a9522a8fb6 (patch) | |
tree | 35b9a82820cf87bb133d4773e416a8d3b293b604 /fs/bio-integrity.c | |
parent | bca266b3886b8bc587db044750c8a00d674b4d09 (diff) |
bio-integrity: Fix bio_integrity_verify segment start bug
This patch addresses a bug in bio_integrity_verify() code that has
been causing DIF READ verify operations to be silently skipped.
The issue is that bio->bi_idx will have been incremented within
bio_advance() code in the normal blk_update_request() ->
req_bio_endio() completion path, and bio_integrity_verify() is
using bio_for_each_segment() which starts the bio segment walk
at the current bio->bi_idx.
So instead use bio_for_each_segment_all() to always start the bio
segment walk from zero, regardless of the current bio->bi_idx
value after bio_advance() has been called.
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Cc: stable@kernel.dk # >= v3.10
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/bio-integrity.c')
-rw-r--r-- | fs/bio-integrity.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/fs/bio-integrity.c b/fs/bio-integrity.c index 80d972d739e5..0bad24ddc2e7 100644 --- a/fs/bio-integrity.c +++ b/fs/bio-integrity.c | |||
@@ -447,20 +447,21 @@ static int bio_integrity_verify(struct bio *bio) | |||
447 | { | 447 | { |
448 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); | 448 | struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev); |
449 | struct blk_integrity_exchg bix; | 449 | struct blk_integrity_exchg bix; |
450 | struct bio_vec bv; | 450 | struct bio_vec *bv; |
451 | struct bvec_iter iter; | ||
452 | sector_t sector = bio->bi_integrity->bip_iter.bi_sector; | 451 | sector_t sector = bio->bi_integrity->bip_iter.bi_sector; |
453 | unsigned int sectors, total, ret; | 452 | unsigned int sectors, total, ret; |
454 | void *prot_buf = bio->bi_integrity->bip_buf; | 453 | void *prot_buf = bio->bi_integrity->bip_buf; |
454 | int i; | ||
455 | 455 | ||
456 | ret = total = 0; | 456 | ret = total = 0; |
457 | bix.disk_name = bio->bi_bdev->bd_disk->disk_name; | 457 | bix.disk_name = bio->bi_bdev->bd_disk->disk_name; |
458 | bix.sector_size = bi->sector_size; | 458 | bix.sector_size = bi->sector_size; |
459 | 459 | ||
460 | bio_for_each_segment(bv, bio, iter) { | 460 | bio_for_each_segment_all(bv, bio, i) { |
461 | void *kaddr = kmap_atomic(bv.bv_page); | 461 | void *kaddr = kmap_atomic(bv->bv_page); |
462 | bix.data_buf = kaddr + bv.bv_offset; | 462 | |
463 | bix.data_size = bv.bv_len; | 463 | bix.data_buf = kaddr + bv->bv_offset; |
464 | bix.data_size = bv->bv_len; | ||
464 | bix.prot_buf = prot_buf; | 465 | bix.prot_buf = prot_buf; |
465 | bix.sector = sector; | 466 | bix.sector = sector; |
466 | 467 | ||
@@ -471,7 +472,7 @@ static int bio_integrity_verify(struct bio *bio) | |||
471 | return ret; | 472 | return ret; |
472 | } | 473 | } |
473 | 474 | ||
474 | sectors = bv.bv_len / bi->sector_size; | 475 | sectors = bv->bv_len / bi->sector_size; |
475 | sector += sectors; | 476 | sector += sectors; |
476 | prot_buf += sectors * bi->tuple_size; | 477 | prot_buf += sectors * bi->tuple_size; |
477 | total += sectors * bi->tuple_size; | 478 | total += sectors * bi->tuple_size; |