Btrfs: change how we iterate bios in endio

Since dio submit has used bio_clone_fast, the submitted bio may not have a
reliable bi_vcnt, for the bio vector iterations in checksum related
functions, bio->bi_iter is not modified yet and it's safe to use
bio_for_each_segment, while for those bio vector iterations in dio read's
endio, we now save a copy of bvec_iter in struct btrfs_io_bio when cloning
bios and use the helper __bio_for_each_segment with the saved bvec_iter to
access each bvec.

Also for dio reads which don't get split, we also need to save a copy of
bio iterator in btrfs_bio_clone to let __bio_for_each_segments to access
each bvec in dio read's endio.  Note that it doesn't affect other calls of
btrfs_bio_clone() because they don't need to use this iterator.

Signed-off-by: Liu Bo <bo.li.liu@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Liu Bo 2017-05-15 15:33:27 -07:00 committed by David Sterba
parent 725130bac5
commit 17347cec15
4 changed files with 37 additions and 32 deletions

View file

@ -7989,6 +7989,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio,
struct bio *bio;
int isector;
int read_mode = 0;
int segs;
int ret;
BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
@ -8004,9 +8005,9 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio,
return -EIO;
}
if ((failed_bio->bi_vcnt > 1)
|| (failed_bio->bi_io_vec->bv_len
> btrfs_inode_sectorsize(inode)))
segs = bio_segments(failed_bio);
if (segs > 1 ||
(failed_bio->bi_io_vec->bv_len > btrfs_inode_sectorsize(inode)))
read_mode |= REQ_FAILFAST_DEV;
isector = start - btrfs_io_bio(failed_bio)->logical;
@ -8069,13 +8070,13 @@ static int __btrfs_correct_data_nocsum(struct inode *inode,
struct btrfs_io_bio *io_bio)
{
struct btrfs_fs_info *fs_info;
struct bio_vec *bvec;
struct bio_vec bvec;
struct bvec_iter iter;
struct btrfs_retry_complete done;
u64 start;
unsigned int pgoff;
u32 sectorsize;
int nr_sectors;
int i;
int ret;
fs_info = BTRFS_I(inode)->root->fs_info;
@ -8083,17 +8084,18 @@ static int __btrfs_correct_data_nocsum(struct inode *inode,
start = io_bio->logical;
done.inode = inode;
io_bio->bio.bi_iter = io_bio->iter;
bio_for_each_segment_all(bvec, &io_bio->bio, i) {
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len);
pgoff = bvec->bv_offset;
bio_for_each_segment(bvec, &io_bio->bio, iter) {
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec.bv_len);
pgoff = bvec.bv_offset;
next_block_or_try_again:
done.uptodate = 0;
done.start = start;
init_completion(&done.done);
ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page,
ret = dio_read_error(inode, &io_bio->bio, bvec.bv_page,
pgoff, start, start + sectorsize - 1,
io_bio->mirror_num,
btrfs_retry_endio_nocsum, &done);
@ -8166,7 +8168,8 @@ static int __btrfs_subio_endio_read(struct inode *inode,
struct btrfs_io_bio *io_bio, int err)
{
struct btrfs_fs_info *fs_info;
struct bio_vec *bvec;
struct bio_vec bvec;
struct bvec_iter iter;
struct btrfs_retry_complete done;
u64 start;
u64 offset = 0;
@ -8174,7 +8177,6 @@ static int __btrfs_subio_endio_read(struct inode *inode,
int nr_sectors;
unsigned int pgoff;
int csum_pos;
int i;
int ret;
fs_info = BTRFS_I(inode)->root->fs_info;
@ -8183,15 +8185,16 @@ static int __btrfs_subio_endio_read(struct inode *inode,
err = 0;
start = io_bio->logical;
done.inode = inode;
io_bio->bio.bi_iter = io_bio->iter;
bio_for_each_segment_all(bvec, &io_bio->bio, i) {
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len);
bio_for_each_segment(bvec, &io_bio->bio, iter) {
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec.bv_len);
pgoff = bvec->bv_offset;
pgoff = bvec.bv_offset;
next_block:
csum_pos = BTRFS_BYTES_TO_BLKS(fs_info, offset);
ret = __readpage_endio_check(inode, io_bio, csum_pos,
bvec->bv_page, pgoff, start,
bvec.bv_page, pgoff, start,
sectorsize);
if (likely(!ret))
goto next;
@ -8200,7 +8203,7 @@ try_again:
done.start = start;
init_completion(&done.done);
ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page,
ret = dio_read_error(inode, &io_bio->bio, bvec.bv_page,
pgoff, start, start + sectorsize - 1,
io_bio->mirror_num,
btrfs_retry_endio, &done);