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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list