mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-23 03:42:19 +00:00
storage: allow metadata preallocation when creating qcow2 images
Add VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA flag to virStorageVolCreateXML and virStorageVolCreateXMLFrom. This flag requests metadata preallocation when creating/cloning qcow2 images, resulting in creating a sparse file with qcow2 metadata. It has only slightly larger disk usage compared to new image with no allocation, but offers higher performance.
This commit is contained in:
parent
b718ded39a
commit
1c9a2fb1ae
@ -2906,6 +2906,10 @@ virStorageVolPtr virStorageVolLookupByPath (virConnectPtr conn,
|
|||||||
const char* virStorageVolGetName (virStorageVolPtr vol);
|
const char* virStorageVolGetName (virStorageVolPtr vol);
|
||||||
const char* virStorageVolGetKey (virStorageVolPtr vol);
|
const char* virStorageVolGetKey (virStorageVolPtr vol);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA = 1 << 0,
|
||||||
|
} virStorageVolCreateFlags;
|
||||||
|
|
||||||
virStorageVolPtr virStorageVolCreateXML (virStoragePoolPtr pool,
|
virStorageVolPtr virStorageVolCreateXML (virStoragePoolPtr pool,
|
||||||
const char *xmldesc,
|
const char *xmldesc,
|
||||||
unsigned int flags);
|
unsigned int flags);
|
||||||
|
@ -13382,11 +13382,16 @@ virStorageVolGetKey(virStorageVolPtr vol)
|
|||||||
* virStorageVolCreateXML:
|
* virStorageVolCreateXML:
|
||||||
* @pool: pointer to storage pool
|
* @pool: pointer to storage pool
|
||||||
* @xmlDesc: description of volume to create
|
* @xmlDesc: description of volume to create
|
||||||
* @flags: extra flags; not used yet, so callers should always pass 0
|
* @flags: bitwise-OR of virStorageVolCreateFlags
|
||||||
*
|
*
|
||||||
* Create a storage volume within a pool based
|
* Create a storage volume within a pool based
|
||||||
* on an XML description. Not all pools support
|
* on an XML description. Not all pools support
|
||||||
* creation of volumes
|
* creation of volumes.
|
||||||
|
*
|
||||||
|
* Since 1.0.1 VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA
|
||||||
|
* in flags can be used to get higher performance with
|
||||||
|
* qcow2 image files which don't support full preallocation,
|
||||||
|
* by creating a sparse image file with metadata.
|
||||||
*
|
*
|
||||||
* Returns the storage volume, or NULL on error
|
* Returns the storage volume, or NULL on error
|
||||||
*/
|
*/
|
||||||
@ -13433,13 +13438,18 @@ error:
|
|||||||
* @pool: pointer to parent pool for the new volume
|
* @pool: pointer to parent pool for the new volume
|
||||||
* @xmlDesc: description of volume to create
|
* @xmlDesc: description of volume to create
|
||||||
* @clonevol: storage volume to use as input
|
* @clonevol: storage volume to use as input
|
||||||
* @flags: extra flags; not used yet, so callers should always pass 0
|
* @flags: bitwise-OR of virStorageVolCreateFlags
|
||||||
*
|
*
|
||||||
* Create a storage volume in the parent pool, using the
|
* Create a storage volume in the parent pool, using the
|
||||||
* 'clonevol' volume as input. Information for the new
|
* 'clonevol' volume as input. Information for the new
|
||||||
* volume (name, perms) are passed via a typical volume
|
* volume (name, perms) are passed via a typical volume
|
||||||
* XML description.
|
* XML description.
|
||||||
*
|
*
|
||||||
|
* Since 1.0.1 VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA
|
||||||
|
* in flags can be used to get higher performance with
|
||||||
|
* qcow2 image files which don't support full preallocation,
|
||||||
|
* by creating a sparse image file with metadata.
|
||||||
|
*
|
||||||
* Returns the storage volume, or NULL on error
|
* Returns the storage volume, or NULL on error
|
||||||
*/
|
*/
|
||||||
virStorageVolPtr
|
virStorageVolPtr
|
||||||
|
@ -668,8 +668,11 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|||||||
virCommandPtr cmd = NULL;
|
virCommandPtr cmd = NULL;
|
||||||
bool do_encryption = (vol->target.encryption != NULL);
|
bool do_encryption = (vol->target.encryption != NULL);
|
||||||
unsigned long long int size_arg;
|
unsigned long long int size_arg;
|
||||||
|
bool preallocate = false;
|
||||||
|
|
||||||
virCheckFlags(0, -1);
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
||||||
|
|
||||||
|
preallocate = !!(flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA);
|
||||||
|
|
||||||
const char *type = virStorageFileFormatTypeToString(vol->target.format);
|
const char *type = virStorageFileFormatTypeToString(vol->target.format);
|
||||||
const char *backingType = vol->backingStore.path ?
|
const char *backingType = vol->backingStore.path ?
|
||||||
@ -697,11 +700,23 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|||||||
inputvol->target.format);
|
inputvol->target.format);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (preallocate && vol->target.format != VIR_STORAGE_FILE_QCOW2) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("metadata preallocation only available with qcow2"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (vol->backingStore.path) {
|
if (vol->backingStore.path) {
|
||||||
int accessRetCode = -1;
|
int accessRetCode = -1;
|
||||||
char *absolutePath = NULL;
|
char *absolutePath = NULL;
|
||||||
|
|
||||||
|
if (preallocate) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("metadata preallocation conflicts with backing"
|
||||||
|
" store"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: Not strictly required: qemu-img has an option a different
|
/* XXX: Not strictly required: qemu-img has an option a different
|
||||||
* backing store, not really sure what use it serves though, and it
|
* backing store, not really sure what use it serves though, and it
|
||||||
* may cause issues with lvm. Untested essentially.
|
* may cause issues with lvm. Untested essentially.
|
||||||
@ -796,14 +811,15 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|||||||
virCommandAddArgList(cmd, "convert", "-f", inputType, "-O", type,
|
virCommandAddArgList(cmd, "convert", "-f", inputType, "-O", type,
|
||||||
inputPath, vol->target.path, NULL);
|
inputPath, vol->target.path, NULL);
|
||||||
|
|
||||||
if (do_encryption) {
|
if (imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS &&
|
||||||
if (imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS) {
|
(do_encryption || preallocate)) {
|
||||||
virCommandAddArgList(cmd, "-o", "encryption=on", NULL);
|
virCommandAddArg(cmd, "-o");
|
||||||
} else {
|
virCommandAddArgFormat(cmd, "%s%s%s", do_encryption ? "encryption=on" : "",
|
||||||
virCommandAddArg(cmd, "-e");
|
(do_encryption && preallocate) ? "," : "",
|
||||||
}
|
preallocate ? "preallocation=metadata" : "");
|
||||||
|
} else if (do_encryption) {
|
||||||
|
virCommandAddArg(cmd, "-e");
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (vol->backingStore.path) {
|
} else if (vol->backingStore.path) {
|
||||||
virCommandAddArgList(cmd, "create", "-f", type,
|
virCommandAddArgList(cmd, "create", "-f", type,
|
||||||
"-b", vol->backingStore.path, NULL);
|
"-b", vol->backingStore.path, NULL);
|
||||||
@ -840,12 +856,14 @@ virStorageBackendCreateQemuImg(virConnectPtr conn,
|
|||||||
vol->target.path, NULL);
|
vol->target.path, NULL);
|
||||||
virCommandAddArgFormat(cmd, "%lluK", size_arg);
|
virCommandAddArgFormat(cmd, "%lluK", size_arg);
|
||||||
|
|
||||||
if (do_encryption) {
|
if (imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS &&
|
||||||
if (imgformat == QEMU_IMG_BACKING_FORMAT_OPTIONS) {
|
(do_encryption || preallocate)) {
|
||||||
virCommandAddArgList(cmd, "-o", "encryption=on", NULL);
|
virCommandAddArg(cmd, "-o");
|
||||||
} else {
|
virCommandAddArgFormat(cmd, "%s%s%s", do_encryption ? "encryption=on" : "",
|
||||||
virCommandAddArg(cmd, "-e");
|
(do_encryption && preallocate) ? "," : "",
|
||||||
}
|
preallocate ? "preallocation=metadata" : "");
|
||||||
|
} else if (do_encryption) {
|
||||||
|
virCommandAddArg(cmd, "-e");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,8 @@ typedef int (*virStorageBackendStopPool)(virConnectPtr conn, virStoragePoolObjPt
|
|||||||
typedef int (*virStorageBackendDeletePool)(virConnectPtr conn, virStoragePoolObjPtr pool, unsigned int flags);
|
typedef int (*virStorageBackendDeletePool)(virConnectPtr conn, virStoragePoolObjPtr pool, unsigned int flags);
|
||||||
|
|
||||||
typedef int (*virStorageBackendBuildVol)(virConnectPtr conn,
|
typedef int (*virStorageBackendBuildVol)(virConnectPtr conn,
|
||||||
virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
virStoragePoolObjPtr pool, virStorageVolDefPtr vol,
|
||||||
|
unsigned int flags);
|
||||||
typedef int (*virStorageBackendCreateVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
typedef int (*virStorageBackendCreateVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
||||||
typedef int (*virStorageBackendRefreshVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
typedef int (*virStorageBackendRefreshVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol);
|
||||||
typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags);
|
typedef int (*virStorageBackendDeleteVol)(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags);
|
||||||
|
@ -1052,7 +1052,8 @@ static int
|
|||||||
_virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
_virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
||||||
virStoragePoolObjPtr pool,
|
virStoragePoolObjPtr pool,
|
||||||
virStorageVolDefPtr vol,
|
virStorageVolDefPtr vol,
|
||||||
virStorageVolDefPtr inputvol)
|
virStorageVolDefPtr inputvol,
|
||||||
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
virStorageBackendBuildVolFrom create_func;
|
virStorageBackendBuildVolFrom create_func;
|
||||||
int tool_type;
|
int tool_type;
|
||||||
@ -1085,7 +1086,7 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_func(conn, pool, vol, inputvol, 0) < 0)
|
if (create_func(conn, pool, vol, inputvol, flags) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1098,8 +1099,11 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
|||||||
static int
|
static int
|
||||||
virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
virStorageBackendFileSystemVolBuild(virConnectPtr conn,
|
||||||
virStoragePoolObjPtr pool,
|
virStoragePoolObjPtr pool,
|
||||||
virStorageVolDefPtr vol) {
|
virStorageVolDefPtr vol,
|
||||||
return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL);
|
unsigned int flags) {
|
||||||
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
||||||
|
|
||||||
|
return _virStorageBackendFileSystemVolBuild(conn, pool, vol, NULL, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1112,9 +1116,9 @@ virStorageBackendFileSystemVolBuildFrom(virConnectPtr conn,
|
|||||||
virStorageVolDefPtr inputvol,
|
virStorageVolDefPtr inputvol,
|
||||||
unsigned int flags)
|
unsigned int flags)
|
||||||
{
|
{
|
||||||
virCheckFlags(0, -1);
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
|
||||||
|
|
||||||
return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol);
|
return _virStorageBackendFileSystemVolBuild(conn, pool, vol, inputvol, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1348,7 +1348,7 @@ storageVolumeCreateXML(virStoragePoolPtr obj,
|
|||||||
virStorageVolDefPtr voldef = NULL;
|
virStorageVolDefPtr voldef = NULL;
|
||||||
virStorageVolPtr ret = NULL, volobj = NULL;
|
virStorageVolPtr ret = NULL, volobj = NULL;
|
||||||
|
|
||||||
virCheckFlags(0, NULL);
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
|
||||||
|
|
||||||
storageDriverLock(driver);
|
storageDriverLock(driver);
|
||||||
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
|
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
|
||||||
@ -1425,7 +1425,7 @@ storageVolumeCreateXML(virStoragePoolPtr obj,
|
|||||||
voldef->building = 1;
|
voldef->building = 1;
|
||||||
virStoragePoolObjUnlock(pool);
|
virStoragePoolObjUnlock(pool);
|
||||||
|
|
||||||
buildret = backend->buildVol(obj->conn, pool, buildvoldef);
|
buildret = backend->buildVol(obj->conn, pool, buildvoldef, flags);
|
||||||
|
|
||||||
storageDriverLock(driver);
|
storageDriverLock(driver);
|
||||||
virStoragePoolObjLock(pool);
|
virStoragePoolObjLock(pool);
|
||||||
@ -1473,7 +1473,7 @@ storageVolumeCreateXMLFrom(virStoragePoolPtr obj,
|
|||||||
virStorageVolPtr ret = NULL, volobj = NULL;
|
virStorageVolPtr ret = NULL, volobj = NULL;
|
||||||
int buildret;
|
int buildret;
|
||||||
|
|
||||||
virCheckFlags(0, NULL);
|
virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
|
||||||
|
|
||||||
storageDriverLock(driver);
|
storageDriverLock(driver);
|
||||||
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
|
pool = virStoragePoolObjFindByUUID(&driver->pools, obj->uuid);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user