[libvirt] [PATCH 09/11] storage_scsi: Allow the direct PCI address for 'parent'
Osier Yang
jyang at redhat.com
Fri Jun 7 17:16:51 UTC 2013
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:
-------------- next part --------------
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();
More information about the libvir-list
mailing list