[Libguestfs] [libnbd PATCH v2 09/12] api: Reset state on changed nbd_set_export_name()

Laszlo Ersek lersek at redhat.com
Fri Sep 9 06:58:53 UTC 2022


On 08/31/22 16:39, Eric Blake wrote:
> The documentation for nbd_internal_reset_size_and_flags() claims we
> should wipe all knowledge of a previously-negotiated export when
> swapping export names.  However, we weren't actually doing that, which
> could lead to a user calling nbd_opt_info() for one export, then
> switching to another export name, then having nbd_get_size() still
> report the size of the old export.  The next patch will add testsuite
> coverage (done separately, to make it easier to prove the test catches
> our flaw without this fix by applying patches out of order).
> 
> While at it, there is no need to wipe state if we change to the same
> name.  Note, however, that we do not bother to store the last name
> we've exposed to the server; as a result, there are instances where we
> clear state but the server does not.  But in general, this is not a
> problem; it's always okay to be more conservative and not utilize
> something the server supports, than to be be overly risky and use the
> server on the basis of stale state.  Here's an example (unlikely to
> happen in real code) where we are over-eager in wiping state, even
> though the server never knows we considered a different name:
> 
> nbd_set_export_name(nbd, "a");
> nbd_opt_info(nbd, callback);    => NBD_OPT_SET_META_CONTEXT("a")
>                                 => NBD_OPT_INFO("a")
> nbd_set_export_name(nbd, "b");
> nbd_set_request_meta_context(nbd, false);
> nbd_set_export_name(nbd, "a");
> nbd_opt_go(nbd);                => NBD_OPT_GO("a")
> 
> At any rate, this patch, plus several earlier ones, give us the
> following state transitions:
> 
> export information (nbd_get_size, nbd_is_read_only, nbd_can_trim, ...)
>  - gated by h->eflags being non-zero, but tracked in multiple
>    variables such as h->eflags, h->exportsize, h->block_minimum, ...
>  - made valid by successful NBD_OPT_INFO or NBD_OPT_GO
>  - wiped by:
>    - failed NBD_OPT_INFO or NBD_OPT_GO
>    - any NBD_OPT_STARTTLS (a later patch may add nbd_opt_starttls;
>      for now, it is not possible to tickle this)
>    - nbd_set_export_name() changing names (not directly caused by
>      server state, but because of how many of our interfaces
>      implicitly reuse h->export_name)
>  - persists over:
>    - NBD_OPT_LIST_META_CONTEXT
>    - NBD_OPT_SET_META_CONTEXT
> context mappings (nbd_can_meta_context)
>  - gated by h->meta_valid, tracked by h->meta_contexts
>  - made valid (returns 0/1 for all names) by:
>    - successful NBD_OPT_SET_META_CONTEXT
>    - if nbd_set_request_meta_context() is true, a successful
>      nbd_opt_info() or nbd_opt_go() that was unable to set contexts
>      (server was oldstyle, or structured replies are lacking, or
>      client didn't use nbd_add_meta_context)
>  - wiped (returns -1 for all names) by:
>    - failed NBD_OPT_SET_META_CONTEXT
>    - any NBD_OPT_STARTTLS
>    - nbd_set_export_name() changing names
>  - persists over:
>   - NBD_OPT_GO, NBD_OPT_LIST
>   - NBD_OPT_LIST_META_CONTEXT

I don't think I can internalize this without a state diagram and/or
being exposed to it repeatedly over a long time. (However, this is
obviously not a suggestion for you to *make* a diagram -- I'm not saying
that, just putting my review's worth in perspective.)

At the same time, the code looks sensible to me.

Reviewed-by: Laszlo Ersek <lersek at redhat.com>

Laszlo


> 
> Fixes: 437a472d ("api: Add nbd_opt_go and nbd_aio_opt_go", v1.3.12)
> ---
>  lib/handle.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/lib/handle.c b/lib/handle.c
> index 4b373f5..d8c0dfe 100644
> --- a/lib/handle.c
> +++ b/lib/handle.c
> @@ -225,6 +225,9 @@ nbd_unlocked_set_export_name (struct nbd_handle *h, const char *export_name)
>      return -1;
>    }
> 
> +  if (strcmp (export_name, h->export_name) == 0)
> +    return 0;
> +
>    new_name = strdup (export_name);
>    if (!new_name) {
>      set_error (errno, "strdup");
> @@ -233,6 +236,7 @@ nbd_unlocked_set_export_name (struct nbd_handle *h, const char *export_name)
> 
>    free (h->export_name);
>    h->export_name = new_name;
> +  nbd_internal_reset_size_and_flags (h);
>    h->meta_valid = false;
>    return 0;
>  }
> 



More information about the Libguestfs mailing list