Re: [PATCH 7/8] libxc: add hypercall buffer arrays

Ian Campbell
Thu, 07 Mar 2013 02:44:06 -0000

On Thu, 2013-02-21 at 17:48 +0000, David Vrabel wrote:
> From: David Vrabel <david.vrabel@citrix.com>
>
> Hypercall buffer arrays are used when a hypercall takes a variable
> length array of buffers.

This looks good to me, I took a quick peek at the 4/4 patch in the kexec
tools series which uses it as well.

Acked-by: Ian Campbell <ian.campbell@citrix.com>

>
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> ---
>  tools/libxc/xc_hcall_buf.c |   73
++++++++++++++++++++++++++++++++++++++++++++
>  tools/libxc/xenctrl.h      |   27 ++++++++++++++++
>  2 files changed, 100 insertions(+), 0 deletions(-)
>
> diff --git a/tools/libxc/xc_hcall_buf.c b/tools/libxc/xc_hcall_buf.c
> index ced9abd..3e01f3f 100644
> --- a/tools/libxc/xc_hcall_buf.c
> +++ b/tools/libxc/xc_hcall_buf.c
> @@ -228,6 +228,79 @@ void xc__hypercall_bounce_post(xc_interface *xch,
xc_hypercall_buffer_t *b)
>      xc__hypercall_buffer_free(xch, b);
>  }
>
> +struct xc_hypercall_buffer_array {
> +    unsigned max_bufs;
> +    xc_hypercall_buffer_t *bufs;
> +};
> +
> +xc_hypercall_buffer_array_t *xc_hypercall_buffer_array_create(xc_interface
*xch,
> +                                                              unsigned n)
> +{
> +    xc_hypercall_buffer_array_t *array;
> +    xc_hypercall_buffer_t *bufs = NULL;
> +
> +    array = malloc(sizeof(*array));
> +    if ( array == NULL )
> +        goto error;
> +
> +    bufs = calloc(n, sizeof(*bufs));
> +    if ( bufs == NULL )
> +        goto error;
> +
> +    array->max_bufs = n;
> +    array->bufs     = bufs;
> +
> +    return array;
> +
> +error:
> +    free(bufs);
> +    free(array);
> +    return NULL;
> +}
> +
> +void *xc__hypercall_buffer_array_alloc(xc_interface *xch,
> +                                       xc_hypercall_buffer_array_t *array,
> +                                       unsigned index,
> +                                       xc_hypercall_buffer_t *hbuf,
> +                                       size_t size)
> +{
> +    void *buf;
> +
> +    if ( index >= array->max_bufs || array->bufs[index].hbuf )
> +        abort();
> +
> +    buf = xc__hypercall_buffer_alloc(xch, hbuf, size);
> +    if ( buf )
> +        array->bufs[index] = *hbuf;
> +    return buf;
> +}
> +
> +void *xc__hypercall_buffer_array_get(xc_interface *xch,
> +                                     xc_hypercall_buffer_array_t *array,
> +                                     unsigned index,
> +                                     xc_hypercall_buffer_t *hbuf)
> +{
> +    if ( index >= array->max_bufs || array->bufs[index].hbuf ==
NULL )
> +        abort();
> +
> +    *hbuf = array->bufs[index];
> +    return array->bufs[index].hbuf;
> +}
> +
> +void xc_hypercall_buffer_array_destroy(xc_interface *xc,
> +                                       xc_hypercall_buffer_array_t *array)
> +{
> +    unsigned i;
> +
> +    if ( array == NULL )
> +        return;
> +
> +    for (i = 0; i < array->max_bufs; i++ )
> +        xc__hypercall_buffer_free(xc, &array->bufs[i]);
> +    free(array->bufs);
> +    free(array);
> +}
> +
>  /*
>   * Local variables:
>   * mode: C
> diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
> index 32122fd..c3b2c28 100644
> --- a/tools/libxc/xenctrl.h
> +++ b/tools/libxc/xenctrl.h
> @@ -317,6 +317,33 @@ void xc__hypercall_buffer_free_pages(xc_interface
*xch, xc_hypercall_buffer_t *b
>  #define xc_hypercall_buffer_free_pages(_xch, _name, _nr)
xc__hypercall_buffer_free_pages(_xch, HYPERCALL_BUFFER(_name), _nr)
>
>  /*
> + * Array of hypercall buffers.
> + *
> + * Create an array with xc_hypercall_buffer_array_create() and
> + * populate it by declaring one hypercall buffer in a loop and
> + * allocating the buffer with xc_hypercall_buffer_array_alloc().
> + *
> + * To access a previously allocated buffers, declare a new hypercall
> + * buffer and call xc_hypercall_buffer_array_get().
> + *
> + * Destroy the array with xc_hypercall_buffer_array_destroy() to free
> + * the array and all its alocated hypercall buffers.
> + */
> +struct xc_hypercall_buffer_array;
> +typedef struct xc_hypercall_buffer_array xc_hypercall_buffer_array_t;
> +
> +xc_hypercall_buffer_array_t *xc_hypercall_buffer_array_create(xc_interface
*xch, unsigned n);
> +void *xc__hypercall_buffer_array_alloc(xc_interface *xch,
xc_hypercall_buffer_array_t *array,
> +                                       unsigned index,
xc_hypercall_buffer_t *hbuf, size_t size);
> +#define xc_hypercall_buffer_array_alloc(_xch, _array, _index, _name,
_size) \
> +    xc__hypercall_buffer_array_alloc(_xch, _array, _index,
HYPERCALL_BUFFER(_name), _size)
> +void *xc__hypercall_buffer_array_get(xc_interface *xch,
xc_hypercall_buffer_array_t *array,
> +                                     unsigned index, xc_hypercall_buffer_t
*hbuf);
> +#define xc_hypercall_buffer_array_get(_xch, _array, _index, _name, _size)
\
> +    xc__hypercall_buffer_array_get(_xch, _array, _index,
HYPERCALL_BUFFER(_name))
> +void xc_hypercall_buffer_array_destroy(xc_interface *xc,
xc_hypercall_buffer_array_t *array);
> +
> +/*
>   * CPUMAP handling
>   */
>  typedef uint8_t *xc_cpumap_t;