Never mind, I guess I was wrong, coz bio_add_page() is always called with "offset" = 0 here, so: offset == bv->bv_offset + bv->bv_len is never matched. Hence, if (bio->bi_vcnt >= bio->bi_max_vecs) return 0; will trigger the if-break. So maybe this is after all just a dm-crypt issue on handling multiple bios created with next_bio (a bio chain)? On 10 August 2017 at 07:27, Tom Yan <tom.ty89@xxxxxxxxx> wrote: > I haven't really tested but I was aware of the commit before I send my > last email. It doesn't seem relevant to be honest, because it doesn't > change the fact that the inner loop wil only end if the whole request > has been looped over. So still one big bio. > > There are a few things that seem suspicious to me. First of all, the > inner loop has an if-break at its end that seem to practically do > nothing, especially in terms of making the inner loop end when the bio > reach its expected size (BIO_MAX_PAGES?). > > bi_size = bio_add_page(bio, ZERO_PAGE(0), sz, 0); > > If you take a look at bio_add_page(): > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/block/bio.c?h=v4.13-rc4#n820 > > it will basically always return "len", which is "sz" here, unchanged. > > if (bi_size < sz) > break; > > So this pretty much never happens, with two exceptions: > > if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED))) > return 0; > > which is most likely irrelevant in this case, > > if (bio->bi_vcnt >= bio->bi_max_vecs) > return 0; > > which seem to matter in this case. However: > > if (page == bv->bv_page && > offset == bv->bv_offset + bv->bv_len) { > bv->bv_len += len; > goto done; > } > ... > if (bio->bi_vcnt >= bio->bi_max_vecs) > return 0; > ... > bio->bi_vcnt++; > done: > bio->bi_iter.bi_size += len; > return len; > > So if the first condition in the above quote is matched, the exception > would never happen either. > > On 9 August 2017 at 21:38, hch@xxxxxx <hch@xxxxxx> wrote: >> Does commit 615d22a51c04856efe62af6e1d5b450aaf5cc2c0 >> "block: Fix __blkdev_issue_zeroout loop" fix the issue for you?