mirror of
https://github.com/libvirt/libvirt.git
synced 2026-09-03 20:53:04 -05:00
scsi_host: Introduce virFindSCSIHostByPCI
Introduce a new function to parse the provided scsi_host parent address and unique_id value in order to find the /sys/class/scsi_host directory which will allow a stable SCSI host address Add a test to scsihosttest to lookup the host# name by using the PCI address and unique_id value
This commit is contained in:
@@ -226,7 +226,10 @@
|
|||||||
For a PCI address of "0000:00:1f:2", the unique identifer files
|
For a PCI address of "0000:00:1f:2", the unique identifer files
|
||||||
can be found using the command
|
can be found using the command
|
||||||
<code>find -H /sys/class/scsi_host/host*/unique_id |
|
<code>find -H /sys/class/scsi_host/host*/unique_id |
|
||||||
xargs grep '[0-9]'</code>.
|
xargs grep '[0-9]'</code>. Optionally, the
|
||||||
|
<code>virsh nodedev-dumpxml scsi_hostN</code>' of a
|
||||||
|
specific scsi_hostN list entry will list the
|
||||||
|
<code>unique_id</code> value.
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</dd>
|
</dd>
|
||||||
|
|||||||
@@ -2113,6 +2113,7 @@ virDoubleToStr;
|
|||||||
virEnumFromString;
|
virEnumFromString;
|
||||||
virEnumToString;
|
virEnumToString;
|
||||||
virFindFCHostCapableVport;
|
virFindFCHostCapableVport;
|
||||||
|
virFindSCSIHostByPCI;
|
||||||
virFormatIntDecimal;
|
virFormatIntDecimal;
|
||||||
virGetDeviceID;
|
virGetDeviceID;
|
||||||
virGetDeviceUnprivSGIO;
|
virGetDeviceUnprivSGIO;
|
||||||
|
|||||||
@@ -1729,6 +1729,98 @@ virReadSCSIUniqueId(const char *sysfs_prefix,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* virFindSCSIHostByPCI:
|
||||||
|
* @sysfs_prefix: "scsi_host" sysfs path, defaults to SYSFS_SCSI_HOST_PATH
|
||||||
|
* @parentaddr: string of the PCI address "scsi_host" device to be found
|
||||||
|
* @unique_id: unique_id value of the to be found "scsi_host" device
|
||||||
|
* @result: Return the host# of the matching "scsi_host" device
|
||||||
|
*
|
||||||
|
* Iterate over the SYSFS_SCSI_HOST_PATH entries looking for a matching
|
||||||
|
* PCI Address in the expected format (dddd:bb:ss.f, where 'dddd' is the
|
||||||
|
* 'domain' value, 'bb' is the 'bus' value, 'ss' is the 'slot' value, and
|
||||||
|
* 'f' is the 'function' value from the PCI address) with a unique_id file
|
||||||
|
* entry having the value expected. Unlike virReadSCSIUniqueId() we don't
|
||||||
|
* have a host number yet and that's what we're looking for.
|
||||||
|
*
|
||||||
|
* Returns the host name of the "scsi_host" which must be freed by the caller,
|
||||||
|
* or NULL on failure
|
||||||
|
*/
|
||||||
|
char *
|
||||||
|
virFindSCSIHostByPCI(const char *sysfs_prefix,
|
||||||
|
const char *parentaddr,
|
||||||
|
unsigned int unique_id)
|
||||||
|
{
|
||||||
|
const char *prefix = sysfs_prefix ? sysfs_prefix : SYSFS_SCSI_HOST_PATH;
|
||||||
|
struct dirent *entry = NULL;
|
||||||
|
DIR *dir = NULL;
|
||||||
|
char *host_link = NULL;
|
||||||
|
char *host_path = NULL;
|
||||||
|
char *p = NULL;
|
||||||
|
char *ret = NULL;
|
||||||
|
char *buf = NULL;
|
||||||
|
char *unique_path = NULL;
|
||||||
|
unsigned int read_unique_id;
|
||||||
|
|
||||||
|
if (!(dir = opendir(prefix))) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to opendir path '%s'"),
|
||||||
|
prefix);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (virDirRead(dir, &entry, prefix) > 0) {
|
||||||
|
if (entry->d_name[0] == '.' || !virFileIsLink(entry->d_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (virAsprintf(&host_link, "%s/%s", prefix, entry->d_name) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virFileResolveLink(host_link, &host_path) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!strstr(host_path, parentaddr)) {
|
||||||
|
VIR_FREE(host_link);
|
||||||
|
VIR_FREE(host_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
VIR_FREE(host_link);
|
||||||
|
VIR_FREE(host_path);
|
||||||
|
|
||||||
|
if (virAsprintf(&unique_path, "%s/%s/unique_id", prefix,
|
||||||
|
entry->d_name) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virFileExists(unique_path)) {
|
||||||
|
VIR_FREE(unique_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (virFileReadAll(unique_path, 1024, &buf) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if ((p = strchr(buf, '\n')))
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
if (virStrToLong_ui(buf, NULL, 10, &read_unique_id) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (read_unique_id != unique_id) {
|
||||||
|
VIR_FREE(unique_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ignore_value(VIR_STRDUP(ret, entry->d_name));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
closedir(dir);
|
||||||
|
VIR_FREE(unique_path);
|
||||||
|
VIR_FREE(host_link);
|
||||||
|
VIR_FREE(host_path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* virReadFCHost:
|
/* virReadFCHost:
|
||||||
* @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
|
* @sysfs_prefix: "fc_host" sysfs path, defaults to SYSFS_FC_HOST_PATH
|
||||||
* @host: Host number, E.g. 5 of "fc_host/host5"
|
* @host: Host number, E.g. 5 of "fc_host/host5"
|
||||||
@@ -2090,6 +2182,15 @@ virReadSCSIUniqueId(const char *sysfs_prefix ATTRIBUTE_UNUSED,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
virFindSCSIHostByPCI(const char *sysfs_prefix ATTRIBUTE_UNUSED,
|
||||||
|
const char *parentaddr ATTRIBUTE_UNUSED,
|
||||||
|
unsigned int unique_id ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
virReportSystemError(ENOSYS, "%s", _("Not supported on this platform"));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED,
|
virReadFCHost(const char *sysfs_prefix ATTRIBUTE_UNUSED,
|
||||||
int host ATTRIBUTE_UNUSED,
|
int host ATTRIBUTE_UNUSED,
|
||||||
|
|||||||
@@ -168,6 +168,10 @@ int virReadSCSIUniqueId(const char *sysfs_prefix,
|
|||||||
int host,
|
int host,
|
||||||
int *result)
|
int *result)
|
||||||
ATTRIBUTE_NONNULL(3);
|
ATTRIBUTE_NONNULL(3);
|
||||||
|
char *
|
||||||
|
virFindSCSIHostByPCI(const char *sysfs_prefix,
|
||||||
|
const char *parentaddr,
|
||||||
|
unsigned int unique_id);
|
||||||
int virReadFCHost(const char *sysfs_prefix,
|
int virReadFCHost(const char *sysfs_prefix,
|
||||||
int host,
|
int host,
|
||||||
const char *entry,
|
const char *entry,
|
||||||
|
|||||||
@@ -196,6 +196,54 @@ testVirReadSCSIUniqueId(const void *data ATTRIBUTE_UNUSED)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test virFindSCSIHostByPCI */
|
||||||
|
static int
|
||||||
|
testVirFindSCSIHostByPCI(const void *data ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
unsigned int unique_id1 = 1;
|
||||||
|
unsigned int unique_id2 = 2;
|
||||||
|
const char *pci_addr1 = "0000:00:1f.1";
|
||||||
|
const char *pci_addr2 = "0000:00:1f.2";
|
||||||
|
char *path_addr = NULL;
|
||||||
|
char *ret_host = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (virAsprintf(&path_addr, "%s/%s", abs_srcdir,
|
||||||
|
"sysfs/class/scsi_host") < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH,
|
||||||
|
pci_addr1, unique_id1)) ||
|
||||||
|
STRNEQ(ret_host, "host0"))
|
||||||
|
goto cleanup;
|
||||||
|
VIR_FREE(ret_host);
|
||||||
|
|
||||||
|
if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH,
|
||||||
|
pci_addr1, unique_id2)) ||
|
||||||
|
STRNEQ(ret_host, "host1"))
|
||||||
|
goto cleanup;
|
||||||
|
VIR_FREE(ret_host);
|
||||||
|
|
||||||
|
if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH,
|
||||||
|
pci_addr2, unique_id1)) ||
|
||||||
|
STRNEQ(ret_host, "host2"))
|
||||||
|
goto cleanup;
|
||||||
|
VIR_FREE(ret_host);
|
||||||
|
|
||||||
|
if (!(ret_host = virFindSCSIHostByPCI(TEST_SCSIHOST_CLASS_PATH,
|
||||||
|
pci_addr2, unique_id2)) ||
|
||||||
|
STRNEQ(ret_host, "host3"))
|
||||||
|
goto cleanup;
|
||||||
|
VIR_FREE(ret_host);
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
VIR_FREE(ret_host);
|
||||||
|
VIR_FREE(path_addr);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
# define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX"
|
# define FAKESYSFSDIRTEMPLATE abs_builddir "/fakesysfsdir-XXXXXX"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -234,6 +282,12 @@ mymain(void)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (virtTestRun("testVirFindSCSIHostByPCI",
|
||||||
|
testVirFindSCSIHostByPCI, NULL) < 0) {
|
||||||
|
ret = -1;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
|||||||
Reference in New Issue
Block a user