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

Reply via email to