diff --git a/block/io.c b/block/io.c index 7323f0fb7b..d5493ba349 100644 --- a/block/io.c +++ b/block/io.c @@ -1180,10 +1180,11 @@ static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int alignment = MAX(bs->bl.pwrite_zeroes_alignment, bs->bl.request_alignment); - assert(is_power_of_2(alignment)); - head = offset & (alignment - 1); - tail = (offset + count) & (alignment - 1); - max_write_zeroes &= ~(alignment - 1); + assert(alignment % bs->bl.request_alignment == 0); + head = offset % alignment; + tail = (offset + count) % alignment; + max_write_zeroes = QEMU_ALIGN_DOWN(max_write_zeroes, alignment); + assert(max_write_zeroes >= bs->bl.request_alignment); while (count > 0 && !ret) { int num = count; @@ -2429,9 +2430,10 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, /* Discard is advisory, so ignore any unaligned head or tail */ align = MAX(bs->bl.pdiscard_alignment, bs->bl.request_alignment); - assert(is_power_of_2(align)); - head = MIN(count, -offset & (align - 1)); + assert(align % bs->bl.request_alignment == 0); + head = offset % align; if (head) { + head = MIN(count, align - head); count -= head; offset += head; } @@ -2449,6 +2451,7 @@ int coroutine_fn bdrv_co_pdiscard(BlockDriverState *bs, int64_t offset, max_pdiscard = QEMU_ALIGN_DOWN(MIN_NON_ZERO(bs->bl.max_pdiscard, INT_MAX), align); + assert(max_pdiscard); while (count > 0) { int ret; diff --git a/include/block/block_int.h b/include/block/block_int.h index 1fe0fd9ff6..47665be81e 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -330,36 +330,39 @@ typedef struct BlockLimits { * otherwise. */ uint32_t request_alignment; - /* maximum number of bytes that can be discarded at once (since it - * is signed, it must be < 2G, if set), should be multiple of + /* Maximum number of bytes that can be discarded at once (since it + * is signed, it must be < 2G, if set). Must be multiple of * pdiscard_alignment, but need not be power of 2. May be 0 if no * inherent 32-bit limit */ int32_t max_pdiscard; - /* optimal alignment for discard requests in bytes, must be power - * of 2, less than max_pdiscard if that is set, and multiple of - * bl.request_alignment. May be 0 if bl.request_alignment is good - * enough */ + /* Optimal alignment for discard requests in bytes. A power of 2 + * is best but not mandatory. Must be a multiple of + * bl.request_alignment, and must be less than max_pdiscard if + * that is set. May be 0 if bl.request_alignment is good enough */ uint32_t pdiscard_alignment; - /* maximum number of bytes that can zeroized at once (since it is - * signed, it must be < 2G, if set), should be multiple of + /* Maximum number of bytes that can zeroized at once (since it is + * signed, it must be < 2G, if set). Must be multiple of * pwrite_zeroes_alignment. May be 0 if no inherent 32-bit limit */ int32_t max_pwrite_zeroes; - /* optimal alignment for write zeroes requests in bytes, must be - * power of 2, less than max_pwrite_zeroes if that is set, and - * multiple of bl.request_alignment. May be 0 if - * bl.request_alignment is good enough */ + /* Optimal alignment for write zeroes requests in bytes. A power + * of 2 is best but not mandatory. Must be a multiple of + * bl.request_alignment, and must be less than max_pwrite_zeroes + * if that is set. May be 0 if bl.request_alignment is good + * enough */ uint32_t pwrite_zeroes_alignment; - /* optimal transfer length in bytes (must be power of 2, and - * multiple of bl.request_alignment), or 0 if no preferred size */ + /* Optimal transfer length in bytes. A power of 2 is best but not + * mandatory. Must be a multiple of bl.request_alignment, or 0 if + * no preferred size */ uint32_t opt_transfer; - /* maximal transfer length in bytes (need not be power of 2, but - * should be multiple of opt_transfer), or 0 for no 32-bit limit. - * For now, anything larger than INT_MAX is clamped down. */ + /* Maximal transfer length in bytes. Need not be power of 2, but + * must be multiple of opt_transfer and bl.request_alignment, or 0 + * for no 32-bit limit. For now, anything larger than INT_MAX is + * clamped down. */ uint32_t max_transfer; /* memory alignment, in bytes so that no bounce buffer is needed */