mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-03 03:25:20 +00:00
node_device: introduce new capability FC_RPORT
Similar to scsi_host and fc_host, there is a relation between a scsi_target and its transport specific fc_remote_port. Let's expose this relation and relevant information behind it. An example for a virsh nodedev-dumpxml: virsh # nodedev-dumpxml scsi_target0_0_0 <device> <name>scsi_target0_0_0</name> <path>/sys/devices/[...]/host0/rport-0:0-0/target0:0:0</path> <parent>scsi_host0</parent> <capability type='scsi_target'> <target>target0:0:0</target> <capability type='fc_remote_port'> <rport>rport-0:0-0</rport> <wwpn>0x9d73bc45f0e21a86</wwpn> </capability> </capability> </device> Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com> Signed-off-by: Bjoern Walk <bwalk@linux.vnet.ibm.com>
This commit is contained in:
parent
c47a3b130d
commit
bb2adfe934
@ -458,6 +458,20 @@
|
||||
</optional>
|
||||
</define>
|
||||
|
||||
<define name='capsfcrport'>
|
||||
<attribute name='type'>
|
||||
<value>fc_remote_port</value>
|
||||
</attribute>
|
||||
|
||||
<element name='rport'>
|
||||
<text/>
|
||||
</element>
|
||||
|
||||
<element name='wwpn'>
|
||||
<ref name='wwn'/>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name='capscsitarget'>
|
||||
<attribute name='type'>
|
||||
<value>scsi_target</value>
|
||||
@ -466,6 +480,12 @@
|
||||
<element name='target'>
|
||||
<text/>
|
||||
</element>
|
||||
|
||||
<optional>
|
||||
<element name='capability'>
|
||||
<ref name='capsfcrport'/>
|
||||
</element>
|
||||
</optional>
|
||||
</define>
|
||||
|
||||
<define name='capscsi'>
|
||||
|
@ -563,6 +563,16 @@ virNodeDeviceDefFormat(const virNodeDeviceDef *def)
|
||||
case VIR_NODE_DEV_CAP_SCSI_TARGET:
|
||||
virBufferEscapeString(&buf, "<target>%s</target>\n",
|
||||
data->scsi_target.name);
|
||||
if (data->scsi_target.flags & VIR_NODE_DEV_CAP_FLAG_FC_RPORT) {
|
||||
virBufferAddLit(&buf, "<capability type='fc_remote_port'>\n");
|
||||
virBufferAdjustIndent(&buf, 2);
|
||||
virBufferAsprintf(&buf, "<rport>%s</rport>\n",
|
||||
data->scsi_target.rport);
|
||||
virBufferAsprintf(&buf, "<wwpn>%s</wwpn>\n",
|
||||
data->scsi_target.wwpn);
|
||||
virBufferAdjustIndent(&buf, -2);
|
||||
virBufferAddLit(&buf, "</capability>\n");
|
||||
}
|
||||
break;
|
||||
case VIR_NODE_DEV_CAP_SCSI:
|
||||
virNodeDeviceCapSCSIDefFormat(&buf, data);
|
||||
@ -932,8 +942,10 @@ virNodeDevCapSCSITargetParseXML(xmlXPathContextPtr ctxt,
|
||||
xmlNodePtr node,
|
||||
virNodeDevCapSCSITargetPtr scsi_target)
|
||||
{
|
||||
xmlNodePtr orignode;
|
||||
int ret = -1;
|
||||
xmlNodePtr orignode, *nodes = NULL;
|
||||
int ret = -1, n = 0;
|
||||
size_t i;
|
||||
char *type = NULL;
|
||||
|
||||
orignode = ctxt->node;
|
||||
ctxt->node = node;
|
||||
@ -946,10 +958,60 @@ virNodeDevCapSCSITargetParseXML(xmlXPathContextPtr ctxt,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((n = virXPathNodeSet("./capability", ctxt, &nodes)) < 0)
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < n; ++i) {
|
||||
type = virXMLPropString(nodes[i], "type");
|
||||
|
||||
if (!type) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("missing type for SCSI target capability for '%s'"),
|
||||
def->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (STREQ(type, "fc_remote_port")) {
|
||||
xmlNodePtr orignode2;
|
||||
|
||||
scsi_target->flags |= VIR_NODE_DEV_CAP_FLAG_FC_RPORT;
|
||||
|
||||
orignode2 = ctxt->node;
|
||||
ctxt->node = nodes[i];
|
||||
|
||||
if (virNodeDevCapsDefParseString("string(./rport[1])",
|
||||
ctxt,
|
||||
&scsi_target->rport) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("missing rport name for '%s'"), def->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (virNodeDevCapsDefParseString("string(./wwpn[1])",
|
||||
ctxt, &scsi_target->wwpn) < 0) {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("missing wwpn identifier for '%s'"),
|
||||
def->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctxt->node = orignode2;
|
||||
} else {
|
||||
virReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("unknown SCSI target capability type '%s' for '%s'"),
|
||||
type, def->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
VIR_FREE(type);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
ctxt->node = orignode;
|
||||
VIR_FREE(type);
|
||||
VIR_FREE(nodes);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2132,6 +2194,8 @@ virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
|
||||
break;
|
||||
case VIR_NODE_DEV_CAP_SCSI_TARGET:
|
||||
VIR_FREE(data->scsi_target.name);
|
||||
VIR_FREE(data->scsi_target.rport);
|
||||
VIR_FREE(data->scsi_target.wwpn);
|
||||
break;
|
||||
case VIR_NODE_DEV_CAP_SCSI:
|
||||
VIR_FREE(data->scsi.type);
|
||||
|
@ -92,6 +92,10 @@ typedef enum {
|
||||
VIR_NODE_DEV_CAP_FLAG_HBA_VPORT_OPS = (1 << 1),
|
||||
} virNodeDevSCSIHostCapFlags;
|
||||
|
||||
typedef enum {
|
||||
VIR_NODE_DEV_CAP_FLAG_FC_RPORT = (1 << 0),
|
||||
} virNodeDevSCSITargetCapsFlags;
|
||||
|
||||
typedef enum {
|
||||
VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION = (1 << 0),
|
||||
VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION = (1 << 1),
|
||||
@ -227,6 +231,9 @@ typedef struct _virNodeDevCapSCSITarget virNodeDevCapSCSITarget;
|
||||
typedef virNodeDevCapSCSITarget *virNodeDevCapSCSITargetPtr;
|
||||
struct _virNodeDevCapSCSITarget {
|
||||
char *name;
|
||||
unsigned int flags; /* enum virNodeDevSCSITargetCapsFlags */
|
||||
char *rport;
|
||||
char *wwpn;
|
||||
};
|
||||
|
||||
typedef struct _virNodeDevCapSCSI virNodeDevCapSCSI;
|
||||
|
@ -56,6 +56,10 @@ static int update_caps(virNodeDeviceObjPtr dev)
|
||||
case VIR_NODE_DEV_CAP_SCSI_HOST:
|
||||
nodeDeviceSysfsGetSCSIHostCaps(&cap->data.scsi_host);
|
||||
break;
|
||||
case VIR_NODE_DEV_CAP_SCSI_TARGET:
|
||||
nodeDeviceSysfsGetSCSITargetCaps(dev->def->sysfs_path,
|
||||
&cap->data.scsi_target);
|
||||
break;
|
||||
case VIR_NODE_DEV_CAP_NET:
|
||||
if (virNetDevGetLinkInfo(cap->data.net.ifname, &cap->data.net.lnk) < 0)
|
||||
return -1;
|
||||
@ -76,7 +80,6 @@ static int update_caps(virNodeDeviceObjPtr dev)
|
||||
case VIR_NODE_DEV_CAP_SYSTEM:
|
||||
case VIR_NODE_DEV_CAP_USB_DEV:
|
||||
case VIR_NODE_DEV_CAP_USB_INTERFACE:
|
||||
case VIR_NODE_DEV_CAP_SCSI_TARGET:
|
||||
case VIR_NODE_DEV_CAP_SCSI:
|
||||
case VIR_NODE_DEV_CAP_STORAGE:
|
||||
case VIR_NODE_DEV_CAP_FC_HOST:
|
||||
|
@ -26,11 +26,13 @@
|
||||
#include <sys/stat.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "dirname.h"
|
||||
#include "node_device_driver.h"
|
||||
#include "node_device_hal.h"
|
||||
#include "node_device_linux_sysfs.h"
|
||||
#include "virerror.h"
|
||||
#include "viralloc.h"
|
||||
#include "virfcp.h"
|
||||
#include "virlog.h"
|
||||
#include "virfile.h"
|
||||
#include "virscsihost.h"
|
||||
@ -125,6 +127,50 @@ nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host)
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
nodeDeviceSysfsGetSCSITargetCaps(const char *sysfsPath,
|
||||
virNodeDevCapSCSITargetPtr scsi_target)
|
||||
{
|
||||
int ret = -1;
|
||||
char *dir = NULL, *rport = NULL;
|
||||
|
||||
VIR_DEBUG("Checking if '%s' is an FC remote port", scsi_target->name);
|
||||
|
||||
/* /sys/devices/[...]/host0/rport-0:0-0/target0:0:0 -> rport-0:0-0 */
|
||||
if (!(dir = mdir_name(sysfsPath)))
|
||||
return -1;
|
||||
|
||||
if (VIR_STRDUP(rport, last_component(dir)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (!virFCIsCapableRport(rport))
|
||||
goto cleanup;
|
||||
|
||||
VIR_FREE(scsi_target->rport);
|
||||
VIR_STEAL_PTR(scsi_target->rport, rport);
|
||||
|
||||
if (virFCReadRportValue(scsi_target->rport, "port_name",
|
||||
&scsi_target->wwpn) < 0) {
|
||||
VIR_WARN("Failed to read port_name for '%s'", scsi_target->rport);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
scsi_target->flags |= VIR_NODE_DEV_CAP_FLAG_FC_RPORT;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
VIR_FREE(scsi_target->rport);
|
||||
VIR_FREE(scsi_target->wwpn);
|
||||
scsi_target->flags &= ~VIR_NODE_DEV_CAP_FLAG_FC_RPORT;
|
||||
}
|
||||
VIR_FREE(rport);
|
||||
VIR_FREE(dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
nodeDeviceSysfsGetPCISRIOVCaps(const char *sysfsPath,
|
||||
virNodeDevCapPCIDevPtr pci_dev)
|
||||
@ -231,6 +277,12 @@ nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host ATTRIBUTE_UNUS
|
||||
return -1;
|
||||
}
|
||||
|
||||
int nodeDeviceSysfsGetSCSITargetCaps(const char *sysfsPath ATTRIBUTE_UNUSED,
|
||||
virNodeDevCapSCSITargetPtr scsi_target ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
nodeDeviceSysfsGetPCIRelatedDevCaps(const char *sysfsPath ATTRIBUTE_UNUSED,
|
||||
virNodeDevCapPCIDevPtr pci_dev ATTRIBUTE_UNUSED)
|
||||
|
@ -26,6 +26,8 @@
|
||||
# include "node_device_conf.h"
|
||||
|
||||
int nodeDeviceSysfsGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host);
|
||||
int nodeDeviceSysfsGetSCSITargetCaps(const char *sysfsPath,
|
||||
virNodeDevCapSCSITargetPtr scsi_target);
|
||||
int nodeDeviceSysfsGetPCIRelatedDevCaps(const char *sysfsPath,
|
||||
virNodeDevCapPCIDevPtr pci_dev);
|
||||
|
||||
|
@ -697,7 +697,7 @@ static int udevProcessSCSIHost(struct udev_device *device ATTRIBUTE_UNUSED,
|
||||
}
|
||||
|
||||
|
||||
static int udevProcessSCSITarget(struct udev_device *device ATTRIBUTE_UNUSED,
|
||||
static int udevProcessSCSITarget(struct udev_device *device,
|
||||
virNodeDeviceDefPtr def)
|
||||
{
|
||||
const char *sysname = NULL;
|
||||
@ -708,6 +708,8 @@ static int udevProcessSCSITarget(struct udev_device *device ATTRIBUTE_UNUSED,
|
||||
if (VIR_STRDUP(scsi_target->name, sysname) < 0)
|
||||
return -1;
|
||||
|
||||
nodeDeviceSysfsGetSCSITargetCaps(def->sysfs_path, &def->caps->data.scsi_target);
|
||||
|
||||
if (udevGenerateDeviceName(device, def, NULL) != 0)
|
||||
return -1;
|
||||
|
||||
|
12
tests/nodedevschemadata/scsi_target1_0_0.xml
Normal file
12
tests/nodedevschemadata/scsi_target1_0_0.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<device>
|
||||
<name>scsi_target1_0_0</name>
|
||||
<path>/sys/devices/css0/0.0.0000/0.0.0000/host1/rport-1:0-0/target1:0:0</path>
|
||||
<parent>scsi_host0</parent>
|
||||
<capability type='scsi_target'>
|
||||
<target>target1:0:0</target>
|
||||
<capability type='fc_remote_port'>
|
||||
<rport>rport-1:0-0</rport>
|
||||
<wwpn>0x9d73bc45f0e21a86</wwpn>
|
||||
</capability>
|
||||
</capability>
|
||||
</device>
|
@ -95,6 +95,7 @@ mymain(void)
|
||||
DO_TEST("pci_0000_00_02_0_header_type");
|
||||
DO_TEST("pci_0000_00_1c_0_header_type");
|
||||
DO_TEST("scsi_target0_0_0");
|
||||
DO_TEST("scsi_target1_0_0");
|
||||
DO_TEST("pci_0000_02_10_7_sriov");
|
||||
DO_TEST("pci_0000_02_10_7_sriov_vfs");
|
||||
DO_TEST("pci_0000_02_10_7_sriov_zero_vfs_max_count");
|
||||
|
Loading…
Reference in New Issue
Block a user