[libvirt] PATCH: Support storage copy on write volumes

Jim Meyering jim at meyering.net
Thu Jan 22 18:15:19 UTC 2009


"Daniel P. Berrange" <berrange at redhat.com> wrote:
> This is a follow up on Miloslav's proposal to add copy on write
> support to the storage APIs, changing the XML to that described
> here:
>
>   http://www.redhat.com/archives/libvir-list/2009-January/msg00231.html
>
> In addition to the original QCOW/VMDK support, I have done an impl which
> can extract the backing store for LVM volumes

This looks fine, but I'd feel a lot better about it
if there were a few tests of the new bits.
A few questions/suggestions:

> diff --git a/src/storage_backend.c b/src/storage_backend.c
...
> @@ -235,38 +263,38 @@ virStorageBackendUpdateVolInfoFD(virConn
>                  continue;
>              if (memcmp(buffer+disk_types[i].offset, &disk_types[i].magic,
>                  disk_types[i].length) == 0) {
> -                vol->target.format = disk_types[i].part_table_type;
> +                target->format = disk_types[i].part_table_type;
>                  break;
>              }
>          }
>      }
>
> -    vol->target.perms.mode = sb.st_mode;
> -    vol->target.perms.uid = sb.st_uid;
> -    vol->target.perms.gid = sb.st_gid;
> +    target->perms.mode = sb.st_mode & (0x200-1);

How about S_IRWXUGO:

       target->perms.mode = sb.st_mode & S_IRWXUGO;

> +    target->perms.uid = sb.st_uid;
> +    target->perms.gid = sb.st_gid;
...
> diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
...
> +static int
> +cowGetBackingStore(virConnectPtr conn,
> +                   char **res,
> +                   const unsigned char *buf,
> +                   size_t buf_size)
> +{
> +    size_t len;
> +
> +    *res = NULL;
> +    if (buf_size < 4+4+1024)
> +        return BACKING_STORE_INVALID;
> +    if (buf[4+4] == '\0') /* cow_header_v2.backing_file[0] */
> +        return BACKING_STORE_OK;
> +
> +    len = 1024;
> +    if (VIR_ALLOC_N(*res, len + 1) < 0) {
> +        virStorageReportError(conn, VIR_ERR_NO_MEMORY, _("backing store path"));
> +        return BACKING_STORE_ERROR;
> +    }
> +    memcpy(*res, buf + 4+4, len); /* cow_header_v2.backing_file */
> +    (*res)[len] = '\0';
> +    if (VIR_REALLOC_N(*res, strlen(*res) + 1) < 0) {

Is this just-copied 1024-byte block of data guaranteed
not to contain any NUL bytes?  Or maybe you just want that
NUL-terminated string?

> +        /* Ignore failure */
> +    }
> +    return BACKING_STORE_OK;
> +}
...
> @@ -846,17 +1081,36 @@ virStorageBackendFileSystemVolCreate(vir
>                                    vol->target.format);
>              return -1;
>          }
> +        if (vol->backingStore.path) {
> +            if ((backingType = virStorageVolFormatFileSystemTypeToString(vol->backingStore.format)) == NULL) {
> +                virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
> +                                      _("unknown storage vol backing store type %d"),
> +                                      vol->backingStore.format);
> +                return -1;
> +            }
> +            if (access(vol->backingStore.path, R_OK) != 0) {
> +                virReportSystemError(conn, errno,
> +                                     _("inaccessible backing store volume %s"),
> +                                     vol->backingStore.path);
> +                return -1;
> +            }
> +        }
>
>          /* Size in KB */
>          snprintf(size, sizeof(size), "%llu", vol->capacity/1024);
>
> -        imgargv[0] = QEMU_IMG;
> -        imgargv[1] = "create";
> -        imgargv[2] = "-f";
> -        imgargv[3] = type;
> -        imgargv[4] = vol->target.path;
> -        imgargv[5] = size;
> -        imgargv[6] = NULL;
> +        i = 0;
> +        imgargv[i++] = QEMU_IMG;
> +        imgargv[i++] = "create";
> +        imgargv[i++] = "-f";
> +        imgargv[i++] = type;
> +        if (vol->backingStore.path != NULL) {
> +            imgargv[i++] = "-b";
> +            imgargv[i++] = vol->backingStore.path;
> +        }
> +        imgargv[i++] = vol->target.path;
> +        imgargv[i++] = size;
> +        imgargv[i++] = NULL;

Add an assertion like

   assert (i < ARRAY_CARDINALITY (imgargv));

Otherwise, it's far too easy to forget to update the "9"
above when adding a new option here.

...
> diff --git a/src/storage_backend_iscsi.c b/src/storage_backend_iscsi.c
> --- a/src/storage_backend_iscsi.c
> +++ b/src/storage_backend_iscsi.c
> @@ -226,7 +226,11 @@ virStorageBackendISCSINewLun(virConnectP
>
>      VIR_FREE(devpath);
>
> -    if (virStorageBackendUpdateVolInfoFD(conn, vol, fd, 1) < 0)
> +    if (virStorageBackendUpdateVolTargetInfoFD(conn,
> +                                               &vol->target,
> +                                               fd,
> +                                               &vol->allocation,
> +                                               &vol->capacity) < 0)
>          goto cleanup;
>
>      /* XXX use unique iSCSI id instead */
> diff --git a/src/storage_backend_logical.c b/src/storage_backend_logical.c
> --- a/src/storage_backend_logical.c
> +++ b/src/storage_backend_logical.c
> @@ -116,8 +116,22 @@ virStorageBackendLogicalMakeVol(virConne
>          strcat(vol->target.path, vol->name);
>      }
>
> +    if (groups[1] && !STREQ(groups[1], "")) {
> +        if (VIR_ALLOC_N(vol->backingStore.path, strlen(pool->def->target.path) +
> +                        1 + strlen(groups[1]) + 1) < 0) {
> +            virStorageReportError(conn, VIR_ERR_NO_MEMORY, "%s", _("volume"));
> +            return -1;
> +        }
> +        strcpy(vol->backingStore.path, pool->def->target.path);
> +        strcat(vol->backingStore.path, "/");
> +        strcat(vol->backingStore.path, groups[1]);

How about using virAsprintf in place of VIR_ALLOC_N + strcpy + strcat?




More information about the libvir-list mailing list