[libvirt] [PATCH] ZFS: Support sparse volumes

Roman Bogorodskiy bogorodskiy at gmail.com
Sat Mar 5 14:35:53 UTC 2016


  Richard Laager wrote:

> By default, `zfs create -V ...` reserves space for the entire volsize,
> plus some extra (which attempts to account for overhead).
> 
> If `zfs create -s -V ...` is used instead, zvols are (fully) sparse.
> 
> A middle ground (partial allocation) can be achieved with
> `zfs create -s -o refreservation=... -V ...`.  Both libvirt and ZFS
> support this approach, so the ZFS storage backend should support it.

Hi!

Thanks for the patch! Some questions inline.

> Signed-off-by: Richard Laager <rlaager at wiktel.com>
> ---
>  src/storage/storage_backend_zfs.c | 31 +++++++++++++++++++++++++++++--
>  1 file changed, 29 insertions(+), 2 deletions(-)
> 
> diff --git a/src/storage/storage_backend_zfs.c b/src/storage/storage_backend_zfs.c
> index 2e6e407..6dc3cec 100644
> --- a/src/storage/storage_backend_zfs.c
> +++ b/src/storage/storage_backend_zfs.c
> @@ -112,7 +112,7 @@ virStorageBackendZFSParseVol(virStoragePoolObjPtr pool,
>      if (!(tokens = virStringSplitCount(volume_string, "\t", 0, &count)))
>          return -1;
>  
> -    if (count != 2)
> +    if (count != 3)
>          goto cleanup;
>  
>      if (!(name_tokens = virStringSplit(tokens[0], "/", 2)))
> @@ -151,6 +151,20 @@ virStorageBackendZFSParseVol(virStoragePoolObjPtr pool,
>          goto cleanup;
>      }
>  
> +    if (virStrToLong_ull(tokens[2], NULL, 10, &volume->target.allocation) < 0) {
> +        virReportError(VIR_ERR_INTERNAL_ERROR,
> +                       "%s", _("malformed refreservation reported"));
> +        goto cleanup;
> +    }
> +    if (volume->target.allocation >= volume->target.capacity) {
> +        /* A zvol created without -s will have a refreservation slightly larger
> +         * than volblocksize.
> +         */
> +        volume->target.allocation = volume->target.capacity;

What if allocation specified will be much larger than capacity?

Neither zfs nor virStorageBackendZFSCreateVol() prevent from creating a
volume with:

  --capacity 2G --allocation 4G

Though it'll be displayed as capacity == allocation == 2G by libvirt.

What's the reason to limit displayed allocation?

PS I noticed that it could be an issue to set refreservation larger than
volsize with ZFS on Linux:
    https://github.com/zfsonlinux/zfs/issues/2468.

The issue is still open and at this moment I cannot check if I can
reproduce that on Linux.

Thanks,

> +    } else {
> +        volume->target.sparse = true;
> +    }
> +
>      if (is_new_vol &&
>          VIR_APPEND_ELEMENT(pool->volumes.objs,
>                             pool->volumes.count,
> @@ -190,7 +204,7 @@ virStorageBackendZFSFindVols(virStoragePoolObjPtr pool,
>      cmd = virCommandNewArgList(ZFS,
>                                 "list", "-Hp",
>                                 "-t", "volume", "-r",
> -                               "-o", "name,volsize",
> +                               "-o", "name,volsize,refreservation",
>                                 pool->def->source.name,
>                                 NULL);
>      virCommandSetOutputBuffer(cmd, &volumes_list);
> @@ -320,15 +334,28 @@ virStorageBackendZFSCreateVol(virConnectPtr conn ATTRIBUTE_UNUSED,
>          goto cleanup;
>      /**
>       * $ zfs create -o volmode=dev -V 10240K test/volname
> +     * $ zfs create -o volmode=dev -s -V 10240K test/volname
> +     * $ zfs create -o volmode=dev -s -o refreservation=1024K -V 10240K test/volname
>       *
>       * -o volmode=dev -- we want to get volumes exposed as cdev
>       *                   devices. If we don't specify that zfs
>       *                   will lookup vfs.zfs.vol.mode sysctl value
> +     * -s -- create a sparse volume
> +     * -o refreservation -- reserve the specified amount of space
>       * -V -- tells to create a volume with the specified size
>       */
>      cmd = virCommandNewArgList(ZFS, "create", NULL);
>      if (volmode_needed)
>          virCommandAddArgList(cmd, "-o", "volmode=dev", NULL);
> +    if (vol->target.capacity != vol->target.allocation) {
> +        virCommandAddArg(cmd, "-s");
> +        if (vol->target.allocation > 0) {
> +            virCommandAddArg(cmd, "-o");
> +            virCommandAddArgFormat(cmd, "refreservation=%lluK",
> +                                   VIR_DIV_UP(vol->target.allocation, 1024));
> +        }
> +        vol->target.sparse = true;
> +    }
>      virCommandAddArg(cmd, "-V");
>      virCommandAddArgFormat(cmd, "%lluK",
>                             VIR_DIV_UP(vol->target.capacity, 1024));
> -- 
> 2.1.4
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list

Roman Bogorodskiy
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20160305/3bb9e1e1/attachment-0001.sig>


More information about the libvir-list mailing list