diff --git a/module/os/linux/zfs/abd_os.c b/module/os/linux/zfs/abd_os.c index 2a31111bb3..3774a9c3de 100644 --- a/module/os/linux/zfs/abd_os.c +++ b/module/os/linux/zfs/abd_os.c @@ -1055,12 +1055,16 @@ bio_map(struct bio *bio, void *buf_ptr, unsigned int bio_size) is_split = B_FALSE; } else if (offset != 0) { + ASSERT(!is_split); + /* * This is a split page, so we need to ensure that we * have room for the tail within this bio. */ - if ((i + 1) == bio->bi_max_vecs) + if ((i + 1) == bio->bi_max_vecs) { + cmn_err(CE_NOTE, "bio_map: avoided misalignment! bio %p", bio); break; + } /* Take up to the end of the page */ size = PAGE_SIZE - offset; @@ -1094,6 +1098,9 @@ bio_map(struct bio *bio, void *buf_ptr, unsigned int bio_size) offset = 0; } + if (is_split) + cmn_err(CE_WARN, "bio_map: still split at exit! bio %p size %lu vecs %lu", bio, BIO_BI_SIZE(bio), bio->bi_vcnt); + return (bio_size); } @@ -1167,12 +1174,16 @@ abd_bio_map_off(struct bio *bio, abd_t *abd, is_split = B_FALSE; } else if (pgoff != 0) { + ASSERT(!is_split); + /* * This is a split page, so we need to ensure that we * have room for the tail within this bio. */ - if ((i + 1) == bio->bi_max_vecs) + if ((i + 1) == bio->bi_max_vecs) { + cmn_err(CE_NOTE, "abd_bio_map_off: avoided misalignment! bio %p", bio); break; + } /* Take up to the end of the page */ len = PAGE_SIZE - pgoff; @@ -1196,6 +1207,9 @@ abd_bio_map_off(struct bio *bio, abd_t *abd, abd_iter_advance(&aiter, len); } + if (is_split) + cmn_err(CE_WARN, "abd_bio_map_off: still split at exit! bio %p size %lu vecs %lu", bio, BIO_BI_SIZE(bio), bio->bi_vcnt); + return (io_size); } diff --git a/module/os/linux/zfs/vdev_disk.c b/module/os/linux/zfs/vdev_disk.c index 0ed1a112f5..0108b42478 100644 --- a/module/os/linux/zfs/vdev_disk.c +++ b/module/os/linux/zfs/vdev_disk.c @@ -693,6 +693,14 @@ retry: bio_size = abd_bio_map_off(dr->dr_bio[i], zio->io_abd, bio_size, abd_offset); + if (BIO_BI_SIZE(dr->dr_bio[i]) & 0xfff) { + cmn_err(CE_WARN, "misaligned bio! zio %p bio %p offset %lu size %lu vecs %lu", zio, dr->dr_bio[i], bio_offset, BIO_BI_SIZE(dr->dr_bio[i]), dr->dr_bio[i]->bi_vcnt); + for (int bi = 0; bi < dr->dr_bio[i]->bi_vcnt; bi++) { + struct bio_vec *bv = &dr->dr_bio[i]->bi_io_vec[bi]; + cmn_err(CE_WARN, " %02x: off %lu len %lu", bi, bv->bv_offset, bv->bv_len); + } + } + /* Advance in buffer and construct another bio if needed */ abd_offset += BIO_BI_SIZE(dr->dr_bio[i]); bio_offset += BIO_BI_SIZE(dr->dr_bio[i]);