On 06/07/2013 01:03 PM, Osier Yang wrote:
This takes use of the two utils introduced in previous patches.
Node device HAL backend represents PCI device like PCI_8086_2922,
(I.E PCI_$vendor_$product), to get the PCI address, we have to
traverse /sys/devices/ to find it out.
And to get the current scsi host number assigned by the system
for the scsi host device. We need to traverse /sys/bus/pci/devices/
with the found PCI address by getScsiHostParentAddress, and the
specified unique_id.
Later patch will allow to omit the "unique_id", by using the
scsi host which has the smallest unique_id.
---
src/storage/storage_backend_scsi.c | 81 +++++++++++++++++++++++++++++++++++++-
1 file changed, 79 insertions(+), 2 deletions(-)
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index 13c498d..a77b9ae 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -591,6 +591,66 @@ out:
return retval;
}
+/*
+ * Node device udev backend and HAL backend represent PCI
+ * device in different style. Udev backend represents it like
+ * pci_0000_00_1f_2, and HAL backend represents it like
+ * pci_8086_2922.
+ *
+ * Covert the value of "parent" into PCI device address string
+ * (e.g. 0000:00:1f:2). Return the PCI address as string on
+ * success, or -1 on failure.
+ */
+static char *
+getScsiHostParentAddress(const char *parent)
+{
+ char **tokens = NULL;
+ char *vendor = NULL;
+ char *product = NULL;
+ char *ret = NULL;
+ int len;
+
+ if (!strchr(parent, '_')) {
+ virReportError(VIR_ERR_XML_ERROR, "%s",
+ _("'parent' of scsi_host adapter must "
+ "be consistent with name of node device"));
+ return NULL;
+ }
+
+ if (!(tokens = virStringSplit(parent, "_", 0)))
+ return NULL;
Given the following code, the call to Split could use 4 (or 5) for the
max... Not that it matters.
+
+ len = virStringListLength(tokens);
+
+ switch (len) {
+ case 4:
+ if (!(ret = virStringJoin((const char **)(&tokens[1]), ":")))
+ goto cleanup;
+ break;
+
+ 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 consistent with name of node device"));
+ goto cleanup;
+ }
+
+cleanup:
+ virStringFreeList(tokens);
+ return ret;
+}
+
static int
getHostNumber(const char *adapter_name,
unsigned int *result)
@@ -627,10 +687,27 @@ static char *
getAdapterName(virStoragePoolSourceAdapter adapter)
{
char *name = NULL;
+ char *addr = NULL;
if (adapter.type != VIR_STORAGE_POOL_SOURCE_ADAPTER_TYPE_FC_HOST) {
- if (VIR_STRDUP(name, adapter.data.scsi_host.name) < 0)
- return NULL;
+ if (adapter.data.scsi_host.parent) {
+ if (!adapter.data.scsi_host.has_unique_id) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("'unique_id' is not specified for "
+ "scsi_host adapter"));
so the optional unique_id isn't so optional after all for a couple of
code paths. Issuing a message here could be confusing. Has this been
tested within an environment where unique_id isn't specified?
+ return NULL;
+ } else {
+ if (!(addr = getScsiHostParentAddress(adapter.data.scsi_host.parent)))
+ return NULL;
+
+ name = virParseStableScsiHostAddress(NULL, addr,
+ adapter.data.scsi_host.unique_id);
You need a VIR_FREE(addr); here
John
+ }
+ } else if (adapter.data.scsi_host.name) {
+ if (VIR_STRDUP(name, adapter.data.scsi_host.name) < 0)
+ return NULL;
+ }
+
return name;
}