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:
parent
725130bac5
commit
17347cec15
|
@ -2700,6 +2700,7 @@ struct bio *btrfs_bio_clone(struct bio *bio, gfp_t gfp_mask)
|
||||||
btrfs_bio->csum = NULL;
|
btrfs_bio->csum = NULL;
|
||||||
btrfs_bio->csum_allocated = NULL;
|
btrfs_bio->csum_allocated = NULL;
|
||||||
btrfs_bio->end_io = NULL;
|
btrfs_bio->end_io = NULL;
|
||||||
|
btrfs_bio->iter = bio->bi_iter;
|
||||||
}
|
}
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
@ -2736,6 +2737,7 @@ struct bio *btrfs_bio_clone_partial(struct bio *orig, gfp_t gfp_mask,
|
||||||
btrfs_bio->end_io = NULL;
|
btrfs_bio->end_io = NULL;
|
||||||
|
|
||||||
bio_trim(bio, offset >> 9, size >> 9);
|
bio_trim(bio, offset >> 9, size >> 9);
|
||||||
|
btrfs_bio->iter = bio->bi_iter;
|
||||||
return bio;
|
return bio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,8 @@ static int __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
|
||||||
u64 logical_offset, u32 *dst, int dio)
|
u64 logical_offset, u32 *dst, int dio)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
|
||||||
struct bio_vec *bvec;
|
struct bio_vec bvec;
|
||||||
|
struct bvec_iter iter;
|
||||||
struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio);
|
struct btrfs_io_bio *btrfs_bio = btrfs_io_bio(bio);
|
||||||
struct btrfs_csum_item *item = NULL;
|
struct btrfs_csum_item *item = NULL;
|
||||||
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
|
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
|
||||||
|
@ -177,7 +178,7 @@ static int __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
|
||||||
u64 page_bytes_left;
|
u64 page_bytes_left;
|
||||||
u32 diff;
|
u32 diff;
|
||||||
int nblocks;
|
int nblocks;
|
||||||
int count = 0, i;
|
int count = 0;
|
||||||
u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
|
u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
|
||||||
|
|
||||||
path = btrfs_alloc_path();
|
path = btrfs_alloc_path();
|
||||||
|
@ -206,8 +207,6 @@ static int __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
|
||||||
if (bio->bi_iter.bi_size > PAGE_SIZE * 8)
|
if (bio->bi_iter.bi_size > PAGE_SIZE * 8)
|
||||||
path->reada = READA_FORWARD;
|
path->reada = READA_FORWARD;
|
||||||
|
|
||||||
WARN_ON(bio->bi_vcnt <= 0);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* the free space stuff is only read when it hasn't been
|
* the free space stuff is only read when it hasn't been
|
||||||
* updated in the current transaction. So, we can safely
|
* updated in the current transaction. So, we can safely
|
||||||
|
@ -223,13 +222,13 @@ static int __btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
|
||||||
if (dio)
|
if (dio)
|
||||||
offset = logical_offset;
|
offset = logical_offset;
|
||||||
|
|
||||||
bio_for_each_segment_all(bvec, bio, i) {
|
bio_for_each_segment(bvec, bio, iter) {
|
||||||
page_bytes_left = bvec->bv_len;
|
page_bytes_left = bvec.bv_len;
|
||||||
if (count)
|
if (count)
|
||||||
goto next;
|
goto next;
|
||||||
|
|
||||||
if (!dio)
|
if (!dio)
|
||||||
offset = page_offset(bvec->bv_page) + bvec->bv_offset;
|
offset = page_offset(bvec.bv_page) + bvec.bv_offset;
|
||||||
count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
|
count = btrfs_find_ordered_sum(inode, offset, disk_bytenr,
|
||||||
(u32 *)csum, nblocks);
|
(u32 *)csum, nblocks);
|
||||||
if (count)
|
if (count)
|
||||||
|
@ -440,15 +439,15 @@ int btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
|
||||||
struct btrfs_ordered_sum *sums;
|
struct btrfs_ordered_sum *sums;
|
||||||
struct btrfs_ordered_extent *ordered = NULL;
|
struct btrfs_ordered_extent *ordered = NULL;
|
||||||
char *data;
|
char *data;
|
||||||
struct bio_vec *bvec;
|
struct bvec_iter iter;
|
||||||
|
struct bio_vec bvec;
|
||||||
int index;
|
int index;
|
||||||
int nr_sectors;
|
int nr_sectors;
|
||||||
int i, j;
|
|
||||||
unsigned long total_bytes = 0;
|
unsigned long total_bytes = 0;
|
||||||
unsigned long this_sum_bytes = 0;
|
unsigned long this_sum_bytes = 0;
|
||||||
|
int i;
|
||||||
u64 offset;
|
u64 offset;
|
||||||
|
|
||||||
WARN_ON(bio->bi_vcnt <= 0);
|
|
||||||
sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
|
sums = kzalloc(btrfs_ordered_sum_size(fs_info, bio->bi_iter.bi_size),
|
||||||
GFP_NOFS);
|
GFP_NOFS);
|
||||||
if (!sums)
|
if (!sums)
|
||||||
|
@ -465,19 +464,19 @@ int btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
|
||||||
sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
|
sums->bytenr = (u64)bio->bi_iter.bi_sector << 9;
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
bio_for_each_segment_all(bvec, bio, j) {
|
bio_for_each_segment(bvec, bio, iter) {
|
||||||
if (!contig)
|
if (!contig)
|
||||||
offset = page_offset(bvec->bv_page) + bvec->bv_offset;
|
offset = page_offset(bvec.bv_page) + bvec.bv_offset;
|
||||||
|
|
||||||
if (!ordered) {
|
if (!ordered) {
|
||||||
ordered = btrfs_lookup_ordered_extent(inode, offset);
|
ordered = btrfs_lookup_ordered_extent(inode, offset);
|
||||||
BUG_ON(!ordered); /* Logic error */
|
BUG_ON(!ordered); /* Logic error */
|
||||||
}
|
}
|
||||||
|
|
||||||
data = kmap_atomic(bvec->bv_page);
|
data = kmap_atomic(bvec.bv_page);
|
||||||
|
|
||||||
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
|
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info,
|
||||||
bvec->bv_len + fs_info->sectorsize
|
bvec.bv_len + fs_info->sectorsize
|
||||||
- 1);
|
- 1);
|
||||||
|
|
||||||
for (i = 0; i < nr_sectors; i++) {
|
for (i = 0; i < nr_sectors; i++) {
|
||||||
|
@ -504,12 +503,12 @@ int btrfs_csum_one_bio(struct inode *inode, struct bio *bio,
|
||||||
+ total_bytes;
|
+ total_bytes;
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
data = kmap_atomic(bvec->bv_page);
|
data = kmap_atomic(bvec.bv_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
sums->sums[index] = ~(u32)0;
|
sums->sums[index] = ~(u32)0;
|
||||||
sums->sums[index]
|
sums->sums[index]
|
||||||
= btrfs_csum_data(data + bvec->bv_offset
|
= btrfs_csum_data(data + bvec.bv_offset
|
||||||
+ (i * fs_info->sectorsize),
|
+ (i * fs_info->sectorsize),
|
||||||
sums->sums[index],
|
sums->sums[index],
|
||||||
fs_info->sectorsize);
|
fs_info->sectorsize);
|
||||||
|
|
|
@ -7989,6 +7989,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio,
|
||||||
struct bio *bio;
|
struct bio *bio;
|
||||||
int isector;
|
int isector;
|
||||||
int read_mode = 0;
|
int read_mode = 0;
|
||||||
|
int segs;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE);
|
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;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((failed_bio->bi_vcnt > 1)
|
segs = bio_segments(failed_bio);
|
||||||
|| (failed_bio->bi_io_vec->bv_len
|
if (segs > 1 ||
|
||||||
> btrfs_inode_sectorsize(inode)))
|
(failed_bio->bi_io_vec->bv_len > btrfs_inode_sectorsize(inode)))
|
||||||
read_mode |= REQ_FAILFAST_DEV;
|
read_mode |= REQ_FAILFAST_DEV;
|
||||||
|
|
||||||
isector = start - btrfs_io_bio(failed_bio)->logical;
|
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_io_bio *io_bio)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info;
|
struct btrfs_fs_info *fs_info;
|
||||||
struct bio_vec *bvec;
|
struct bio_vec bvec;
|
||||||
|
struct bvec_iter iter;
|
||||||
struct btrfs_retry_complete done;
|
struct btrfs_retry_complete done;
|
||||||
u64 start;
|
u64 start;
|
||||||
unsigned int pgoff;
|
unsigned int pgoff;
|
||||||
u32 sectorsize;
|
u32 sectorsize;
|
||||||
int nr_sectors;
|
int nr_sectors;
|
||||||
int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fs_info = BTRFS_I(inode)->root->fs_info;
|
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;
|
start = io_bio->logical;
|
||||||
done.inode = inode;
|
done.inode = inode;
|
||||||
|
io_bio->bio.bi_iter = io_bio->iter;
|
||||||
|
|
||||||
bio_for_each_segment_all(bvec, &io_bio->bio, i) {
|
bio_for_each_segment(bvec, &io_bio->bio, iter) {
|
||||||
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len);
|
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec.bv_len);
|
||||||
pgoff = bvec->bv_offset;
|
pgoff = bvec.bv_offset;
|
||||||
|
|
||||||
next_block_or_try_again:
|
next_block_or_try_again:
|
||||||
done.uptodate = 0;
|
done.uptodate = 0;
|
||||||
done.start = start;
|
done.start = start;
|
||||||
init_completion(&done.done);
|
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,
|
pgoff, start, start + sectorsize - 1,
|
||||||
io_bio->mirror_num,
|
io_bio->mirror_num,
|
||||||
btrfs_retry_endio_nocsum, &done);
|
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_io_bio *io_bio, int err)
|
||||||
{
|
{
|
||||||
struct btrfs_fs_info *fs_info;
|
struct btrfs_fs_info *fs_info;
|
||||||
struct bio_vec *bvec;
|
struct bio_vec bvec;
|
||||||
|
struct bvec_iter iter;
|
||||||
struct btrfs_retry_complete done;
|
struct btrfs_retry_complete done;
|
||||||
u64 start;
|
u64 start;
|
||||||
u64 offset = 0;
|
u64 offset = 0;
|
||||||
|
@ -8174,7 +8177,6 @@ static int __btrfs_subio_endio_read(struct inode *inode,
|
||||||
int nr_sectors;
|
int nr_sectors;
|
||||||
unsigned int pgoff;
|
unsigned int pgoff;
|
||||||
int csum_pos;
|
int csum_pos;
|
||||||
int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fs_info = BTRFS_I(inode)->root->fs_info;
|
fs_info = BTRFS_I(inode)->root->fs_info;
|
||||||
|
@ -8183,15 +8185,16 @@ static int __btrfs_subio_endio_read(struct inode *inode,
|
||||||
err = 0;
|
err = 0;
|
||||||
start = io_bio->logical;
|
start = io_bio->logical;
|
||||||
done.inode = inode;
|
done.inode = inode;
|
||||||
|
io_bio->bio.bi_iter = io_bio->iter;
|
||||||
|
|
||||||
bio_for_each_segment_all(bvec, &io_bio->bio, i) {
|
bio_for_each_segment(bvec, &io_bio->bio, iter) {
|
||||||
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len);
|
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec.bv_len);
|
||||||
|
|
||||||
pgoff = bvec->bv_offset;
|
pgoff = bvec.bv_offset;
|
||||||
next_block:
|
next_block:
|
||||||
csum_pos = BTRFS_BYTES_TO_BLKS(fs_info, offset);
|
csum_pos = BTRFS_BYTES_TO_BLKS(fs_info, offset);
|
||||||
ret = __readpage_endio_check(inode, io_bio, csum_pos,
|
ret = __readpage_endio_check(inode, io_bio, csum_pos,
|
||||||
bvec->bv_page, pgoff, start,
|
bvec.bv_page, pgoff, start,
|
||||||
sectorsize);
|
sectorsize);
|
||||||
if (likely(!ret))
|
if (likely(!ret))
|
||||||
goto next;
|
goto next;
|
||||||
|
@ -8200,7 +8203,7 @@ static int __btrfs_subio_endio_read(struct inode *inode,
|
||||||
done.start = start;
|
done.start = start;
|
||||||
init_completion(&done.done);
|
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,
|
pgoff, start, start + sectorsize - 1,
|
||||||
io_bio->mirror_num,
|
io_bio->mirror_num,
|
||||||
btrfs_retry_endio, &done);
|
btrfs_retry_endio, &done);
|
||||||
|
|
|
@ -280,6 +280,7 @@ struct btrfs_io_bio {
|
||||||
u8 csum_inline[BTRFS_BIO_INLINE_CSUM_SIZE];
|
u8 csum_inline[BTRFS_BIO_INLINE_CSUM_SIZE];
|
||||||
u8 *csum_allocated;
|
u8 *csum_allocated;
|
||||||
btrfs_io_bio_end_io_t *end_io;
|
btrfs_io_bio_end_io_t *end_io;
|
||||||
|
struct bvec_iter iter;
|
||||||
struct bio bio;
|
struct bio bio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue