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(a)cn.fujitsu.com>
---
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