aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--block/io.c15
-rw-r--r--include/block/block_int.h37
2 files changed, 29 insertions, 23 deletions
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 */