* [PATCH net-next V3] net/mlx5: Expedite notifier unregistration during device teardown
@ 2026-08-11 6:28 Tariq Toukan
2026-08-12 2:48 ` 答复: [外部邮件] " Li,Rongqing
2026-08-17 22:55 ` Jakub Kicinski
0 siblings, 2 replies; 4+ messages in thread
From: Tariq Toukan @ 2026-08-11 6:28 UTC (permalink / raw)
To: Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski,
netdev, Paolo Abeni
Cc: Frederic Weisbecker, Gal Pressman, Leon Romanovsky, linux-kernel,
linux-rdma, Li RongQing, liyongkang, Mark Bloch, Paul E. McKenney,
Saeed Mahameed, Tariq Toukan
From: Li RongQing <lirongqing@baidu.com>
During device hot-unplug, the mlx5 driver expects quickly unregister
notification chains. The standard atomic_notifier_chain_unregister()
calls synchronize_rcu(), which introduces significant latency and
can become a bottleneck during mass resource cleanup.
Introduce atomic_notifier_chain_unregister_expedited() to leverage
synchronize_rcu_expedited(), and use it significantly reducing wait
times in the following paths:
- Event Queue (EQ) notifier chain
- Firmware event notifier chain
- IRQ notifier chain
On x86-64 with HZ=1000, 64 networking channels:
- Average teardown time: 3.59s -> 1.9s (47% reduction)
On x86-64 with HZ=250, 64 networking channels:
- Average teardown time: 5.5s -> 1.9s (65% reduction)
Co-developed-by: liyongkang <liyongkang01@baidu.com>
Signed-off-by: liyongkang <liyongkang01@baidu.com>
Signed-off-by: Li RongQing <lirongqing@baidu.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
---
V3: rebased.
V2:
https://lore.kernel.org/all/20260317003544.2583-1-lirongqing@baidu.com/
drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/events.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/pci_irq.c | 2 +-
include/linux/notifier.h | 2 ++
kernel/notifier.c | 24 +++++++++++++++++++
5 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
index d11ec263d53c..c86090cb58c6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
@@ -1243,6 +1243,6 @@ int mlx5_eq_notifier_unregister(struct mlx5_core_dev *dev, struct mlx5_nb *nb)
{
struct mlx5_eq_table *eqt = dev->priv.eq_table;
- return atomic_notifier_chain_unregister(&eqt->nh[nb->event_type], &nb->nb);
+ return atomic_notifier_chain_unregister_expedited(&eqt->nh[nb->event_type], &nb->nb);
}
EXPORT_SYMBOL(mlx5_eq_notifier_unregister);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c
index 4d7f35b96876..753cb15cdeee 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
@@ -436,7 +436,7 @@ int mlx5_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *n
{
struct mlx5_events *events = dev->priv.events;
- return atomic_notifier_chain_unregister(&events->fw_nh, nb);
+ return atomic_notifier_chain_unregister_expedited(&events->fw_nh, nb);
}
EXPORT_SYMBOL(mlx5_notifier_unregister);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
index 0f5b8bc7861e..cb31e8c7a244 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
@@ -343,7 +343,7 @@ int mlx5_irq_detach_nb(struct mlx5_irq *irq, struct notifier_block *nb)
{
int err = 0;
- err = atomic_notifier_chain_unregister(&irq->nh, nb);
+ err = atomic_notifier_chain_unregister_expedited(&irq->nh, nb);
mlx5_irq_put(irq);
return err;
}
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 01b6c9d9956f..156d958f98f0 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -159,6 +159,8 @@ extern int blocking_notifier_chain_register_unique_prio(
extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
struct notifier_block *nb);
+extern int atomic_notifier_chain_unregister_expedited(struct atomic_notifier_head *nh,
+ struct notifier_block *nb);
extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
struct notifier_block *nb);
extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
diff --git a/kernel/notifier.c b/kernel/notifier.c
index 2f9fe7c30287..9b35822fc2c0 100644
--- a/kernel/notifier.c
+++ b/kernel/notifier.c
@@ -197,6 +197,30 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
}
EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
+/**
+ * atomic_notifier_chain_unregister_expedited - Remove notifier from an atomic notifier chain
+ * @nh: Pointer to head of the atomic notifier chain
+ * @n: Entry to remove from notifier chain
+ *
+ * Removes a notifier from an atomic notifier chain and forcefully
+ * accelerates the RCU grace period.
+ *
+ * Return: 0 on success, or -ENOENT on failure.
+ */
+int atomic_notifier_chain_unregister_expedited(struct atomic_notifier_head *nh,
+ struct notifier_block *n)
+{
+ unsigned long flags;
+ int ret;
+
+ spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_unregister(&nh->head, n);
+ spin_unlock_irqrestore(&nh->lock, flags);
+ synchronize_rcu_expedited();
+ return ret;
+}
+EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister_expedited);
+
/**
* atomic_notifier_call_chain - Call functions in an atomic notifier chain
* @nh: Pointer to head of the atomic notifier chain
base-commit: d67e5dbda22604d0fcde32fce58c65f88676e676
--
2.44.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* 答复: [外部邮件] [PATCH net-next V3] net/mlx5: Expedite notifier unregistration during device teardown
2026-08-11 6:28 [PATCH net-next V3] net/mlx5: Expedite notifier unregistration during device teardown Tariq Toukan
@ 2026-08-12 2:48 ` Li,Rongqing
2026-08-12 23:45 ` Jakub Kicinski
2026-08-17 22:55 ` Jakub Kicinski
1 sibling, 1 reply; 4+ messages in thread
From: Li,Rongqing @ 2026-08-12 2:48 UTC (permalink / raw)
To: Tariq Toukan, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, netdev@vger.kernel.org, Paolo Abeni
Cc: Frederic Weisbecker, Gal Pressman, Leon Romanovsky,
linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org,
Li,Yongkang(ACG CCN), Mark Bloch, Paul E. McKenney,
Saeed Mahameed
>
> From: Li RongQing <lirongqing@baidu.com>
>
> During device hot-unplug, the mlx5 driver expects quickly unregister
> notification chains. The standard atomic_notifier_chain_unregister()
> calls synchronize_rcu(), which introduces significant latency and can become
> a bottleneck during mass resource cleanup.
>
> Introduce atomic_notifier_chain_unregister_expedited() to leverage
> synchronize_rcu_expedited(), and use it significantly reducing wait times in
> the following paths:
> - Event Queue (EQ) notifier chain
> - Firmware event notifier chain
> - IRQ notifier chain
>
> On x86-64 with HZ=1000, 64 networking channels:
> - Average teardown time: 3.59s -> 1.9s (47% reduction) On x86-64 with
> HZ=250, 64 networking channels:
> - Average teardown time: 5.5s -> 1.9s (65% reduction)
>
> Co-developed-by: liyongkang <liyongkang01@baidu.com>
> Signed-off-by: liyongkang <liyongkang01@baidu.com>
> Signed-off-by: Li RongQing <lirongqing@baidu.com>
> Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
> ---
> V3: rebased.
>
> V2:
> https://lore.kernel.org/all/20260317003544.2583-1-lirongqing@baidu.com/
>
> drivers/net/ethernet/mellanox/mlx5/core/eq.c | 2
> +- .../net/ethernet/mellanox/mlx5/core/events.c | 2
> +- .../net/ethernet/mellanox/mlx5/core/pci_irq.c | 2 +-
> include/linux/notifier.h | 2 ++
> kernel/notifier.c | 24
> +++++++++++++++++++
> 5 files changed, 29 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> index d11ec263d53c..c86090cb58c6 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> @@ -1243,6 +1243,6 @@ int mlx5_eq_notifier_unregister(struct
> mlx5_core_dev *dev, struct mlx5_nb *nb) {
> struct mlx5_eq_table *eqt = dev->priv.eq_table;
>
> - return atomic_notifier_chain_unregister(&eqt->nh[nb->event_type],
> &nb->nb);
> + return
> +atomic_notifier_chain_unregister_expedited(&eqt->nh[nb->event_type],
> +&nb->nb);
> }
> EXPORT_SYMBOL(mlx5_eq_notifier_unregister);
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c
> b/drivers/net/ethernet/mellanox/mlx5/core/events.c
> index 4d7f35b96876..753cb15cdeee 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
> @@ -436,7 +436,7 @@ int mlx5_notifier_unregister(struct mlx5_core_dev
> *dev, struct notifier_block *n {
> struct mlx5_events *events = dev->priv.events;
>
> - return atomic_notifier_chain_unregister(&events->fw_nh, nb);
> + return atomic_notifier_chain_unregister_expedited(&events->fw_nh,
> nb);
> }
> EXPORT_SYMBOL(mlx5_notifier_unregister);
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
> b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
> index 0f5b8bc7861e..cb31e8c7a244 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
> @@ -343,7 +343,7 @@ int mlx5_irq_detach_nb(struct mlx5_irq *irq, struct
> notifier_block *nb) {
> int err = 0;
>
> - err = atomic_notifier_chain_unregister(&irq->nh, nb);
> + err = atomic_notifier_chain_unregister_expedited(&irq->nh, nb);
> mlx5_irq_put(irq);
> return err;
> }
> diff --git a/include/linux/notifier.h b/include/linux/notifier.h index
> 01b6c9d9956f..156d958f98f0 100644
> --- a/include/linux/notifier.h
> +++ b/include/linux/notifier.h
> @@ -159,6 +159,8 @@ extern int
> blocking_notifier_chain_register_unique_prio(
>
> extern int atomic_notifier_chain_unregister(struct atomic_notifier_head
> *nh,
> struct notifier_block *nb);
> +extern int atomic_notifier_chain_unregister_expedited(struct
> atomic_notifier_head *nh,
> + struct notifier_block *nb);
> extern int blocking_notifier_chain_unregister(struct blocking_notifier_head
> *nh,
> struct notifier_block *nb);
> extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh, diff
> --git a/kernel/notifier.c b/kernel/notifier.c index 2f9fe7c30287..9b35822fc2c0
> 100644
> --- a/kernel/notifier.c
> +++ b/kernel/notifier.c
> @@ -197,6 +197,30 @@ int atomic_notifier_chain_unregister(struct
> atomic_notifier_head *nh, }
> EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
>
> +/**
> + * atomic_notifier_chain_unregister_expedited - Remove notifier from an
> atomic notifier chain
> + * @nh: Pointer to head of the atomic notifier chain
> + * @n: Entry to remove from notifier chain
> + *
> + * Removes a notifier from an atomic notifier chain and forcefully
> + * accelerates the RCU grace period.
> + *
> + * Return: 0 on success, or -ENOENT on failure.
> + */
> +int atomic_notifier_chain_unregister_expedited(struct atomic_notifier_head
> *nh,
> + struct notifier_block *n)
> +{
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&nh->lock, flags);
> + ret = notifier_chain_unregister(&nh->head, n);
> + spin_unlock_irqrestore(&nh->lock, flags);
> + synchronize_rcu_expedited();
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister_expedited);
> +
> /**
> * atomic_notifier_call_chain - Call functions in an atomic notifier chain
> * @nh: Pointer to head of the atomic notifier chain
>
> base-commit: d67e5dbda22604d0fcde32fce58c65f88676e676
> --
> 2.44.0
The netdev/build_allmodconfig_warn bot reports a new sparse warning at line 217:
../kernel/notifier.c:217:42: warning: incorrect type in argument 1 (different address spaces)
This is not a new class of problem. The same warning already exists throughout notifier.c on every notifier-chain helper call site:
../kernel/notifier.c:148:40: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:171:40: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:193:42: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:217:42: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:247:36: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:285:49: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:288:40: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:348:51: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:351:42: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:369:51: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:404:44: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:429:41: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:446:43: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:453:44: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:477:37: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:507:49: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:510:40: warning: incorrect type in argument 1 (different address spaces)
../kernel/notifier.c:537:51: warning: incorrect type in argument 1 (different address spaces)
The new function added by this change simply follows the existing pattern, so it adds one more instance of an already-present warning rather than introducing a new issue.
Root cause: the notifier_chain_*() helpers take a plain struct notifier_block **, whereas the chain heads (nh->head) and the notifier_block::next links are annotated __rcu. Passing &nh->head drops the __rcu annotation at the helper boundary, and that annotation mismatch is all sparse is flagging.
This is safe. The helpers walk the list under the chain's write-side lock and publish updates via rcu_assign_pointer(), while the read/traversal path uses rcu_dereference_raw(). RCU correctness is therefore fully preserved; only the compile-time annotation is lost across the pointer-to-pointer argument. __rcu is a sparse-only attribute with no codegen effect, so the generated code is identical either way.
Cleaning this up properly would mean annotating the nl parameter of the notifier_chain_*() helpers as __rcu and using rcu_dereference_raw() for the bare reads, which touches all chain types (atomic/blocking/raw/srcu) and is orthogonal to this change.
thanks
[Li,Rongqing]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [外部邮件] [PATCH net-next V3] net/mlx5: Expedite notifier unregistration during device teardown
2026-08-12 2:48 ` 答复: [外部邮件] " Li,Rongqing
@ 2026-08-12 23:45 ` Jakub Kicinski
0 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2026-08-12 23:45 UTC (permalink / raw)
To: Li,Rongqing
Cc: Tariq Toukan, Andrew Lunn, David S. Miller, Eric Dumazet,
netdev@vger.kernel.org, Paolo Abeni, Frederic Weisbecker,
Gal Pressman, Leon Romanovsky, linux-kernel@vger.kernel.org,
linux-rdma@vger.kernel.org, Li,Yongkang(ACG CCN), Mark Bloch,
Paul E. McKenney, Saeed Mahameed
On Wed, 12 Aug 2026 02:48:58 +0000 Li,Rongqing wrote:
> The netdev/build_allmodconfig_warn bot reports a new sparse warning at line 217:
>
> ../kernel/notifier.c:217:42: warning: incorrect type in argument 1 (different address spaces)
Why do you feel the need to send this reply?
Sparse is flaky, the maintainers understand this.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net-next V3] net/mlx5: Expedite notifier unregistration during device teardown
2026-08-11 6:28 [PATCH net-next V3] net/mlx5: Expedite notifier unregistration during device teardown Tariq Toukan
2026-08-12 2:48 ` 答复: [外部邮件] " Li,Rongqing
@ 2026-08-17 22:55 ` Jakub Kicinski
1 sibling, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2026-08-17 22:55 UTC (permalink / raw)
To: tariqt
Cc: Jakub Kicinski, andrew+netdev, davem, edumazet, netdev, pabeni,
frederic, gal, leon, linux-kernel, linux-rdma, lirongqing,
liyongkang01, mbloch, paulmck, saeedm
This is an AI-generated review of your patch. The human sending this
email has considered the AI review valid, or at least plausible.
---
net/mlx5: Expedite notifier unregistration during device teardown
This adds a new exported core helper,
atomic_notifier_chain_unregister_expedited(), which unlinks the notifier
block and then calls synchronize_rcu_expedited() instead of
synchronize_rcu(). Three mlx5 helpers (EQ notifier, FW event notifier,
IRQ notifier) are converted to it.
A few questions below about the commit message scope, the new API's
documented contract, and the expedited grace period being taken once per
notifier block.
> net/mlx5: Expedite notifier unregistration during device teardown
>
> During device hot-unplug, the mlx5 driver expects quickly unregister
> notification chains.
> ...
> Introduce atomic_notifier_chain_unregister_expedited() to leverage
> synchronize_rcu_expedited(), and use it significantly reducing wait
> times in the following paths:
> - Event Queue (EQ) notifier chain
> - Firmware event notifier chain
> - IRQ notifier chain
[Severity: Medium]
The change is described as a device hot-unplug optimization, but the
conversion happens inside three generic exported helpers with no gating on
teardown state, so every caller now takes an expedited grace period. Could
the message be extended to cover the runtime paths that are affected too?
Verified non-hot-unplug callers include mlx5_cmd_use_polling() on command
mode switches, mlx5e_disable_async_events() on netdev close,
mlx5_eswitch_disable_locked() and mlx5_eswitch_event_handler_unregister()
on devlink eswitch-mode change and SR-IOV disable, the monitor-stats
disable loop in en/monitor_stats.c, pcie_cong_event cleanup, macsec and
ipsec cleanup, fw_tracer probe-time error rollback, LAG port removal,
clock/PPS cleanup, and mlx5_eq_notifier_unregister() in
drivers/vfio/pci/mlx5/cmd.c.
> On x86-64 with HZ=1000, 64 networking channels:
> - Average teardown time: 3.59s -> 1.9s (47% reduction)
> On x86-64 with HZ=250, 64 networking channels:
> - Average teardown time: 5.5s -> 1.9s (65% reduction)
Are these numbers configuration dependent? synchronize_rcu_expedited()
falls back to a normal grace period when rcu_gp_is_normal() is set
(rcupdate.rcu_normal or rcu_normal_after_boot):
kernel/rcu/tree_exp.h:synchronize_rcu_expedited() {
/* If expedited grace periods are prohibited, fall back to normal. */
if (rcu_gp_is_normal()) {
synchronize_rcu_normal();
return;
}
...
}
and under CONFIG_TINY_RCU include/linux/rcutiny.h maps
synchronize_rcu_expedited() to plain synchronize_rcu(), so no reduction is
expected in those configurations.
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> index d11ec263d53c9..c86090cb58c6a 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c
> @@ -1243,6 +1243,6 @@ int mlx5_eq_notifier_unregister(struct mlx5_core_dev *dev, struct mlx5_nb *nb)
> {
> struct mlx5_eq_table *eqt = dev->priv.eq_table;
>
> - return atomic_notifier_chain_unregister(&eqt->nh[nb->event_type], &nb->nb);
> + return atomic_notifier_chain_unregister_expedited(&eqt->nh[nb->event_type], &nb->nb);
> }
> EXPORT_SYMBOL(mlx5_eq_notifier_unregister);
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/events.c b/drivers/net/ethernet/mellanox/mlx5/core/events.c
> index 4d7f35b968761..753cb15cdeee1 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/events.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/events.c
> @@ -436,7 +436,7 @@ int mlx5_notifier_unregister(struct mlx5_core_dev *dev, struct notifier_block *n
> {
> struct mlx5_events *events = dev->priv.events;
>
> - return atomic_notifier_chain_unregister(&events->fw_nh, nb);
> + return atomic_notifier_chain_unregister_expedited(&events->fw_nh, nb);
> }
> EXPORT_SYMBOL(mlx5_notifier_unregister);
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
> index 0f5b8bc7861eb..cb31e8c7a244f 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
> @@ -343,7 +343,7 @@ int mlx5_irq_detach_nb(struct mlx5_irq *irq, struct notifier_block *nb)
> {
> int err = 0;
>
> - err = atomic_notifier_chain_unregister(&irq->nh, nb);
> + err = atomic_notifier_chain_unregister_expedited(&irq->nh, nb);
> mlx5_irq_put(irq);
> return err;
> }
> diff --git a/include/linux/notifier.h b/include/linux/notifier.h
> index 01b6c9d9956f9..156d958f98f05 100644
> --- a/include/linux/notifier.h
> +++ b/include/linux/notifier.h
> @@ -159,6 +159,8 @@ extern int blocking_notifier_chain_register_unique_prio(
>
> extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
> struct notifier_block *nb);
> +extern int atomic_notifier_chain_unregister_expedited(struct atomic_notifier_head *nh,
> + struct notifier_block *nb);
[Severity: Low]
Should the API comment block at the top of include/linux/notifier.h be
updated for the new symbol? It currently reads:
* atomic_notifier_chain_register() may be called from an atomic context,
* but blocking_notifier_chain_register() and srcu_notifier_chain_register()
* must be called from a process context. Ditto for the corresponding
* _unregister() routines.
*
* atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),
* and srcu_notifier_chain_unregister() _must not_ be called from within
* the call chain.
The new helper is not listed in the second rule, and the first rule as
written would suggest it may be called from atomic context, which is not
true since synchronize_rcu_expedited() blocks and warns:
kernel/rcu/tree_exp.h:synchronize_rcu_expedited() {
RCU_LOCKDEP_WARN(lock_is_held(&rcu_bh_lock_map) ||
lock_is_held(&rcu_lock_map) ||
lock_is_held(&rcu_sched_lock_map),
"Illegal synchronize_rcu_expedited() in RCU read-side critical section");
...
}
Note the "Ditto ... _unregister()" inaccuracy is pre-existing and was not
introduced by this patch, since atomic_notifier_chain_unregister() already
calls synchronize_rcu(); only the omission of the new symbol from both
rules is new.
> extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
> struct notifier_block *nb);
> extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
> diff --git a/kernel/notifier.c b/kernel/notifier.c
> index 2f9fe7c30287f..9b35822fc2c02 100644
> --- a/kernel/notifier.c
> +++ b/kernel/notifier.c
> @@ -197,6 +197,30 @@ int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
> }
> EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
>
> +/**
> + * atomic_notifier_chain_unregister_expedited - Remove notifier from an atomic notifier chain
> + * @nh: Pointer to head of the atomic notifier chain
> + * @n: Entry to remove from notifier chain
> + *
> + * Removes a notifier from an atomic notifier chain and forcefully
> + * accelerates the RCU grace period.
[Severity: Low]
Could this kernel-doc state that the caller must be in sleepable process
context and must not call it from within the notifier call chain? Also,
"forcefully accelerates the RCU grace period" does not hold for
CONFIG_TINY_RCU, where include/linux/rcutiny.h defines
synchronize_rcu_expedited() as synchronize_rcu(), nor when
rcu_gp_is_normal() forces the normal grace period fallback.
> + *
> + * Return: 0 on success, or -ENOENT on failure.
> + */
> +int atomic_notifier_chain_unregister_expedited(struct atomic_notifier_head *nh,
> + struct notifier_block *n)
> +{
> + unsigned long flags;
> + int ret;
> +
> + spin_lock_irqsave(&nh->lock, flags);
> + ret = notifier_chain_unregister(&nh->head, n);
> + spin_unlock_irqrestore(&nh->lock, flags);
> + synchronize_rcu_expedited();
^^^^
[Severity: High]
Does this put one expedited grace period per notifier block into paths that
unregister notifiers in a loop? The synchronize_rcu_expedited() kernel-doc
asks for the opposite:
kernel/rcu/tree_exp.h:
* implementations, it is still unfriendly to real-time workloads, so is
* thus not recommended for any sort of common-case code. In fact, if
* you are using synchronize_rcu_expedited() in a loop, please restructure
* your code to batch your updates, and then use a single synchronize_rcu()
* instead.
The converted helpers are loop bodies. In mlx5_eq_table_destroy():
xa_for_each(&table->comp_eqs, index, eq)
destroy_comp_eq(dev, eq, index);
and destroy_comp_eq() -> mlx5_eq_disable() -> mlx5_irq_detach_nb(), so the
64-channel device from the commit message performs 64 back-to-back
expedited grace periods, each IPI'ing every non-idle non-nohz online CPU.
mlx5_events_stop() is a second loop:
for (i = ARRAY_SIZE(events_nbs_ref) - 1; i >= 0 ; i--)
mlx5_eq_notifier_unregister(dev, &events->notifiers[i].nb);
as are the monitor-stats disable loop in en/monitor_stats.c and the LAG
port loops in lag/lag.c.
Would a _nosync unregister variant plus a single grace period after all
blocks are unlinked fit the documented guidance better?
There is also a repeatable userspace trigger. In vfio_main.c,
vfio_ioctl_device_feature_logging_stop() calls
device->log_ops->log_stop(device), which reaches
mlx5vf_stop_page_tracker() -> _mlx5vf_free_page_tracker_resources() ->
mlx5_eq_notifier_unregister() in drivers/vfio/pci/mlx5/cmd.c, so a device
fd holder can alternate DMA_LOGGING_START/STOP and force an all-CPU IPI per
cycle. With plain synchronize_rcu() only the caller waited; is the shift of
that cost onto every other CPU acceptable for isolated, nohz_full or RT
workloads, given the only mitigation is the administrative
rcupdate.rcu_normal=1?
> + return ret;
> +}
> +EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister_expedited);
> +
--
pw-bot: cr
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-08-17 22:55 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 6:28 [PATCH net-next V3] net/mlx5: Expedite notifier unregistration during device teardown Tariq Toukan
2026-08-12 2:48 ` 答复: [外部邮件] " Li,Rongqing
2026-08-12 23:45 ` Jakub Kicinski
2026-08-17 22:55 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox