All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eric Blake <eblake@redhat.com>
To: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>,
	qemu-block@nongnu.org
Cc: kwolf@redhat.com, fam@euphon.net, integration@gluster.org,
	berto@igalia.com, pavel.dovgaluk@ispras.ru, dillaman@redhat.com,
	qemu-devel@nongnu.org, sw@weilnetz.de, pl@kamp.de,
	ronniesahlberg@gmail.com, mreitz@redhat.com, den@openvz.org,
	sheepdog@lists.wpkg.org, stefanha@redhat.com,
	namei.unix@gmail.com, pbonzini@redhat.com, jsnow@redhat.com,
	ari@tuxera.com
Subject: Re: [PATCH v3 06/17] block/io: support int64_t bytes in bdrv_aligned_pwritev()
Date: Fri, 8 May 2020 15:38:40 -0500	[thread overview]
Message-ID: <1b585d4f-69d3-b475-d763-b252f7317d0e@redhat.com> (raw)
In-Reply-To: <20200430111033.29980-7-vsementsov@virtuozzo.com>

On 4/30/20 6:10 AM, Vladimir Sementsov-Ogievskiy wrote:
> 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, prepare bdrv_aligned_pwritev() now and convert the dependencies:
> bdrv_co_write_req_prepare() and bdrv_co_write_req_finish() to signed
> type bytes.
> 
> Series: 64bit-block-status
> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
> ---
>   block/io.c | 17 ++++++++++-------
>   1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/block/io.c b/block/io.c
> index b83749cc50..8bb4ea6285 100644
> --- a/block/io.c
> +++ b/block/io.c
> @@ -1686,12 +1686,11 @@ fail:
>   }
>   
>   static inline int coroutine_fn
> -bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
> +bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, int64_t bytes,
>                             BdrvTrackedRequest *req, int flags)

Changes from unsigned to signed.  Audit of callers:

bdrv_aligned_pwritev() - adjusted this patch, safe
bdrv_do_pdiscard() - passes int64_t, safe
bdrv_co_copy_range_internal() - passes int64_t, safe
bdrv_do_truncate() - passes int64_t, safe

Internal usage:

>   {
>       BlockDriverState *bs = child->bs;
>       bool waited;
> -    int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);

Drops an old sector calculation, and replaces it with:

>   
>       if (bs->read_only) {
>           return -EPERM;
> @@ -1716,8 +1715,10 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
>       }
>   
>       assert(req->overlap_offset <= offset);
> +    assert(offset <= INT64_MAX - bytes);
>       assert(offset + bytes <= req->overlap_offset + req->overlap_bytes);
> -    assert(end_sector <= bs->total_sectors || child->perm & BLK_PERM_RESIZE);
> +    assert(offset + bytes <= bs->total_sectors * BDRV_SECTOR_SIZE ||
> +           child->perm & BLK_PERM_RESIZE);

assertions that things fit within 63 bits.  Safe

[The req->overlap_offset+ req->overlap_bytes calculation used to be 
unsigned, but was changed to be signed earlier in this series]

