qemu-block
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Libguestfs] [libnbd PATCH v3 20/22] interop: Add test of 64-bit blo


From: Richard W.M. Jones
Subject: Re: [Libguestfs] [libnbd PATCH v3 20/22] interop: Add test of 64-bit block status
Date: Thu, 8 Jun 2023 10:46:15 +0100
User-agent: Mutt/1.5.21 (2010-09-15)

On Thu, May 25, 2023 at 08:01:06AM -0500, Eric Blake wrote:
> Prove that we can round-trip a block status request larger than 4G
> through a new-enough qemu-nbd.  Also serves as a unit test of our shim
> for converting internal 64-bit representation back to the older 32-bit
> nbd_block_status callback interface.

I think it would be best to call this test "large-block-status.{c,sh}"
as "large-status" is ambiguous.  (Or even "block-status-64"?)

The test itself is fine, so if renamed:

Reviewed-by: Richard W.M. Jones <rjones@redhat.com>

> Signed-off-by: Eric Blake <eblake@redhat.com>
> ---
>  interop/Makefile.am     |   6 ++
>  interop/large-status.c  | 186 ++++++++++++++++++++++++++++++++++++++++
>  interop/large-status.sh |  49 +++++++++++
>  .gitignore              |   1 +
>  4 files changed, 242 insertions(+)
>  create mode 100644 interop/large-status.c
>  create mode 100755 interop/large-status.sh
> 
> diff --git a/interop/Makefile.am b/interop/Makefile.am
> index 3f81df0c..9a7a5967 100644
> --- a/interop/Makefile.am
> +++ b/interop/Makefile.am
> @@ -21,6 +21,7 @@ EXTRA_DIST = \
>       dirty-bitmap.sh \
>       interop-qemu-storage-daemon.sh \
>       interop-qemu-block-size.sh \
> +     large-status.sh \
>       list-exports-nbd-config \
>       list-exports-test-dir/disk1 \
>       list-exports-test-dir/disk2 \
> @@ -134,6 +135,7 @@ check_PROGRAMS += \
>       list-exports-qemu-nbd \
>       socket-activation-qemu-nbd \
>       dirty-bitmap \
> +     large-status \
>       structured-read \
>       opt-extended-headers \
>       $(NULL)
> @@ -144,6 +146,7 @@ TESTS += \
>       list-exports-qemu-nbd \
>       socket-activation-qemu-nbd \
>       dirty-bitmap.sh \
> +     large-status.sh \
>       structured-read.sh \
>       interop-qemu-block-size.sh \
>       opt-extended-headers.sh \
> @@ -235,6 +238,9 @@ socket_activation_qemu_nbd_LDADD = 
> $(top_builddir)/lib/libnbd.la
>  dirty_bitmap_SOURCES = dirty-bitmap.c
>  dirty_bitmap_LDADD = $(top_builddir)/lib/libnbd.la
> 
> +large_status_SOURCES = large-status.c
> +large_status_LDADD = $(top_builddir)/lib/libnbd.la
> +
>  structured_read_SOURCES = structured-read.c
>  structured_read_LDADD = $(top_builddir)/lib/libnbd.la
> 
> diff --git a/interop/large-status.c b/interop/large-status.c
> new file mode 100644
> index 00000000..36415653
> --- /dev/null
> +++ b/interop/large-status.c
> @@ -0,0 +1,186 @@
> +/* NBD client library in userspace
> + * Copyright Red Hat
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> + */
> +
> +/* Test 64-bit block status with qemu. */
> +
> +#include <config.h>
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <unistd.h>
> +#include <assert.h>
> +#include <stdbool.h>
> +#include <errno.h>
> +
> +#include <libnbd.h>
> +
> +static const char *bitmap;
> +
> +struct data {
> +  bool req_one;    /* input: true if req_one was passed to request */
> +  int count;       /* input: count of expected remaining calls */
> +  bool seen_base;  /* output: true if base:allocation encountered */
> +  bool seen_dirty; /* output: true if qemu:dirty-bitmap encountered */
> +};
> +
> +static int
> +cb32 (void *opaque, const char *metacontext, uint64_t offset,
> +      uint32_t *entries, size_t len, int *error)
> +{
> +  struct data *data = opaque;
> +
> +  assert (offset == 0);
> +  assert (data->count-- > 0);
> +
> +  if (strcmp (metacontext, LIBNBD_CONTEXT_BASE_ALLOCATION) == 0) {
> +    assert (!data->seen_base);
> +    data->seen_base = true;
> +
> +    /* Data block offset 0 size 64k, remainder is hole */
> +    assert (len == 4);
> +    assert (entries[0] == 65536);
> +    assert (entries[1] == 0);
> +    /* libnbd had to truncate qemu's >4G answer */
> +    assert (entries[2] == 4227858432);
> +    assert (entries[3] == (LIBNBD_STATE_HOLE|LIBNBD_STATE_ZERO));
> +  }
> +  else if (strcmp (metacontext, bitmap) == 0) {
> +    assert (!data->seen_dirty);
> +    data->seen_dirty = true;
> +
> +    /* Dirty block at offset 5G-64k, remainder is clean */
> +    /* libnbd had to truncate qemu's >4G answer */
> +    assert (len == 2);
> +    assert (entries[0] == 4227858432);
> +    assert (entries[1] == 0);
> +  }
> +  else {
> +    fprintf (stderr, "unexpected context %s\n", metacontext);
> +    exit (EXIT_FAILURE);
> +  }
> +  return 0;
> +}
> +
> +static int
> +cb64 (void *opaque, const char *metacontext, uint64_t offset,
> +      nbd_extent *entries, size_t len, int *error)
> +{
> +  struct data *data = opaque;
> +
> +  assert (offset == 0);
> +  assert (data->count-- > 0);
> +
> +  if (strcmp (metacontext, LIBNBD_CONTEXT_BASE_ALLOCATION) == 0) {
> +    assert (!data->seen_base);
> +    data->seen_base = true;
> +
> +    /* Data block offset 0 size 64k, remainder is hole */
> +    assert (len == 2);
> +    assert (entries[0].length == 65536);
> +    assert (entries[0].flags == 0);
> +    assert (entries[1].length == 5368643584ULL);
> +    assert (entries[1].flags == (LIBNBD_STATE_HOLE|LIBNBD_STATE_ZERO));
> +  }
> +  else if (strcmp (metacontext, bitmap) == 0) {
> +    assert (!data->seen_dirty);
> +    data->seen_dirty = true;
> +
> +    /* Dirty block at offset 5G-64k, remainder is clean */
> +    assert (len == 2);
> +    assert (entries[0].length == 5368643584ULL);
> +    assert (entries[0].flags == 0);
> +    assert (entries[1].length == 65536);
> +    assert (entries[1].flags == 1);
> +  }
> +  else {
> +    fprintf (stderr, "unexpected context %s\n", metacontext);
> +    exit (EXIT_FAILURE);
> +  }
> +  return 0;
> +}
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct nbd_handle *nbd;
> +  int64_t exportsize;
> +  struct data data;
> +
> +  if (argc < 3) {
> +    fprintf (stderr, "%s bitmap qemu-nbd [args ...]\n", argv[0]);
> +    exit (EXIT_FAILURE);
> +  }
> +  bitmap = argv[1];
> +
> +  nbd = nbd_create ();
> +  if (nbd == NULL) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +
> +  nbd_add_meta_context (nbd, LIBNBD_CONTEXT_BASE_ALLOCATION);
> +  nbd_add_meta_context (nbd, bitmap);
> +
> +  if (nbd_connect_systemd_socket_activation (nbd, &argv[2]) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +
> +  exportsize = nbd_get_size (nbd);
> +  if (exportsize == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +
> +  if (nbd_get_extended_headers_negotiated (nbd) != 1) {
> +    fprintf (stderr, "skipping: qemu-nbd lacks extended headers\n");
> +    exit (77);
> +  }
> +
> +  /* Prove that we can round-trip a >4G block status request */
> +  data = (struct data) { .count = 2, };
> +  if (nbd_block_status_64 (nbd, exportsize, 0,
> +                           (nbd_extent64_callback) { .callback = cb64,
> +                             .user_data = &data },
> +                           0) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +  assert (data.seen_base && data.seen_dirty);
> +
> +  /* Check libnbd's handling of a >4G response through older interface  */
> +  data = (struct data) { .count = 2, };
> +  if (nbd_block_status (nbd, exportsize, 0,
> +                        (nbd_extent_callback) { .callback = cb32,
> +                          .user_data = &data },
> +                        0) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +  assert (data.seen_base && data.seen_dirty);
> +
> +  if (nbd_shutdown (nbd, 0) == -1) {
> +    fprintf (stderr, "%s\n", nbd_get_error ());
> +    exit (EXIT_FAILURE);
> +  }
> +
> +  nbd_close (nbd);
> +
> +  exit (EXIT_SUCCESS);
> +}
> diff --git a/interop/large-status.sh b/interop/large-status.sh
> new file mode 100755
> index 00000000..46810dc3
> --- /dev/null
> +++ b/interop/large-status.sh
> @@ -0,0 +1,49 @@
> +#!/usr/bin/env bash
> +# nbd client library in userspace
> +# Copyright Red Hat
> +#
> +# This library is free software; you can redistribute it and/or
> +# modify it under the terms of the GNU Lesser General Public
> +# License as published by the Free Software Foundation; either
> +# version 2 of the License, or (at your option) any later version.
> +#
> +# This library is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +# Lesser General Public License for more details.
> +#
> +# You should have received a copy of the GNU Lesser General Public
> +# License along with this library; if not, write to the Free Software
> +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 
> USA
> +
> +# Test reading qemu dirty-bitmap.
> +
> +source ../tests/functions.sh
> +set -e
> +set -x
> +
> +requires qemu-img bitmap --help
> +requires qemu-nbd --version
> +
> +# This test uses the qemu-nbd -B option.
> +if ! qemu-nbd --help | grep -sq -- -B; then
> +    echo "$0: skipping because qemu-nbd does not support the -B option"
> +    exit 77
> +fi
> +
> +files="large-status.qcow2"
> +rm -f $files
> +cleanup_fn rm -f $files
> +
> +# Create mostly-sparse file with intentionally different data vs. dirty areas
> +# (64k data, 5G-64k hole,zero; 5G-64k clean, 64k dirty)
> +qemu-img create -f qcow2 large-status.qcow2 5G
> +qemu-img bitmap --add --enable -f qcow2 large-status.qcow2 bitmap0
> +qemu-io -f qcow2 -c "w -z $((5*1024*1024*1024 - 64*1024)) 64k" \
> +        large-status.qcow2
> +qemu-img bitmap --disable -f qcow2 large-status.qcow2 bitmap0
> +qemu-io -f qcow2 -c 'w 0 64k' large-status.qcow2
> +
> +# Run the test.
> +$VG ./large-status qemu:dirty-bitmap:bitmap0 \
> +    qemu-nbd -f qcow2 -B bitmap0 large-status.qcow2
> diff --git a/.gitignore b/.gitignore
> index 24642748..fd81357b 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -114,6 +114,7 @@ Makefile.in
>  /interop/interop-qemu-nbd
>  /interop/interop-qemu-nbd-tls-certs
>  /interop/interop-qemu-nbd-tls-psk
> +/interop/large-status
>  /interop/list-exports-nbd-server
>  /interop/list-exports-nbdkit
>  /interop/list-exports-qemu-nbd

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-builder quickly builds VMs from scratch
http://libguestfs.org/virt-builder.1.html




reply via email to

[Prev in Thread] Current Thread [Next in Thread]