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(a)widodh.nl>
---
src/storage/storage_backend_rbd.c | 48 +++++++++++++++++++++++++++++++++++----
1 file changed, 44 insertions(+), 4 deletions(-)
diff --git a/src/storage/storage_backend_rbd.c b/src/storage/storage_backend_rbd.c
index 5d73370..cdcfa48 100644
--- a/src/storage/storage_backend_rbd.c
+++ b/src/storage/storage_backend_rbd.c
@@ -279,6 +279,20 @@ virStorageBackendRBDCloseRADOSConn(virStorageBackendRBDStatePtr ptr)
return ret;
}
+#if LIBRBD_VERSION_CODE > 265
+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;
+}
+#endif
+
static int
volStorageBackendRBDRefreshVolInfo(virStorageVolDefPtr vol,
virStoragePoolObjPtr pool,
@@ -288,6 +302,8 @@ volStorageBackendRBDRefreshVolInfo(virStorageVolDefPtr vol,
int r = 0;
rbd_image_t image = NULL;
rbd_image_info_t info;
+ uint64_t features ATTRIBUTE_UNUSED;
+ uint64_t used_size ATTRIBUTE_UNUSED = 0;
if ((r = rbd_open_read_only(ptr->ioctx, vol->name, &image, NULL)) < 0)
{
ret = -r;
@@ -303,15 +319,39 @@ 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);
-
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 LIBRBD_VERSION_CODE > 265
+ if ((r = rbd_get_features(image, &features)) < 0) {
+ virReportSystemError(-r, _("failed to get flags of RBD image
'%s'"),
+ vol->name);
+ goto cleanup;
+ }
+
+ if (features & RBD_FEATURE_FAST_DIFF) {
+ VIR_DEBUG("RBD image %s/%s has fast-diff enabled. Querying
allocation",
+ pool->def->source.name, vol->name);
+
+ if ((r = rbd_diff_iterate2(image, NULL, 0, info.size, 0, 1,
+ &virStorageBackendRBDRefreshVolInfoCb,
+ &used_size)) < 0) {
+ virReportSystemError(-r, _("failed to iterate RBD image
'%s'"),
+ vol->name);
+ goto cleanup;
+ }
+
+ vol->target.allocation = used_size;
+ }
+#endif
+
+ 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,
--
1.9.1