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 { typedef enum {
VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA = 1 << 0, VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA = 1 << 0,
VIR_STORAGE_VOL_CREATE_REFLINK = 1 << 1, /* perform a btrfs lightweight copy */
} virStorageVolCreateFlags; } virStorageVolCreateFlags;
virStorageVolPtr virStorageVolCreateXML (virStoragePoolPtr pool, virStorageVolPtr virStorageVolCreateXML (virStoragePoolPtr pool,

View File

@ -185,7 +185,8 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol, virStorageVolDefPtr inputvol,
int fd, int fd,
unsigned long long *total, unsigned long long *total,
bool want_sparse) bool want_sparse,
bool reflink_copy)
{ {
int inputfd = -1; int inputfd = -1;
int amtread = -1; int amtread = -1;
@ -224,6 +225,19 @@ virStorageBackendCopyToFD(virStorageVolDefPtr vol,
goto cleanup; 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) { while (amtread != 0) {
int amtleft; int amtleft;
@ -304,8 +318,11 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
struct stat st; struct stat st;
gid_t gid; gid_t gid;
uid_t uid; 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) { if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@ -314,6 +331,9 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
goto cleanup; goto cleanup;
} }
if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
reflink_copy = true;
if ((fd = open(vol->target.path, O_RDWR)) < 0) { if ((fd = open(vol->target.path, O_RDWR)) < 0) {
virReportSystemError(errno, virReportSystemError(errno,
_("cannot create path '%s'"), _("cannot create path '%s'"),
@ -325,7 +345,7 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
if (inputvol) { if (inputvol) {
int res = virStorageBackendCopyToFD(vol, inputvol, int res = virStorageBackendCopyToFD(vol, inputvol,
fd, &remain, false); fd, &remain, false, reflink_copy);
if (res < 0) if (res < 0)
goto cleanup; goto cleanup;
} }
@ -370,7 +390,8 @@ virStorageBackendCreateBlockFrom(virConnectPtr conn ATTRIBUTE_UNUSED,
static int static int
createRawFile(int fd, virStorageVolDefPtr vol, createRawFile(int fd, virStorageVolDefPtr vol,
virStorageVolDefPtr inputvol) virStorageVolDefPtr inputvol,
bool reflink_copy)
{ {
bool need_alloc = true; bool need_alloc = true;
int ret = 0; int ret = 0;
@ -417,7 +438,8 @@ createRawFile(int fd, virStorageVolDefPtr vol,
bool want_sparse = !need_alloc || bool want_sparse = !need_alloc ||
(vol->target.allocation < inputvol->target.capacity); (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) if (ret < 0)
goto cleanup; goto cleanup;
} }
@ -452,8 +474,11 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
int ret = -1; int ret = -1;
int fd = -1; int fd = -1;
int operation_flags; 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) { if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@ -462,6 +487,10 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
goto cleanup; goto cleanup;
} }
if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
reflink_copy = true;
if (vol->target.encryption != NULL) { if (vol->target.encryption != NULL) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("storage pool does not support encrypted volumes")); _("storage pool does not support encrypted volumes"));
@ -504,7 +533,7 @@ virStorageBackendCreateRaw(virConnectPtr conn ATTRIBUTE_UNUSED,
#endif #endif
} }
if ((ret = createRawFile(fd, vol, inputvol)) < 0) if ((ret = createRawFile(fd, vol, inputvol, reflink_copy)) < 0)
/* createRawFile already reported the exact error. */ /* createRawFile already reported the exact error. */
ret = -1; ret = -1;

View File

@ -1105,7 +1105,9 @@ virStorageBackendFileSystemVolBuild(virConnectPtr conn,
virStorageVolDefPtr vol, virStorageVolDefPtr vol,
unsigned int flags) 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); return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL, flags);
} }
@ -1120,7 +1122,9 @@ virStorageBackendFileSystemVolBuildFrom(virConnectPtr conn,
virStorageVolDefPtr inputvol, virStorageVolDefPtr inputvol,
unsigned int flags) 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); return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol, flags);
} }

View File

@ -1756,7 +1756,9 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj,
unsigned long long allocation; unsigned long long allocation;
int buildret; int buildret;
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL); virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
VIR_STORAGE_VOL_CREATE_REFLINK,
NULL);
storageDriverLock(); storageDriverLock();
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid); pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);