On Sat, Apr 06, 2019 at 09:53:07AM +0800, Qu Wenruo wrote:
> Hi,
>
> I'm looking into a strange behavior that we can't break
> bio_for_each_segment_all() after commit 6dc4f100c175 ("block: allow
> bio_for_each_segment_all() to iterate over multi-page bvec").
>
> It's screwing up all bio_for_each_segment_all() call with error out branch.
>
>
> There is one relatively easy to trigger setup.
>
> Here is my kernel branch, which is based on David Sterb's misc-next branch:
> https://github.com/adam900710/linux/tree/tree_checker_testing
>
> It's just two commits ahead.
>
> Then some debug diff:
>
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index c2c0640aea55..05c880a5254b 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -851,16 +851,22 @@ static blk_status_t btree_csum_one_bio(struct bio
> *bio)
> struct bio_vec *bvec;
> struct btrfs_root *root;
> int i, ret = 0;
> + int err = 0;
> struct bvec_iter_all iter_all;
>
> ASSERT(!bio_flagged(bio, BIO_CLONED));
> bio_for_each_segment_all(bvec, bio, i, iter_all) {
> root = BTRFS_I(bvec->bv_page->mapping->host)->root;
> ret = csum_dirty_buffer(root->fs_info, bvec->bv_page);
> - if (ret)
> + if (ret) {
> + err = ret;
> + pr_info("breaking out with ret=%d\n", ret);
> break;
> + }
> }
>
> + if (err)
> + pr_info("err=%d out, but ret=%d\n",err, ret);
> return errno_to_blk_status(ret);
> }
>
> Straightforward, if we break, we should have err == ret.
>
Thanks for the report, and it should be easy to fix, will post patch
soon.
Thanks,
Ming