[Libguestfs] [nbdkit PATCH 1/4] server: Normalize plugin can_* values

Richard W.M. Jones rjones at redhat.com
Tue Mar 17 08:10:46 UTC 2020


On Mon, Mar 16, 2020 at 10:36:14PM -0500, Eric Blake wrote:
> The documentation for .can_write and friends mentioned merely that the
> callback must return a boolean value, or -1 on failure.  Historically,
> we have treated any non-zero value other than -1 as true, and some
> plugins have sloppily relied on this behavior, including the
> standalone nbd plugin prior to the use of libnbd in v1.14.  But in
> 1.15.1, we added an assert in our backend code if an enabled feature
> bit is not exactly 1.  To avoid tripping the assertion, we have to
> normalize the plugin values before storing our internal value.
> 
> Fixes: c306fa93ab
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---
>  server/plugins.c | 24 ++++++++++++++++--------
>  1 file changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/server/plugins.c b/server/plugins.c
> index 78ed6723..4a4fcdee 100644
> --- a/server/plugins.c
> +++ b/server/plugins.c
> @@ -1,5 +1,5 @@
>  /* nbdkit
> - * Copyright (C) 2013-2019 Red Hat Inc.
> + * Copyright (C) 2013-2020 Red Hat Inc.
>   *
>   * Redistribution and use in source and binary forms, with or without
>   * modification, are permitted provided that the following conditions are
> @@ -308,13 +308,21 @@ plugin_get_size (struct backend *b, void *handle)
>    return p->plugin.get_size (handle);
>  }
> 
> +static int normalize_bool (int value)
> +{
> +  if (value == -1 || value == 0)
> +    return value;
> +  /* Normalize all other non-zero values to true */
> +  return 1;
> +}
> +
>  static int
>  plugin_can_write (struct backend *b, void *handle)
>  {
>    struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
> 
>    if (p->plugin.can_write)
> -    return p->plugin.can_write (handle);
> +    return normalize_bool (p->plugin.can_write (handle));
>    else
>      return p->plugin.pwrite || p->plugin._pwrite_v1;
>  }
> @@ -325,7 +333,7 @@ plugin_can_flush (struct backend *b, void *handle)
>    struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
> 
>    if (p->plugin.can_flush)
> -    return p->plugin.can_flush (handle);
> +    return normalize_bool (p->plugin.can_flush (handle));
>    else
>      return p->plugin.flush || p->plugin._flush_v1;
>  }
> @@ -336,7 +344,7 @@ plugin_is_rotational (struct backend *b, void *handle)
>    struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
> 
>    if (p->plugin.is_rotational)
> -    return p->plugin.is_rotational (handle);
> +    return normalize_bool (p->plugin.is_rotational (handle));
>    else
>      return 0; /* assume false */
>  }
> @@ -347,7 +355,7 @@ plugin_can_trim (struct backend *b, void *handle)
>    struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
> 
>    if (p->plugin.can_trim)
> -    return p->plugin.can_trim (handle);
> +    return normalize_bool (p->plugin.can_trim (handle));
>    else
>      return p->plugin.trim || p->plugin._trim_v1;
>  }
> @@ -380,7 +388,7 @@ plugin_can_fast_zero (struct backend *b, void *handle)
>    int r;
> 
>    if (p->plugin.can_fast_zero)
> -    return p->plugin.can_fast_zero (handle);
> +    return normalize_bool (p->plugin.can_fast_zero (handle));
>    /* Advertise support for fast zeroes if no .zero or .can_zero is
>     * false: in those cases, we fail fast instead of using .pwrite.
>     * This also works when v1 plugin has only ._zero_v1.
> @@ -399,7 +407,7 @@ plugin_can_extents (struct backend *b, void *handle)
>    struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
> 
>    if (p->plugin.can_extents)
> -    return p->plugin.can_extents (handle);
> +    return normalize_bool (p->plugin.can_extents (handle));
>    else
>      return p->plugin.extents != NULL;
>  }
> @@ -430,7 +438,7 @@ plugin_can_multi_conn (struct backend *b, void *handle)
>    struct backend_plugin *p = container_of (b, struct backend_plugin, backend);
> 
>    if (p->plugin.can_multi_conn)
> -    return p->plugin.can_multi_conn (handle);
> +    return normalize_bool (p->plugin.can_multi_conn (handle));
>    else
>      return 0; /* assume false */
>  }
> -- 

Nice one, ACK.

I guess this one will need to be backported to (only?) 1.16 and 1.18?

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
virt-p2v converts physical machines to virtual machines.  Boot with a
live CD or over the network (PXE) and turn machines into KVM guests.
http://libguestfs.org/virt-v2v




More information about the Libguestfs mailing list