On 08/06/13 01:03, Osier Yang wrote:
To be more flexible, except allowing to specify 'parent' with name
produced by node device udev/HAL backends, this supports to specify
'parent' with PCI address directly (e.g. 0000:00:1f:2). The specified
address will be padded if it's not consistent with what sysfs exposed.
(e.g 0:0:2:2 will be padded to 0000:00:02:2).
---
src/storage/storage_backend_scsi.c | 117 +++++++++++++++++++++++++++++--------
1 file changed, 93 insertions(+), 24 deletions(-)
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index a77b9ae..5635f73 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -604,51 +604,120 @@ out:
static char *
getScsiHostParentAddress(const char *parent)
{
+ virBuffer buf = VIR_BUFFER_INITIALIZER;
char **tokens = NULL;
char *vendor = NULL;
char *product = NULL;
char *ret = NULL;
- int len;
+ int length;
+ int i;
- if (!strchr(parent, '_')) {
+ if (!strchr(parent, '_') &&
+ !strchr(parent, ':')) {
virReportError(VIR_ERR_XML_ERROR, "%s",
- _("'parent' of scsi_host adapter must "
- "be consistent with name of node device"));
+ _("'parent' of scsi_host adapter must be "
+ "either consistent with name of mode "
+ "device, or in domain:bus:slot:function "
+ "format"));
return NULL;
}
- if (!(tokens = virStringSplit(parent, "_", 0)))
- return NULL;
+ if (strchr(parent, '_')) {
+ if (!(tokens = virStringSplit(parent, "_", 0)))
+ return NULL;
- len = virStringListLength(tokens);
+ length = virStringListLength(tokens);
+
+ switch (length) {
+ case 4:
+ if (!(ret = virStringJoin((const char **)(&tokens[1]), ":")))
+ goto cleanup;
+ break;
- switch (len) {
- case 4:
- if (!(ret = virStringJoin((const char **)(&tokens[1]), ":")))
+ case 2:
+ vendor = tokens[1];
+ product = tokens[2];
+ if (!(ret = virFindPCIDeviceByVPD(NULL, vendor, product))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Unable to find PCI device with vendor '%s' "
+ "product '%s'"), vendor, product);
+ goto cleanup;
+ }
+
+ break;
+ default:
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("'parent' of scsi_host adapter must be "
+ "either consistent with name of mode "
+ "device, or in domain:bus:slot:function "
+ "format"));
goto cleanup;
- break;
+ }
+ } else if (strchr(parent, ':')) {
+ char *padstr = NULL;
+
+ if (!(tokens = virStringSplit(parent, ":", 0)))
+ return NULL;
- case 2:
- vendor = tokens[1];
- product = tokens[2];
- if (!(ret = virFindPCIDeviceByVPD(NULL, vendor, product))) {
- virReportError(VIR_ERR_INTERNAL_ERROR,
- _("Unable to find PCI device with vendor '%s' "
- "product '%s'"), vendor, product);
+ length = virStringListLength(tokens);
+
+ if (length != 4) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid PCI address for scsi_host "
+ "'parent' '%s'"), parent);
goto cleanup;
}
- break;
- default:
- virReportError(VIR_ERR_XML_ERROR, "%s",
- _("'parent' of scsi_host adapter must "
- "be consistent with name of node device"));
- goto cleanup;
+ for (i = 0; i < length; i++) {
+ if (strlen(tokens[i]) == 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("invalid PCI address for scsi_host "
+ "'parent' '%s'"), parent);
+ goto cleanup;
+ }
+ }
+
+ /* sysfs always exposes the PCI address like "0000:00:1f:2",
+ * this do the padding if the address prodived by user is
+ * not padded (e.g. 0:0:2:0).
+ */
+ if (strlen(tokens[0]) != 4) {
+ if (!(padstr = virStringPad(tokens[0], '0', 4, false)))
+ goto cleanup;
+
+ virBufferAsprintf(&buf, "%s", padstr);
+ VIR_FREE(padstr);
+ } else {
+ virBufferAsprintf(&buf, "%s", tokens[0]);
+ }
+
+ for (i = 1; i < 3; i++) {
+ if (strlen(tokens[i]) != 2) {
+ if (!(padstr = virStringPad(tokens[i], '0', 2, false)))
+ goto error;
+ virBufferAsprintf(&buf, "%s", padstr);
With the attached diff squashed in:
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index da6a5dd..05af408 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -695,13 +695,15 @@ getScsiHostParentAddress(const char *parent)
if (strlen(tokens[i]) != 2) {
if (!(padstr = virStringPad(tokens[i], '0', 2, false)))
goto error;
- virBufferAsprintf(&buf, "%s", padstr);
+ virBufferAsprintf(&buf, ":%s", padstr);
VIR_FREE(padstr);
} else {
- virBufferAsprintf(&buf, "%s", tokens[i]);
+ virBufferAsprintf(&buf, ":%s", tokens[i]);
}
}
+ virBufferAsprintf(&buf, ":%s", tokens[3]);
+
if (virBufferError(&buf)) {
virBufferFreeAndReset(&buf);
virReportOOMError();
--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list