From: John Ferlan Date: Tue, 29 Nov 2016 15:44:36 +0000 (-0500) Subject: storage: Introduce virStorageVolInfoFlags X-Git-Tag: v3.0.0-rc1~255 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0c234889c4b0bd21ab2103c8bbac0290db1ff600;p=thirdparty%2Flibvirt.git storage: Introduce virStorageVolInfoFlags 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 --- diff --git a/daemon/remote.c b/daemon/remote.c index 46773da634..23c9de429a 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 0974f6ed29..8a861e4340 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 afcb12bc84..48e588a546 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 48996ba4c9..05eec8a9d4 100644 --- a/src/libvirt-storage.c +++ b/src/libvirt-storage.c @@ -1913,6 +1913,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 diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index e01604cad8..12ef085c51 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 888052045e..46da06f0a4 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 e8382dc51d..b846ef2138 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 b71accc073..41bc3bd247 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 a79acc6f06..5fc706634a 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 */