We don't take advantage of clone of btrfs. So a)try to do a btrfs lightweight copy b)fall back to a standard copy if COW copy not supported. Signed-off-by: Chen Hanxiao <chenhanxiao@xxxxxxxxxxxxxx> --- include/libvirt/libvirt-storage.h | 1 + src/storage/storage_backend.c | 39 ++++++++++++++++++++++++++++++++------- src/storage/storage_backend_fs.c | 8 ++++++-- src/storage/storage_driver.c | 4 +++- 4 files changed, 42 insertions(+), 10 deletions(-) diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h index 1f3087b..4ae42e1 100644 --- a/include/libvirt/libvirt-storage.h +++ b/include/libvirt/libvirt-storage.h @@ -306,6 +306,7 @@ const char* virStorageVolGetKey (virStorageVolPtr vol); typedef enum { VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA = 1 << 0, + VIR_STORAGE_VOL_CREATE_REFLINK = 1 << 1, } virStorageVolCreateFlags; virStorageVolPtr virStorageVolCreateXML (virStoragePoolPtr pool, diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 5ce3566..838398e 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -187,7 +187,8 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol, virStorageVolDefPtr inputvol, int fd, unsigned long long *total, - bool want_sparse) + bool want_sparse, + bool reflink_copy) { int inputfd = -1; int amtread = -1; @@ -226,6 +227,15 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol, goto cleanup; } + if (reflink_copy) { + if (btrfsCloneFile(fd, inputfd) == -1) { + VIR_DEBUG("btrfs clone not supported, try another way."); + } else { + VIR_DEBUG("btrfs clone findished."); + goto cleanup; + } + } + while (amtread != 0) { int amtleft; @@ -306,8 +316,11 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED, struct stat st; gid_t gid; uid_t uid; + bool reflink_copy = false; - virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1); + virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA | + VIR_STORAGE_VOL_CREATE_REFLINK, + -1); if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -316,6 +329,9 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED, goto cleanup; } + if (flags & VIR_STORAGE_VOL_CREATE_REFLINK) + reflink_copy = true; + if ((fd = open(vol->target.path, O_RDWR)) < 0) { virReportSystemError(errno, _("cannot create path '%s'"), @@ -327,7 +343,7 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED, if (inputvol) { int res = virStorageBackendCopyToFD(vol, inputvol, - fd, &remain, false); + fd, &remain, false, reflink_copy); if (res < 0) goto cleanup; } @@ -372,7 +388,8 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED, static int createRawFile(int fd, virStorageVolDefPtr vol, - virStorageVolDefPtr inputvol) + virStorageVolDefPtr inputvol, + bool reflink_copy) { bool need_alloc = true; int ret = 0; @@ -419,7 +436,8 @@ createRawFile(int fd, virStorageVolDefPtr vol, bool want_sparse = !need_alloc || (vol->target.allocation < inputvol->target.capacity); - ret = virStorageBackendCopyToFD(vol, inputvol, fd, &remain, want_sparse); + ret = virStorageBackendCopyToFD(vol, inputvol, fd, &remain, + want_sparse, reflink_copy); if (ret < 0) goto cleanup; } @@ -454,8 +472,11 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED, int ret = -1; int fd = -1; int operation_flags; + bool reflink_copy = false; - virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1); + virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA | + VIR_STORAGE_VOL_CREATE_REFLINK, + -1); if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", @@ -464,6 +485,10 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED, goto cleanup; } + if (flags & VIR_STORAGE_VOL_CREATE_REFLINK) + reflink_copy = true; + + if (vol->target.encryption != NULL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("storage pool does not support encrypted volumes")); @@ -506,7 +531,7 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED, #endif } - if ((ret = createRawFile(fd, vol, inputvol)) < 0) + if ((ret = createRawFile(fd, vol, inputvol, reflink_copy)) < 0) /* createRawFile already reported the exact error. */ ret = -1; diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index 34f2153..cf30aab 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -1105,7 +1105,9 @@ virStorageBackendFileSystemVolBuild(virConnectPtr conn, virStorageVolDefPtr vol, unsigned int flags) { - virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1); + virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA | + VIR_STORAGE_VOL_CREATE_REFLINK, + -1); return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL, flags); } @@ -1120,7 +1122,9 @@ virStorageBackendFileSystemVolBuildFrom(virConnectPtr conn, virStorageVolDefPtr inputvol, unsigned int flags) { - virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1); + virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA | + VIR_STORAGE_VOL_CREATE_REFLINK, + -1); return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol, flags); } diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 66dc994..2c7af48 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -1775,7 +1775,9 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj, unsigned long long allocation; int buildret; - virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL); + virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA | + VIR_STORAGE_VOL_CREATE_REFLINK, + NULL); storageDriverLock(); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); -- 1.9.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list