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