[RFC v4 4/5] interrupts: close interrupt FDs
From: David Marchand <hidden>
Date: 2026-09-08 07:39:10
Subsystem:
library code, networking drivers, the rest · Maintainers:
Andrew Morton, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Add rte_intr_fd_close() and rte_intr_dev_fd_close() helpers to
encapsulate the common pattern of closing an interrupt handle's
file descriptor and resetting it to -1.
This simplifies code in multiple drivers that previously had to:
if (rte_intr_fd_get(handle) >= 0) {
close(rte_intr_fd_get(handle));
rte_intr_fd_set(handle, -1);
}
Signed-off-by: David Marchand <redacted>
---
Changes since RFC v2:
- added unit test,
- converted bus/cdx and FreeBSD EAL interrupt code,
- added wrappers for common/cnxk,
---
app/test/test_interrupts.c | 72 ++++++++++++++++++++++++++
doc/guides/rel_notes/release_26_11.rst | 2 +
drivers/bus/cdx/cdx_vfio.c | 6 +--
drivers/bus/pci/bsd/pci.c | 7 +--
drivers/bus/pci/linux/pci_uio.c | 15 ++----
drivers/bus/pci/linux/pci_vfio.c | 16 ++----
drivers/bus/pci/pci_common_uio.c | 12 +----
drivers/bus/vmbus/linux/vmbus_uio.c | 13 ++---
drivers/bus/vmbus/vmbus_common_uio.c | 11 +---
drivers/common/cnxk/roc_platform.h | 2 +
drivers/net/memif/memif_socket.c | 13 ++---
lib/eal/common/eal_common_interrupts.c | 23 ++++++++
lib/eal/freebsd/eal_alarm.c | 3 +-
lib/eal/include/rte_interrupts.h | 27 ++++++++++
lib/eal/linux/eal_dev.c | 5 +-
15 files changed, 147 insertions(+), 80 deletions(-)
diff --git a/app/test/test_interrupts.c b/app/test/test_interrupts.c
index 747dfc4f48..67f1e6429a 100644
--- a/app/test/test_interrupts.c
+++ b/app/test/test_interrupts.c@@ -169,6 +169,65 @@ test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l, return 0; } +/** + * Tests for rte_intr_fd_close() and rte_intr_dev_fd_close(). + */ +static int +test_interrupt_close(void) +{ + struct rte_intr_handle *intr_handle; + int pipefd[2]; + + /* check with null intr_handle */ + rte_intr_fd_close(NULL); + rte_intr_dev_fd_close(NULL); + + intr_handle = rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE); + if (!intr_handle) + return -1; + + if (pipe(pipefd) < 0) { + rte_intr_instance_free(intr_handle); + return -1; + } + + if (rte_intr_fd_set(intr_handle, pipefd[0]) < 0 || + rte_intr_dev_fd_set(intr_handle, pipefd[1]) < 0) { + close(pipefd[0]); + close(pipefd[1]); + rte_intr_instance_free(intr_handle); + return -1; + } + + /* check rte_intr_fd_close */ + rte_intr_fd_close(intr_handle); + + if (rte_intr_fd_get(intr_handle) != -1) { + printf("fd not set to -1 after close\n"); + close(pipefd[1]); + rte_intr_instance_free(intr_handle); + return -1; + } + + /* calling again should be a noop */ + rte_intr_fd_close(intr_handle); + + /* check rte_intr_dev_fd_close */ + rte_intr_dev_fd_close(intr_handle); + + if (rte_intr_dev_fd_get(intr_handle) != -1) { + printf("dev_fd not set to -1 after close\n"); + rte_intr_instance_free(intr_handle); + return -1; + } + + /* calling again should be a noop */ + rte_intr_dev_fd_close(intr_handle); + + rte_intr_instance_free(intr_handle); + return 0; +} + #else /* to be implemented for bsd later */ static inline int
@@ -206,6 +265,12 @@ test_interrupt_handle_compare(struct rte_intr_handle *intr_handle_l, return 0; } + +static int +test_interrupt_close(void) +{ + return 0; +} #endif /* RTE_EXEC_ENV_LINUX */ /**
@@ -566,6 +631,13 @@ test_interrupt(void) } rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); + printf("start interrupt close test\n"); + if (test_interrupt_close() < 0) { + printf("fail to check interrupt close\n"); + goto out; + } + rte_delay_ms(TEST_INTERRUPT_CHECK_INTERVAL); + ret = 0; out:
diff --git a/doc/guides/rel_notes/release_26_11.rst b/doc/guides/rel_notes/release_26_11.rst
index 36d6f3a05f..07b90f1529 100644
--- a/doc/guides/rel_notes/release_26_11.rst
+++ b/doc/guides/rel_notes/release_26_11.rst@@ -99,6 +99,8 @@ API Changes * ``rte_intr_instance_alloc()`` now initializes file descriptors to invalid values instead of zero. + * Added ``rte_intr_fd_close()`` and ``rte_intr_dev_fd_close()`` + helpers to close file descriptors and reset them to -1. ABI Changes
diff --git a/drivers/bus/cdx/cdx_vfio.c b/drivers/bus/cdx/cdx_vfio.c
index 0e4af4e940..8d67058bfe 100644
--- a/drivers/bus/cdx/cdx_vfio.c
+++ b/drivers/bus/cdx/cdx_vfio.c@@ -110,11 +110,7 @@ cdx_vfio_unmap_resource_primary(struct rte_cdx_device *dev) CDX_BUS_ERR("Error when disabling bus master for %s", dev->device.name); - if (close(rte_intr_fd_get(dev->intr_handle)) < 0) { - CDX_BUS_ERR("Error when closing eventfd file descriptor for %s", - dev->device.name); - return -1; - } + rte_intr_fd_close(dev->intr_handle); } vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
diff --git a/drivers/bus/pci/bsd/pci.c b/drivers/bus/pci/bsd/pci.c
index bbe08605af..f1012bb91b 100644
--- a/drivers/bus/pci/bsd/pci.c
+++ b/drivers/bus/pci/bsd/pci.c@@ -93,11 +93,8 @@ pci_uio_free_resource(struct rte_pci_device *dev, { rte_free(uio_res); - if (rte_intr_fd_get(dev->intr_handle) >= 0) { - close(rte_intr_fd_get(dev->intr_handle)); - rte_intr_fd_set(dev->intr_handle, -1); - rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); - } + rte_intr_fd_close(dev->intr_handle); + rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); } int
diff --git a/drivers/bus/pci/linux/pci_uio.c b/drivers/bus/pci/linux/pci_uio.c
index 40e96b1c67..0983474994 100644
--- a/drivers/bus/pci/linux/pci_uio.c
+++ b/drivers/bus/pci/linux/pci_uio.c@@ -197,20 +197,11 @@ void pci_uio_free_resource(struct rte_pci_device *dev, struct mapped_pci_resource *uio_res) { - int uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle); - rte_free(uio_res); - if (uio_cfg_fd >= 0) { - close(uio_cfg_fd); - rte_intr_dev_fd_set(dev->intr_handle, -1); - } - - if (rte_intr_fd_get(dev->intr_handle) >= 0) { - close(rte_intr_fd_get(dev->intr_handle)); - rte_intr_fd_set(dev->intr_handle, -1); - rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); - } + rte_intr_dev_fd_close(dev->intr_handle); + rte_intr_fd_close(dev->intr_handle); + rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); } int
diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
index a92a0d86ec..84c338c68e 100644
--- a/drivers/bus/pci/linux/pci_vfio.c
+++ b/drivers/bus/pci/linux/pci_vfio.c@@ -354,9 +354,7 @@ pci_vfio_enable_notifier(struct rte_pci_device *dev, int vfio_dev_fd) return 0; error: - close(fd); - - rte_intr_fd_set(dev->vfio_req_intr_handle, -1); + rte_intr_fd_close(dev->vfio_req_intr_handle); rte_intr_type_set(dev->vfio_req_intr_handle, RTE_INTR_HANDLE_UNKNOWN); rte_intr_dev_fd_set(dev->vfio_req_intr_handle, -1);
@@ -383,9 +381,7 @@ pci_vfio_disable_notifier(struct rte_pci_device *dev) return -1; } - close(rte_intr_fd_get(dev->vfio_req_intr_handle)); - - rte_intr_fd_set(dev->vfio_req_intr_handle, -1); + rte_intr_fd_close(dev->vfio_req_intr_handle); rte_intr_type_set(dev->vfio_req_intr_handle, RTE_INTR_HANDLE_UNKNOWN); rte_intr_dev_fd_set(dev->vfio_req_intr_handle, -1);
@@ -1073,13 +1069,7 @@ pci_vfio_unmap_resource_primary(struct rte_pci_device *dev) return -1; } - if (rte_intr_fd_get(dev->intr_handle) < 0) - return -1; - - if (close(rte_intr_fd_get(dev->intr_handle)) < 0) { - PCI_LOG(INFO, "Error when closing eventfd file descriptor for %s", pci_addr); - return -1; - } + rte_intr_fd_close(dev->intr_handle); vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle); if (vfio_dev_fd < 0)
diff --git a/drivers/bus/pci/pci_common_uio.c b/drivers/bus/pci/pci_common_uio.c
index 47d50721dc..52a10f806a 100644
--- a/drivers/bus/pci/pci_common_uio.c
+++ b/drivers/bus/pci/pci_common_uio.c@@ -211,7 +211,6 @@ pci_uio_unmap_resource(struct rte_pci_device *dev) struct mapped_pci_resource *uio_res; struct mapped_pci_res_list *uio_res_list = RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); - int uio_cfg_fd; if (dev == NULL) return;
@@ -222,15 +221,8 @@ pci_uio_unmap_resource(struct rte_pci_device *dev) return; /* close fd */ - if (rte_intr_fd_get(dev->intr_handle) >= 0) - close(rte_intr_fd_get(dev->intr_handle)); - uio_cfg_fd = rte_intr_dev_fd_get(dev->intr_handle); - if (uio_cfg_fd >= 0) { - close(uio_cfg_fd); - rte_intr_dev_fd_set(dev->intr_handle, -1); - } - - rte_intr_fd_set(dev->intr_handle, -1); + rte_intr_fd_close(dev->intr_handle); + rte_intr_dev_fd_close(dev->intr_handle); rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); /* secondary processes - just free maps */
diff --git a/drivers/bus/vmbus/linux/vmbus_uio.c b/drivers/bus/vmbus/linux/vmbus_uio.c
index fbafc5027d..c52d6738a5 100644
--- a/drivers/bus/vmbus/linux/vmbus_uio.c
+++ b/drivers/bus/vmbus/linux/vmbus_uio.c@@ -67,16 +67,9 @@ vmbus_uio_free_resource(struct rte_vmbus_device *dev, { rte_free(uio_res); - if (rte_intr_dev_fd_get(dev->intr_handle) >= 0) { - close(rte_intr_dev_fd_get(dev->intr_handle)); - rte_intr_dev_fd_set(dev->intr_handle, -1); - } - - if (rte_intr_fd_get(dev->intr_handle) >= 0) { - close(rte_intr_fd_get(dev->intr_handle)); - rte_intr_fd_set(dev->intr_handle, -1); - rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); - } + rte_intr_dev_fd_close(dev->intr_handle); + rte_intr_fd_close(dev->intr_handle); + rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); } int
diff --git a/drivers/bus/vmbus/vmbus_common_uio.c b/drivers/bus/vmbus/vmbus_common_uio.c
index 7459f4ea7a..9765f5f609 100644
--- a/drivers/bus/vmbus/vmbus_common_uio.c
+++ b/drivers/bus/vmbus/vmbus_common_uio.c@@ -254,14 +254,7 @@ vmbus_uio_unmap_resource(struct rte_vmbus_device *dev) rte_free(uio_res); /* close fd */ - if (rte_intr_fd_get(dev->intr_handle) >= 0) - close(rte_intr_fd_get(dev->intr_handle)); - - if (rte_intr_dev_fd_get(dev->intr_handle) >= 0) { - close(rte_intr_dev_fd_get(dev->intr_handle)); - rte_intr_dev_fd_set(dev->intr_handle, -1); - } - - rte_intr_fd_set(dev->intr_handle, -1); + rte_intr_fd_close(dev->intr_handle); + rte_intr_dev_fd_close(dev->intr_handle); rte_intr_type_set(dev->intr_handle, RTE_INTR_HANDLE_UNKNOWN); }
diff --git a/drivers/common/cnxk/roc_platform.h b/drivers/common/cnxk/roc_platform.h
index ac4f76473f..aba9782023 100644
--- a/drivers/common/cnxk/roc_platform.h
+++ b/drivers/common/cnxk/roc_platform.h@@ -171,8 +171,10 @@ plt_thread_is_valid(plt_thread_t thr) #define plt_intr_vec_list_free rte_intr_vec_list_free #define plt_intr_fd_set rte_intr_fd_set #define plt_intr_fd_get rte_intr_fd_get +#define plt_intr_fd_close rte_intr_fd_close #define plt_intr_dev_fd_get rte_intr_dev_fd_get #define plt_intr_dev_fd_set rte_intr_dev_fd_set +#define plt_intr_dev_fd_close rte_intr_dev_fd_close #define plt_intr_type_get rte_intr_type_get #define plt_intr_type_set rte_intr_type_set #define plt_intr_instance_alloc rte_intr_instance_alloc
diff --git a/drivers/net/memif/memif_socket.c b/drivers/net/memif/memif_socket.c
index 649f8d0e61..94cd70fb89 100644
--- a/drivers/net/memif/memif_socket.c
+++ b/drivers/net/memif/memif_socket.c@@ -510,8 +510,7 @@ memif_intr_unregister_handler(struct rte_intr_handle *intr_handle, void *arg) struct memif_control_channel *cc = arg; /* close control channel fd */ - if (rte_intr_fd_get(intr_handle) >= 0) - close(rte_intr_fd_get(intr_handle)); + rte_intr_fd_close(intr_handle); /* clear message queue */ while ((elt = TAILQ_FIRST(&cc->msg_queue)) != NULL) { TAILQ_REMOVE(&cc->msg_queue, elt, next);
@@ -596,10 +595,7 @@ memif_disconnect(struct rte_eth_dev *dev) continue; } - if (rte_intr_fd_get(mq->intr_handle) > 0) { - close(rte_intr_fd_get(mq->intr_handle)); - rte_intr_fd_set(mq->intr_handle, -1); - } + rte_intr_fd_close(mq->intr_handle); } for (i = 0; i < pmd->cfg.num_s2c_rings; i++) { if (pmd->role == MEMIF_ROLE_SERVER) {
@@ -614,10 +610,7 @@ memif_disconnect(struct rte_eth_dev *dev) continue; } - if (rte_intr_fd_get(mq->intr_handle) > 0) { - close(rte_intr_fd_get(mq->intr_handle)); - rte_intr_fd_set(mq->intr_handle, -1); - } + rte_intr_fd_close(mq->intr_handle); } memif_free_regions(dev);
diff --git a/lib/eal/common/eal_common_interrupts.c b/lib/eal/common/eal_common_interrupts.c
index 4e31a71319..8176eb089a 100644
--- a/lib/eal/common/eal_common_interrupts.c
+++ b/lib/eal/common/eal_common_interrupts.c@@ -4,6 +4,7 @@ #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <rte_errno.h> #include <rte_interrupts.h>
@@ -219,6 +220,17 @@ int rte_intr_fd_get(const struct rte_intr_handle *intr_handle) return -1; } +RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_intr_fd_close, 26.11) +void rte_intr_fd_close(struct rte_intr_handle *intr_handle) +{ + int fd = rte_intr_fd_get(intr_handle); + + if (fd >= 0) { + close(fd); + rte_intr_fd_set(intr_handle, -1); + } +} + RTE_EXPORT_SYMBOL(rte_intr_type_set) int rte_intr_type_set(struct rte_intr_handle *intr_handle, enum rte_intr_handle_type type)
@@ -265,6 +277,17 @@ int rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle) return -1; } +RTE_EXPORT_INTERNAL_SYMBOL(rte_intr_dev_fd_close) +void rte_intr_dev_fd_close(struct rte_intr_handle *intr_handle) +{ + int fd = rte_intr_dev_fd_get(intr_handle); + + if (fd >= 0) { + close(fd); + rte_intr_dev_fd_set(intr_handle, -1); + } +} + RTE_EXPORT_INTERNAL_SYMBOL(rte_intr_max_intr_set) int rte_intr_max_intr_set(struct rte_intr_handle *intr_handle, int max_intr)
diff --git a/lib/eal/freebsd/eal_alarm.c b/lib/eal/freebsd/eal_alarm.c
index 65d0af9aaa..ee4a961f9f 100644
--- a/lib/eal/freebsd/eal_alarm.c
+++ b/lib/eal/freebsd/eal_alarm.c@@ -55,8 +55,7 @@ rte_eal_alarm_cleanup(void) int ret = rte_intr_callback_unregister_sync(intr_handle, eal_alarm_callback, (void *)-1); if (ret >= 0) { - close(rte_intr_fd_get(intr_handle)); - rte_intr_fd_set(intr_handle, -1); + rte_intr_fd_close(intr_handle); rte_intr_instance_free(intr_handle); intr_handle = NULL; }
diff --git a/lib/eal/include/rte_interrupts.h b/lib/eal/include/rte_interrupts.h
index 1cfb9d3f8e..d04c0c7b15 100644
--- a/lib/eal/include/rte_interrupts.h
+++ b/lib/eal/include/rte_interrupts.h@@ -279,6 +279,19 @@ rte_intr_fd_set(struct rte_intr_handle *intr_handle, int fd); int rte_intr_fd_get(const struct rte_intr_handle *intr_handle); +/** + * Close the FD of the given interrupt handle instance, + * and set FD to -1. + * + * If FD is not valid (< 0), nothing is done. + * + * @param intr_handle + * pointer to the interrupt handle. + */ +__rte_experimental +void +rte_intr_fd_close(struct rte_intr_handle *intr_handle); + /** * Set the type field of interrupt handle with user provided * interrupt type.
@@ -467,6 +480,20 @@ __rte_internal int rte_intr_dev_fd_get(const struct rte_intr_handle *intr_handle); +/** + * @internal + * Close the device FD of the given interrupt handle instance, + * and set device FD to -1. + * + * If device FD is not valid (< 0), nothing is done. + * + * @param intr_handle + * pointer to the interrupt handle. + */ +__rte_internal +void +rte_intr_dev_fd_close(struct rte_intr_handle *intr_handle); + /** * @internal * Set the max intr field of interrupt handle with user
diff --git a/lib/eal/linux/eal_dev.c b/lib/eal/linux/eal_dev.c
index c78e565427..4f55dcc4e7 100644
--- a/lib/eal/linux/eal_dev.c
+++ b/lib/eal/linux/eal_dev.c@@ -217,10 +217,7 @@ static void dev_delayed_unregister(void *param) { rte_intr_callback_unregister(intr_handle, dev_uev_handler, param); - if (rte_intr_fd_get(intr_handle) >= 0) { - close(rte_intr_fd_get(intr_handle)); - rte_intr_fd_set(intr_handle, -1); - } + rte_intr_fd_close(intr_handle); } static void
--
2.54.0