[libvirt] Add virStorageVolResize()

Eric Blake eblake at redhat.com
Sat Jan 28 03:23:48 UTC 2012


On 01/27/2012 04:40 PM, Zeeshan Ali (Khattak) wrote:
> From: "Zeeshan Ali (Khattak)" <zeeshanak at gnome.org>
> 
> Add a new function to allow changing of capacity of storage volumes.

I know you still have to rebase, but here's some more review comments:

> diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
> index 75ed676..a37bf7c 100644
> --- a/src/storage/storage_backend.h
> +++ b/src/storage/storage_backend.h
> @@ -44,6 +44,11 @@ typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjP
>  typedef int (*virStorageBackendBuildVolFrom)(virConnectPtr conn, virStoragePoolObjPtr pool,
>                                               virStorageVolDefPtr origvol, virStorageVolDefPtr newvol,
>                                               unsigned int flags);
> +typedef int (*virStorageBackendVolumeResize)(virConnectPtr conn,
> +                                             virStoragePoolObjPtr pool,
> +                                             virStorageVolDefPtr vol,
> +                                             unsigned long long capacity,

You'll want to change this to long long.

> +                                             unsigned int flags);
>  
>  
> +static int
> +virStorageBackendFilesystemResizeQemuImg(const char *path,
> +                                         unsigned long long capacity)
> +{
> +    int ret = -1;
> +    char *img_tool;
> +    virCommandPtr cmd = NULL;
> +
> +    /* KVM is usually ahead of qemu on features, so try that first */
> +    img_tool = virFindFileInPath("kvm-img");
> +    if (!img_tool)
> +        img_tool = virFindFileInPath("qemu-img");

I'm surprised we're not caching this in some helper function.  Oh well,
that's an independent cleanup.

> +
> +    cmd = virCommandNew(img_tool);
> +    virCommandAddArgList(cmd, "resize", path, NULL);
> +    virCommandAddArgFormat(cmd, "%llu", capacity);

Guess what - qemu-img can do delta resizing, as well as shrinking.  In
fact, qemu-img can even do (sparse-only) resizing of raw files!  But for
raw files, I think we are better off doing it ourselves (as your patch
already did), as it means fewer forks and more control over whether the
result is sparse.

qemu-img resize foo 10M # reset size to 10M, regardless of whether that
is bigger or smaller - which means you have to check the capacity
yourself before calling qemu-img with a smaller capacity

qemu-img resize foo +10M # add 10M to capacity

qemu-img resize foo -10M # remove 10M from capacity

That all means that you have to be careful of the incoming flags, and
control whether you output a sign in the command line argument.


> +/**
> + * Resize a volume
> + */
> +static int
> +virStorageBackendFileSystemVolResize(virConnectPtr conn ATTRIBUTE_UNUSED,
> +                                     virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
> +                                     virStorageVolDefPtr vol,
> +                                     unsigned long long capacity,
> +                                     unsigned int flags)
> +{
> +    virCheckFlags(0, -1);
> +
> +    if (vol->target.format == VIR_STORAGE_FILE_RAW) {
> +        return virStorageFileResize(vol->target.path, capacity);

That signature loses the notion of whether you are doing a delta or an
absolute change.  Either you need to convert delta into absolute before
forwarding lower down the chain, or you need to add a bool parameter
stating whether a delta change is desired.

> +    } else if (vol->target.format == VIR_STORAGE_FILE_DIR) {
> +        virStorageReportError(VIR_ERR_NO_SUPPORT,
> +                              "%s", _("Changing size of directory based "
> +                                      "volumes is not supported"));
> +        return -1;


> @@ -1199,6 +1255,7 @@ virStorageBackend virStorageBackendDirectory = {
>      .createVol = virStorageBackendFileSystemVolCreate,
>      .refreshVol = virStorageBackendFileSystemVolRefresh,
>      .deleteVol = virStorageBackendFileSystemVolDelete,
> +    .resizeVol = virStorageBackendFileSystemVolResize,

I'd leave this one out.  That way, you don't have to handle
VIR_STORAGE_FILE_DIR in virStorageBackendFileSystemVolResize in the
first place.

>  
> +static int
> +storageVolumeResize(virStorageVolPtr obj,
> +                    unsigned long long capacity,
> +                    unsigned int flags)
> +{
> +    virStorageDriverStatePtr driver = obj->conn->storagePrivateData;
> +    virStorageBackendPtr backend;
> +    virStoragePoolObjPtr pool = NULL;
> +    virStorageVolDefPtr vol = NULL;
> +    int ret = -1;
> +
> +    virCheckFlags(0, -1);

Make sure you permit the flags you plan on supporting in at least one
backend (and it's okay if you don't support them all up front).

> +++ b/src/util/storage_file.c
> @@ -931,6 +931,22 @@ virStorageFileFreeMetadata(virStorageFileMetadata *meta)
>      VIR_FREE(meta);
>  }
>  
> +/**
> + * virStorageFileResize:
> + *
> + * Change the capacity of the raw storage file at 'path'.
> + */
> +int
> +virStorageFileResize(const char *path, unsigned long long capacity)
> +{
> +    if (truncate(path, capacity) < 0) {
> +        virReportSystemError(errno, _("Failed to truncate file '%s'"), path);
> +        return -1;
> +    }

Here, if the allocate flag is specified, you'd want two implementations:

If posix_fallocate exists, then open() the file, and use posix_fallocate
to ensure that the delta from the old size to the new size is allocated.

If it does not exist, then you need a while loop that writes a '\0' byte
every 4096 bytes or so, in order to force the capacity increase to be
non-sparse.

-- 
Eric Blake   eblake at redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 620 bytes
Desc: OpenPGP digital signature
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20120127/85f5e56e/attachment-0001.sig>


More information about the libvir-list mailing list