Commit 97861cd1 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by David Sterba
Browse files

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: default avatarNikolay Borisov <nborisov@suse.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
[ update changelog ]
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent a5aa7ab6
Loading
Loading
Loading
Loading
+40 −46
Original line number Diff line number Diff line
@@ -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 (ret)
				if (btrfs_validate_metadata_buffer(bbio,
						page, start, end, mirror))
					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,15 +3098,41 @@ 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);
		}
		ASSERT(bio_offset + len > bio_offset);
		bio_offset += len;

		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;

	}
	/* Release the last extent */
	endio_readpage_release_extent(&processed, NULL, 0, 0, false);
	btrfs_bio_free_csum(bbio);