[libvirt] [PATCH v2 2/6] logical: Fix parsing of the 'devices' field lvs output

Pavel Hrdina phrdina at redhat.com
Fri Jan 29 16:07:23 UTC 2016


On Thu, Jan 28, 2016 at 05:44:05PM -0500, John Ferlan wrote:

[...]

> Signed-off-by: John Ferlan <jferlan at redhat.com>
> ---
>  src/storage/storage_backend_logical.c | 149 ++++++++++++----------------------
>  tests/virstringtest.c                 |  11 +++
>  2 files changed, 62 insertions(+), 98 deletions(-)
> 
> diff --git a/src/storage/storage_backend_logical.c b/src/storage/storage_backend_logical.c
> index 7c05b6a..3232c08 100644
> --- a/src/storage/storage_backend_logical.c
> +++ b/src/storage/storage_backend_logical.c
> @@ -64,8 +64,6 @@ virStorageBackendLogicalSetActive(virStoragePoolObjPtr pool,
>  }
>  
>  
> -#define VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED "striped"
> -
>  struct virStorageBackendLogicalPoolVolData {
>      virStoragePoolObjPtr pool;
>      virStorageVolDefPtr vol;
> @@ -75,121 +73,76 @@ static int
>  virStorageBackendLogicalParseVolExtents(virStorageVolDefPtr vol,
>                                          char **const groups)
>  {
> -    int nextents, ret = -1;
> -    const char *regex_unit = "(\\S+)\\((\\S+)\\)";
> -    char *regex = NULL;
> -    regex_t *reg = NULL;
> -    regmatch_t *vars = NULL;
> -    char *p = NULL;
> -    size_t i;
> -    int err, nvars;
> +    int ret = -1;
> +    char **extents = NULL;
> +    char *extnum, *end;
> +    size_t i, nextents = 0;
>      unsigned long long offset, size, length;
>  
> -    nextents = 1;
> -    if (STREQ(groups[4], VIR_STORAGE_VOL_LOGICAL_SEGTYPE_STRIPED)) {
> -        if (virStrToLong_i(groups[5], NULL, 10, &nextents) < 0) {
> -            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> -                           _("malformed volume extent stripes value"));
> -            goto cleanup;
> -        }
> -    }
> +    /* The 'devices' (or extents) are split by a comma ",", so let's split
> +     * each out into a parseable string. Since our regex to generate this
> +     * data is "(\\S+)", we can safely assume at least one exists. */
> +    if (!(extents = virStringSplitCount(groups[3], ",", 0, &nextents)))
> +        goto cleanup;

At first I thought of the same solution but what if the device path contains
a comma?  I know, it's very unlikely but it's possible.

>      /* Allocate and fill in extents information */
>      if (VIR_REALLOC_N(vol->source.extents,
>                        vol->source.nextent + nextents) < 0)
>          goto cleanup;
> +    vol->source.nextent += nextents;

I've also mentioned, that this could be done using VIR_APPEND_ELEMENT by
dropping this pre-allocation and ... [1]

>  
> -    if (virStrToLong_ull(groups[6], NULL, 10, &length) < 0) {
> +    if (virStrToLong_ull(groups[5], NULL, 10, &length) < 0) {
>          virReportError(VIR_ERR_INTERNAL_ERROR,
>                         "%s", _("malformed volume extent length value"));
>          goto cleanup;
>      }
>  
> -    if (virStrToLong_ull(groups[7], NULL, 10, &size) < 0) {
> +    if (virStrToLong_ull(groups[6], NULL, 10, &size) < 0) {
>          virReportError(VIR_ERR_INTERNAL_ERROR,
>                         "%s", _("malformed volume extent size value"));
>          goto cleanup;
>      }
>  
> -    if (VIR_STRDUP(regex, regex_unit) < 0)
> -        goto cleanup;
> -
> -    for (i = 1; i < nextents; i++) {
> -        if (VIR_REALLOC_N(regex, strlen(regex) + strlen(regex_unit) + 2) < 0)
> -            goto cleanup;
> -        /* "," is the separator of "devices" field */
> -        strcat(regex, ",");
> -        strncat(regex, regex_unit, strlen(regex_unit));
> -    }

I would rather allocate the string with correct size outside of the cycle as we
know the length and just simply fill the string in a cycle.  The regex is more
robust than splitting the string by comma.

[...]

> -
> -        vol->source.extents[vol->source.nextent].start = offset * size;
> -        vol->source.extents[vol->source.nextent].end = (offset * size) + length;
> -        vol->source.nextent++;
> +        vol->source.extents[i].start = offset * size;
> +        vol->source.extents[i].end = (offset * size) + length;

[1] ... there you would call VIR_APPEND_ELEMENT().

>      }
> -
>      ret = 0;
>  
>   cleanup:
> -    VIR_FREE(regex);
> -    VIR_FREE(reg);
> -    VIR_FREE(vars);
> +    virStringFreeList(extents);
> +
>      return ret;

The cleanup is nice, but still I would rather use VIR_APPEND_ELEMENT as it's
more common in libvirt to create a new array of some elements.

One more question about the mirror device name, it's not actually a device name
but internal name used by lvm and it's mapped to real device.  Shouldn't we do
the job for user and display a real device?

Pavel




More information about the libvir-list mailing list