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;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
remain = vol->target.allocation;
|
remain = vol->target.capacity;
|
||||||
|
|
||||||
if (inputvol) {
|
if (inputvol) {
|
||||||
int res = virStorageBackendCopyToFD(vol, inputvol,
|
int res = virStorageBackendCopyToFD(vol, inputvol,
|
||||||
@ -401,6 +401,12 @@ createRawFile(int fd, virStorageVolDefPtr vol,
|
|||||||
int ret = 0;
|
int ret = 0;
|
||||||
unsigned long long pos = 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
|
/* Seek to the final size, so the capacity is available upfront
|
||||||
* for progress reporting */
|
* for progress reporting */
|
||||||
if (ftruncate(fd, vol->target.capacity) < 0) {
|
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
|
* to writing zeroes block by block in case fallocate isn't
|
||||||
* available, and since we're going to copy data from another
|
* available, and since we're going to copy data from another
|
||||||
* file it doesn't make sense to write the file twice. */
|
* 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) {
|
if (fallocate(fd, 0, 0, vol->target.allocation) == 0) {
|
||||||
need_alloc = false;
|
need_alloc = false;
|
||||||
} else if (errno != ENOSYS && errno != EOPNOTSUPP) {
|
} else if (errno != ENOSYS && errno != EOPNOTSUPP) {
|
||||||
@ -433,21 +439,20 @@ createRawFile(int fd, virStorageVolDefPtr vol,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (inputvol) {
|
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
|
/* allow zero blocks to be skipped if we've requested sparse
|
||||||
* allocation (allocation < capacity) or we have already
|
* allocation (allocation < capacity) or we have already
|
||||||
* been able to allocate the required space. */
|
* been able to allocate the required space. */
|
||||||
bool want_sparse = !need_alloc ||
|
|
||||||
(vol->target.allocation < inputvol->target.capacity);
|
|
||||||
|
|
||||||
ret = virStorageBackendCopyToFD(vol, inputvol, fd, &remain,
|
ret = virStorageBackendCopyToFD(vol, inputvol, fd, &remain,
|
||||||
want_sparse, reflink_copy);
|
!need_alloc, reflink_copy);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto cleanup;
|
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) {
|
if (need_alloc) {
|
||||||
|
@ -1978,11 +1978,6 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
|
|||||||
if (newvol->target.capacity < origvol->target.capacity)
|
if (newvol->target.capacity < origvol->target.capacity)
|
||||||
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) {
|
if (!backend->buildVolFrom) {
|
||||||
virReportError(VIR_ERR_NO_SUPPORT,
|
virReportError(VIR_ERR_NO_SUPPORT,
|
||||||
"%s", _("storage pool does not support"
|
"%s", _("storage pool does not support"
|
||||||
|
Loading…
Reference in New Issue
Block a user