[libvirt] [PATCH 08/15] qemu: block: Add helpers for hot-adding virStorageSource via blockdev

Peter Krempa pkrempa at redhat.com
Fri May 18 11:28:58 UTC 2018


These helpers add infrastructure which simplifies adding and rolling
back virStorageSources to a running qemu instance. Using of the helper
structure and separate functions allows for a much cleaner code in the
section dealing with the monitor.

Signed-off-by: Peter Krempa <pkrempa at redhat.com>
---
 src/qemu/qemu_block.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_block.h |  34 +++++++++++
 2 files changed, 189 insertions(+)

diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c
index a514e8a055..09437cdb40 100644
--- a/src/qemu/qemu_block.c
+++ b/src/qemu/qemu_block.c
@@ -1467,3 +1467,158 @@ qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src)
     virJSONValueFree(props);
     return ret;
 }
+
+
+void
+qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data)
+{
+    if (!data)
+        return;
+
+    virJSONValueFree(data->storageProps);
+    virJSONValueFree(data->formatProps);
+    VIR_FREE(data);
+}
+
+
+/**
+ * qemuBlockStorageSourceAttachPrepareBlockdev:
+ * @src: storage source to prepare data from
+ *
+ * Creates a qemuBlockStorageSourceAttachData structure containing data to attach
+ * @src to a VM using the blockdev-add approach. Note that this function only
+ * creates the data for the storage source itself, any other related
+ * authentication/encryption/... objects need to be prepared separately.
+ *
+ * The changes are then applied using qemuBlockStorageSourceAttachApply.
+ *
+ * Returns the filled data structure on success or NULL on error and a libvirt
+ * error is reported
+ */
+qemuBlockStorageSourceAttachDataPtr
+qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src)
+{
+    qemuBlockStorageSourceAttachDataPtr data;
+    qemuBlockStorageSourceAttachDataPtr ret = NULL;
+
+    if (VIR_ALLOC(data) < 0)
+        return NULL;
+
+    if (!(data->formatProps = qemuBlockStorageSourceGetBlockdevProps(src)) ||
+        !(data->storageProps = qemuBlockStorageSourceGetBackendProps(src, false)))
+        goto cleanup;
+
+    data->storageNodeName = src->nodestorage;
+    data->formatNodeName = src->nodeformat;
+
+    VIR_STEAL_PTR(ret, data);
+
+ cleanup:
+    qemuBlockStorageSourceAttachDataFree(data);
+    return ret;
+}
+
+
+/**
+ * qemuBlockStorageSourceAttachApply:
+ * @mon: monitor object
+ * @data: structure holding data of block device to apply
+ *
+ * Attaches a virStorageSource definition converted to
+ * qemuBlockStorageSourceAttachData to a running VM. This function expects being
+ * called after the monitor was entered.
+ *
+ * Returns 0 on success and -1 on error with a libvirt error reported. If an
+ * error occured, changes which were already applied need to be rolled back by
+ * calling qemuBlockStorageSourceAttachRollback.
+ */
+int
+qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon,
+                                  qemuBlockStorageSourceAttachDataPtr data)
+{
+    int rv;
+
+    if (data->storageProps) {
+        rv = qemuMonitorBlockdevAdd(mon, data->storageProps);
+        data->storageProps = NULL;
+
+        if (rv < 0)
+            return -1;
+
+        data->storageAttached = true;
+    }
+
+    if (data->formatProps) {
+        rv = qemuMonitorBlockdevAdd(mon, data->formatProps);
+        data->formatProps = NULL;
+
+        if (rv < 0)
+            return -1;
+
+        data->formatAttached = true;
+    }
+
+    return 0;
+}
+
+
+/**
+ * qemuBlockStorageSourceAttachRollback:
+ * @mon: monitor object
+ * @data: structure holding data of block device to roll back
+ *
+ * Attempts a best effort rollback of changes which were made to a running VM by
+ * qemuBlockStorageSourceAttachApply. Preserves any existing errors.
+ *
+ * This function expects being called after the monitor was entered.
+ */
+void
+qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon,
+                                     qemuBlockStorageSourceAttachDataPtr data)
+{
+    virErrorPtr orig_err;
+
+    virErrorPreserveLast(&orig_err);
+
+    if (data->formatAttached)
+        ignore_value(qemuMonitorBlockdevDel(mon, data->formatNodeName));
+
+    if (data->storageAttached)
+        ignore_value(qemuMonitorBlockdevDel(mon, data->storageNodeName));
+
+    virErrorRestore(&orig_err);
+}
+
+
+/**
+ * qemuBlockStorageSourceDetachOneBlockdev:
+ * @driver: qemu driver object
+ * @vm: domain object
+ * @asyncJob: currently running async job
+ * @src: storage source to detach
+ *
+ * Detaches one virStorageSource using blockdev-del. Note that this does not
+ * detach any authentication/encryption objects. This function enters the
+ * monitor internally.
+ */
+int
+qemuBlockStorageSourceDetachOneBlockdev(virQEMUDriverPtr driver,
+                                        virDomainObjPtr vm,
+                                        qemuDomainAsyncJob asyncJob,
+                                        virStorageSourcePtr src)
+{
+    int ret;
+
+    if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+        return -1;
+
+    ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm), src->nodeformat);
+
+    if (ret == 0)
+        ret = qemuMonitorBlockdevDel(qemuDomainGetMonitor(vm), src->nodestorage);
+
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        return -1;
+
+    return ret;
+}
diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h
index f819c6f907..bbaf9ec0f1 100644
--- a/src/qemu/qemu_block.h
+++ b/src/qemu/qemu_block.h
@@ -67,4 +67,38 @@ qemuBlockStorageSourceGetURI(virStorageSourcePtr src);
 virJSONValuePtr
 qemuBlockStorageSourceGetBlockdevProps(virStorageSourcePtr src);

+
+typedef struct qemuBlockStorageSourceAttachData qemuBlockStorageSourceAttachData;
+typedef qemuBlockStorageSourceAttachData *qemuBlockStorageSourceAttachDataPtr;
+struct qemuBlockStorageSourceAttachData {
+    virJSONValuePtr storageProps;
+    const char *storageNodeName;
+    bool storageAttached;
+
+    virJSONValuePtr formatProps;
+    const char *formatNodeName;
+    bool formatAttached;
+};
+
+
+void
+qemuBlockStorageSourceAttachDataFree(qemuBlockStorageSourceAttachDataPtr data);
+
+qemuBlockStorageSourceAttachDataPtr
+qemuBlockStorageSourceAttachPrepareBlockdev(virStorageSourcePtr src);
+
+int
+qemuBlockStorageSourceAttachApply(qemuMonitorPtr mon,
+                                  qemuBlockStorageSourceAttachDataPtr data);
+
+void
+qemuBlockStorageSourceAttachRollback(qemuMonitorPtr mon,
+                                     qemuBlockStorageSourceAttachDataPtr data);
+
+int
+qemuBlockStorageSourceDetachOneBlockdev(virQEMUDriverPtr driver,
+                                        virDomainObjPtr vm,
+                                        qemuDomainAsyncJob asyncJob,
+                                        virStorageSourcePtr src);
+
 #endif /* __QEMU_BLOCK_H__ */
-- 
2.16.2




More information about the libvir-list mailing list