btrfs: refactor end_bio_extent_readpage code flow

Untangle the goto and move the code it jumps to so it goes in the order
of the most likely states first.

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Christoph Hellwig 2022-05-22 13:47:51 +02:00 committed by David Sterba
parent a5aa7ab6e7
commit 97861cd166

View file

@ -3017,7 +3017,6 @@ static void end_bio_extent_readpage(struct bio *bio)
*/
u32 bio_offset = 0;
int mirror;
int ret;
struct bvec_iter_all iter_all;
ASSERT(!bio_flagged(bio, BIO_CLONED));
@ -3028,6 +3027,7 @@ static void end_bio_extent_readpage(struct bio *bio)
struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
const u32 sectorsize = fs_info->sectorsize;
unsigned int error_bitmap = (unsigned int)-1;
bool repair = false;
u64 start;
u64 end;
u32 len;
@ -3065,55 +3065,23 @@ static void end_bio_extent_readpage(struct bio *bio)
if (is_data_inode(inode)) {
error_bitmap = btrfs_verify_data_csum(bbio,
bio_offset, page, start, end);
ret = error_bitmap;
if (error_bitmap)
uptodate = false;
} else {
ret = btrfs_validate_metadata_buffer(bbio,
page, start, end, mirror);
if (btrfs_validate_metadata_buffer(bbio,
page, start, end, mirror))
uptodate = false;
}
if (ret)
uptodate = false;
else
clean_io_failure(BTRFS_I(inode)->root->fs_info,
failure_tree, tree, start,
page,
btrfs_ino(BTRFS_I(inode)), 0);
}
if (likely(uptodate))
goto readpage_ok;
if (is_data_inode(inode)) {
/*
* If we failed to submit the IO at all we'll have a
* mirror_num == 0, in which case we need to just mark
* the page with an error and unlock it and carry on.
*/
if (mirror == 0)
goto readpage_ok;
/*
* submit_data_read_repair() will handle all the good
* and bad sectors, we just continue to the next bvec.
*/
submit_data_read_repair(inode, bio, bio_offset, bvec,
mirror, error_bitmap);
ASSERT(bio_offset + len > bio_offset);
bio_offset += len;
continue;
} else {
struct extent_buffer *eb;
eb = find_extent_buffer_readpage(fs_info, page, start);
set_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
eb->read_mirror = mirror;
atomic_dec(&eb->io_pages);
}
readpage_ok:
if (likely(uptodate)) {
loff_t i_size = i_size_read(inode);
pgoff_t end_index = i_size >> PAGE_SHIFT;
clean_io_failure(BTRFS_I(inode)->root->fs_info,
failure_tree, tree, start, page,
btrfs_ino(BTRFS_I(inode)), 0);
/*
* Zero out the remaining part if this range straddles
* i_size.
@ -3130,14 +3098,40 @@ static void end_bio_extent_readpage(struct bio *bio)
zero_user_segment(page, zero_start,
offset_in_page(end) + 1);
}
} else if (is_data_inode(inode)) {
/*
* Only try to repair bios that actually made it to a
* device. If the bio failed to be submitted mirror
* is 0 and we need to fail it without retrying.
*/
if (mirror > 0)
repair = true;
} else {
struct extent_buffer *eb;
eb = find_extent_buffer_readpage(fs_info, page, start);
set_bit(EXTENT_BUFFER_READ_ERR, &eb->bflags);
eb->read_mirror = mirror;
atomic_dec(&eb->io_pages);
}
if (repair) {
/*
* submit_data_read_repair() will handle all the good
* and bad sectors, we just continue to the next bvec.
*/
submit_data_read_repair(inode, bio, bio_offset, bvec,
mirror, error_bitmap);
} else {
/* Update page status and unlock */
end_page_read(page, uptodate, start, len);
endio_readpage_release_extent(&processed, BTRFS_I(inode),
start, end, PageUptodate(page));
}
ASSERT(bio_offset + len > bio_offset);
bio_offset += len;
/* Update page status and unlock */
end_page_read(page, uptodate, start, len);
endio_readpage_release_extent(&processed, BTRFS_I(inode),
start, end, PageUptodate(page));
}
/* Release the last extent */
endio_readpage_release_extent(&processed, NULL, 0, 0, false);