This change has no semantic impact: all drivers either leave the value at 0 (no inherent 32-bit limit is still translated into fragmentation below 2G; see the previous patch for that audit), or set it to a value less than 2G. However, switching to a larger type and enforcing the 2G cap at the block layer makes it easier to audit specific drivers for their robustness to larger sizing, by letting them specify a value larger than INT_MAX if they have been audited to be 64-bit clean.
Signed-off-by: Eric Blake <ebl...@redhat.com> --- include/block/block_int.h | 8 +++++--- block/io.c | 7 +++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/block/block_int.h b/include/block/block_int.h index f605622216d..b19d94dac5f 100644 --- a/include/block/block_int.h +++ b/include/block/block_int.h @@ -549,9 +549,11 @@ typedef struct BlockLimits { /* 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; + * for no 32-bit limit. The block layer fragments all actions + * below 2G, so setting this value to anything larger than INT_MAX + * implies that the driver has been audited for 64-bit + * cleanness. */ + uint64_t max_transfer; /* memory alignment, in bytes so that no bounce buffer is needed */ size_t min_mem_alignment; diff --git a/block/io.c b/block/io.c index 39d4e7a3ae1..4911a1123eb 100644 --- a/block/io.c +++ b/block/io.c @@ -159,6 +159,13 @@ void bdrv_refresh_limits(BlockDriverState *bs, Error **errp) if (drv->bdrv_refresh_limits) { drv->bdrv_refresh_limits(bs, errp); } + + /* Clamp max_transfer to 2G */ + if (bs->bl.max_transfer > UINT32_MAX) { + bs->bl.max_transfer = QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES, + MAX(bs->bl.opt_transfer, + bs->bl.request_alignment)); + } } /** -- 2.17.2