[libvirt] [PATCH 1/2] qemu: Add callback struct for qemuBuildCommandLine

Osier Yang jyang at redhat.com
Wed May 15 15:25:19 UTC 2013


Since 0d70656afded, it starts to access the sysfs files to build
the qemu command line (by virSCSIDeviceGetSgName, which is to find
out the scsi generic device name by adpater:bus:target:unit), there
is no way to work around, qemu wants to see the scsi generic device
like "/dev/sg6" anyway.

And there might be other places which need to access sysfs files
when building qemu command line in future.

Instead of increasing the arguments of qemuBuildCommandLine, this
introduces a new callback for qemuBuildCommandLine, and thus tests
can register their own callbacks for sysfs test input files accessing.

"tests/sysfsroot" is created to hold the sysfs related test input
files.

* src/qemu/qemu_command.h: (New callback struct
                            qemuBuildCommandLineCallbacks;
                            extern buildCommandLineCallbacks)
* src/qemu/qemu_command.c: (Helper qemuSCSIDeviceGetSgName;
                            wire up the callback struct)
* src/qemu/qemu_driver.c: (Use the new syntax of qemuBuildCommandLine)
* src/qemu/qemu_hotplug.c: Likewise
* src/qemu/qemu_process.c: Likewise
* src/util/virscsi.c: (Allow to specify the sysfs root for
                       virSCSIDeviceGetSgName)
* src/util/virscsi.h: (Change the definition of virSCSIDeviceGetSgName)
* tests/qemuxml2argvtest.c: (Helper testSCSIDeviceGetSgName;
                             callback struct testCallbacks;
                             Use the callback struct)
* src/tests/qemuxmlnstest.c :( Use the new syntax of qemuBuildCommandLine)
* tests/sysfsroot/* : (New test input files)
* tests/Makefile.am: (Add "sysfsroot" in EXTRA_DIST)
---
 src/qemu/qemu_command.c                            | 31 ++++++++++++++-----
 src/qemu/qemu_command.h                            | 16 ++++++++--
 src/qemu/qemu_driver.c                             |  3 +-
 src/qemu/qemu_hotplug.c                            |  6 ++--
 src/qemu/qemu_process.c                            |  3 +-
 src/util/virscsi.c                                 | 35 ++++++++++++++++++----
 src/util/virscsi.h                                 |  3 +-
 tests/Makefile.am                                  |  1 +
 tests/qemuxml2argvtest.c                           | 18 ++++++++++-
 tests/qemuxmlnstest.c                              |  3 +-
 .../bus/scsi/devices/0:0:0:0/scsi_generic/sg0/dev  |  1 +
 11 files changed, 97 insertions(+), 23 deletions(-)
 create mode 100644 tests/sysfsroot/bus/scsi/devices/0:0:0:0/scsi_generic/sg0/dev

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 5b95c07..b71a3b9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4757,17 +4757,18 @@ qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev)
 
 char *
 qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
-                           virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED)
+                           virQEMUCapsPtr qemuCaps ATTRIBUTE_UNUSED,
+                           qemuBuildCommandLineCallbacksPtr callbacks)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
     char *sg = NULL;
 
-    if (!(sg = virSCSIDeviceGetSgName(dev->source.subsys.u.scsi.adapter,
-                                      dev->source.subsys.u.scsi.bus,
-                                      dev->source.subsys.u.scsi.target,
-                                      dev->source.subsys.u.scsi.unit))) {
+    sg = (callbacks->qemuGetSCSIDeviceSgName)(dev->source.subsys.u.scsi.adapter,
+                                              dev->source.subsys.u.scsi.bus,
+                                              dev->source.subsys.u.scsi.target,
+                                              dev->source.subsys.u.scsi.unit);
+    if (!sg)
         goto error;
-    }
 
     virBufferAsprintf(&buf, "file=/dev/%s,if=none", sg);
     virBufferAsprintf(&buf, ",id=%s-%s",
@@ -6405,6 +6406,19 @@ qemuBuildGraphicsCommandLine(virQEMUDriverConfigPtr cfg,
     return 0;
 }
 
+static char *
+qemuSCSIDeviceGetSgName(const char *adapter,
+                        unsigned int bus,
+                        unsigned int target,
+                        unsigned int unit)
+{
+    return virSCSIDeviceGetSgName(adapter, bus, target, unit, NULL);
+}
+
+qemuBuildCommandLineCallbacks buildCommandLineCallbacks = {
+    .qemuGetSCSIDeviceSgName = qemuSCSIDeviceGetSgName,
+};
+
 /*
  * Constructs a argv suitable for launching qemu with config defined
  * for a given virtual machine.
@@ -6422,7 +6436,8 @@ qemuBuildCommandLine(virConnectPtr conn,
                      const char *migrateFrom,
                      int migrateFd,
                      virDomainSnapshotObjPtr snapshot,
-                     enum virNetDevVPortProfileOp vmop)
+                     enum virNetDevVPortProfileOp vmop,
+                     qemuBuildCommandLineCallbacksPtr callbacks)
 {
     virErrorPtr originalError = NULL;
     int i, j;
@@ -8243,7 +8258,7 @@ qemuBuildCommandLine(virConnectPtr conn,
                 char *drvstr;
 
                 virCommandAddArg(cmd, "-drive");
-                if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps)))
+                if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, qemuCaps, callbacks)))
                     goto error;
                 virCommandAddArg(cmd, drvstr);
                 VIR_FREE(drvstr);
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 36dfa6b..23b6af3 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -51,6 +51,16 @@
 # define QEMU_WEBSOCKET_PORT_MIN  5700
 # define QEMU_WEBSOCKET_PORT_MAX  65535
 
+typedef struct _qemuBuildCommandLineCallbacks qemuBuildCommandLineCallbacks;
+typedef qemuBuildCommandLineCallbacks *qemuBuildCommandLineCallbacksPtr;
+struct _qemuBuildCommandLineCallbacks {
+    char * (*qemuGetSCSIDeviceSgName) (const char *adapter,
+                                       unsigned int bus,
+                                       unsigned int target,
+                                       unsigned int unit);
+};
+
+extern qemuBuildCommandLineCallbacks buildCommandLineCallbacks;
 
 virCommandPtr qemuBuildCommandLine(virConnectPtr conn,
                                    virQEMUDriverPtr driver,
@@ -61,7 +71,8 @@ virCommandPtr qemuBuildCommandLine(virConnectPtr conn,
                                    const char *migrateFrom,
                                    int migrateFd,
                                    virDomainSnapshotObjPtr current_snapshot,
-                                   enum virNetDevVPortProfileOp vmop)
+                                   enum virNetDevVPortProfileOp vmop,
+                                   qemuBuildCommandLineCallbacksPtr callbacks)
     ATTRIBUTE_NONNULL(1);
 
 /* Generate string for arch-specific '-device' parameter */
@@ -142,7 +153,8 @@ char * qemuBuildUSBHostdevDevStr(virDomainHostdevDefPtr dev,
                                  virQEMUCapsPtr qemuCaps);
 
 char * qemuBuildSCSIHostdevDrvStr(virDomainHostdevDefPtr dev,
-                                  virQEMUCapsPtr qemuCaps);
+                                  virQEMUCapsPtr qemuCaps,
+                                  qemuBuildCommandLineCallbacksPtr callbacks);
 char * qemuBuildSCSIHostdevDevStr(virDomainDefPtr def,
                                   virDomainHostdevDefPtr dev,
                                   virQEMUCapsPtr qemuCaps);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b1630f8..cb46276 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5362,7 +5362,8 @@ static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
 
     if (!(cmd = qemuBuildCommandLine(conn, driver, def,
                                      &monConfig, monitor_json, qemuCaps,
-                                     NULL, -1, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP)))
+                                     NULL, -1, NULL, VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
+                                     &buildCommandLineCallbacks)))
         goto cleanup;
 
     ret = virCommandToString(cmd);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index d037c9d..77d9f4f 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1226,7 +1226,8 @@ qemuDomainAttachHostScsiDevice(virQEMUDriverPtr driver,
     if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, 0) < 0)
         goto cleanup;
 
