git: 0d022baa047a - main - LinuxKPI: Run irq_work callbacks under RCU protection
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 11 Sep 2026 15:50:55 UTC
The branch main has been updated by wulf:
URL: https://cgit.FreeBSD.org/src/commit/?id=0d022baa047aea6499e394d2cd8d097820ecf486
commit 0d022baa047aea6499e394d2cd8d097820ecf486
Author: JustAnotherHumanBeing <oleglelchuk@gmail.com>
AuthorDate: 2026-09-11 15:49:23 +0000
Commit: Vladimir Kondratyev <wulf@FreeBSD.org>
CommitDate: 2026-09-11 15:49:23 +0000
LinuxKPI: Run irq_work callbacks under RCU protection
Linux executes irq_work callbacks from an interrupt context that
provides implicit RCU read-side protection. LinuxKPI dispatches these
callbacks through a taskqueue, so provide equivalent protection
explicitly.
This prevents an RCU grace period from completing while an irq_work
callback is still using an RCU-protected object.
Suggested by: wulf
Tested by: JustAnotherHumanBeing
Signed-off-by: JustAnotherHumanBeing <oleglelchuk@gmail.com>
Pull Request: https://github.com/freebsd/freebsd-src/pull/2385
---
sys/compat/linuxkpi/common/include/linux/irq_work.h | 2 ++
sys/compat/linuxkpi/common/src/linux_work.c | 3 +++
2 files changed, 5 insertions(+)
diff --git a/sys/compat/linuxkpi/common/include/linux/irq_work.h b/sys/compat/linuxkpi/common/include/linux/irq_work.h
index 7c4019bc0242..120df40d0c0f 100644
--- a/sys/compat/linuxkpi/common/include/linux/irq_work.h
+++ b/sys/compat/linuxkpi/common/include/linux/irq_work.h
@@ -33,6 +33,7 @@
#include <sys/taskqueue.h>
#include <linux/llist.h>
+#include <linux/rcupdate.h>
#include <linux/workqueue.h>
#define LKPI_IRQ_WORK_STD_TQ system_wq->taskqueue
@@ -85,6 +86,7 @@ static inline void
irq_work_sync(struct irq_work *irqw)
{
taskqueue_drain(LKPI_IRQ_WORK_TQ, &irqw->irq_task);
+ synchronize_rcu();
}
#endif /* _LINUXKPI_LINUX_IRQ_WORK_H_ */
diff --git a/sys/compat/linuxkpi/common/src/linux_work.c b/sys/compat/linuxkpi/common/src/linux_work.c
index bb25893d9c71..02dfb35d9fd0 100644
--- a/sys/compat/linuxkpi/common/src/linux_work.c
+++ b/sys/compat/linuxkpi/common/src/linux_work.c
@@ -757,7 +757,9 @@ linux_irq_work_fn(void *context, int pending)
{
struct irq_work *irqw = context;
+ rcu_read_lock();
irqw->func(irqw);
+ rcu_read_unlock();
}
static void
@@ -791,6 +793,7 @@ SYSINIT(linux_irq_work_init, SI_SUB_TASKQ, SI_ORDER_SECOND,
static void
linux_irq_work_uninit(void *arg)
{
+ /* taskqueue_drain_all() executes synchronize_rcu() implicitly */
taskqueue_drain_all(linux_irq_work_tq);
taskqueue_free(linux_irq_work_tq);
}