* [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism @ 2018-06-29 10:24 Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 1/9] bus: introduce hotplug failure handler Jeff Guo ` (8 more replies) 0 siblings, 9 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang As we know, hot plug is an importance feature, either use for the datacenter device’s fail-safe, or use for SRIOV Live Migration in SDN/NFV. It could bring the higher flexibility and continuality to the networking services in multiple use cases in industry. So let we see, dpdk as an importance networking framework, what can it help to implement hot plug solution for users. We already have a general device event detect mechanism, failsafe driver, bonding driver and hot plug/unplug api in framework, app could use these to develop their hot plug solution. let’s see the case of hot unplug, it can happen when a hardware device is be removed physically, or when the software disables it. App need to call ether dev API to detach the device, to unplug the device at the bus level and make access to the device invalid. But the problem is that, the removal of the device from the software lists is not going to be instantaneous, at this time if the data(fast) path still read/write the device, it will cause MMIO error and result of the app crash out. Seems that we have got fail-safe driver(or app) + RTE_ETH_EVENT_INTR_RMV + kernel core driver solution to handle it, but still not have failsafe driver (or app) + RTE_DEV_EVENT_REMOVE + PCIe pmd driver failure handle solution. So there is an absence in dpdk hot plug solution right now. Also, we know that kernel only guaranty hot plug on the kernel side, but not for the user mode side. Firstly we can hardly have a gatekeeper for any MMIO for multiple PMD driver. Secondly, no more specific 3rd tools such as udev/driverctl have especially cover these hot plug failure processing. Third, the feasibility of app’s implement for multiple user mode PMD driver is still a problem. Here, a general hot plug failure handle mechanism in dpdk framework would be proposed, it aim to guaranty that, when hot unplug occur, the system will not crash and app will not be break out, and user space can normally stop and release any relevant resources, then unplug of the device at the bus level cleanly. The mechanism should be come across as bellow: Firstly, app enabled the device event monitor and register the hot plug event’s callback before running data path. Once the hot unplug behave occur, the mechanism will detect the removal event and then accordingly do the failure handle. In order to do that, below functional will be bring in. - Add a new bus ops “handle_hot_unplug” to handle bus read/write error, it is bus-specific and each kind of bus can implement its own logic. - Implement pci bus specific ops “pci_handle_hot_unplug”. It will base on the failure address to remap memory for the corresponding device that unplugged. For the data path or other unexpected control from the control path when hot unplug occur. - Implement a new sigbus handler, it is registered when start device even monitoring. The handler is per process. Base on the signal event principle, control path thread and data path thread will randomly receive the sigbus error, but will go to the common sigbus handler. Once the MMIO sigbus error exposure, it will trigger the above hot unplug operation. The sigbus will be check if it is cause of the hot unplug or not, if not will info exception as the original sigbus handler. If yes, will do memory remapping. For the control path and the igb uio release: - When hot unplug device, the kernel will release the device resource in the kernel side, such as the fd sys file will disappear, and the irq will be released. At this time, if igb uio driver still try to release this resource, it will cause kernel crash. On the other hand, something like interrupt disable do not automatically process in kernel side. If not handler it, this redundancy and dirty thing will affect the interrupt resource be used by other device. So the igb_uio driver have to check the hot plug status and corresponding process should be taken in igb uio deriver. This patch propose to add structure of rte_udev_state into rte_uio_pci_dev of igb_uio kernel driver, which will record the state of uio device, such as probed/opened/released/removed/unplug. When detect the unexpected removal which cause of hot unplug behavior, it will corresponding disable interrupt resource, while for the part of releasement which kernel have already handle, just skip it to avoid double free or null pointer kernel crash issue. The mechanism could be use for fail-safe driver and app which want to use hot plug solution. At this stage, will only use testpmd as reference to show how to use the mechanism. - Enable device event monitor->device unplug->failure handle->stop forwarding-> stop port->close port->detach port. This process will not breaking the app/fail-safe running, and will not break other irrelevance device. And app could plug in the device and restart the date path again by below. - Device plug in->bind igb_uio driver ->attached device->start port-> start forwarding. patchset history: v4->v3: split patches to be small and clear change to use new parameter "--hotplug-mode" in testpmd to identify the eal hotplug and ethdev hotplug v3->v2: change bus ops name to bus_hotplug_handler. add new API and bus ops of bus_signal_handler distingush handle generic sigbus and hotplug sigbus v2->v1(v21): refine some doc and commit log fix igb uio kernel issue for control path failure rebase testpmd code Since the hot plug solution be discussed serval around in the public, the scope be changed and the patch set be split into many times. Coming to the recently RFC and feature design, it just focus on the hot unplug failure handler at this patch set, so in order let this topic more clear and focus, summarize privours patch set in history “v1(v21)”, the v2 here go ahead for further track. "v1(21)" == v21 as below: v21->v20: split function in hot unplug ops sync failure hanlde to fix multiple process issue fix attach port issue for multiple devices case. combind rmv callback function to be only one. v20->v19: clean the code refine the remap logic for multiple device. remove the auto binding v19->18: note for limitation of multiple hotplug,fix some typo, sqeeze patch. v18->v15: add document, add signal bus handler, refine the code to be more clear. the prior patch history please check the patch set "add device event monitor framework" Jeff Guo (9): bus: introduce hotplug failure handler bus/pci: implement hotplug handler operation bus: introduce sigbus handler bus/pci: implement sigbus handler operation bus: add helper to handle sigbus eal: add failure handle mechanism for hot plug igb_uio: fix uio release issue when hot unplug app/testpmd: show example to handle hot unplug app/testpmd: enable device hotplug monitoring app/test-pmd/parameters.c | 20 ++++++-- app/test-pmd/testpmd.c | 31 +++++++----- app/test-pmd/testpmd.h | 8 ++- doc/guides/testpmd_app_ug/run_app.rst | 10 +++- drivers/bus/pci/pci_common.c | 78 +++++++++++++++++++++++++++++ drivers/bus/pci/pci_common_uio.c | 33 +++++++++++++ drivers/bus/pci/private.h | 12 +++++ kernel/linux/igb_uio/igb_uio.c | 50 +++++++++++++++++-- lib/librte_eal/common/eal_common_bus.c | 34 ++++++++++++- lib/librte_eal/common/eal_private.h | 11 +++++ lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++ lib/librte_eal/linuxapp/eal/eal_dev.c | 88 ++++++++++++++++++++++++++++++++- 12 files changed, 381 insertions(+), 25 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 1/9] bus: introduce hotplug failure handler 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 2/9] bus/pci: implement hotplug handler operation Jeff Guo ` (7 subsequent siblings) 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang When a hardware device is removed physically or the software disables it, the hotplug occur. App need to call ether dev API to detach the device, to unplug the device at the bus level and make access to the device invalid. But the removal of the device from the software lists is not going to be instantaneous, at this time if the data path still read/write the device, it will cause MMIO error and result of the app crash out. So a hotplug failure handle mechanism need to be used to guaranty app will not crash out when hot unplug device. To handle device hot plug failure is a bus-specific behavior, this patch introduces a bus ops so that each kind of bus can implement its own logic. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: split patches to be small and clear. --- lib/librte_eal/common/include/rte_bus.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h index eb9eded..3642aeb 100644 --- a/lib/librte_eal/common/include/rte_bus.h +++ b/lib/librte_eal/common/include/rte_bus.h @@ -168,6 +168,19 @@ typedef int (*rte_bus_unplug_t)(struct rte_device *dev); typedef int (*rte_bus_parse_t)(const char *name, void *addr); /** + * Implementation a specific hot plug handler, which is responsible + * for handle the failure when hot remove the device, guaranty the system + * would not crash in the case. + * @param dev + * Pointer of the device structure. + * + * @return + * 0 on success. + * !0 on error. + */ +typedef int (*rte_bus_hotplug_handler_t)(struct rte_device *dev); + +/** * Bus scan policies */ enum rte_bus_scan_mode { @@ -211,6 +224,8 @@ struct rte_bus { rte_bus_parse_t parse; /**< Parse a device name */ struct rte_bus_conf conf; /**< Bus configuration */ rte_bus_get_iommu_class_t get_iommu_class; /**< Get iommu class */ + rte_bus_hotplug_handler_t hotplug_handler; + /**< handle hot plug on bus */ }; /** -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 2/9] bus/pci: implement hotplug handler operation 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 1/9] bus: introduce hotplug failure handler Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 3/9] bus: introduce sigbus handler Jeff Guo ` (6 subsequent siblings) 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang This patch implements the ops of hotplug handler for PCI bus, it is functional to remap a new dummy memory which overlap to the failure memory to avoid MMIO read/write error. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: split patches to be small and clear. --- drivers/bus/pci/pci_common.c | 28 ++++++++++++++++++++++++++++ drivers/bus/pci/pci_common_uio.c | 33 +++++++++++++++++++++++++++++++++ drivers/bus/pci/private.h | 12 ++++++++++++ 3 files changed, 73 insertions(+) diff --git a/drivers/bus/pci/pci_common.c b/drivers/bus/pci/pci_common.c index d8151b0..095cd4e 100644 --- a/drivers/bus/pci/pci_common.c +++ b/drivers/bus/pci/pci_common.c @@ -401,6 +401,33 @@ pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, } static int +pci_hotplug_handler(struct rte_device *dev) +{ + struct rte_pci_device *pdev = NULL; + int ret = 0; + + pdev = RTE_DEV_TO_PCI(dev); + if (!pdev) + return -1; + + switch (pdev->kdrv) { + case RTE_KDRV_IGB_UIO: + case RTE_KDRV_UIO_GENERIC: + case RTE_KDRV_NIC_UIO: + /* mmio resources is invalid, remap it to be safe. */ + ret = pci_uio_remap_resource(pdev); + break; + default: + RTE_LOG(DEBUG, EAL, + "Not managed by a supported kernel driver, skipped\n"); + ret = -1; + break; + } + + return ret; +} + +static int pci_plug(struct rte_device *dev) { return pci_probe_all_drivers(RTE_DEV_TO_PCI(dev)); @@ -430,6 +457,7 @@ struct rte_pci_bus rte_pci_bus = { .unplug = pci_unplug, .parse = pci_parse, .get_iommu_class = rte_pci_get_iommu_class, + .hotplug_handler = pci_hotplug_handler, }, .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list), .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list), diff --git a/drivers/bus/pci/pci_common_uio.c b/drivers/bus/pci/pci_common_uio.c index 54bc20b..7ea73db 100644 --- a/drivers/bus/pci/pci_common_uio.c +++ b/drivers/bus/pci/pci_common_uio.c @@ -146,6 +146,39 @@ pci_uio_unmap(struct mapped_pci_resource *uio_res) } } +/* remap the PCI resource of a PCI device in anonymous virtual memory */ +int +pci_uio_remap_resource(struct rte_pci_device *dev) +{ + int i; + void *map_address; + + if (dev == NULL) + return -1; + + /* Remap all BARs */ + for (i = 0; i != PCI_MAX_RESOURCE; i++) { + /* skip empty BAR */ + if (dev->mem_resource[i].phys_addr == 0) + continue; + map_address = mmap(dev->mem_resource[i].addr, + (size_t)dev->mem_resource[i].len, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); + if (map_address == MAP_FAILED) { + RTE_LOG(ERR, EAL, + "Cannot remap resource for device %s\n", + dev->name); + return -1; + } + RTE_LOG(INFO, EAL, + "Successful remap resource for device %s\n", + dev->name); + } + + return 0; +} + static struct mapped_pci_resource * pci_uio_find_resource(struct rte_pci_device *dev) { diff --git a/drivers/bus/pci/private.h b/drivers/bus/pci/private.h index 8ddd03e..6b312e5 100644 --- a/drivers/bus/pci/private.h +++ b/drivers/bus/pci/private.h @@ -123,6 +123,18 @@ void pci_uio_free_resource(struct rte_pci_device *dev, struct mapped_pci_resource *uio_res); /** + * Remap the PCI resource of a PCI device in anonymous virtual memory. + * + * @param dev + * Point to the struct rte pci device. + * @return + * - On success, zero. + * - On failure, a negative value. + */ +int +pci_uio_remap_resource(struct rte_pci_device *dev); + +/** * Map device memory to uio resource * * This function is private to EAL. -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 3/9] bus: introduce sigbus handler 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 1/9] bus: introduce hotplug failure handler Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 2/9] bus/pci: implement hotplug handler operation Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 4/9] bus/pci: implement sigbus handler operation Jeff Guo ` (5 subsequent siblings) 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang When device be hotplug, if data path still read/write device, the sigbus error will occur, this error need to be handled. So a handler need to be here to capture the signal and handle it correspondingly. To handle sigbus error is a bus-specific behavior, this patch introduces a bus ops so that each kind of bus can implement its own logic. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: split patches to be small and clear. --- lib/librte_eal/common/include/rte_bus.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/librte_eal/common/include/rte_bus.h b/lib/librte_eal/common/include/rte_bus.h index 3642aeb..231bd3d 100644 --- a/lib/librte_eal/common/include/rte_bus.h +++ b/lib/librte_eal/common/include/rte_bus.h @@ -181,6 +181,20 @@ typedef int (*rte_bus_parse_t)(const char *name, void *addr); typedef int (*rte_bus_hotplug_handler_t)(struct rte_device *dev); /** + * Implementation a specific sigbus handler, which is responsible + * for handle the sigbus error which is original memory error, or specific + * memory error that caused of hot unplug. + * @param failure_addr + * Pointer of the fault address of the sigbus error. + * + * @return + * 0 for success handle the sigbus. + * 1 for no handle the sigbus. + * -1 for failed to handle the sigbus + */ +typedef int (*rte_bus_sigbus_handler_t)(const void *failure_addr); + +/** * Bus scan policies */ enum rte_bus_scan_mode { @@ -226,6 +240,8 @@ struct rte_bus { rte_bus_get_iommu_class_t get_iommu_class; /**< Get iommu class */ rte_bus_hotplug_handler_t hotplug_handler; /**< handle hot plug on bus */ + rte_bus_sigbus_handler_t sigbus_handler; /**< handle sigbus error */ + }; /** -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 4/9] bus/pci: implement sigbus handler operation 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo ` (2 preceding siblings ...) 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 3/9] bus: introduce sigbus handler Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus Jeff Guo ` (4 subsequent siblings) 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang This patch implements the ops of sigbus handler for PCI bus, it is functional to find the corresponding pci device which is be hot removal. and then handle the hot plug failure for this device. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: split patches to be small and clear. --- drivers/bus/pci/pci_common.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/drivers/bus/pci/pci_common.c b/drivers/bus/pci/pci_common.c index 095cd4e..0f5b4af 100644 --- a/drivers/bus/pci/pci_common.c +++ b/drivers/bus/pci/pci_common.c @@ -400,6 +400,32 @@ pci_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, return NULL; } +/* check the failure address belongs to which device. */ +static struct rte_pci_device * +pci_find_device_by_addr(const void *failure_addr) +{ + struct rte_pci_device *pdev = NULL; + int i; + + FOREACH_DEVICE_ON_PCIBUS(pdev) { + for (i = 0; i != RTE_DIM(pdev->mem_resource); i++) { + if ((uint64_t)(uintptr_t)failure_addr >= + (uint64_t)(uintptr_t)pdev->mem_resource[i].addr && + (uint64_t)(uintptr_t)failure_addr < + (uint64_t)(uintptr_t)pdev->mem_resource[i].addr + + pdev->mem_resource[i].len) { + RTE_LOG(INFO, EAL, "Failure address " + "%16.16"PRIx64" belongs to " + "device %s!\n", + (uint64_t)(uintptr_t)failure_addr, + pdev->device.name); + return pdev; + } + } + } + return NULL; +} + static int pci_hotplug_handler(struct rte_device *dev) { @@ -428,6 +454,29 @@ pci_hotplug_handler(struct rte_device *dev) } static int +pci_sigbus_handler(const void *failure_addr) +{ + struct rte_pci_device *pdev = NULL; + int ret = 0; + + pdev = pci_find_device_by_addr(failure_addr); + if (!pdev) { + /* It is a generic sigbus error. */ + ret = 1; + } else { + /* The sigbus error is caused of hot removal. */ + ret = pci_hotplug_handler(&pdev->device); + if (ret) { + RTE_LOG(ERR, EAL, "Failed to handle hot plug for " + "device %s", pdev->name); + ret = -1; + rte_errno = -1; + } + } + return ret; +} + +static int pci_plug(struct rte_device *dev) { return pci_probe_all_drivers(RTE_DEV_TO_PCI(dev)); @@ -458,6 +507,7 @@ struct rte_pci_bus rte_pci_bus = { .parse = pci_parse, .get_iommu_class = rte_pci_get_iommu_class, .hotplug_handler = pci_hotplug_handler, + .sigbus_handler = pci_sigbus_handler, }, .device_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.device_list), .driver_list = TAILQ_HEAD_INITIALIZER(rte_pci_bus.driver_list), -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo ` (3 preceding siblings ...) 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 4/9] bus/pci: implement sigbus handler operation Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 6/9] eal: add failure handle mechanism for hot plug Jeff Guo ` (3 subsequent siblings) 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang This patch aim to add a helper to iterate all buses to find the corresponding bus to handle the sigbus error. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: split patches to be small and clear. --- lib/librte_eal/common/eal_common_bus.c | 34 +++++++++++++++++++++++++++++++++- lib/librte_eal/common/eal_private.h | 11 +++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c index 0943851..34c4f2d 100644 --- a/lib/librte_eal/common/eal_common_bus.c +++ b/lib/librte_eal/common/eal_common_bus.c @@ -37,6 +37,7 @@ #include <rte_bus.h> #include <rte_debug.h> #include <rte_string_fns.h> +#include <rte_errno.h> #include "eal_private.h" @@ -220,7 +221,6 @@ rte_bus_find_by_device_name(const char *str) return rte_bus_find(NULL, bus_can_parse, name); } - /* * Get iommu class of devices on the bus. */ @@ -242,3 +242,35 @@ rte_bus_get_iommu_class(void) } return mode; } + +static int +bus_handle_sigbus(const struct rte_bus *bus, + const void *failure_addr) +{ + return !(bus->sigbus_handler && bus->sigbus_handler(failure_addr) <= 0); +} + +int +rte_bus_sigbus_handler(const void *failure_addr) +{ + struct rte_bus *bus; + int old_errno = rte_errno; + int ret = 0; + + rte_errno = 0; + + bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "No bus can handle the sigbus error!"); + ret = -1; + } else if (rte_errno != 0) { + RTE_LOG(ERR, EAL, "Failed to handle the sigbus error!"); + ret = -1; + } + + /* if sigbus not be handled, return back old errno. */ + if (ret) + rte_errno = old_errno; + + return ret; +} diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index bdadc4d..9517f2b 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -258,4 +258,15 @@ int rte_mp_channel_init(void); */ void dev_callback_process(char *device_name, enum rte_dev_event_type event); + +/** + * Iterate all buses to find the corresponding bus, to handle the sigbus error. + * @param failure_addr + * Pointer of the fault address of the sigbus error. + * + * @return + * 0 on success. + * -1 on error + */ +int rte_bus_sigbus_handler(const void *failure_addr); #endif /* _EAL_PRIVATE_H_ */ -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 6/9] eal: add failure handle mechanism for hot plug 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo ` (4 preceding siblings ...) 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 7/9] igb_uio: fix uio release issue when hot unplug Jeff Guo ` (2 subsequent siblings) 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang This patch introduces a failure handler mechanism to handle device hot plug removal event. First register sigbus handler, once sigbus error be captured, will check the failure address and accordingly remap the invalid memory for the corresponding device. Bese on this mechanism, it could guaranty the application not to be crash when hot unplug devices. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: split patches to be small and clear. --- lib/librte_eal/linuxapp/eal/eal_dev.c | 88 ++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/linuxapp/eal/eal_dev.c b/lib/librte_eal/linuxapp/eal/eal_dev.c index 1cf6aeb..c9dddab 100644 --- a/lib/librte_eal/linuxapp/eal/eal_dev.c +++ b/lib/librte_eal/linuxapp/eal/eal_dev.c @@ -4,6 +4,8 @@ #include <string.h> #include <unistd.h> +#include <fcntl.h> +#include <signal.h> #include <sys/socket.h> #include <linux/netlink.h> @@ -14,15 +16,24 @@ #include <rte_malloc.h> #include <rte_interrupts.h> #include <rte_alarm.h> +#include <rte_bus.h> +#include <rte_eal.h> +#include <rte_spinlock.h> +#include <rte_errno.h> #include "eal_private.h" static struct rte_intr_handle intr_handle = {.fd = -1 }; static bool monitor_started; +extern struct rte_bus_list rte_bus_list; + #define EAL_UEV_MSG_LEN 4096 #define EAL_UEV_MSG_ELEM_LEN 128 +/* spinlock for device failure process */ +static rte_spinlock_t dev_failure_lock = RTE_SPINLOCK_INITIALIZER; + static void dev_uev_handler(__rte_unused void *param); /* identify the system layer which reports this event. */ @@ -33,6 +44,34 @@ enum eal_dev_event_subsystem { EAL_DEV_EVENT_SUBSYSTEM_MAX }; +static void sigbus_handler(int signum __rte_unused, siginfo_t *info, + void *ctx __rte_unused) +{ + int ret; + + RTE_LOG(DEBUG, EAL, "Thread[%d] catch SIGBUS, fault address:%p\n", + (int)pthread_self(), info->si_addr); + + rte_spinlock_lock(&dev_failure_lock); + ret = rte_bus_sigbus_handler(info->si_addr); + rte_spinlock_unlock(&dev_failure_lock); + if (!ret) + RTE_LOG(INFO, EAL, + "Success to handle SIGBUS error for hotplug!\n"); + else + rte_exit(EXIT_FAILURE, + "A generic SIGBUS error, (rte_errno: %s)!", + strerror(rte_errno)); +} + +static int cmp_dev_name(const struct rte_device *dev, + const void *_name) +{ + const char *name = _name; + + return strcmp(dev->name, name); +} + static int dev_uev_socket_fd_create(void) { @@ -147,6 +186,9 @@ dev_uev_handler(__rte_unused void *param) struct rte_dev_event uevent; int ret; char buf[EAL_UEV_MSG_LEN]; + struct rte_bus *bus; + struct rte_device *dev; + const char *busname; memset(&uevent, 0, sizeof(struct rte_dev_event)); memset(buf, 0, EAL_UEV_MSG_LEN); @@ -171,13 +213,48 @@ dev_uev_handler(__rte_unused void *param) RTE_LOG(DEBUG, EAL, "receive uevent(name:%s, type:%d, subsystem:%d)\n", uevent.devname, uevent.type, uevent.subsystem); - if (uevent.devname) + switch (uevent.subsystem) { + case EAL_DEV_EVENT_SUBSYSTEM_PCI: + case EAL_DEV_EVENT_SUBSYSTEM_UIO: + busname = "pci"; + break; + default: + break; + } + + if (uevent.devname) { + if (uevent.type == RTE_DEV_EVENT_REMOVE) { + bus = rte_bus_find_by_name(busname); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", + busname); + return; + } + dev = bus->find_device(NULL, cmp_dev_name, + uevent.devname); + if (dev == NULL) { + RTE_LOG(ERR, EAL, "Cannot find device (%s) on " + "bus (%s)\n", uevent.devname, busname); + return; + } + rte_spinlock_lock(&dev_failure_lock); + ret = bus->hotplug_handler(dev); + rte_spinlock_unlock(&dev_failure_lock); + if (ret) { + RTE_LOG(ERR, EAL, "Can not handle hotplug for " + "device (%s)\n", dev->name); + return; + } + } dev_callback_process(uevent.devname, uevent.type); + } } int __rte_experimental rte_dev_event_monitor_start(void) { + sigset_t mask; + struct sigaction action; int ret; if (monitor_started) @@ -197,6 +274,14 @@ rte_dev_event_monitor_start(void) return -1; } + /* register sigbus handler */ + sigemptyset(&mask); + sigaddset(&mask, SIGBUS); + action.sa_flags = SA_SIGINFO; + action.sa_mask = mask; + action.sa_sigaction = sigbus_handler; + sigaction(SIGBUS, &action, NULL); + monitor_started = true; return 0; @@ -220,5 +305,6 @@ rte_dev_event_monitor_stop(void) close(intr_handle.fd); intr_handle.fd = -1; monitor_started = false; + return 0; } -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 7/9] igb_uio: fix uio release issue when hot unplug 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo ` (5 preceding siblings ...) 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 6/9] eal: add failure handle mechanism for hot plug Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 8/9] app/testpmd: show example to handle " Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 9/9] app/testpmd: enable device hotplug monitoring Jeff Guo 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang When hot unplug device, the kernel will release the device resource in the kernel side, such as the fd sys file will disappear, and the irq will be released. At this time, if igb uio driver still try to release this resource, it will cause kernel crash. On the other hand, something like interrupt disabling do not automatically process in kernel side. If not handler it, this redundancy and dirty thing will affect the interrupt resource be used by other device. So the igb_uio driver have to check the hot plug status, and the corresponding process should be taken in igb uio driver. This patch propose to add structure of rte_udev_state into rte_uio_pci_dev of igb_uio kernel driver, which will record the state of uio device, such as probed/opened/released/removed/unplug. When detect the unexpected removal which cause of hot unplug behavior, it will corresponding disable interrupt resource, while for the part of releasement which kernel have already handle, just skip it to avoid double free or null pointer kernel crash issue. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: no change --- kernel/linux/igb_uio/igb_uio.c | 50 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/kernel/linux/igb_uio/igb_uio.c b/kernel/linux/igb_uio/igb_uio.c index b3233f1..d301302 100644 --- a/kernel/linux/igb_uio/igb_uio.c +++ b/kernel/linux/igb_uio/igb_uio.c @@ -19,6 +19,15 @@ #include "compat.h" +/* uio pci device state */ +enum rte_udev_state { + RTE_UDEV_PROBED, + RTE_UDEV_OPENNED, + RTE_UDEV_RELEASED, + RTE_UDEV_REMOVED, + RTE_UDEV_UNPLUG +}; + /** * A structure describing the private information for a uio device. */ @@ -28,6 +37,7 @@ struct rte_uio_pci_dev { enum rte_intr_mode mode; struct mutex lock; int refcnt; + enum rte_udev_state state; }; static char *intr_mode; @@ -194,12 +204,20 @@ igbuio_pci_irqhandler(int irq, void *dev_id) { struct rte_uio_pci_dev *udev = (struct rte_uio_pci_dev *)dev_id; struct uio_info *info = &udev->info; + struct pci_dev *pdev = udev->pdev; /* Legacy mode need to mask in hardware */ if (udev->mode == RTE_INTR_MODE_LEGACY && !pci_check_and_mask_intx(udev->pdev)) return IRQ_NONE; + /* check the uevent of the kobj */ + if ((&pdev->dev.kobj)->state_remove_uevent_sent == 1) { + dev_notice(&pdev->dev, "device:%s, sent remove uevent!\n", + (&pdev->dev.kobj)->name); + udev->state = RTE_UDEV_UNPLUG; + } + uio_event_notify(info); /* Message signal mode, no share IRQ and automasked */ @@ -308,7 +326,6 @@ igbuio_pci_disable_interrupts(struct rte_uio_pci_dev *udev) #endif } - /** * This gets called while opening uio device file. */ @@ -330,24 +347,33 @@ igbuio_pci_open(struct uio_info *info, struct inode *inode) /* enable interrupts */ err = igbuio_pci_enable_interrupts(udev); - mutex_unlock(&udev->lock); if (err) { dev_err(&dev->dev, "Enable interrupt fails\n"); + pci_clear_master(dev); return err; } + udev->state = RTE_UDEV_OPENNED; + mutex_unlock(&udev->lock); return 0; } +/** + * This gets called while closing uio device file. + */ static int igbuio_pci_release(struct uio_info *info, struct inode *inode) { + struct rte_uio_pci_dev *udev = info->priv; struct pci_dev *dev = udev->pdev; + if (udev->state == RTE_UDEV_REMOVED) + return 0; + mutex_lock(&udev->lock); if (--udev->refcnt > 0) { mutex_unlock(&udev->lock); - return 0; + return -1; } /* disable interrupts */ @@ -355,7 +381,7 @@ igbuio_pci_release(struct uio_info *info, struct inode *inode) /* stop the device from further DMA */ pci_clear_master(dev); - + udev->state = RTE_UDEV_RELEASED; mutex_unlock(&udev->lock); return 0; } @@ -557,6 +583,7 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) (unsigned long long)map_dma_addr, map_addr); } + udev->state = RTE_UDEV_PROBED; return 0; fail_remove_group: @@ -573,11 +600,24 @@ igbuio_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) static void igbuio_pci_remove(struct pci_dev *dev) { + struct rte_uio_pci_dev *udev = pci_get_drvdata(dev); + int ret; + + /* handler hot unplug */ + if (udev->state == RTE_UDEV_OPENNED || + udev->state == RTE_UDEV_UNPLUG) { + dev_notice(&dev->dev, "Unexpected removal!\n"); + ret = igbuio_pci_release(&udev->info, NULL); + if (ret) + return; + udev->state = RTE_UDEV_REMOVED; + return; + } mutex_destroy(&udev->lock); - sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); uio_unregister_device(&udev->info); + sysfs_remove_group(&dev->dev.kobj, &dev_attr_grp); igbuio_pci_release_iomem(&udev->info); pci_disable_device(dev); pci_set_drvdata(dev, NULL); -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 8/9] app/testpmd: show example to handle hot unplug 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo ` (6 preceding siblings ...) 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 7/9] igb_uio: fix uio release issue when hot unplug Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 9/9] app/testpmd: enable device hotplug monitoring Jeff Guo 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang Use testpmd for example, to show how an application smoothly handle failure when device being hot unplug. If app have enabled the device event monitor and register the hot plug event’s callback before running, once app detect the removal event, the callback would be called. It will first stop the packet forwarding, then stop the port, close the port, and finally detach the port to remove the device out from the device lists. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: remove some unused code --- app/test-pmd/testpmd.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 24c1998..42ed196 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -2196,6 +2196,9 @@ static void eth_dev_event_callback(char *device_name, enum rte_dev_event_type type, __rte_unused void *arg) { + uint16_t port_id; + int ret; + if (type >= RTE_DEV_EVENT_MAX) { fprintf(stderr, "%s called upon invalid event %d\n", __func__, type); @@ -2206,9 +2209,12 @@ eth_dev_event_callback(char *device_name, enum rte_dev_event_type type, case RTE_DEV_EVENT_REMOVE: RTE_LOG(ERR, EAL, "The device: %s has been removed!\n", device_name); - /* TODO: After finish failure handle, begin to stop - * packet forward, stop port, close port, detach port. - */ + ret = rte_eth_dev_get_port_by_name(device_name, &port_id); + if (ret) { + printf("can not get port by device %s!\n", device_name); + return; + } + rmv_event_callback((void *)(intptr_t)port_id); break; case RTE_DEV_EVENT_ADD: RTE_LOG(ERR, EAL, "The device: %s has been added!\n", @@ -2736,7 +2742,6 @@ main(int argc, char** argv) return -1; } eth_dev_event_callback_register(); - } if (start_port(RTE_PORT_ALL) != 0) -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 9/9] app/testpmd: enable device hotplug monitoring 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo ` (7 preceding siblings ...) 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 8/9] app/testpmd: show example to handle " Jeff Guo @ 2018-06-29 10:24 ` Jeff Guo 8 siblings, 0 replies; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:24 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang As we know, there 2 different hotplug mechanisms in dpdk, the one is ethdev event + kernel driver hotplug solution, while the other one is eal device event + pci uio driver hotplug solution, each of them have different configure and callback process in testpmd. In oder to avoid the race between them, this patch aim to use a new parameter "--hotplug-mode" to replace the previous "--hot-plug" command parameter, to identify these different mode. There are 3 modes on hotplug mode: disable, eal, or ethdev(default). If user want to use eal device event monitor mode, could use below command when start testpmd. If not set this parameter, ethdev hotplug mode is default to be used. E.g. ./build/app/testpmd -c 0x3 --n 4 -- -i --hotplug-mode=eal Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: change to use new parameter "--hotplug-mode" in testpmd to identify the eal hotplug and ethdev hotplug --- app/test-pmd/parameters.c | 20 ++++++++++++++++---- app/test-pmd/testpmd.c | 18 +++++++++++------- app/test-pmd/testpmd.h | 8 +++++++- doc/guides/testpmd_app_ug/run_app.rst | 10 ++++++++-- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 7580762..601e13e 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -186,7 +186,8 @@ usage(char* progname) printf(" --flow-isolate-all: " "requests flow API isolated mode on all ports at initialization time.\n"); printf(" --tx-offloads=0xXXXXXXXX: hexadecimal bitmask of TX queue offloads\n"); - printf(" --hot-plug: enable hot plug for device.\n"); + printf(" --hotplug-mode=N: set hotplug mode for device " + "(N: disable (default) or eal or ethdev.\n"); printf(" --vxlan-gpe-port=N: UPD port of tunnel VXLAN-GPE\n"); printf(" --mlockall: lock all memory\n"); printf(" --no-mlockall: do not lock all memory\n"); @@ -621,7 +622,7 @@ launch_args_parse(int argc, char** argv) { "print-event", 1, 0, 0 }, { "mask-event", 1, 0, 0 }, { "tx-offloads", 1, 0, 0 }, - { "hot-plug", 0, 0, 0 }, + { "hotplug-mode", 1, 0, 0 }, { "vxlan-gpe-port", 1, 0, 0 }, { "mlockall", 0, 0, 0 }, { "no-mlockall", 0, 0, 0 }, @@ -1139,8 +1140,19 @@ launch_args_parse(int argc, char** argv) rte_exit(EXIT_FAILURE, "invalid mask-event argument\n"); } - if (!strcmp(lgopts[opt_idx].name, "hot-plug")) - hot_plug = 1; + if (!strcmp(lgopts[opt_idx].name, "hotplug-mode")) { + if (!strcmp(optarg, "disable")) + hotplug_mode = HOTPLUG_MODE_DISABLE; + else if (!strcmp(optarg, "eal")) + hotplug_mode = HOTPLUG_MODE_EAL; + else if (!strcmp(optarg, "ethdev")) + hotplug_mode = HOTPLUG_MODE_ETHDEV; + else + rte_exit(EXIT_FAILURE, + "hotplug-mode %s invalid - must be: " + "disable, eal, ethdev.\n", + optarg); + } if (!strcmp(lgopts[opt_idx].name, "mlockall")) do_mlockall = 1; if (!strcmp(lgopts[opt_idx].name, "no-mlockall")) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 42ed196..9269400 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -286,7 +286,7 @@ uint8_t lsc_interrupt = 1; /* enabled by default */ */ uint8_t rmv_interrupt = 1; /* enabled by default */ -uint8_t hot_plug = 0; /**< hotplug disabled by default. */ +uint8_t hotplug_mode = HOTPLUG_MODE_ETHDEV; /**< hotplug disabled by default. */ /* * Display or mask ether events @@ -2043,7 +2043,7 @@ pmd_test_exit(void) } } - if (hot_plug) { + if (hotplug_mode == HOTPLUG_MODE_EAL) { ret = rte_dev_event_monitor_stop(); if (ret) RTE_LOG(ERR, EAL, @@ -2181,9 +2181,13 @@ eth_event_callback(portid_t port_id, enum rte_eth_event_type type, void *param, switch (type) { case RTE_ETH_EVENT_INTR_RMV: - if (rte_eal_alarm_set(100000, - rmv_event_callback, (void *)(intptr_t)port_id)) - fprintf(stderr, "Could not set up deferred device removal\n"); + if (hotplug_mode == HOTPLUG_MODE_ETHDEV) { + if (rte_eal_alarm_set(100000, + rmv_event_callback, + (void *)(intptr_t)port_id)) + fprintf(stderr, "Could not set up deferred " + "device removal\n"); + } break; default: break; @@ -2734,8 +2738,8 @@ main(int argc, char** argv) init_config(); - if (hot_plug) { - /* enable hot plug monitoring */ + if (hotplug_mode == HOTPLUG_MODE_EAL) { + /* enable hotplug event monitoring */ ret = rte_dev_event_monitor_start(); if (ret) { rte_errno = EINVAL; diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index f51cd9d..e29ee2a 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -69,6 +69,12 @@ enum { PORT_TOPOLOGY_LOOP, }; +enum { + HOTPLUG_MODE_DISABLE, + HOTPLUG_MODE_EAL, + HOTPLUG_MODE_ETHDEV, +}; + #ifdef RTE_TEST_PMD_RECORD_BURST_STATS /** * The data structure associated with RX and TX packet burst statistics @@ -335,7 +341,7 @@ extern uint8_t lsc_interrupt; /**< disabled by "--no-lsc-interrupt" parameter */ extern uint8_t rmv_interrupt; /**< disabled by "--no-rmv-interrupt" parameter */ extern uint32_t event_print_mask; /**< set by "--print-event xxxx" and "--mask-event xxxx parameters */ -extern uint8_t hot_plug; /**< enable by "--hot-plug" parameter */ +extern uint8_t hotplug_mode; /**< set by "--hotplug-mode" parameter */ extern int do_mlockall; /**< set by "--mlockall" or "--no-mlockall" parameter */ #ifdef RTE_LIBRTE_IXGBE_BYPASS diff --git a/doc/guides/testpmd_app_ug/run_app.rst b/doc/guides/testpmd_app_ug/run_app.rst index f301c2b..09e2716 100644 --- a/doc/guides/testpmd_app_ug/run_app.rst +++ b/doc/guides/testpmd_app_ug/run_app.rst @@ -482,9 +482,15 @@ The commandline options are: Set the hexadecimal bitmask of TX queue offloads. The default value is 0. -* ``--hot-plug`` +* ``--hotplug-mode`` - Enable device event monitor machenism for hotplug. + Set the hotplug handle mode, that is ``disable`` or ``eal`` or ``ethdev`` (the default). + + In ``disable`` mode, it will not handle the hotplug for device. + + In ``eal`` mode, it will start device event monitor and register eth_dev_event_callback for hotplug process. + + In ``ethdev`` mode, it will process RTE_ETH_EVENT_INTR_RMV event which is detected from ethdev. * ``--vxlan-gpe-port=N`` -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH v3 0/2] add uevent api for hot plug @ 2017-06-29 4:37 Jeff Guo 2018-06-29 10:30 ` [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo 0 siblings, 1 reply; 16+ messages in thread From: Jeff Guo @ 2017-06-29 4:37 UTC (permalink / raw) To: helin.zhang, jingjing.wu; +Cc: dev, jia.guo From: "Guo, Jia" <jia.guo@intel.com> This patch set aim to add a variable "uevent_fd" in structure "rte_intr_handle" for enable kernel object uevent monitoring, and add some uevent API in rte eal interrupt, that is “rte_uevent_connect” and “rte_uevent_get”. The patch use i40e for example, the driver could use these API to monitor and read out the uevent, then corresponding to handle these uevent, such as detach or attach the device. Guo, Jia (2): eal: add uevent api for hot plug net/i40e: add hot plug monitor in i40e drivers/net/i40e/i40e_ethdev.c | 19 +++ lib/librte_eal/common/eal_common_pci_uio.c | 6 +- lib/librte_eal/linuxapp/eal/eal_interrupts.c | 136 ++++++++++++++++++++- lib/librte_eal/linuxapp/eal/eal_pci_uio.c | 6 + .../linuxapp/eal/include/exec-env/rte_interrupts.h | 37 ++++++ 5 files changed, 201 insertions(+), 3 deletions(-) -- 1.8.3.1 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism 2017-06-29 4:37 [dpdk-dev] [PATCH v3 0/2] add uevent api for hot plug Jeff Guo @ 2018-06-29 10:30 ` Jeff Guo 2018-06-29 10:30 ` [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus Jeff Guo 0 siblings, 1 reply; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:30 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang As we know, hot plug is an importance feature, either use for the datacenter device’s fail-safe, or use for SRIOV Live Migration in SDN/NFV. It could bring the higher flexibility and continuality to the networking services in multiple use cases in industry. So let we see, dpdk as an importance networking framework, what can it help to implement hot plug solution for users. We already have a general device event detect mechanism, failsafe driver, bonding driver and hot plug/unplug api in framework, app could use these to develop their hot plug solution. let’s see the case of hot unplug, it can happen when a hardware device is be removed physically, or when the software disables it. App need to call ether dev API to detach the device, to unplug the device at the bus level and make access to the device invalid. But the problem is that, the removal of the device from the software lists is not going to be instantaneous, at this time if the data(fast) path still read/write the device, it will cause MMIO error and result of the app crash out. Seems that we have got fail-safe driver(or app) + RTE_ETH_EVENT_INTR_RMV + kernel core driver solution to handle it, but still not have failsafe driver (or app) + RTE_DEV_EVENT_REMOVE + PCIe pmd driver failure handle solution. So there is an absence in dpdk hot plug solution right now. Also, we know that kernel only guaranty hot plug on the kernel side, but not for the user mode side. Firstly we can hardly have a gatekeeper for any MMIO for multiple PMD driver. Secondly, no more specific 3rd tools such as udev/driverctl have especially cover these hot plug failure processing. Third, the feasibility of app’s implement for multiple user mode PMD driver is still a problem. Here, a general hot plug failure handle mechanism in dpdk framework would be proposed, it aim to guaranty that, when hot unplug occur, the system will not crash and app will not be break out, and user space can normally stop and release any relevant resources, then unplug of the device at the bus level cleanly. The mechanism should be come across as bellow: Firstly, app enabled the device event monitor and register the hot plug event’s callback before running data path. Once the hot unplug behave occur, the mechanism will detect the removal event and then accordingly do the failure handle. In order to do that, below functional will be bring in. - Add a new bus ops “handle_hot_unplug” to handle bus read/write error, it is bus-specific and each kind of bus can implement its own logic. - Implement pci bus specific ops “pci_handle_hot_unplug”. It will base on the failure address to remap memory for the corresponding device that unplugged. For the data path or other unexpected control from the control path when hot unplug occur. - Implement a new sigbus handler, it is registered when start device even monitoring. The handler is per process. Base on the signal event principle, control path thread and data path thread will randomly receive the sigbus error, but will go to the common sigbus handler. Once the MMIO sigbus error exposure, it will trigger the above hot unplug operation. The sigbus will be check if it is cause of the hot unplug or not, if not will info exception as the original sigbus handler. If yes, will do memory remapping. For the control path and the igb uio release: - When hot unplug device, the kernel will release the device resource in the kernel side, such as the fd sys file will disappear, and the irq will be released. At this time, if igb uio driver still try to release this resource, it will cause kernel crash. On the other hand, something like interrupt disable do not automatically process in kernel side. If not handler it, this redundancy and dirty thing will affect the interrupt resource be used by other device. So the igb_uio driver have to check the hot plug status and corresponding process should be taken in igb uio deriver. This patch propose to add structure of rte_udev_state into rte_uio_pci_dev of igb_uio kernel driver, which will record the state of uio device, such as probed/opened/released/removed/unplug. When detect the unexpected removal which cause of hot unplug behavior, it will corresponding disable interrupt resource, while for the part of releasement which kernel have already handle, just skip it to avoid double free or null pointer kernel crash issue. The mechanism could be use for fail-safe driver and app which want to use hot plug solution. At this stage, will only use testpmd as reference to show how to use the mechanism. - Enable device event monitor->device unplug->failure handle->stop forwarding-> stop port->close port->detach port. This process will not breaking the app/fail-safe running, and will not break other irrelevance device. And app could plug in the device and restart the date path again by below. - Device plug in->bind igb_uio driver ->attached device->start port-> start forwarding. patchset history: v4->v3: split patches to be small and clear change to use new parameter "--hotplug-mode" in testpmd to identify the eal hotplug and ethdev hotplug v3->v2: change bus ops name to bus_hotplug_handler. add new API and bus ops of bus_signal_handler distingush handle generic sigbus and hotplug sigbus v2->v1(v21): refine some doc and commit log fix igb uio kernel issue for control path failure rebase testpmd code Since the hot plug solution be discussed serval around in the public, the scope be changed and the patch set be split into many times. Coming to the recently RFC and feature design, it just focus on the hot unplug failure handler at this patch set, so in order let this topic more clear and focus, summarize privours patch set in history “v1(v21)”, the v2 here go ahead for further track. "v1(21)" == v21 as below: v21->v20: split function in hot unplug ops sync failure hanlde to fix multiple process issue fix attach port issue for multiple devices case. combind rmv callback function to be only one. v20->v19: clean the code refine the remap logic for multiple device. remove the auto binding v19->18: note for limitation of multiple hotplug,fix some typo, sqeeze patch. v18->v15: add document, add signal bus handler, refine the code to be more clear. the prior patch history please check the patch set "add device event monitor framework" Jeff Guo (9): bus: introduce hotplug failure handler bus/pci: implement hotplug handler operation bus: introduce sigbus handler bus/pci: implement sigbus handler operation bus: add helper to handle sigbus eal: add failure handle mechanism for hot plug igb_uio: fix uio release issue when hot unplug app/testpmd: show example to handle hot unplug app/testpmd: enable device hotplug monitoring app/test-pmd/parameters.c | 20 ++++++-- app/test-pmd/testpmd.c | 31 +++++++----- app/test-pmd/testpmd.h | 8 ++- doc/guides/testpmd_app_ug/run_app.rst | 10 +++- drivers/bus/pci/pci_common.c | 78 +++++++++++++++++++++++++++++ drivers/bus/pci/pci_common_uio.c | 33 +++++++++++++ drivers/bus/pci/private.h | 12 +++++ kernel/linux/igb_uio/igb_uio.c | 50 +++++++++++++++++-- lib/librte_eal/common/eal_common_bus.c | 34 ++++++++++++- lib/librte_eal/common/eal_private.h | 11 +++++ lib/librte_eal/common/include/rte_bus.h | 31 ++++++++++++ lib/librte_eal/linuxapp/eal/eal_dev.c | 88 ++++++++++++++++++++++++++++++++- 12 files changed, 381 insertions(+), 25 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus 2018-06-29 10:30 ` [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo @ 2018-06-29 10:30 ` Jeff Guo 2018-06-29 10:51 ` Ananyev, Konstantin 0 siblings, 1 reply; 16+ messages in thread From: Jeff Guo @ 2018-06-29 10:30 UTC (permalink / raw) To: stephen, bruce.richardson, ferruh.yigit, konstantin.ananyev, gaetan.rivet, jingjing.wu, thomas, motih, matan, harry.van.haaren, qi.z.zhang, shaopeng.he, bernard.iremonger Cc: jblunck, shreyansh.jain, dev, jia.guo, helin.zhang This patch aim to add a helper to iterate all buses to find the corresponding bus to handle the sigbus error. Signed-off-by: Jeff Guo <jia.guo@intel.com> --- v4->v3: split patches to be small and clear. --- lib/librte_eal/common/eal_common_bus.c | 34 +++++++++++++++++++++++++++++++++- lib/librte_eal/common/eal_private.h | 11 +++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c index 0943851..34c4f2d 100644 --- a/lib/librte_eal/common/eal_common_bus.c +++ b/lib/librte_eal/common/eal_common_bus.c @@ -37,6 +37,7 @@ #include <rte_bus.h> #include <rte_debug.h> #include <rte_string_fns.h> +#include <rte_errno.h> #include "eal_private.h" @@ -220,7 +221,6 @@ rte_bus_find_by_device_name(const char *str) return rte_bus_find(NULL, bus_can_parse, name); } - /* * Get iommu class of devices on the bus. */ @@ -242,3 +242,35 @@ rte_bus_get_iommu_class(void) } return mode; } + +static int +bus_handle_sigbus(const struct rte_bus *bus, + const void *failure_addr) +{ + return !(bus->sigbus_handler && bus->sigbus_handler(failure_addr) <= 0); +} + +int +rte_bus_sigbus_handler(const void *failure_addr) +{ + struct rte_bus *bus; + int old_errno = rte_errno; + int ret = 0; + + rte_errno = 0; + + bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); + if (bus == NULL) { + RTE_LOG(ERR, EAL, "No bus can handle the sigbus error!"); + ret = -1; + } else if (rte_errno != 0) { + RTE_LOG(ERR, EAL, "Failed to handle the sigbus error!"); + ret = -1; + } + + /* if sigbus not be handled, return back old errno. */ + if (ret) + rte_errno = old_errno; + + return ret; +} diff --git a/lib/librte_eal/common/eal_private.h b/lib/librte_eal/common/eal_private.h index bdadc4d..9517f2b 100644 --- a/lib/librte_eal/common/eal_private.h +++ b/lib/librte_eal/common/eal_private.h @@ -258,4 +258,15 @@ int rte_mp_channel_init(void); */ void dev_callback_process(char *device_name, enum rte_dev_event_type event); + +/** + * Iterate all buses to find the corresponding bus, to handle the sigbus error. + * @param failure_addr + * Pointer of the fault address of the sigbus error. + * + * @return + * 0 on success. + * -1 on error + */ +int rte_bus_sigbus_handler(const void *failure_addr); #endif /* _EAL_PRIVATE_H_ */ -- 2.7.4 ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus 2018-06-29 10:30 ` [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus Jeff Guo @ 2018-06-29 10:51 ` Ananyev, Konstantin 2018-06-29 11:23 ` Guo, Jia 0 siblings, 1 reply; 16+ messages in thread From: Ananyev, Konstantin @ 2018-06-29 10:51 UTC (permalink / raw) To: Guo, Jia, stephen, Richardson, Bruce, Yigit, Ferruh, gaetan.rivet, Wu, Jingjing, thomas, motih, matan, Van Haaren, Harry, Zhang, Qi Z, He, Shaopeng, Iremonger, Bernard Cc: jblunck, shreyansh.jain, dev, Zhang, Helin > +int > +rte_bus_sigbus_handler(const void *failure_addr) > +{ > + struct rte_bus *bus; > + int old_errno = rte_errno; > + int ret = 0; > + > + rte_errno = 0; > + > + bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); > + if (bus == NULL) { > + RTE_LOG(ERR, EAL, "No bus can handle the sigbus error!"); > + ret = -1; > + } else if (rte_errno != 0) { > + RTE_LOG(ERR, EAL, "Failed to handle the sigbus error!"); > + ret = -1; > + } > + > + /* if sigbus not be handled, return back old errno. */ > + if (ret) > + rte_errno = old_errno; Hmm, not sure why we need to set/restore rte_errno here? > + > + return ret; > +} ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus 2018-06-29 10:51 ` Ananyev, Konstantin @ 2018-06-29 11:23 ` Guo, Jia 2018-06-29 12:21 ` Ananyev, Konstantin 0 siblings, 1 reply; 16+ messages in thread From: Guo, Jia @ 2018-06-29 11:23 UTC (permalink / raw) To: Ananyev, Konstantin, stephen, Richardson, Bruce, Yigit, Ferruh, gaetan.rivet, Wu, Jingjing, thomas, motih, matan, Van Haaren, Harry, Zhang, Qi Z, He, Shaopeng, Iremonger, Bernard Cc: jblunck, shreyansh.jain, dev, Zhang, Helin hi, konstantin On 6/29/2018 6:51 PM, Ananyev, Konstantin wrote: >> +int >> +rte_bus_sigbus_handler(const void *failure_addr) >> +{ >> + struct rte_bus *bus; >> + int old_errno = rte_errno; >> + int ret = 0; >> + >> + rte_errno = 0; >> + >> + bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); >> + if (bus == NULL) { >> + RTE_LOG(ERR, EAL, "No bus can handle the sigbus error!"); >> + ret = -1; >> + } else if (rte_errno != 0) { >> + RTE_LOG(ERR, EAL, "Failed to handle the sigbus error!"); >> + ret = -1; >> + } >> + >> + /* if sigbus not be handled, return back old errno. */ >> + if (ret) >> + rte_errno = old_errno; > Hmm, not sure why we need to set/restore rte_errno here? restore old_errno just use to let caller know that the generic sigbus still not handler by bus hotplug handler, that involve find a bus handle but failed and can not find a hander, and can corresponding use the previous sigbus handler to process it. that is also unwser your question in other patch. do you think that make sense? >> + >> + return ret; >> +} ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus 2018-06-29 11:23 ` Guo, Jia @ 2018-06-29 12:21 ` Ananyev, Konstantin 2018-06-29 12:52 ` Gaëtan Rivet 0 siblings, 1 reply; 16+ messages in thread From: Ananyev, Konstantin @ 2018-06-29 12:21 UTC (permalink / raw) To: Guo, Jia, stephen, Richardson, Bruce, Yigit, Ferruh, gaetan.rivet, Wu, Jingjing, thomas, motih, matan, Van Haaren, Harry, Zhang, Qi Z, He, Shaopeng, Iremonger, Bernard Cc: jblunck, shreyansh.jain, dev, Zhang, Helin > -----Original Message----- > From: Guo, Jia > Sent: Friday, June 29, 2018 12:23 PM > To: Ananyev, Konstantin <konstantin.ananyev@intel.com>; stephen@networkplumber.org; Richardson, Bruce > <bruce.richardson@intel.com>; Yigit, Ferruh <ferruh.yigit@intel.com>; gaetan.rivet@6wind.com; Wu, Jingjing > <jingjing.wu@intel.com>; thomas@monjalon.net; motih@mellanox.com; matan@mellanox.com; Van Haaren, Harry > <harry.van.haaren@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; He, Shaopeng <shaopeng.he@intel.com>; Iremonger, Bernard > <bernard.iremonger@intel.com> > Cc: jblunck@infradead.org; shreyansh.jain@nxp.com; dev@dpdk.org; Zhang, Helin <helin.zhang@intel.com> > Subject: Re: [PATCH V4 5/9] bus: add helper to handle sigbus > > hi, konstantin > > > On 6/29/2018 6:51 PM, Ananyev, Konstantin wrote: > >> +int > >> +rte_bus_sigbus_handler(const void *failure_addr) > >> +{ > >> + struct rte_bus *bus; > >> + int old_errno = rte_errno; > >> + int ret = 0; > >> + > >> + rte_errno = 0; > >> + > >> + bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); > >> + if (bus == NULL) { > >> + RTE_LOG(ERR, EAL, "No bus can handle the sigbus error!"); > >> + ret = -1; > >> + } else if (rte_errno != 0) { > >> + RTE_LOG(ERR, EAL, "Failed to handle the sigbus error!"); > >> + ret = -1; > >> + } > >> + > >> + /* if sigbus not be handled, return back old errno. */ > >> + if (ret) > >> + rte_errno = old_errno; > > Hmm, not sure why we need to set/restore rte_errno here? > > restore old_errno just use to let caller know that the generic sigbus > still not handler by bus hotplug handler, that involve find a bus > handle but failed and can not find a hander, and can corresponding use > the previous sigbus handler to process it. > that is also unwser your question in other patch. do you think that make > sense? Sorry, still don't understand the intention. Suppose rte_bus_find() will return NULL, in that case you'll setup rte_errno to what it was before calling that function. If the returned bus is not NULL, but bus_find() set's an rte_errno, you still would restore rte_ernno? What is the prupose? Why do you need to touch rte_errno at all in that function? Konstantin > > >> + > >> + return ret; > >> +} ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus 2018-06-29 12:21 ` Ananyev, Konstantin @ 2018-06-29 12:52 ` Gaëtan Rivet 2018-07-03 11:24 ` Guo, Jia 0 siblings, 1 reply; 16+ messages in thread From: Gaëtan Rivet @ 2018-06-29 12:52 UTC (permalink / raw) To: Ananyev, Konstantin Cc: Guo, Jia, stephen, Richardson, Bruce, Yigit, Ferruh, Wu, Jingjing, thomas, motih, matan, Van Haaren, Harry, Zhang, Qi Z, He, Shaopeng, Iremonger, Bernard, jblunck, shreyansh.jain, dev, Zhang, Helin On Fri, Jun 29, 2018 at 12:21:39PM +0000, Ananyev, Konstantin wrote: > > > > -----Original Message----- > > From: Guo, Jia > > Sent: Friday, June 29, 2018 12:23 PM > > To: Ananyev, Konstantin <konstantin.ananyev@intel.com>; stephen@networkplumber.org; Richardson, Bruce > > <bruce.richardson@intel.com>; Yigit, Ferruh <ferruh.yigit@intel.com>; gaetan.rivet@6wind.com; Wu, Jingjing > > <jingjing.wu@intel.com>; thomas@monjalon.net; motih@mellanox.com; matan@mellanox.com; Van Haaren, Harry > > <harry.van.haaren@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; He, Shaopeng <shaopeng.he@intel.com>; Iremonger, Bernard > > <bernard.iremonger@intel.com> > > Cc: jblunck@infradead.org; shreyansh.jain@nxp.com; dev@dpdk.org; Zhang, Helin <helin.zhang@intel.com> > > Subject: Re: [PATCH V4 5/9] bus: add helper to handle sigbus > > > > hi, konstantin > > > > > > On 6/29/2018 6:51 PM, Ananyev, Konstantin wrote: > > >> +int > > >> +rte_bus_sigbus_handler(const void *failure_addr) > > >> +{ > > >> + struct rte_bus *bus; > > >> + int old_errno = rte_errno; > > >> + int ret = 0; > > >> + > > >> + rte_errno = 0; > > >> + > > >> + bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); > > >> + if (bus == NULL) { > > >> + RTE_LOG(ERR, EAL, "No bus can handle the sigbus error!"); > > >> + ret = -1; > > >> + } else if (rte_errno != 0) { > > >> + RTE_LOG(ERR, EAL, "Failed to handle the sigbus error!"); > > >> + ret = -1; > > >> + } > > >> + > > >> + /* if sigbus not be handled, return back old errno. */ > > >> + if (ret) > > >> + rte_errno = old_errno; > > > Hmm, not sure why we need to set/restore rte_errno here? > > > > restore old_errno just use to let caller know that the generic sigbus > > still not handler by bus hotplug handler, that involve find a bus > > handle but failed and can not find a hander, and can corresponding use > > the previous sigbus handler to process it. > > that is also unwser your question in other patch. do you think that make > > sense? > > Sorry, still don't understand the intention. > Suppose rte_bus_find() will return NULL, in that case you'll setup rte_errno > to what it was before calling that function. > If the returned bus is not NULL, but bus_find() set's an rte_errno, > you still would restore rte_ernno? > What is the prupose? > Why do you need to touch rte_errno at all in that function? > Konstantin > The way it is written here does not work, but the intention is to make sure that a previous error is still catched. Something like that: int old_errno = rte_errno; rte_errno = 0; rte_eal_call(); if (rte_errno) return -1; else { rte_errno = old_errno; return 0; } If someone calls the function while rte_errno is already set, then an earlier error would be hidden by setting rte_errno to 0 within the function. I'm not sure this is useful, but sometimes when using errno within a library call I'm bothered that I am masking previous issues. Should it be avoided? -- Gaëtan Rivet 6WIND ^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus 2018-06-29 12:52 ` Gaëtan Rivet @ 2018-07-03 11:24 ` Guo, Jia 0 siblings, 0 replies; 16+ messages in thread From: Guo, Jia @ 2018-07-03 11:24 UTC (permalink / raw) To: Gaëtan Rivet, Ananyev, Konstantin Cc: stephen, Richardson, Bruce, Yigit, Ferruh, Wu, Jingjing, thomas, motih, matan, Van Haaren, Harry, Zhang, Qi Z, He, Shaopeng, Iremonger, Bernard, jblunck, shreyansh.jain, dev, Zhang, Helin hi, gaetan and konstantin answer both of your questions here as below. On 6/29/2018 8:52 PM, Gaëtan Rivet wrote: > On Fri, Jun 29, 2018 at 12:21:39PM +0000, Ananyev, Konstantin wrote: >> >>> -----Original Message----- >>> From: Guo, Jia >>> Sent: Friday, June 29, 2018 12:23 PM >>> To: Ananyev, Konstantin <konstantin.ananyev@intel.com>; stephen@networkplumber.org; Richardson, Bruce >>> <bruce.richardson@intel.com>; Yigit, Ferruh <ferruh.yigit@intel.com>; gaetan.rivet@6wind.com; Wu, Jingjing >>> <jingjing.wu@intel.com>; thomas@monjalon.net; motih@mellanox.com; matan@mellanox.com; Van Haaren, Harry >>> <harry.van.haaren@intel.com>; Zhang, Qi Z <qi.z.zhang@intel.com>; He, Shaopeng <shaopeng.he@intel.com>; Iremonger, Bernard >>> <bernard.iremonger@intel.com> >>> Cc: jblunck@infradead.org; shreyansh.jain@nxp.com; dev@dpdk.org; Zhang, Helin <helin.zhang@intel.com> >>> Subject: Re: [PATCH V4 5/9] bus: add helper to handle sigbus >>> >>> hi, konstantin >>> >>> >>> On 6/29/2018 6:51 PM, Ananyev, Konstantin wrote: >>>>> +int >>>>> +rte_bus_sigbus_handler(const void *failure_addr) >>>>> +{ >>>>> + struct rte_bus *bus; >>>>> + int old_errno = rte_errno; >>>>> + int ret = 0; >>>>> + >>>>> + rte_errno = 0; >>>>> + >>>>> + bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); >>>>> + if (bus == NULL) { >>>>> + RTE_LOG(ERR, EAL, "No bus can handle the sigbus error!"); >>>>> + ret = -1; >>>>> + } else if (rte_errno != 0) { >>>>> + RTE_LOG(ERR, EAL, "Failed to handle the sigbus error!"); >>>>> + ret = -1; >>>>> + } >>>>> + >>>>> + /* if sigbus not be handled, return back old errno. */ >>>>> + if (ret) >>>>> + rte_errno = old_errno; >>>> Hmm, not sure why we need to set/restore rte_errno here? >>> restore old_errno just use to let caller know that the generic sigbus >>> still not handler by bus hotplug handler, that involve find a bus >>> handle but failed and can not find a hander, and can corresponding use >>> the previous sigbus handler to process it. >>> that is also unwser your question in other patch. do you think that make >>> sense? >> Sorry, still don't understand the intention. >> Suppose rte_bus_find() will return NULL, in that case you'll setup rte_errno >> to what it was before calling that function. >> If the returned bus is not NULL, but bus_find() set's an rte_errno, >> you still would restore rte_ernno? >> What is the prupose? >> Why do you need to touch rte_errno at all in that function? >> Konstantin >> > The way it is written here does not work, but the intention is > to make sure that a previous error is still catched. Something like > that: > > int old_errno = rte_errno; > > rte_errno = 0; > rte_eal_call(); > > if (rte_errno) > return -1; > else { > rte_errno = old_errno; > return 0; > } > > If someone calls the function while rte_errno is already set, then an > earlier error would be hidden by setting rte_errno to 0 within the > function. > > I'm not sure this is useful, but sometimes when using errno within a > library call I'm bothered that I am masking previous issues. > > Should it be avoided? i agree with konstantin about distinguish to process the handle failed or no handle, and agree with gaetan about restore the errno if it is not belong to the sigbus handler. Could you check if it is fulfill that as bellow, -1 means find bus but handle failed, use rte_exit. 1 means can no find bus, use older handler to handle. 0 means find bus and success handle. the handler is the new handler. static int bus_handle_sigbus(const struct rte_bus *bus, const void *failure_addr) { int ret; ret = bus->sigbus_handler(failure_addr); rte_errno = ret; return !(bus->sigbus_handler && ret <= 0); } int rte_bus_sigbus_handler(const void *failure_addr) { struct rte_bus *bus; int ret = 0; int old_errno = rte_errno; rte_errno = 0; bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr); /* failed to handle the sigbus, pass the new errno. */ if (bus && rte_errno == -1) return -1; else if (!bus) ret =1; /* otherwise restore the old errno. */ rte_errno = old_errno; return ret; } static void sigbus_handler(int signum, siginfo_t *info, void *ctx __rte_unused) { int ret; rte_spinlock_lock(&dev_failure_lock); ret = rte_bus_sigbus_handler(info->si_addr); rte_spinlock_unlock(&dev_failure_lock); if (ret == -1) { rte_exit(EXIT_FAILURE, "Failed to handle SIGBUS for hotplug, " "(rte_errno: %s)!", strerror(rte_errno)); } else if (ret == 1) { if (sigbus_action_old.sa_handler) (*(sigbus_action_old.sa_handler))(signum); else rte_exit(EXIT_FAILURE, "Failed to handle generic SIGBUS!"); } } ^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2018-07-03 11:24 UTC | newest] Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-06-29 10:24 [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 1/9] bus: introduce hotplug failure handler Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 2/9] bus/pci: implement hotplug handler operation Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 3/9] bus: introduce sigbus handler Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 4/9] bus/pci: implement sigbus handler operation Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 6/9] eal: add failure handle mechanism for hot plug Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 7/9] igb_uio: fix uio release issue when hot unplug Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 8/9] app/testpmd: show example to handle " Jeff Guo 2018-06-29 10:24 ` [dpdk-dev] [PATCH V4 9/9] app/testpmd: enable device hotplug monitoring Jeff Guo -- strict thread matches above, loose matches on Subject: below -- 2017-06-29 4:37 [dpdk-dev] [PATCH v3 0/2] add uevent api for hot plug Jeff Guo 2018-06-29 10:30 ` [dpdk-dev] [PATCH V4 0/9] hot plug failure handle mechanism Jeff Guo 2018-06-29 10:30 ` [dpdk-dev] [PATCH V4 5/9] bus: add helper to handle sigbus Jeff Guo 2018-06-29 10:51 ` Ananyev, Konstantin 2018-06-29 11:23 ` Guo, Jia 2018-06-29 12:21 ` Ananyev, Konstantin 2018-06-29 12:52 ` Gaëtan Rivet 2018-07-03 11:24 ` Guo, Jia
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).