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:
Chen Hanxiao 2015-01-23 18:22:35 +08:00 committed by Ján Tomko
parent 466b29c8c3
commit 95da191376
4 changed files with 46 additions and 10 deletions

View File

@ -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,

View File

@ -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;

View File

@ -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);
}

View File

@ -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);