From c81bba4f6f925eda28e64bc6593e916f852db99e Mon Sep 17 00:00:00 2001 From: Richard Laager Date: Thu, 24 Mar 2016 00:11:11 -0500 Subject: [PATCH] ZFS: Support sparse volumes 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. Signed-off-by: Richard Laager --- src/storage/storage_backend_zfs.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/storage/storage_backend_zfs.c b/src/storage/storage_backend_zfs.c index 5c0c1fce5d..a3477e28e9 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,15 @@ 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) + volume->target.sparse = true; + if (is_new_vol && VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, @@ -190,7 +199,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); @@ -323,15 +332,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)); -- GitLab