Use the output of the 'lvs' command in order to determine the current
allocation value for logical volumes. The capacity value for these pools
can still be obtained via the existing methodology to lseek to the end
of the block file in virStorageBackendUpdateVolTargetInfoFD.
The real need is for the thin logical volumes where the thin pool keeps
track of the capacity and the thin logical volume keeps track of the
allocation value.
In the future someone could add a fetch for the 'data_percent' in order
to determine the percentage of data used for the allocated space.
Signed-off-by: John Ferlan <jferlan(a)redhat.com>
---
src/storage/storage_backend_logical.c | 97 +++++++++++++++++++++++++++++++++++
1 file changed, 97 insertions(+)
diff --git a/src/storage/storage_backend_logical.c
b/src/storage/storage_backend_logical.c
index 45df38c..8b7325b 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -904,6 +904,102 @@ virStorageBackendLogicalCreateVol(virConnectPtr conn,
return -1;
}
+struct virStorageBackendLogicalVolRefreshData {
+ virStorageVolDefPtr vol;
+ bool alloc_sent;
+};
+
+static int
+virStorageBackendLogicalRefreshVolFunc(char **const groups,
+ void *opaque)
+{
+ struct virStorageBackendLogicalVolRefreshData *data = opaque;
+ virStorageVolDefPtr vol = data->vol;
+
+ if (data->alloc_sent) {
+ /* The capacity of the thin logical volume is kept in the 'lv_size'
+ * of the pool which will be sent when the RefreshVol code determines
+ * that this is a thin logical volume
+ */
+ if (virStrToLong_ull(groups[0], NULL, 10, &vol->target.capacity) < 0)
+ return -1;
+ } else {
+ if (virStrToLong_ull(groups[0], NULL, 10, &vol->target.allocation) <
0)
+ return -1;
+ data->alloc_sent = true;
+ }
+
+ return 0;
+}
+
+static int
+virStorageBackendLogicalRefreshVol(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ virStorageVolDefPtr vol)
+{
+ /*
+ * # lvs --noheadings --units b --unbuffered --nosuffix \
+ * --options "lv_size" VGNAME/LVNAME [VGNAME/thinpool_LVNAME]
+ *
+ * Pull out lv_size for volume capacity and if necessary pull
+ * out thinpool size for allocation. The output will either be
+ * one or two lines. The first line will be the capacity value.
+ * While, if there is a thin volume involved, the second line will
+ * be the allocation value for the thin lv from the thin pool
+ */
+ const char *regexes[] = {
+ "^\\s*([0-9]+)\\s*$"
+ };
+ int vars[] = {
+ 1
+ };
+ virCommandPtr cmd = NULL;
+ int ret = -1;
+ struct virStorageBackendLogicalVolRefreshData cbdata = {
+ .vol = vol,
+ .alloc_sent = false,
+ };
+
+ cmd = virCommandNewArgList(LVS,
+ "--noheadings",
+ "--units", "b",
+ "--unbuffered",
+ "--nosuffix",
+ "--options", "lv_size",
+ NULL);
+ virCommandAddArgFormat(cmd, "%s/%s",
+ pool->def->source.name,
+ vol->name);
+
+ /* If this is a thin volume, let's add the fetch of the thin volume size
+ * This will gernate two lines of output, which we'll handle via the
+ * alloc_sent boolean - this is where the pool capacity is stored from
+ * the -V during the lvcreate process
+ */
+ if (vol->target.thinVolume)
+ virCommandAddArgFormat(cmd, "%s/thinpool_%s",
+ pool->def->source.name,
+ vol->name);
+
+ /* Now get allocation of the logical volume and perhaps the capacity
+ * of the thin volume
+ */
+ if (virCommandRunRegex(cmd,
+ 1,
+ regexes,
+ vars,
+ virStorageBackendLogicalRefreshVolFunc,
+ &cbdata,
+ "lvs") < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virCommandFree(cmd);
+ return ret;
+}
+
static int
virStorageBackendLogicalBuildVolFrom(virConnectPtr conn,
virStoragePoolObjPtr pool,
@@ -961,6 +1057,7 @@ virStorageBackend virStorageBackendLogical = {
.buildVol = NULL,
.buildVolFrom = virStorageBackendLogicalBuildVolFrom,
.createVol = virStorageBackendLogicalCreateVol,
+ .refreshVol = virStorageBackendLogicalRefreshVol,
.deleteVol = virStorageBackendLogicalDeleteVol,
.uploadVol = virStorageBackendVolUploadLocal,
.downloadVol = virStorageBackendVolDownloadLocal,
--
1.9.3