When creating RAW file, we don't take advantage of clone of btrfs. Try to do a btrfs lightweight copy, or error out. Signed-off-by: Chen Hanxiao <chenhanxiao@xxxxxxxxxxxxxx> --- include/libvirt/libvirt-storage.h | 1 + src/storage/storage_backend.c | 43 ++++++++++++++++++++++++++++++++------- src/storage/storage_backend_fs.c | 8 ++++++-- src/storage/storage_driver.c | 4 +++- 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h index 1f3087b..453089e 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, /* perform a btrfs lightweight copy */ } virStorageVolCreateFlags; virStorageVolPtr virStorageVolCreateXML (virStoragePoolPtr pool, diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index d2a664b..cf13704 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -185,7 +185,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; @@ -224,6 +225,19 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol, goto cleanup; } + if (reflink_copy) { + if (btrfsCloneFile(fd, inputfd) < 0) { + ret = -errno; + virReportSystemError(errno, + _("failed to clone files from '%s'"), + inputvol->target.path); + goto cleanup; + } else { + VIR_DEBUG("btrfs clone findished."); + goto cleanup; + } + } + while (amtread != 0) { int amtleft; @@ -304,8 +318,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", @@ -314,6 +331,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'"), @@ -325,7 +345,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; } @@ -370,7 +390,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; @@ -417,7 +438,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; } @@ -452,8 +474,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", @@ -462,6 +487,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")); @@ -504,7 +533,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); -- 2.1.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list