>   
>       switch (req->type) {
>       case BDRV_TRACKED_WRITE:
> @@ -1738,7 +1739,7 @@ bdrv_co_write_req_prepare(BdrvChild *child, int64_t offset, uint64_t bytes,
>   }
>   
>   static inline void coroutine_fn
> -bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
> +bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, int64_t bytes,
>                            BdrvTrackedRequest *req, int ret)
>   {

Similar to the above; same four callers, all pass int64_t.


>       int64_t end_sector = DIV_ROUND_UP(offset + bytes, BDRV_SECTOR_SIZE);

This computation needs analysis.  Previously, we had:

DIV_ROUND_UP(int64_t + uint64_t, unsigned long long)
which expands to:
(((uint64_t) + (ull) - int) / (ull))
which simplifies to uint64_t.

Now we have:
DIV_ROUND_UP(int64_t + int64_t, ull)
Okay, in spite of our argument changing type, the macro still results in 
a 64-bit unsigned answer.  Either way, that answer fits within 63 bits, 
so it is safe when assigned to int64_t.

Also in this function:
             stat64_max(&bs->wr_highest_offset, offset + bytes);
in include/qemu/stats64.h, takes uint64_t parameter, but we're passing a 
positive 63-bit number - safe
             bdrv_set_dirty(bs, offset, bytes);
in block/dirty-bitmap.c, takes int64_t parameter - safe

> @@ -1780,14 +1781,14 @@ bdrv_co_write_req_finish(BdrvChild *child, int64_t offset, uint64_t bytes,
>    * after possibly fragmenting it.
>    */
>   static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
> -    BdrvTrackedRequest *req, int64_t offset, unsigned int bytes,
> +    BdrvTrackedRequest *req, int64_t offset, int64_t bytes,
>       int64_t align, QEMUIOVector *qiov, size_t qiov_offset, int flags)
>   {

changes signature from unsigned 32-bit to signed 64-bit.  callers:

bdrv_co_do_zero_pwritev() - passes int64_t, but that was clamped to 
either pad.buf_len [BdrvRequestPadding uses 'size_t buf_len', but 
initializes it in bdrv_init_padding() to at most 2*align] or align set 
from BlockLimits.request_alignment (naturally uint32_t, but documented 
as 'a power of 2 less than INT_MAX' which is at most 1G), so the old 
code never overflowed, and the new code introduces no change

Perhaps we should separately fix BdrvRequestPadding to use a saner type 
than size_t for continuity between 32- and 64-bit platforms (perhaps 
uint32_t rather than int64_t, since we know our padding is bounded by 
request_alignment), but it doesn't impact this patch

bdrv_do_pwritev_part() - still passes unsigned int at this point in the 
series, safe

Usage within the function:

>       BlockDriverState *bs = child->bs;
>       BlockDriver *drv = bs->drv;
>       int ret;
>   
> -    uint64_t bytes_remaining = bytes;
> +    int64_t bytes_remaining = bytes;

Previously we widened unsigned 32-bit into unsigned 64-bit; now we use 
signed 64-bit unchanged.

>       int max_transfer;
>   
>       if (!drv) {
> @@ -1799,6 +1800,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BdrvChild *child,
>       }
>   
>       assert(is_power_of_2(align));
> +    assert(offset >= 0);
> +    assert(bytes >= 0);
>       assert((offset & (align - 1)) == 0);
>       assert((bytes & (align - 1)) == 0);
>       assert(!qiov || qiov_offset + bytes <= qiov->size);

qiov->size is only size_t, while 'qiov_offset + bytes' changed from 
'size_t + unsigned int' to 'size_t + int64_t'.  The resulting type of 
the computation changes for some platforms, but the assertion is proving 
that things still fit (including in 32 bits, when size_t is constrained).

     ret = bdrv_co_write_req_prepare(child, offset, bytes, req, flags);
also touched in this patch, safe

         qemu_iovec_is_zero(qiov, qiov_offset, bytes)) {
Passes an 'int64_t' to a 'size_t' parameter, which is possibly 
narrowing.  Fortunately, the assertions just above prove that by this 
point, we are constrained by qiov->size, which is also size_t. Safe.

         ret = bdrv_co_do_pwrite_zeroes(bs, offset, bytes, flags);
Passes to int64_t, safe

         ret = bdrv_driver_pwritev_compressed(bs, offset, bytes,
Passes to int64_t, safe

         ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, qiov_offset, 
flags);
Passes to int64_t, safe

             ret = bdrv_driver_pwritev(bs, offset + bytes - bytes_remaining,
                                       num, qiov, bytes - bytes_remaining,
Passes int64_t to size_t parameter, but the previous assertion proved we 
did not overflow qiov->size which is size_t. Safe

     bdrv_co_write_req_finish(child, offset, bytes, req, ret);
also touched in this patch, safe

> @@ -1899,7 +1902,7 @@ static int coroutine_fn bdrv_co_do_zero_pwritev(BdrvChild *child,
>       assert(!bytes || (offset & (align - 1)) == 0);
>       if (bytes >= align) {
>           /* Write the aligned part in the middle. */
> -        uint64_t aligned_bytes = bytes & ~(align - 1);
> +        int64_t aligned_bytes = bytes & ~(align - 1);
>           ret = bdrv_aligned_pwritev(child, req, offset, aligned_bytes, align,
>                                      NULL, 0, flags);
>           if (ret < 0) {
> 

Reviewed-by: Eric Blake <eblake@redhat.com>

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3226
Virtualization:  qemu.org | libvirt.org



  reply	other threads:[~2020-05-08 20:39 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-30 11:10 [PATCH v3 00/17] 64bit block-layer Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 01/17] block/throttle-groups: throttle_group_co_io_limits_intercept(): 64bit bytes Vladimir Sementsov-Ogievskiy
2020-05-11 15:28   ` Alberto Garcia
2020-04-30 11:10 ` [PATCH v3 02/17] block: use int64_t as bytes type in tracked requests Vladimir Sementsov-Ogievskiy
2020-05-11 15:32   ` Alberto Garcia
2020-05-22 19:09   ` Eric Blake
2020-04-30 11:10 ` [PATCH v3 03/17] block/io: use int64_t bytes parameter in bdrv_check_byte_request() Vladimir Sementsov-Ogievskiy
2020-05-11 15:57   ` Alberto Garcia
2020-04-30 11:10 ` [PATCH v3 04/17] block/io: use int64_t bytes in driver wrappers Vladimir Sementsov-Ogievskiy
2020-05-11 16:30   ` Alberto Garcia
2020-04-30 11:10 ` [PATCH v3 05/17] block/io: support int64_t bytes in bdrv_co_do_pwrite_zeroes() Vladimir Sementsov-Ogievskiy
2020-05-08 18:20   ` Eric Blake
2020-05-11 17:17   ` Alberto Garcia
2020-05-11 18:34     ` Eric Blake
2020-06-23 10:20       ` Vladimir Sementsov-Ogievskiy
2020-06-23 16:37         ` Eric Blake
2020-04-30 11:10 ` [PATCH v3 06/17] block/io: support int64_t bytes in bdrv_aligned_pwritev() Vladimir Sementsov-Ogievskiy
2020-05-08 20:38   ` Eric Blake [this message]
2020-06-18 14:29   ` Alberto Garcia
2020-04-30 11:10 ` [PATCH v3 07/17] block/io: support int64_t bytes in bdrv_co_do_copy_on_readv() Vladimir Sementsov-Ogievskiy
2020-05-21 22:29   ` Eric Blake
2020-05-22  6:30     ` Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 08/17] block/io: support int64_t bytes in bdrv_aligned_preadv() Vladimir Sementsov-Ogievskiy
2020-05-22 15:14   ` Eric Blake
2020-06-18 14:35     ` Alberto Garcia
2020-06-18 14:47       ` Eric Blake
2020-04-30 11:10 ` [PATCH v3 09/17] block/io: support int64_t bytes in bdrv_co_p{read, write}v_part() Vladimir Sementsov-Ogievskiy
2020-05-22 19:34   ` [PATCH v3 09/17] block/io: support int64_t bytes in bdrv_co_p{read,write}v_part() Eric Blake
2020-04-30 11:10 ` [PATCH v3 10/17] block/io: support int64_t bytes in read/write wrappers Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 11/17] block/io: use int64_t bytes in copy_range Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 12/17] block/block-backend: convert blk io path to use int64_t parameters Vladimir Sementsov-Ogievskiy
2020-06-23 22:11   ` Eric Blake
2020-04-30 11:10 ` [PATCH v3 13/17] block: use int64_t instead of uint64_t in driver read handlers Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 14/17] block: use int64_t instead of uint64_t in driver write handlers Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 15/17] block: use int64_t instead of uint64_t in copy_range driver handlers Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 16/17] block: use int64_t instead of int in driver write_zeroes handlers Vladimir Sementsov-Ogievskiy
2020-04-30 11:10 ` [PATCH v3 17/17] block: use int64_t instead of int in driver discard handlers Vladimir Sementsov-Ogievskiy
2020-05-06  6:40   ` Vladimir Sementsov-Ogievskiy
2020-04-30 20:51 ` [PATCH v3 00/17] 64bit block-layer no-reply
2020-05-06  6:39   ` Vladimir Sementsov-Ogievskiy
2020-04-30 20:57 ` no-reply
2020-12-01 16:07 ` Vladimir Sementsov-Ogievskiy
2020-12-01 16:56   ` Vladimir Sementsov-Ogievskiy
2020-12-01 21:50   ` Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1b585d4f-69d3-b475-d763-b252f7317d0e@redhat.com \
    --to=eblake@redhat.com \
    --cc=ari@tuxera.com \
    --cc=berto@igalia.com \
    --cc=den@openvz.org \
    --cc=dillaman@redhat.com \
    --cc=fam@euphon.net \
    --cc=integration@gluster.org \
    --cc=jsnow@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=namei.unix@gmail.com \
    --cc=pavel.dovgaluk@ispras.ru \
    --cc=pbonzini@redhat.com \
    --cc=pl@kamp.de \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=ronniesahlberg@gmail.com \
    --cc=sheepdog@lists.wpkg.org \
    --cc=stefanha@redhat.com \
    --cc=sw@weilnetz.de \
    --cc=vsementsov@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.