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 <jferlan@redhat.com>
This commit is contained in:
John Ferlan 2016-11-29 10:44:36 -05:00
parent 78661cb1f4
commit 0c234889c4
9 changed files with 197 additions and 5 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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 ....

View File

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

View File

@ -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
};

View File

@ -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,
};

View File

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