mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-01 17:35:17 +00:00
storage: add a flag to clone files on btrfs
When creating a RAW file, we don't take advantage of clone of btrfs. Add a VIR_STORAGE_VOL_CREATE_REFLINK flag to request a reflink copy. Signed-off-by: Chen Hanxiao <chenhanxiao@cn.fujitsu.com> Signed-off-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
parent
466b29c8c3
commit
95da191376
@ -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,
|
||||
|
@ -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 finished.");
|
||||
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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -1756,7 +1756,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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user