提交 42a021c1 编写于 作者: J John Ferlan

storage: Ensure fc_host parent matches wwnn/wwpn

https://bugzilla.redhat.com/show_bug.cgi?id=1160565

The existing code assumed that the configuration of a 'parent' attribute
was correct for the createVport path. As it turns out, that may not be
the case which leads errors during the deleteVport path because the
wwnn/wwpn isn't associated with the parent.

With this change the following is reported:

error: Failed to start pool fc_pool_host3
error: XML error: Parent attribute 'scsi_host4' does not match parent 'scsi_host3' determined for the 'scsi_host16' wwnn/wwpn lookup.

for XML as follows:

  <pool type='scsi'>
    <name>fc_pool</name>
    <source>
      <adapter type='fc_host' parent='scsi_host4' wwnn='5001a4aaf3ca174b' wwpn='5001a4a77192b864'/>
    </source>

Where 'nodedev-dumpxml scsi_host16' provides:

  <device>
    <name>scsi_host16</name>
    <path>/sys/devices/pci0000:00/0000:00:04.0/0000:10:00.0/host3/vport-3:0-11/host16</path>
    <parent>scsi_host3</parent>
    <capability type='scsi_host'>
      <host>16</host>
      <unique_id>13</unique_id>
      <capability type='fc_host'>
        <wwnn>5001a4aaf3ca174b</wwnn>
        <wwpn>5001a4a77192b864</wwpn>
...

The patch also adjusts the description of the storage pool to describe the
restrictions.
Signed-off-by: NJohn Ferlan <jferlan@redhat.com>
上级 844c1d7e
......@@ -166,7 +166,13 @@
to uniquely identify the device in the Fibre Channel storage fabric
(the device can be either a HBA or vHBA). Both wwnn and wwpn should
be specified. Use the command 'virsh nodedev-dumpxml' to determine
how to set the values for the wwnn/wwpn of a (v)HBA.
how to set the values for the wwnn/wwpn of a (v)HBA. The wwnn and
wwpn have very specific numerical format requirements based on the
hypervisor being used, thus care should be taken if you decide to
generate your own to follow the standards; otherwise, the pool
will fail to start with an opaque error message indicating failure
to write to the vport_create file during vport create/delete due
to "No such file or directory".
<span class="since">Since 1.0.4</span>
</dd>
</dl>
......@@ -176,7 +182,12 @@
parent scsi_host device defined in the
<a href="formatnode.html">Node Device</a> database as the
<a href="http://wiki.libvirt.org/page/NPIV_in_libvirt">NPIV</a>
virtual Host Bus Adapter (vHBA).
virtual Host Bus Adapter (vHBA). The value provided must be
a vport capable scsi_host. The value is not the scsi_host of
the vHBA created by 'virsh nodedev-create', rather it is
the parent of that vHBA. If the value is not provided, libvirt
will determine the parent based either finding the wwnn,wwpn
defined for an existing scsi_host or by creating a vHBA.
<span class="since">Since 1.0.4</span>
</dd>
</dl>
......
......@@ -34,6 +34,7 @@
#include "virlog.h"
#include "virfile.h"
#include "vircommand.h"
#include "viraccessapicheck.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
......@@ -547,8 +548,103 @@ getAdapterName(virStoragePoolSourceAdapter adapter)
return name;
}
/*
* Using the host# name found via wwnn/wwpn lookup in the fc_host
* sysfs tree to get the parent 'scsi_host#'. On entry we need 'conn'
* set. We won't get here from the autostart path since the caller
* will return true before calling this function. For the shutdown
* path we won't be able to delete the vport.
*/
static char * ATTRIBUTE_NONNULL(1)
getVhbaSCSIHostParent(virConnectPtr conn,
const char *name)
{
char *nodedev_name = NULL;
virNodeDevicePtr device = NULL;
char *xml = NULL;
virNodeDeviceDefPtr def = NULL;
char *vhba_parent = NULL;
virErrorPtr savedError = NULL;
VIR_DEBUG("conn=%p, name=%s", conn, name);
/* We get passed "host#" from the return from virGetFCHostNameByWWN,
* so we need to adjust that to what the nodedev lookup expects
*/
if (virAsprintf(&nodedev_name, "scsi_%s", name) < 0)
goto cleanup;
/* Compare the scsi_host for the name with the provided parent
* if not the same, then fail
*/
if (!(device = virNodeDeviceLookupByName(conn, nodedev_name))) {
virReportError(VIR_ERR_XML_ERROR,
_("Cannot find '%s' in node device database"),
nodedev_name);
goto cleanup;
}
if (!(xml = virNodeDeviceGetXMLDesc(device, 0)))
goto cleanup;
if (!(def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL)))
goto cleanup;
ignore_value(VIR_STRDUP(vhba_parent, def->parent));
cleanup:
if (!vhba_parent)
savedError = virSaveLastError();
VIR_FREE(nodedev_name);
virNodeDeviceDefFree(def);
VIR_FREE(xml);
virNodeDeviceFree(device);
if (savedError) {
virSetError(savedError);
virFreeError(savedError);
}
return vhba_parent;
}
/*
* Using the host# name found via wwnn/wwpn lookup in the fc_host
* sysfs tree to get the parent 'scsi_host#' to ensure it matches.
*/
static bool
checkVhbaSCSIHostParent(virConnectPtr conn,
const char *name,
const char *parent_name)
{
char *vhba_parent = NULL;
bool retval = false;
VIR_DEBUG("conn=%p, name=%s, parent_name=%s", conn, name, parent_name);
/* autostarted pool - assume we're OK */
if (!conn)
return true;
if (!(vhba_parent = getVhbaSCSIHostParent(conn, name)))
goto cleanup;
if (STRNEQ(parent_name, vhba_parent)) {
virReportError(VIR_ERR_XML_ERROR,
_("Parent attribute '%s' does not match parent '%s' "
"determined for the '%s' wwnn/wwpn lookup."),
parent_name, vhba_parent, name);
goto cleanup;
}
retval = true;
cleanup:
VIR_FREE(vhba_parent);
return retval;
}
static int
createVport(virStoragePoolSourceAdapter adapter)
createVport(virConnectPtr conn,
virStoragePoolSourceAdapter adapter)
{
unsigned int parent_host;
char *name = NULL;
......@@ -570,11 +666,23 @@ createVport(virStoragePoolSourceAdapter adapter)
}
}
/* This filters either HBA or already created vHBA */
/* If we find an existing HBA/vHBA within the fc_host sysfs
* using the wwnn/wwpn, then a nodedev is already created for
* this pool and we don't have to create the vHBA
*/
if ((name = virGetFCHostNameByWWN(NULL, adapter.data.fchost.wwnn,
adapter.data.fchost.wwpn))) {
int retval = 0;
/* If a parent was provided, let's make sure the 'name' we've
* retrieved has the same parent
*/
if (adapter.data.fchost.parent &&
!checkVhbaSCSIHostParent(conn, name, adapter.data.fchost.parent))
retval = -1;
VIR_FREE(name);
return 0;
return retval;
}
if (!adapter.data.fchost.parent) {
......@@ -705,11 +813,11 @@ virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
}
static int
virStorageBackendSCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStorageBackendSCSIStartPool(virConnectPtr conn,
virStoragePoolObjPtr pool)
{
virStoragePoolSourceAdapter adapter = pool->def->source.adapter;
return createVport(adapter);
return createVport(conn, adapter);
}
static int
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册