Re: [Libguestfs] [libnbd PATCH 4/8] states: Prepare for read callback

Richard W.M. Jones
Thu, 20 Jun 2019 08:29:05 -0000

On Mon, Jun 17, 2019 at 07:07:54PM -0500, Eric Blake
wrote:
> The next patch will add a new 'nbd_aio_pread_callback' function for
> allowing the user more immediate access as each chunk of a structured
> reply read is received. But before we do that, let's refactor the
> command code. This includes a revert of 12843a1a, since the read
> callback will need both a buffer and the user's opaque object at the
> same time.

This patch on its own is fine, although of course if you want to push
it upstream now you'll need to adjust the commit message.

ACK

Rich.

>  generator/states-reply-structured.c |  8 ++++----
>  lib/internal.h                      | 17 +++++++++++++----
>  lib/rw.c                            |  9 ++++++---
>  3 files changed, 23 insertions(+), 11 deletions(-)
>
> diff --git a/generator/states-reply-structured.c
b/generator/states-reply-structured.c
> index 6740400..657106e 100644
> --- a/generator/states-reply-structured.c
> +++ b/generator/states-reply-structured.c
> @@ -123,7 +123,7 @@
>        set_error (0, "invalid length in
NBD_REPLY_TYPE_BLOCK_STATUS");
>        return -1;
>      }
> -    if (cmd->extent_fn == NULL) {
> +    if (cmd->cb.fn.extent == NULL) {
>        SET_NEXT_STATE (%.DEAD);
>        set_error (0, "not expecting NBD_REPLY_TYPE_BLOCK_STATUS
here");
>        return -1;
> @@ -375,7 +375,7 @@
>      length = be32toh (h->sbuf.sr.structured_reply.length);
>
>      assert (cmd); /* guaranteed by CHECK */
> -    assert (cmd->extent_fn);
> +    assert (cmd->cb.fn.extent);
>      assert (h->bs_entries);
>      assert (length >= 12);
>
> @@ -401,8 +401,8 @@
>        if (meta_context) {
>          /* Call the caller's extent function. */
>          errno = 0;
> -        if (cmd->extent_fn (cmd->data, meta_context->name,
cmd->offset,
> -                            &h->bs_entries[1], (length-4) / 4) ==
-1)
> +        if (cmd->cb.fn.extent (cmd->cb.opaque,
meta_context->name, cmd->offset,
> +                               &h->bs_entries[1], (length-4) / 4)
== -1)
>            cmd->error = errno ? errno : EPROTO;
>        }
>        else
> diff --git a/lib/internal.h b/lib/internal.h
> index 1f8f789..cb0e170 100644
> --- a/lib/internal.h
> +++ b/lib/internal.h
> @@ -231,7 +231,16 @@ struct socket {
>    const struct socket_ops *ops;
>  };
>
> -typedef int (*extent_fn) (void *data, const char *metacontext, uint64_t
offset, uint32_t *entries, size_t nr_entries);
> +typedef int (*extent_fn) (void *data, const char *metacontext, uint64_t
offset,
> +                          uint32_t *entries, size_t nr_entries);
> +
> +struct command_cb {
> +  void *opaque;
> +  union {
> +    extent_fn extent;
> +    /* More to come */
> +  } fn;
> +};
>
>  struct command_in_flight {
>    struct command_in_flight *next;
> @@ -240,8 +249,8 @@ struct command_in_flight {
>    uint64_t handle;
>    uint64_t offset;
>    uint32_t count;
> -  void *data; /* Buffer for read/write, opaque for block status */
> -  extent_fn extent_fn;
> +  void *data; /* Buffer for read/write */
> +  struct command_cb cb;
>    bool data_seen; /* For read, true if at least one data chunk seen */
>    uint32_t error; /* Local errno value */
>  };
> @@ -300,7 +309,7 @@ extern const char *nbd_internal_name_of_nbd_cmd
(uint16_t type);
>  extern int64_t nbd_internal_command_common (struct nbd_handle *h,
>                                              uint16_t flags, uint16_t type,
>                                              uint64_t offset, uint64_t
count,
> -                                            void *data, extent_fn extent);
> +                                            void *data, struct command_cb
*cb);
>
>  /* socket.c */
>  struct socket *nbd_internal_socket_create (int fd);
> diff --git a/lib/rw.c b/lib/rw.c
> index ad9c8a0..dc81c57 100644
> --- a/lib/rw.c
> +++ b/lib/rw.c
> @@ -143,7 +143,7 @@ int64_t
>  nbd_internal_command_common (struct nbd_handle *h,
>                               uint16_t flags, uint16_t type,
>                               uint64_t offset, uint64_t count, void *data,
> -                             extent_fn extent)
> +                             struct command_cb *cb)
>  {
>    struct command_in_flight *cmd, *prev_cmd;
>
> @@ -183,7 +183,8 @@ nbd_internal_command_common (struct nbd_handle *h,
>    cmd->offset = offset;
>    cmd->count = count;
>    cmd->data = data;
> -  cmd->extent_fn = extent;
> +  if (cb)
> +    cmd->cb = *cb;
>
>    /* If structured replies were negotiated then we trust the server to
>     * send back sufficient data to cover the whole buffer.  It's tricky
> @@ -360,6 +361,8 @@ nbd_unlocked_aio_block_status (struct nbd_handle *h,
>                                 void *data, extent_fn extent,
>                                 uint32_t flags)
>  {
> +  struct command_cb cb = { .opaque = data, .fn.extent = extent, };
> +
>    if (!h->structured_replies) {
>      set_error (ENOTSUP, "server does not support structured
replies");
>      return -1;
> @@ -383,5 +386,5 @@ nbd_unlocked_aio_block_status (struct nbd_handle *h,
>    }
>
>    return nbd_internal_command_common (h, flags, NBD_CMD_BLOCK_STATUS,
offset,
> -                                      count, data, extent);
> +                                      count, NULL, &cb);
>  }
> --
> 2.20.1
>
> _______________________________________________
> Libguestfs mailing list
> Libguestfs@redhat.com
> https://www.redhat.com/mailman/listinfo/libguestfs

--
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-top is 'top' for virtual machines.  Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.