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 */