[GEDI] [PATCH v3 04/17] block/io: use int64_t bytes in driver wrappers

Vladimir Sementsov-Ogievskiy vsementsov at virtuozzo.com
Thu Apr 30 11:10:20 UTC 2020


We are generally moving to int64_t for both offset and bytes parameters
on all io paths.

Main motivation is realization of 64-bit write_zeroes operation for
fast zeroing large disk chunks, up to the whole disk.

We chose signed type, to be consistent with off_t (which is signed) and
with possibility for signed return type (where negative value means
error).

So, convert driver wrappers parameters which are already 64bit to
signed type.

Patch-correctness audit by Eric Blake:

  bdrv_driver_preadv

    Remains 64 bits, the question is whether any caller could pass in
    something larger than 63 bits.  Callers are:

    bdrv_co_do_copy_on_readv() - passes 'int64_t pnum', but sets pnum
      in a fragmenting loop, MAX_BOUNCE_BUFFER when copy-on-read is
      needed, or max_transfer bounded by BDRV_REQUEST_MAX_BYTES
      otherwise
    bdrv_aligned_preadv() - passes 'unsigned int bytes' further limited
      by fragmenting loop on max_transfer <= INT_MAX

    Input is bounded to < 2G, internal use of 'bytes' is:

    drv->bdrv_co_preadv_part(uint64_t) - safe
    qemu_iovec_init_slice(size_t) - potential truncation on 32-bit
      platform [*]
    drv->bdrv_co_preadv(uint64_t) - safe
    drv->bdrv_aio_preadv(uint64_t) - safe
    drv->bdrv_co_readv(int) after assertion of <2G - safe

  bdrv_driver_pwritev

    Remains 64 bits, the question is whether any caller could pass in
    something larger than 63.  Callers are:

    bdrv_co_do_copy_on_readv() - passes 'int64_t pnum', but set in a
      fragmenting loop bounded by MAX_BOUNCE_BUFFER
    bdrv_co_do_pwrite_zeroes() - passes 'int num'
    bdrv_aligned_pwritev() - passes 'unsigned int bytes' further
      limited by fragmenting loop on max_transfer <= INT_MAX

    Input is bounded to < 2G, internal use of 'bytes' is:

    drv->bdrv_co_pwritev_part(uint64_t) - safe
    qemu_iovec_init_slice(size_t) - potential truncation on 32-bit
      platform [*]
    drv->bdrv_co_pwritev(uint64_t) - safe
    drv->bdrv_aio_pwritev(uint64_t) - safe
    drv->bdrv_co_writev(int) after assertion of <2G - safe

  bdrv_driver_pwritev_compressed

    bdrv_aligned_pwritev() - passes 'unsigned int bytes'

    Input is bounded to < 4G, internal use of 'bytes' is:

    drv->bdrv_co_pwritev_compressed_part(uint64_t) - safe
    drv->bdrv_co_pwritev_compressed(uint64_t) - safe
    qemu_iovec_init_slice(size_t) - potential truncation on 32-bit
      platform [*]

[*]: QEMUIOVector is in-RAM data, so size_t seems a valid type for
it's operation. To avoid truncations we should require max_transfer to
be not greater than SIZE_MAX, limiting RAM-occupying operations and
QEMUIOVector usage. Still, 64bit discard and write_zeroes (which
doesn't use QEMUIOVector) should work even on 32bit machines, not being
limited by max_transfer.

For now, we safe anyway, as all input goes through
bdrv_aligned_pwritev() and bdrv_aligned_preadv(), which are limiting
max_transfer to INT_MAX.

Series: 64bit-block-status
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov at virtuozzo.com>
Reviewed-by: Eric Blake <eblake at redhat.com>
---
 block/io.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/block/io.c b/block/io.c
index 7a7d4e578d..eeba3b828c 100644
--- a/block/io.c
+++ b/block/io.c
@@ -906,7 +906,7 @@ static void bdrv_co_io_em_complete(void *opaque, int ret)
 }
 
 static int coroutine_fn bdrv_driver_preadv(BlockDriverState *bs,
-                                           uint64_t offset, uint64_t bytes,
+                                           int64_t offset, int64_t bytes,
                                            QEMUIOVector *qiov,
                                            size_t qiov_offset, int flags)
 {
@@ -975,7 +975,7 @@ out:
 }
 
 static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
-                                            uint64_t offset, uint64_t bytes,
+                                            int64_t offset, int64_t bytes,
                                             QEMUIOVector *qiov,
                                             size_t qiov_offset, int flags)
 {
@@ -1055,8 +1055,8 @@ emulate_flags:
 }
 
 static int coroutine_fn
-bdrv_driver_pwritev_compressed(BlockDriverState *bs, uint64_t offset,
-                               uint64_t bytes, QEMUIOVector *qiov,
+bdrv_driver_pwritev_compressed(BlockDriverState *bs, int64_t offset,
+                               int64_t bytes, QEMUIOVector *qiov,
                                size_t qiov_offset)
 {
     BlockDriver *drv = bs->drv;
-- 
2.21.0



More information about the integration mailing list