-    if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, priv->qemuCaps)))
+    if (!(drvstr = qemuBuildSCSIHostdevDrvStr(hostdev, priv->qemuCaps,
+                                              &buildCommandLineCallbacks)))
         goto cleanup;
 
     if (!(devstr = qemuBuildSCSIHostdevDevStr(vm->def, hostdev, priv->qemuCaps)))
@@ -2543,7 +2544,8 @@ qemuDomainDetachHostScsiDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    if (!(drvstr = qemuBuildSCSIHostdevDrvStr(detach, priv->qemuCaps)))
+    if (!(drvstr = qemuBuildSCSIHostdevDrvStr(detach, priv->qemuCaps,
+                                              &buildCommandLineCallbacks)))
         goto cleanup;
     if (!(devstr = qemuBuildSCSIHostdevDevStr(vm->def, detach, priv->qemuCaps)))
         goto cleanup;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index dbbb7bf..3b247a5 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -3638,7 +3638,8 @@ int qemuProcessStart(virConnectPtr conn,
     VIR_DEBUG("Building emulator command line");
     if (!(cmd = qemuBuildCommandLine(conn, driver, vm->def, priv->monConfig,
                                      priv->monJSON, priv->qemuCaps,
-                                     migrateFrom, stdin_fd, snapshot, vmop)))
+                                     migrateFrom, stdin_fd, snapshot, vmop,
+                                     &buildCommandLineCallbacks)))
         goto cleanup;
 
     /* now that we know it is about to start call the hook if present */
diff --git a/src/util/virscsi.c b/src/util/virscsi.c
index d6685fa..56a2cbf 100644
--- a/src/util/virscsi.c
+++ b/src/util/virscsi.c
@@ -100,26 +100,48 @@ virSCSIDeviceGetAdapterId(const char *adapter,
     return 0;
 }
 
