mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 22:55:23 +00:00
Fix cloning of raw, sparse volumes
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@linux.vnet.ibm.com> Signed-off-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
e30297b096
commit
dd519a294b
@ -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 original 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) {
|
||||
|
@ -1978,11 +1978,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"
|
||||
|
Loading…
Reference in New Issue
Block a user