From: Prerna Saxena <prerna@xxxxxxxxxxxxxxxxxx> When virsh vol-clone is attempted on a raw file where capacity > allocation, the resulting cloned volume has a size that matches the virtual-size of the parent; in place of matching its actual, disk size. This patch fixes the cloned disk to have same _allocated_size_ as the parent file from which it was cloned. Ref: http://www.redhat.com/archives/libvir-list/2015-May/msg00050.html Also fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1130739 Signed-off-by: Prerna Saxena <prerna@xxxxxxxxxxxxxxxxxx> Signed-off-by: Ján Tomko <jtomko@xxxxxxxxxx> --- src/storage/storage_backend.c | 23 ++++++++++++++--------- src/storage/storage_driver.c | 5 ----- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index c71545c..bab81e3 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -342,7 +342,7 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED, goto cleanup; } - remain = vol->target.allocation; + remain = vol->target.capacity; if (inputvol) { int res = virStorageBackendCopyToFD(vol, inputvol, @@ -401,6 +401,12 @@ createRawFile(int fd, virStorageVolDefPtr vol, int ret = 0; unsigned long long pos = 0; + /* If the new allocation is lower than the capacity of the orignal file, + * the cloned volume will be sparse */ + if (inputvol && + vol->target.allocation < inputvol->target.capacity) + need_alloc = false; + /* Seek to the final size, so the capacity is available upfront * for progress reporting */ if (ftruncate(fd, vol->target.capacity) < 0) { @@ -420,7 +426,7 @@ createRawFile(int fd, virStorageVolDefPtr vol, * to writing zeroes block by block in case fallocate isn't * available, and since we're going to copy data from another * file it doesn't make sense to write the file twice. */ - if (vol->target.allocation) { + if (vol->target.allocation && need_alloc) { if (fallocate(fd, 0, 0, vol->target.allocation) == 0) { need_alloc = false; } else if (errno != ENOSYS && errno != EOPNOTSUPP) { @@ -433,21 +439,20 @@ createRawFile(int fd, virStorageVolDefPtr vol, } #endif - if (inputvol) { - unsigned long long remain = vol->target.allocation; + unsigned long long remain = inputvol->target.capacity; /* allow zero blocks to be skipped if we've requested sparse * allocation (allocation < capacity) or we have already * been able to allocate the required space. */ - bool want_sparse = !need_alloc || - (vol->target.allocation < inputvol->target.capacity); - ret = virStorageBackendCopyToFD(vol, inputvol, fd, &remain, - want_sparse, reflink_copy); + !need_alloc, reflink_copy); if (ret < 0) goto cleanup; - pos = vol->target.allocation - remain; + /* If the new allocation is greater than the original capacity, + * but fallocate failed, fill the rest with zeroes. + */ + pos = inputvol->target.capacity - remain; } if (need_alloc) { diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index e600514..ba27acf 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1975,11 +1975,6 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj, if (newvol->target.capacity < origvol->target.capacity) newvol->target.capacity = origvol->target.capacity; - /* Make sure allocation is at least as large as the destination cap, - * to make absolutely sure we copy all possible contents */ - if (newvol->target.allocation < origvol->target.capacity) - newvol->target.allocation = origvol->target.capacity; - if (!backend->buildVolFrom) { virReportError(VIR_ERR_NO_SUPPORT, "%s", _("storage pool does not support" -- 2.3.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list