+static char *
+virSCSIDeviceSysfsPrefix(const char *sysfs_root)
+{
+    char *ret = NULL;
+
+    if (sysfs_root) {
+        if (virAsprintf(&ret, "%s/bus/scsi/devices", sysfs_root) < 0) {
+            virReportOOMError();
+            return NULL;
+        }
+    } else {
+        if (VIR_STRDUP(ret, SYSFS_SCSI_DEVICES) < 0)
+            return NULL;
+    }
+
+    return ret;
+}
+
 char *
 virSCSIDeviceGetSgName(const char *adapter,
                        unsigned int bus,
                        unsigned int target,
-                       unsigned int unit)
+                       unsigned int unit,
+                       const char *sysfs_root)
 {
     DIR *dir = NULL;
     struct dirent *entry;
     char *path = NULL;
     char *sg = NULL;
     unsigned int adapter_id;
+    char *sysfs_prefix = NULL;
 
     if (virSCSIDeviceGetAdapterId(adapter, &adapter_id) < 0)
         return NULL;
 
-    if (virAsprintf(&path,
-                    SYSFS_SCSI_DEVICES "/%d:%d:%d:%d/scsi_generic",
-                    adapter_id, bus, target, unit) < 0) {
-        virReportOOMError();
+    if (!(sysfs_prefix = virSCSIDeviceSysfsPrefix(sysfs_root)))
         return NULL;
+
+    if (virAsprintf(&path, "%s/%d:%d:%d:%d/scsi_generic",
+                    sysfs_prefix, adapter_id, bus, target, unit) < 0) {
+        virReportOOMError();
+        goto cleanup;
     }
 
     if (!(dir = opendir(path))) {
@@ -138,6 +160,7 @@ virSCSIDeviceGetSgName(const char *adapter,
 
 cleanup:
     closedir(dir);
+    VIR_FREE(sysfs_prefix);
     VIR_FREE(path);
     return sg;
 }
@@ -166,7 +189,7 @@ virSCSIDeviceNew(const char *adapter,
     dev->unit = unit;
     dev->readonly = readonly;
 
-    if (!(sg = virSCSIDeviceGetSgName(adapter, bus, target, unit)))
+    if (!(sg = virSCSIDeviceGetSgName(adapter, bus, target, unit, NULL)))
         goto cleanup;
 
     if (virSCSIDeviceGetAdapterId(adapter, &dev->adapter) < 0)
diff --git a/src/util/virscsi.h b/src/util/virscsi.h
index 8268cdf..749e8d9 100644
--- a/src/util/virscsi.h
+++ b/src/util/virscsi.h
@@ -36,7 +36,8 @@ typedef virSCSIDeviceList *virSCSIDeviceListPtr;
 char *virSCSIDeviceGetSgName(const char *adapter,
                              unsigned int bus,
                              unsigned int target,
-                             unsigned int unit);
+                             unsigned int unit,
+                             const char *sysfs_root);
 
 virSCSIDevicePtr virSCSIDeviceNew(const char *adapter,
                                   unsigned int bus,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 41c4067..a6cc5bf 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -80,6 +80,7 @@ EXTRA_DIST =		\
 	storagevolschematest \
 	storagevolxml2xmlin \
 	storagevolxml2xmlout \
+	sysfsroot \
 	sysinfodata \
 	test-lib.sh	\
 	vmx2xmldata \
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index ac31d2a..3d22491 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -82,6 +82,21 @@ typedef enum {
     FLAG_JSON               = 1 << 3,
 } virQemuXML2ArgvTestFlags;
 
+# define TEST_SYSFS_ROOT "./sysfsroot"
+
+static char *
+testSCSIDeviceGetSgName(const char *adapter,
+                        unsigned int bus,
+                        unsigned int target,
+                        unsigned int unit)
+{
+    return virSCSIDeviceGetSgName(adapter, bus, target, unit, TEST_SYSFS_ROOT);
+}
+
+static qemuBuildCommandLineCallbacks testCallbacks = {
+    .qemuGetSCSIDeviceSgName = testSCSIDeviceGetSgName,
+};
+
 static int testCompareXMLToArgvFiles(const char *xml,
                                      const char *cmdline,
                                      virQEMUCapsPtr extraFlags,
@@ -157,7 +172,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
     if (!(cmd = qemuBuildCommandLine(conn, &driver, vmdef, &monitor_chr,
                                      (flags & FLAG_JSON), extraFlags,
                                      migrateFrom, migrateFd, NULL,
-                                     VIR_NETDEV_VPORT_PROFILE_OP_NO_OP))) {
+                                     VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
+                                     &testCallbacks))) {
         if (flags & FLAG_EXPECT_FAILURE) {
             ret = 0;
             if (virTestGetDebug() > 1)
diff --git a/tests/qemuxmlnstest.c b/tests/qemuxmlnstest.c
index 952b8e2..9d3d2a0 100644
--- a/tests/qemuxmlnstest.c
+++ b/tests/qemuxmlnstest.c
@@ -113,7 +113,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
     if (!(cmd = qemuBuildCommandLine(conn, &driver,
                                      vmdef, &monitor_chr, json, extraFlags,
                                      migrateFrom, migrateFd, NULL,
-                                     VIR_NETDEV_VPORT_PROFILE_OP_NO_OP)))
+                                     VIR_NETDEV_VPORT_PROFILE_OP_NO_OP,
+                                     NULL)))
         goto fail;
 
     if (!!virGetLastError() != expectError) {
diff --git a/tests/sysfsroot/bus/scsi/devices/0:0:0:0/scsi_generic/sg0/dev b/tests/sysfsroot/bus/scsi/devices/0:0:0:0/scsi_generic/sg0/dev
new file mode 100644
index 0000000..992e920
--- /dev/null
+++ b/tests/sysfsroot/bus/scsi/devices/0:0:0:0/scsi_generic/sg0/dev
@@ -0,0 +1 @@
+21:0
-- 
1.8.1.4




More information about the libvir-list mailing list