[libvirt PATCH 5/7] nodedev: add PostParse callback for nodedev parsing

Jonathon Jongsma jjongsma at redhat.com
Fri Jul 23 16:40:40 UTC 2021


This can be used similarly to other postparse callbacks in libvirt --
filling in additional information that can be determined by using the
information provided in the XML. In this case, we determine the address
of the parent device and cache it in the mdev caps so that we can use it
for generating a unique name and interacting with mdevctl.

Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
---
 src/conf/node_device_conf.c          |  7 +++++
 src/node_device/node_device_driver.c | 45 +++++++++++++++++++++-------
 src/node_device/node_device_driver.h |  3 ++
 src/node_device/node_device_udev.c   |  1 +
 tests/nodedevmdevctltest.c           |  1 +
 5 files changed, 46 insertions(+), 11 deletions(-)

diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c
index cd1c07092d..a7cd90b9e6 100644
--- a/src/conf/node_device_conf.c
+++ b/src/conf/node_device_conf.c
@@ -2189,6 +2189,13 @@ virNodeDeviceDefParse(const char *str,
 
     if (parserCallbacks) {
         int ret = 0;
+        /* fill in backend-specific aspects */
+        if (parserCallbacks->postParse) {
+            ret = parserCallbacks->postParse(def, opaque);
+            if (ret < 0)
+                return NULL;
+        }
+
         /* validate definition */
         if (parserCallbacks->validate) {
             ret = parserCallbacks->validate(def, opaque);
diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c
index 8f39d79c68..d76268285f 100644
--- a/src/node_device/node_device_driver.c
+++ b/src/node_device/node_device_driver.c
@@ -718,11 +718,9 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
                             char **outbuf,
                             char **errbuf)
 {
-    g_autofree char *parent_addr = NULL;
     g_autoptr(virCommand) cmd = NULL;
     const char *subcommand = virMdevctlCommandTypeToString(cmd_type);
     g_autofree char *inbuf = NULL;
-    virNodeDeviceObj *parent_obj = NULL;
 
     switch (cmd_type) {
     case MDEVCTL_CMD_CREATE:
@@ -747,12 +745,7 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
     switch (cmd_type) {
     case MDEVCTL_CMD_CREATE:
     case MDEVCTL_CMD_DEFINE:
-        if ((parent_obj = nodeDeviceObjFindByName(def->parent))) {
-            parent_addr = nodeDeviceObjFormatAddress(parent_obj);
-            virNodeDeviceObjEndAPI(&parent_obj);
-        }
-
-        if (!parent_addr) {
+        if (!def->caps->data.mdev.parent_addr) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            _("unable to find parent device '%s'"), def->parent);
             return NULL;
@@ -764,7 +757,7 @@ nodeDeviceGetMdevctlCommand(virNodeDeviceDef *def,
             return NULL;
         }
 
-        virCommandAddArgPair(cmd, "--parent", parent_addr);
+        virCommandAddArgPair(cmd, "--parent", def->caps->data.mdev.parent_addr);
         virCommandAddArgPair(cmd, "--jsonfile", "/dev/stdin");
 
         virCommandSetInputBuffer(cmd, inbuf);
@@ -1765,9 +1758,30 @@ nodeDeviceDefCopyFromMdevctl(virNodeDeviceDef *dst,
 }
 
 
+int nodeDeviceDefPostParse(virNodeDeviceDef *def,
+                           G_GNUC_UNUSED void *opaque)
+{
+    virNodeDevCapsDef *caps = NULL;
+    for (caps = def->caps; caps != NULL; caps = caps->next) {
+        if (caps->data.type == VIR_NODE_DEV_CAP_MDEV) {
+            virNodeDeviceObj *obj = NULL;
+
+            if (def->parent)
+                obj = virNodeDeviceObjListFindByName(driver->devs, def->parent);
+
+            if (obj) {
+                caps->data.mdev.parent_addr = nodeDeviceObjFormatAddress(obj);
+                virNodeDeviceObjEndAPI(&obj);
+            }
+        }
+    }
+    return 0;
+}
+
+
 /* validate that parent exists */
 static int nodeDeviceDefValidateMdev(virNodeDeviceDef *def,
-                                     G_GNUC_UNUSED virNodeDevCapMdev *mdev,
+                                     virNodeDevCapMdev *mdev,
                                      G_GNUC_UNUSED void *opaque)
 {
     virNodeDeviceObj *obj = NULL;
@@ -1783,8 +1797,17 @@ static int nodeDeviceDefValidateMdev(virNodeDeviceDef *def,
                        def->parent);
         return -1;
     }
-
     virNodeDeviceObjEndAPI(&obj);
+
+    /* the post-parse callback should have found the address of the parent
+     * device and stored it in the mdev caps */
+    if (!mdev->parent_addr) {
+        virReportError(VIR_ERR_PARSE_FAILED,
+                       _("Unable to find address for parent device '%s'"),
+                       def->parent);
+        return -1;
+    }
+
     return 0;
 }
 
diff --git a/src/node_device/node_device_driver.h b/src/node_device/node_device_driver.h
index d9b9b7a961..fdc92b8aef 100644
--- a/src/node_device/node_device_driver.h
+++ b/src/node_device/node_device_driver.h
@@ -172,5 +172,8 @@ int
 nodeDeviceCreate(virNodeDevice *dev,
                  unsigned int flags);
 
+int nodeDeviceDefPostParse(virNodeDeviceDef *def,
+                           void *opaque);
+
 int nodeDeviceDefValidate(virNodeDeviceDef *def,
                           void *opaque);
diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index ccf94d8e7d..81037d8139 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -2243,6 +2243,7 @@ nodeStateInitialize(bool privileged,
     driver->privateData = priv;
     driver->nodeDeviceEventState = virObjectEventStateNew();
 
+    driver->parserCallbacks.postParse = nodeDeviceDefPostParse;
     driver->parserCallbacks.validate = nodeDeviceDefValidate;
 
     if (udevPCITranslateInit(privileged) < 0)
diff --git a/tests/nodedevmdevctltest.c b/tests/nodedevmdevctltest.c
index bf1d7b4984..d88e08f485 100644
--- a/tests/nodedevmdevctltest.c
+++ b/tests/nodedevmdevctltest.c
@@ -13,6 +13,7 @@
 #define VIRT_TYPE "QEMU"
 
 static virNodeDeviceDefParserCallbacks parser_callbacks = {
+    .postParse = nodeDeviceDefPostParse,
     .validate = nodeDeviceDefValidate
 };
 
-- 
2.31.1




More information about the libvir-list mailing list