mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-22 19:32:19 +00:00
rbd: Use RBD fast-diff for querying actual volume allocation
Since Ceph version Infernalis (9.2.0) the new fast-diff mechanism of RBD allows for querying actual volume usage. Prior to this version there was no easy and fast way to query how much allocation a RBD volume had inside a Ceph cluster. To use the fast-diff feature it needs to be enabled per RBD image and is only supported by Ceph cluster running version Infernalis (9.2.0) or newer. Without the fast-diff feature enabled libvirt will report an allocation identical to the image capacity. This is how libvirt behaves currently. 'virsh vol-info rbd/image2' might output for example: Name: image2 Type: network Capacity: 1,00 GiB Allocation: 124,00 MiB Newly created volumes will have the fast-diff feature enabled if the backing Ceph cluster supports it. Signed-off-by: Wido den Hollander <wido@widodh.nl>
This commit is contained in:
parent
ab342e99f6
commit
98782f8899
@ -297,6 +297,68 @@ volStorageBackendRBDGetFeatures(rbd_image_t image,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if LIBRBD_VERSION_CODE > 265
|
||||
static bool
|
||||
volStorageBackendRBDUseFastDiff(uint64_t features)
|
||||
{
|
||||
return features & RBD_FEATURE_FAST_DIFF;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendRBDRefreshVolInfoCb(uint64_t offset ATTRIBUTE_UNUSED,
|
||||
size_t len,
|
||||
int exists,
|
||||
void *arg)
|
||||
{
|
||||
uint64_t *used_size = (uint64_t *)(arg);
|
||||
if (exists)
|
||||
(*used_size) += len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendRBDSetAllocation(virStorageVolDefPtr vol,
|
||||
rbd_image_t *image,
|
||||
rbd_image_info_t *info)
|
||||
{
|
||||
int r, ret = -1;
|
||||
uint64_t allocation = 0;
|
||||
|
||||
if ((r = rbd_diff_iterate2(image, NULL, 0, info->size, 0, 1,
|
||||
&virStorageBackendRBDRefreshVolInfoCb,
|
||||
&allocation)) < 0) {
|
||||
virReportSystemError(-r, _("failed to iterate RBD image '%s'"),
|
||||
vol->name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Found %zu bytes allocated for RBD image %s",
|
||||
allocation, vol->name);
|
||||
|
||||
vol->target.allocation = allocation;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
static int
|
||||
volStorageBackendRBDUseFastDiff(uint64_t features ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
virStorageBackendRBDSetAllocation(virStorageVolDefPtr vol ATTRIBUTE_UNUSED,
|
||||
rbd_image_t *image ATTRIBUTE_UNUSED,
|
||||
rbd_image_info_t *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
volStorageBackendRBDRefreshVolInfo(virStorageVolDefPtr vol,
|
||||
virStoragePoolObjPtr pool,
|
||||
@ -306,6 +368,7 @@ volStorageBackendRBDRefreshVolInfo(virStorageVolDefPtr vol,
|
||||
int r = 0;
|
||||
rbd_image_t image = NULL;
|
||||
rbd_image_info_t info;
|
||||
uint64_t features;
|
||||
|
||||
if ((r = rbd_open_read_only(ptr->ioctx, vol->name, &image, NULL)) < 0) {
|
||||
ret = -r;
|
||||
@ -321,15 +384,29 @@ volStorageBackendRBDRefreshVolInfo(virStorageVolDefPtr vol,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Refreshed RBD image %s/%s (size: %zu obj_size: %zu num_objs: %zu)",
|
||||
pool->def->source.name, vol->name, info.size, info.obj_size,
|
||||
info.num_objs);
|
||||
if (volStorageBackendRBDGetFeatures(image, vol->name, &features) < 0)
|
||||
goto cleanup;
|
||||
|
||||
vol->target.capacity = info.size;
|
||||
vol->target.allocation = info.obj_size * info.num_objs;
|
||||
vol->type = VIR_STORAGE_VOL_NETWORK;
|
||||
vol->target.format = VIR_STORAGE_FILE_RAW;
|
||||
|
||||
if (volStorageBackendRBDUseFastDiff(features)) {
|
||||
VIR_DEBUG("RBD image %s/%s has fast-diff feature enabled. "
|
||||
"Querying for actual allocation",
|
||||
pool->def->source.name, vol->name);
|
||||
|
||||
if (virStorageBackendRBDSetAllocation(vol, image, &info) < 0)
|
||||
goto cleanup;
|
||||
} else {
|
||||
vol->target.allocation = info.obj_size * info.num_objs;
|
||||
}
|
||||
|
||||
VIR_DEBUG("Refreshed RBD image %s/%s (capacity: %llu allocation: %llu "
|
||||
"obj_size: %zu num_objs: %zu)",
|
||||
pool->def->source.name, vol->name, vol->target.capacity,
|
||||
vol->target.allocation, info.obj_size, info.num_objs);
|
||||
|
||||
VIR_FREE(vol->target.path);
|
||||
if (virAsprintf(&vol->target.path, "%s/%s",
|
||||
pool->def->source.name,
|
||||
|
Loading…
x
Reference in New Issue
Block a user