https://bugzilla.redhat.com/show_bug.cgi?id=1332019 This function will essentially be a wrapper to virStorageVolInfo in order to provide a mechanism to have the "physical" size of the volume returned instead of the "allocation" size. This will provide similar capabilities to the virDomainBlockInfo which can return both allocation and physical of a domain storage volume. NB: Since we're reusing the _virStorageVolInfo and not creating a new _virStorageVolInfoFlags structure, we'll need to generate the rpc APIs remoteStorageVolGetInfoFlags and remoteDispatchStorageVolGetInfoFlags (although both were originally created from gendispatch.pl and then just copied into daemon/remote.c and src/remote/remote_driver.c). The new API will allow the usage of a VIR_STORAGE_VOL_GET_PHYSICAL flag and will make the decision to return the physical or allocation value into the allocation field. In order to get that physical value, virStorageBackendUpdateVolTargetInfoFD adds logic to fill in physical value matching logic in qemuStorageLimitsRefresh used by virDomainBlockInfo when the domain is inactive. Signed-off-by: John Ferlan <jferlan@xxxxxxxxxx> --- daemon/remote.c | 38 +++++++++++++++++++++++++++++ include/libvirt/libvirt-storage.h | 11 +++++++++ src/driver-storage.h | 6 +++++ src/libvirt-storage.c | 51 +++++++++++++++++++++++++++++++++++++++ src/libvirt_public.syms | 5 ++++ src/remote/remote_driver.c | 37 ++++++++++++++++++++++++++++ src/remote/remote_protocol.x | 20 ++++++++++++++- src/remote_protocol-structs | 10 ++++++++ src/storage/storage_driver.c | 24 +++++++++++++++--- 9 files changed, 197 insertions(+), 5 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 46773da..23c9de4 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -6594,6 +6594,44 @@ remoteDispatchDomainInterfaceAddresses(virNetServerPtr server ATTRIBUTE_UNUSED, } +static int +remoteDispatchStorageVolGetInfoFlags(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_storage_vol_get_info_flags_args *args, + remote_storage_vol_get_info_flags_ret *ret) +{ + int rv = -1; + virStorageVolPtr vol = NULL; + virStorageVolInfo tmp; + struct daemonClientPrivate *priv = + virNetServerClientGetPrivateData(client); + + if (!priv->conn) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); + goto cleanup; + } + + if (!(vol = get_nonnull_storage_vol(priv->conn, args->vol))) + goto cleanup; + + if (virStorageVolGetInfoFlags(vol, &tmp, args->flags) < 0) + goto cleanup; + + ret->type = tmp.type; + ret->capacity = tmp.capacity; + ret->allocation = tmp.allocation; + rv = 0; + + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + virObjectUnref(vol); + return rv; +} + + /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire diff --git a/include/libvirt/libvirt-storage.h b/include/libvirt/libvirt-storage.h index 0974f6e..8a861e4 100644 --- a/include/libvirt/libvirt-storage.h +++ b/include/libvirt/libvirt-storage.h @@ -167,6 +167,14 @@ typedef enum { # endif } virStorageVolWipeAlgorithm; +typedef enum { + VIR_STORAGE_VOL_USE_ALLOCATION = 0, + + /* Return the physical size in allocation */ + VIR_STORAGE_VOL_GET_PHYSICAL = 1 << 0, + +} virStorageVolInfoFlags; + typedef struct _virStorageVolInfo virStorageVolInfo; struct _virStorageVolInfo { @@ -359,6 +367,9 @@ int virStorageVolFree (virStorageVolPtr vol); int virStorageVolGetInfo (virStorageVolPtr vol, virStorageVolInfoPtr info); +int virStorageVolGetInfoFlags (virStorageVolPtr vol, + virStorageVolInfoPtr info, + unsigned int flags); char * virStorageVolGetXMLDesc (virStorageVolPtr pool, unsigned int flags); diff --git a/src/driver-storage.h b/src/driver-storage.h index afcb12b..48e588a 100644 --- a/src/driver-storage.h +++ b/src/driver-storage.h @@ -158,6 +158,11 @@ typedef int (*virDrvStorageVolGetInfo)(virStorageVolPtr vol, virStorageVolInfoPtr info); +typedef int +(*virDrvStorageVolGetInfoFlags)(virStorageVolPtr vol, + virStorageVolInfoPtr info, + unsigned int flags); + typedef char * (*virDrvStorageVolGetXMLDesc)(virStorageVolPtr pool, unsigned int flags); @@ -257,6 +262,7 @@ struct _virStorageDriver { virDrvStorageVolWipe storageVolWipe; virDrvStorageVolWipePattern storageVolWipePattern; virDrvStorageVolGetInfo storageVolGetInfo; + virDrvStorageVolGetInfoFlags storageVolGetInfoFlags; virDrvStorageVolGetXMLDesc storageVolGetXMLDesc; virDrvStorageVolGetPath storageVolGetPath; virDrvStorageVolResize storageVolResize; diff --git a/src/libvirt-storage.c b/src/libvirt-storage.c index 48996ba..05eec8a 100644 --- a/src/libvirt-storage.c +++ b/src/libvirt-storage.c @@ -1914,6 +1914,57 @@ virStorageVolGetInfo(virStorageVolPtr vol, /** + * virStorageVolGetInfoFlags: + * @vol: pointer to storage volume + * @info: pointer at which to store info + * @flags: bitwise-OR of virStorageVolInfoFlags + * + * Fetches volatile information about the storage + * volume such as its current allocation. + * + * If the @flags argument is VIR_STORAGE_VOL_GET_PHYSICAL, then the physical + * bytes used for the volume will be returned in the @info allocation field. + * This is useful for sparse files and certain volume file types where the + * physical on disk usage can be different than the calculated allocation value + * as is the case with qcow2 files. + * + * Returns 0 on success, or -1 on failure + */ +int +virStorageVolGetInfoFlags(virStorageVolPtr vol, + virStorageVolInfoPtr info, + unsigned int flags) +{ + virConnectPtr conn; + VIR_DEBUG("vol=%p, info=%p, flags=%x", vol, info, flags); + + virResetLastError(); + + if (info) + memset(info, 0, sizeof(*info)); + + virCheckStorageVolReturn(vol, -1); + virCheckNonNullArgGoto(info, error); + + conn = vol->conn; + + if (conn->storageDriver->storageVolGetInfoFlags) { + int ret; + ret = conn->storageDriver->storageVolGetInfoFlags(vol, info, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(vol->conn); + return -1; +} + + +/** * virStorageVolGetXMLDesc: * @vol: pointer to storage volume * @flags: extra flags; not used yet, so callers should always pass 0 diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index e01604c..12ef085 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -746,4 +746,9 @@ LIBVIRT_2.2.0 { virConnectNodeDeviceEventDeregisterAny; } LIBVIRT_2.0.0; +LIBVIRT_3.0.0 { + global: + virStorageVolGetInfoFlags; +} LIBVIRT_2.2.0; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 8880520..46da06f 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7842,6 +7842,42 @@ remoteDomainRename(virDomainPtr dom, const char *new_name, unsigned int flags) } +static int +remoteStorageVolGetInfoFlags(virStorageVolPtr vol, + virStorageVolInfoPtr result, + unsigned int flags) +{ + int rv = -1; + struct private_data *priv = vol->conn->privateData; + remote_storage_vol_get_info_flags_args args; + remote_storage_vol_get_info_flags_ret ret; + + remoteDriverLock(priv); + + make_nonnull_storage_vol(&args.vol, vol); + args.flags = flags; + + memset(&ret, 0, sizeof(ret)); + + if (call(vol->conn, priv, 0, REMOTE_PROC_STORAGE_VOL_GET_INFO_FLAGS, + (xdrproc_t)xdr_remote_storage_vol_get_info_flags_args, + (char *)&args, + (xdrproc_t)xdr_remote_storage_vol_get_info_flags_ret, + (char *)&ret) == -1) { + goto done; + } + + result->type = ret.type; + result->capacity = ret.capacity; + result->allocation = ret.allocation; + rv = 0; + + done: + remoteDriverUnlock(priv); + return rv; +} + + /* get_nonnull_domain and get_nonnull_network turn an on-wire * (name, uuid) pair into virDomainPtr or virNetworkPtr object. * These can return NULL if underlying memory allocations fail, @@ -8290,6 +8326,7 @@ static virStorageDriver storage_driver = { .storageVolWipe = remoteStorageVolWipe, /* 0.8.0 */ .storageVolWipePattern = remoteStorageVolWipePattern, /* 0.9.10 */ .storageVolGetInfo = remoteStorageVolGetInfo, /* 0.4.1 */ + .storageVolGetInfoFlags = remoteStorageVolGetInfoFlags, /* 3.0.0 */ .storageVolGetXMLDesc = remoteStorageVolGetXMLDesc, /* 0.4.1 */ .storageVolGetPath = remoteStorageVolGetPath, /* 0.4.1 */ .storageVolResize = remoteStorageVolResize, /* 0.9.10 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index e8382dc..b846ef2 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1941,6 +1941,17 @@ struct remote_storage_vol_get_info_ret { /* insert@1 */ unsigned hyper allocation; }; +struct remote_storage_vol_get_info_flags_args { + remote_nonnull_storage_vol vol; + unsigned int flags; +}; + +struct remote_storage_vol_get_info_flags_ret { /* insert@1 */ + char type; + unsigned hyper capacity; + unsigned hyper allocation; +}; + struct remote_storage_vol_get_path_args { remote_nonnull_storage_vol vol; }; @@ -5934,5 +5945,12 @@ enum remote_procedure { * @generate: both * @acl: none */ - REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377 + REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377, + + /** + * @generate: none + * @priority: high + * @acl: storage_vol:read + */ + REMOTE_PROC_STORAGE_VOL_GET_INFO_FLAGS = 378 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index b71accc..41bc3bd 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1472,6 +1472,15 @@ struct remote_storage_vol_get_info_ret { uint64_t capacity; uint64_t allocation; }; +struct remote_storage_vol_get_info_flags_args { + remote_nonnull_storage_vol vol; + u_int flags; +}; +struct remote_storage_vol_get_info_flags_ret { + char type; + uint64_t capacity; + uint64_t allocation; +}; struct remote_storage_vol_get_path_args { remote_nonnull_storage_vol vol; }; @@ -3169,4 +3178,5 @@ enum remote_procedure { REMOTE_PROC_CONNECT_NODE_DEVICE_EVENT_DEREGISTER_ANY = 375, REMOTE_PROC_NODE_DEVICE_EVENT_LIFECYCLE = 376, REMOTE_PROC_NODE_DEVICE_EVENT_UPDATE = 377, + REMOTE_PROC_STORAGE_VOL_GET_INFO_FLAGS = 378, }; diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index a79acc6..5fc7066 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -2620,18 +2620,21 @@ storageVolWipe(virStorageVolPtr obj, static int -storageVolGetInfo(virStorageVolPtr obj, - virStorageVolInfoPtr info) +storageVolGetInfoFlags(virStorageVolPtr obj, + virStorageVolInfoPtr info, + unsigned int flags) { virStoragePoolObjPtr pool; virStorageBackendPtr backend; virStorageVolDefPtr vol; int ret = -1; + virCheckFlags(VIR_STORAGE_VOL_GET_PHYSICAL, -1); + if (!(vol = virStorageVolDefFromVol(obj, &pool, &backend))) return -1; - if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0) + if (virStorageVolGetInfoFlagsEnsureACL(obj->conn, pool->def, vol) < 0) goto cleanup; if (backend->refreshVol && @@ -2641,7 +2644,10 @@ storageVolGetInfo(virStorageVolPtr obj, memset(info, 0, sizeof(*info)); info->type = vol->type; info->capacity = vol->target.capacity; - info->allocation = vol->target.allocation; + if (flags & VIR_STORAGE_VOL_GET_PHYSICAL) + info->allocation = vol->target.physical; + else + info->allocation = vol->target.allocation; ret = 0; cleanup: @@ -2649,6 +2655,15 @@ storageVolGetInfo(virStorageVolPtr obj, return ret; } + +static int +storageVolGetInfo(virStorageVolPtr obj, + virStorageVolInfoPtr info) +{ + return storageVolGetInfoFlags(obj, info, 0); +} + + static char * storageVolGetXMLDesc(virStorageVolPtr obj, unsigned int flags) @@ -2803,6 +2818,7 @@ static virStorageDriver storageDriver = { .storageVolWipe = storageVolWipe, /* 0.8.0 */ .storageVolWipePattern = storageVolWipePattern, /* 0.9.10 */ .storageVolGetInfo = storageVolGetInfo, /* 0.4.0 */ + .storageVolGetInfoFlags = storageVolGetInfoFlags, /* 3.0.0 */ .storageVolGetXMLDesc = storageVolGetXMLDesc, /* 0.4.0 */ .storageVolGetPath = storageVolGetPath, /* 0.4.0 */ .storageVolResize = storageVolResize, /* 0.9.10 */ -- 2.7.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list