diff --git a/src/Makefile.am b/src/Makefile.am index 289b037472..b0ddfdfb75 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1168,9 +1168,7 @@ ACCESS_DRIVER_POLKIT_POLICY = \ NODE_DEVICE_DRIVER_SOURCES = \ node_device/node_device_driver.c \ - node_device/node_device_driver.h \ - node_device/node_device_linux_sysfs.c \ - node_device/node_device_linux_sysfs.h + node_device/node_device_driver.h NODE_DEVICE_DRIVER_HAL_SOURCES = \ node_device/node_device_hal.c \ diff --git a/src/conf/node_device_conf.c b/src/conf/node_device_conf.c index a72a742bc8..d3c3618281 100644 --- a/src/conf/node_device_conf.c +++ b/src/conf/node_device_conf.c @@ -33,11 +33,13 @@ #include "virstring.h" #include "node_device_conf.h" #include "device_conf.h" +#include "dirname.h" #include "virxml.h" #include "virbuffer.h" #include "viruuid.h" #include "virrandom.h" #include "virlog.h" +#include "virfcp.h" #define VIR_FROM_THIS VIR_FROM_NODEDEV @@ -2514,10 +2516,160 @@ virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host) return ret; } + +int +virNodeDeviceGetSCSITargetCaps(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 +virNodeDeviceGetPCISRIOVCaps(const char *sysfsPath, + virNodeDevCapPCIDevPtr pci_dev) +{ + size_t i; + int ret; + + /* this could be a refresh, so clear out the old data */ + for (i = 0; i < pci_dev->num_virtual_functions; i++) + VIR_FREE(pci_dev->virtual_functions[i]); + VIR_FREE(pci_dev->virtual_functions); + pci_dev->num_virtual_functions = 0; + pci_dev->max_virtual_functions = 0; + pci_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; + pci_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION; + + ret = virPCIGetPhysicalFunction(sysfsPath, + &pci_dev->physical_function); + if (ret < 0) + goto cleanup; + + if (pci_dev->physical_function) + pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION; + + ret = virPCIGetVirtualFunctions(sysfsPath, &pci_dev->virtual_functions, + &pci_dev->num_virtual_functions, + &pci_dev->max_virtual_functions); + if (ret < 0) + goto cleanup; + + if (pci_dev->num_virtual_functions > 0 || + pci_dev->max_virtual_functions > 0) + pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; + + cleanup: + return ret; +} + + +static int +virNodeDeviceGetPCIIOMMUGroupCaps(virNodeDevCapPCIDevPtr pci_dev) +{ + size_t i; + int tmpGroup, ret = -1; + virPCIDeviceAddress addr; + + /* this could be a refresh, so clear out the old data */ + for (i = 0; i < pci_dev->nIommuGroupDevices; i++) + VIR_FREE(pci_dev->iommuGroupDevices[i]); + VIR_FREE(pci_dev->iommuGroupDevices); + pci_dev->nIommuGroupDevices = 0; + pci_dev->iommuGroupNumber = 0; + + addr.domain = pci_dev->domain; + addr.bus = pci_dev->bus; + addr.slot = pci_dev->slot; + addr.function = pci_dev->function; + tmpGroup = virPCIDeviceAddressGetIOMMUGroupNum(&addr); + if (tmpGroup == -1) { + /* error was already reported */ + goto cleanup; + } + if (tmpGroup == -2) { + /* -2 return means there is no iommu_group data */ + ret = 0; + goto cleanup; + } + if (tmpGroup >= 0) { + if (virPCIDeviceAddressGetIOMMUGroupAddresses(&addr, &pci_dev->iommuGroupDevices, + &pci_dev->nIommuGroupDevices) < 0) + goto cleanup; + pci_dev->iommuGroupNumber = tmpGroup; + } + + ret = 0; + cleanup: + return ret; +} + + +/* virNodeDeviceGetPCIDynamicCaps() get info that is stored in sysfs + * about devices related to this device, i.e. things that can change + * without this device itself changing. These must be refreshed + * anytime full XML of the device is requested, because they can + * change with no corresponding notification from the kernel/udev. + */ +int +virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath, + virNodeDevCapPCIDevPtr pci_dev) +{ + if (virNodeDeviceGetPCISRIOVCaps(sysfsPath, pci_dev) < 0) + return -1; + if (virNodeDeviceGetPCIIOMMUGroupCaps(pci_dev) < 0) + return -1; + return 0; +} + #else int -virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host ATTRIBUTE_UNUSED) +virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath ATTRIBUTE_UNUSED, + virNodeDevCapPCIDevPtr pci_dev ATTRIBUTE_UNUSED) +{ + return -1; +} + + +int virNodeDeviceGetSCSITargetCaps(const char *sysfsPath ATTRIBUTE_UNUSED, + virNodeDevCapSCSITargetPtr scsi_target ATTRIBUTE_UNUSED) { return -1; } diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index cf79773aa0..4e3154875e 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -393,4 +393,11 @@ virNodeDeviceDeleteVport(virConnectPtr conn, int virNodeDeviceGetSCSIHostCaps(virNodeDevCapSCSIHostPtr scsi_host); +int +virNodeDeviceGetSCSITargetCaps(const char *sysfsPath, + virNodeDevCapSCSITargetPtr scsi_target); + +int +virNodeDeviceGetPCIDynamicCaps(const char *sysfsPath, + virNodeDevCapPCIDevPtr pci_dev); #endif /* __VIR_NODE_DEVICE_CONF_H__ */ diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index f2a2c8650d..1467796d4b 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -707,7 +707,9 @@ virNodeDeviceDefParseNode; virNodeDeviceDefParseString; virNodeDeviceDeleteVport; virNodeDeviceGetParentName; +virNodeDeviceGetPCIDynamicCaps; virNodeDeviceGetSCSIHostCaps; +virNodeDeviceGetSCSITargetCaps; virNodeDeviceGetWWNs; diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index a2f687942f..2e42d35274 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -38,7 +38,6 @@ #include "node_device_event.h" #include "node_device_driver.h" #include "node_device_hal.h" -#include "node_device_linux_sysfs.h" #include "virvhba.h" #include "viraccessapicheck.h" #include "virnetdev.h" @@ -59,7 +58,7 @@ nodeDeviceUpdateCaps(virNodeDeviceDefPtr def) virNodeDeviceGetSCSIHostCaps(&cap->data.scsi_host); break; case VIR_NODE_DEV_CAP_SCSI_TARGET: - nodeDeviceSysfsGetSCSITargetCaps(def->sysfs_path, + virNodeDeviceGetSCSITargetCaps(def->sysfs_path, &cap->data.scsi_target); break; case VIR_NODE_DEV_CAP_NET: @@ -70,8 +69,8 @@ nodeDeviceUpdateCaps(virNodeDeviceDefPtr def) return -1; break; case VIR_NODE_DEV_CAP_PCI_DEV: - if (nodeDeviceSysfsGetPCIRelatedDevCaps(def->sysfs_path, - &cap->data.pci_dev) < 0) + if (virNodeDeviceGetPCIDynamicCaps(def->sysfs_path, + &cap->data.pci_dev) < 0) return -1; break; diff --git a/src/node_device/node_device_hal.c b/src/node_device/node_device_hal.c index 9fac5780e7..26fcd7918c 100644 --- a/src/node_device/node_device_hal.c +++ b/src/node_device/node_device_hal.c @@ -31,7 +31,6 @@ #include "node_device_conf.h" #include "node_device_driver.h" #include "node_device_hal.h" -#include "node_device_linux_sysfs.h" #include "virerror.h" #include "driver.h" #include "datatypes.h" diff --git a/src/node_device/node_device_linux_sysfs.c b/src/node_device/node_device_linux_sysfs.c deleted file mode 100644 index b3f80a5554..0000000000 --- a/src/node_device/node_device_linux_sysfs.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * node_device_linux_sysfs.c: Linux specific code to gather device data - * that is available from sysfs (but not from UDEV or HAL). - * - * Copyright (C) 2009-2015 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * . - * - */ - -#include - -#include -#include -#include - -#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" -#include "virstring.h" -#include "virvhba.h" - -#define VIR_FROM_THIS VIR_FROM_NODEDEV - -#ifdef __linux__ - -VIR_LOG_INIT("node_device.node_device_linux_sysfs"); - - -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) -{ - size_t i; - int ret; - - /* this could be a refresh, so clear out the old data */ - for (i = 0; i < pci_dev->num_virtual_functions; i++) - VIR_FREE(pci_dev->virtual_functions[i]); - VIR_FREE(pci_dev->virtual_functions); - pci_dev->num_virtual_functions = 0; - pci_dev->max_virtual_functions = 0; - pci_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; - pci_dev->flags &= ~VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION; - - ret = virPCIGetPhysicalFunction(sysfsPath, - &pci_dev->physical_function); - if (ret < 0) - goto cleanup; - - if (pci_dev->physical_function) - pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_PHYSICAL_FUNCTION; - - ret = virPCIGetVirtualFunctions(sysfsPath, &pci_dev->virtual_functions, - &pci_dev->num_virtual_functions, - &pci_dev->max_virtual_functions); - if (ret < 0) - goto cleanup; - - if (pci_dev->num_virtual_functions > 0 || - pci_dev->max_virtual_functions > 0) - pci_dev->flags |= VIR_NODE_DEV_CAP_FLAG_PCI_VIRTUAL_FUNCTION; - - cleanup: - return ret; -} - - -static int -nodeDeviceSysfsGetPCIIOMMUGroupCaps(virNodeDevCapPCIDevPtr pci_dev) -{ - size_t i; - int tmpGroup, ret = -1; - virPCIDeviceAddress addr; - - /* this could be a refresh, so clear out the old data */ - for (i = 0; i < pci_dev->nIommuGroupDevices; i++) - VIR_FREE(pci_dev->iommuGroupDevices[i]); - VIR_FREE(pci_dev->iommuGroupDevices); - pci_dev->nIommuGroupDevices = 0; - pci_dev->iommuGroupNumber = 0; - - addr.domain = pci_dev->domain; - addr.bus = pci_dev->bus; - addr.slot = pci_dev->slot; - addr.function = pci_dev->function; - tmpGroup = virPCIDeviceAddressGetIOMMUGroupNum(&addr); - if (tmpGroup == -1) { - /* error was already reported */ - goto cleanup; - } - if (tmpGroup == -2) { - /* -2 return means there is no iommu_group data */ - ret = 0; - goto cleanup; - } - if (tmpGroup >= 0) { - if (virPCIDeviceAddressGetIOMMUGroupAddresses(&addr, &pci_dev->iommuGroupDevices, - &pci_dev->nIommuGroupDevices) < 0) - goto cleanup; - pci_dev->iommuGroupNumber = tmpGroup; - } - - ret = 0; - cleanup: - return ret; -} - - -/* nodeDeviceSysfsGetPCIRelatedCaps() get info that is stored in sysfs - * about devices related to this device, i.e. things that can change - * without this device itself changing. These must be refreshed - * anytime full XML of the device is requested, because they can - * change with no corresponding notification from the kernel/udev. - */ -int -nodeDeviceSysfsGetPCIRelatedDevCaps(const char *sysfsPath, - virNodeDevCapPCIDevPtr pci_dev) -{ - if (nodeDeviceSysfsGetPCISRIOVCaps(sysfsPath, pci_dev) < 0) - return -1; - if (nodeDeviceSysfsGetPCIIOMMUGroupCaps(pci_dev) < 0) - return -1; - return 0; -} - - -#else - -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) -{ - return -1; -} - -#endif /* __linux__ */ diff --git a/src/node_device/node_device_linux_sysfs.h b/src/node_device/node_device_linux_sysfs.h deleted file mode 100644 index 9392d69349..0000000000 --- a/src/node_device/node_device_linux_sysfs.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * node_device_linux_sysfs.h: Linux specific code to gather device data - * that is available from sysfs (but not from UDEV or HAL). - * - * Copyright (C) 2015 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * . - * - */ - -#ifndef __VIR_NODE_DEVICE_LINUX_SYSFS_H__ -# define __VIR_NODE_DEVICE_LINUX_SYSFS_H__ - -# include "node_device_conf.h" - -int nodeDeviceSysfsGetSCSITargetCaps(const char *sysfsPath, - virNodeDevCapSCSITargetPtr scsi_target); -int nodeDeviceSysfsGetPCIRelatedDevCaps(const char *sysfsPath, - virNodeDevCapPCIDevPtr pci_dev); - -#endif /* __VIR_NODE_DEVICE_LINUX_SYSFS_H__ */ diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index 4cc531d2c1..519b0bf6fa 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -30,7 +30,6 @@ #include "node_device_conf.h" #include "node_device_event.h" #include "node_device_driver.h" -#include "node_device_linux_sysfs.h" #include "node_device_udev.h" #include "virerror.h" #include "driver.h" @@ -558,7 +557,7 @@ udevProcessPCI(struct udev_device *device, &pci_dev->numa_node, 10) < 0) goto cleanup; - if (nodeDeviceSysfsGetPCIRelatedDevCaps(def->sysfs_path, pci_dev) < 0) + if (virNodeDeviceGetPCIDynamicCaps(def->sysfs_path, pci_dev) < 0) goto cleanup; if (!(pciDev = virPCIDeviceNew(pci_dev->domain, @@ -802,7 +801,7 @@ udevProcessSCSITarget(struct udev_device *device, if (VIR_STRDUP(scsi_target->name, sysname) < 0) return -1; - nodeDeviceSysfsGetSCSITargetCaps(def->sysfs_path, &def->caps->data.scsi_target); + virNodeDeviceGetSCSITargetCaps(def->sysfs_path, &def->caps->data.scsi_target); if (udevGenerateDeviceName(device, def, NULL) != 0) return -1;