diff options
Diffstat (limited to 'results/classifier/108/other/1310')
| -rw-r--r-- | results/classifier/108/other/1310 | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/results/classifier/108/other/1310 b/results/classifier/108/other/1310 new file mode 100644 index 000000000..3de5c8e32 --- /dev/null +++ b/results/classifier/108/other/1310 @@ -0,0 +1,205 @@ +graphic: 0.918 +other: 0.908 +semantic: 0.835 +performance: 0.829 +permissions: 0.821 +debug: 0.809 +vnc: 0.806 +device: 0.759 +KVM: 0.728 +socket: 0.690 +network: 0.673 +boot: 0.668 +PID: 0.645 +files: 0.616 + +qemu-nbd export img and detect block if is zero with libnbd +Description of problem: +In our project,we use qemu-nbd to export a img,and use libnbd to read/write data.if the img is preallocated,we wonder the data block if is zero,we use api nbd_block_status in libnbd to get the block status,but it shows server does not support structured replies: Operation not supported.I know our qemu is too old.so,i want to know how can i know if the block in preallocated is zero or not in nbd client. +Steps to reproduce: +1.qemu-nbd -p 8889 -f raw a.img + +2.the nbd client use libnbd,code is: +```c +#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 fail; /* input: true to return failure */ + bool seen_base; /* output: true if base:allocation encountered */ + bool seen_dirty; /* output: true if qemu:dirty-bitmap encountered */ +}; + +static int +cb (void *opaque, const char *metacontext, uint64_t offset, + uint32_t *entries, size_t len, int *error) +{ + struct data *data = opaque; + + /* libnbd does not actually verify that a server is fully compliant + * to the spec; the asserts marked [qemu-nbd] are thus dependent on + * the fact that qemu-nbd is compliant. Furthermore, qemu 5.2 and + * 6.0 disagree on whether base:allocation includes the hole bit for + * the zeroes at 512k (both answers are compliant); but we care more + * that the zeroes show up in the dirty bitmap + */ + assert (offset == 0); + assert (!*error || (data->fail && data->count == 1 && *error == EPROTO)); + assert (data->count-- > 0); /* [qemu-nbd] */ + + if (strcmp (metacontext, LIBNBD_CONTEXT_BASE_ALLOCATION) == 0) { + assert (!data->seen_base); /* [qemu-nbd] */ + data->seen_base = true; + if (data->req_one) + assert (len == 2); /* [qemu-nbd] */ + else + assert ((len & 1) == 0 && len > 2); /* [qemu-nbd] */ + + /* Data block offset 0 size 128k */ + assert (entries[0] == 131072); assert (entries[1] == 0); + if (!data->req_one) { + if (len == 4) { + /* hole|zero offset 128k size 896k */ + assert (entries[2] == 917504); + assert (entries[3] == (LIBNBD_STATE_HOLE| + LIBNBD_STATE_ZERO)); + } + else { + assert (len == 8); + /* hole|zero offset 128k size 384k */ + assert (entries[2] == 393216); + assert (entries[3] == (LIBNBD_STATE_HOLE| + LIBNBD_STATE_ZERO)); + /* allocated zero offset 512k size 64k */ + assert (entries[4] == 65536); + assert (entries[5] == LIBNBD_STATE_ZERO); + /* hole|zero offset 576k size 448k */ + assert (entries[6] == 458752); + assert (entries[7] == (LIBNBD_STATE_HOLE| + LIBNBD_STATE_ZERO)); + } + } + } + else if (strcmp (metacontext, bitmap) == 0) { + assert (!data->seen_dirty); /* [qemu-nbd] */ + data->seen_dirty = true; + assert (len == (data->req_one ? 2 : 10)); /* [qemu-nbd] */ + + assert (entries[0] == 65536); assert (entries[1] == 0); + if (!data->req_one) { + /* dirty block offset 64K size 64K */ + assert (entries[2] == 65536); assert (entries[3] == 1); + assert (entries[4] == 393216); assert (entries[5] == 0); + /* dirty block offset 512K size 64K */ + assert (entries[6] == 65536); assert (entries[7] == 1); + assert (entries[8] == 458752); assert (entries[9] == 0); + } + } + else { + fprintf (stderr, "unexpected context %s\n", metacontext); + exit (EXIT_FAILURE); + } + + if (data->fail) { + /* Something NBD servers can't send */ + *error = data->count == 1 ? EPROTO : ECONNREFUSED; + return -1; + } + return 0; +} + +int +main (int argc, char *argv[]) +{ + struct nbd_handle *nbd; + int64_t exportsize; + struct data data; + char c; + + 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_tcp (nbd, argv[2],argv[3]) == -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); + } + + data = (struct data) { .count = 2, }; + if (nbd_block_status (nbd, exportsize, 0, + (nbd_extent_callback) { .callback = cb, .user_data = &data }, + 0) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + assert (data.seen_base && data.seen_dirty); + + data = (struct data) { .req_one = true, .count = 2, }; + if (nbd_block_status (nbd, exportsize, 0, + (nbd_extent_callback) { .callback = cb, .user_data = &data }, + LIBNBD_CMD_FLAG_REQ_ONE) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + assert (data.seen_base && data.seen_dirty); + + /* Trigger a failed callback, to prove connection stays up. */ + data = (struct data) { .count = 2, .fail = true, }; + if (nbd_block_status (nbd, exportsize, 0, + (nbd_extent_callback) { .callback = cb, .user_data = &data }, + 0) != -1) { + fprintf (stderr, "unexpected block status success\n"); + exit (EXIT_FAILURE); + } + assert (nbd_get_errno () == EPROTO && nbd_aio_is_ready (nbd)); + assert (data.seen_base && data.seen_dirty); + + if (nbd_pread (nbd, &c, 1, 0, 0) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + + if (nbd_shutdown (nbd, 0) == -1) { + fprintf (stderr, "%s\n", nbd_get_error ()); + exit (EXIT_FAILURE); + } + + nbd_close (nbd); + + exit (EXIT_SUCCESS); +} + +``` +3. +Additional information: + |