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. Then run fstests btrfs/151, which will trigger a false alert in tree-checker: BTRFS critical (device dm-1): corrupt leaf: root=3 block=570572800 slot=1 devid=1 invalid total bytes: have 0 BTRFS error (device dm-1): block=570572800 write time tree block corruption detected breaking out with ret=-117 err=-117 out, but ret=0 So it looks like the break line doens't really break, but continue executing. Thanks, Qu
Attachment:
signature.asc
Description: OpenPGP digital signature