From: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
To: Eric Blake <eblake@redhat.com>, qemu-devel@nongnu.org
Cc: qemu-stable@nongnu.org,
"open list:Network Block Dev..." <qemu-block@nongnu.org>
Subject: Re: [PATCH for-5.1] nbd: Fix large trim/zero requests
Date: Thu, 23 Jul 2020 10:23:53 +0300 [thread overview]
Message-ID: <e7b8151d-b9d3-b5c5-9bc4-661a045d4ff9@virtuozzo.com> (raw)
In-Reply-To: <20200722212231.535072-1-eblake@redhat.com>
23.07.2020 00:22, Eric Blake wrote:
> Although qemu as NBD client limits requests to <2G, the NBD protocol
> allows clients to send requests almost all the way up to 4G. But
> because our block layer is not yet 64-bit clean, we accidentally wrap
> such requests into a negative size, and fail with EIO instead of
> performing the intended operation.
>
> The bug is visible in modern systems with something as simple as:
>
> $ qemu-img create -f qcow2 /tmp/image.img 5G
> $ sudo qemu-nbd --connect=/dev/nbd0 /tmp/image.img
> $ sudo blkdiscard /dev/nbd0
>
> or with user-space only:
>
> $ truncate --size=3G file
> $ qemu-nbd -f raw file
> $ nbdsh -u nbd://localhost:10809 -c 'h.trim(3*1024*1024*1024,0)'
>
> Alas, our iotests do not currently make it easy to add external
> dependencies on blkdiscard or nbdsh, so we have to rely on manual
> testing for now.
>
> This patch can be reverted when we later improve the overall block
> layer to be 64-bit clean, but for now, a minimal fix was deemed less
> risky prior to release.
>
> CC: qemu-stable@nongnu.org
> Fixes: 1f4d6d18ed
> Fixes: 1c6c4bb7f0
> Fixes: https://github.com/systemd/systemd/issues/16242
> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
> nbd/server.c | 26 ++++++++++++++++++++++----
> 1 file changed, 22 insertions(+), 4 deletions(-)
>
> diff --git a/nbd/server.c b/nbd/server.c
> index 4752a6c8bc07..029618017c90 100644
> --- a/nbd/server.c
> +++ b/nbd/server.c
> @@ -2378,8 +2378,17 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
> if (request->flags & NBD_CMD_FLAG_FAST_ZERO) {
> flags |= BDRV_REQ_NO_FALLBACK;
> }
> - ret = blk_pwrite_zeroes(exp->blk, request->from + exp->dev_offset,
> - request->len, flags);
> + ret = 0;
> + /* FIXME simplify this when blk_pwrite_zeroes switches to 64-bit */
> + while (ret == 0 && request->len) {
> + int align = client->check_align ?: 1;
> + int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES,
> + align));
> + ret = blk_pwrite_zeroes(exp->blk, request->from + exp->dev_offset,
> + len, flags);
> + request->len -= len;
> + request->from += len;
> + }
> return nbd_send_generic_reply(client, request->handle, ret,
> "writing to file failed", errp);
>
> @@ -2393,8 +2402,17 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
> "flush failed", errp);
>
> case NBD_CMD_TRIM:
> - ret = blk_co_pdiscard(exp->blk, request->from + exp->dev_offset,
> - request->len);
> + ret = 0;
> + /* FIXME simplify this when blk_co_pdiscard switches to 64-bit */
> + while (ret == 0 && request->len) {
Did you check all the paths not to return positive ret on success? I'd prefer to compare ret >= 0 for this temporary code to not care of it
> + int align = client->check_align ?: 1;
> + int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES,
> + align));
> + ret = blk_co_pdiscard(exp->blk, request->from + exp->dev_offset,
> + len);
> + request->len -= len;
> + request->from += len;
Hmm.. Modifying the function parameter. Safe now, as nbd_handle_request() call is the last usage of request in nbd_trip().
> + }
> if (ret == 0 && request->flags & NBD_CMD_FLAG_FUA) {
> ret = blk_co_flush(exp->blk);
> }
>
--
Best regards,
Vladimir
next prev parent reply other threads:[~2020-07-23 7:25 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-22 21:22 [PATCH for-5.1] nbd: Fix large trim/zero requests Eric Blake
2020-07-23 7:23 ` Vladimir Sementsov-Ogievskiy [this message]
2020-07-23 11:47 ` Eric Blake
2020-07-23 13:08 ` Vladimir Sementsov-Ogievskiy
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=e7b8151d-b9d3-b5c5-9bc4-661a045d4ff9@virtuozzo.com \
--to=vsementsov@virtuozzo.com \
--cc=eblake@redhat.com \
--cc=qemu-block@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=qemu-stable@nongnu.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).