The block layer uses the queue's virt_boundary to enforce alignment between vectors, but iov_iter_gap_alignment() returned the starting address or'ed with all but the last the length. Fix it to return alignment for each vector's starting address except the first, and each vector's ending address except the last. Signed-off-by: Keith Busch <kbusch@xxxxxxxxxx> --- lib/iov_iter.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 51595bf3af85..9cfaf2fd5cfd 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1252,12 +1252,12 @@ unsigned long iov_iter_gap_alignment(const struct iov_iter *i) } iterate_all_kinds(i, size, v, - (res |= (!res ? 0 : (unsigned long)v.iov_base) | - (size != v.iov_len ? size : 0), 0), - (res |= (!res ? 0 : (unsigned long)v.bv_offset) | - (size != v.bv_len ? size : 0)), - (res |= (!res ? 0 : (unsigned long)v.iov_base) | - (size != v.iov_len ? size : 0)) + (res |= (size == i->count ? 0 : (unsigned long)v.iov_base) | + (size == v.iov_len ? 0 : (unsigned long)v.iov_base + v.iov_len), 0), + res |= (size == i->count ? 0 : v.bv_offset) | + (size == v.bv_len ? 0 : v.bv_offset + v.bv_len), + res |= (size == i->count ? 0 : (unsigned long)v.iov_base) | + (size == v.iov_len ? 0 : (unsigned long)v.iov_base + v.iov_len) ); return res; } -- 2.24.1