From: Zhang Yuwei Date: Fri, 10 Apr 2026 02:44:48 +0000 (+0800) Subject: driver core: Use mod_delayed_work to prevent lost deferred probe work X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=1137838865bfc9a7cd5869c1dc5c22aa45ec12c8;p=thirdparty%2Fkernel%2Flinux.git driver core: Use mod_delayed_work to prevent lost deferred probe work The deferred_probe_timeout_work may be permanently and unexpectedly canceled when deferred_probe_extend_timeout() executes concurrently. Starting with deferred_probe_timeout_work pending, the problem can occur after the following sequence: CPU0 CPU1 deferred_probe_extend_timeout -> cancel_delayed_work() => true deferred_probe_extend_timeout -> cancel_delayed_work() -> __cancel_work() -> try_grab_pending() -> schedule_delayed_work() -> queue_delayed_work_on() (Since the pending bit is grabbed, it just returns without queuing) -> set_work_pool_and_clear_pending() (This __cancel_work() returns false and the work will never be queued again) The root cause is that the WORK_STRUCT_PENDING_BIT of the work_struct is set temporarily in __cancel_work() (via try_grab_pending()). This transient state prevents the work_struct from being successfully queued by another CPU. To fix this, replace the original non-atomic cancel and schedule mechanism with mod_delayed_work(). This ensures the modification is handled atomically and guarantees that the work is not lost. Fixes: 2b28a1a84a0e ("driver core: Extend deferred probe timeout on driver registration") Signed-off-by: Zhang Yuwei Link: https://patch.msgid.link/20260410024448.387231-1-zhangyuwei20@huawei.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 5799a60fd0585..172a02a438a21 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -323,12 +323,10 @@ void deferred_probe_extend_timeout(void) * If the work hasn't been queued yet or if the work expired, don't * start a new one. */ - if (cancel_delayed_work(&deferred_probe_timeout_work)) { - schedule_delayed_work(&deferred_probe_timeout_work, - driver_deferred_probe_timeout * HZ); + if (mod_delayed_work(system_wq, &deferred_probe_timeout_work, + driver_deferred_probe_timeout)) pr_debug("Extended deferred probe timeout by %d secs\n", driver_deferred_probe_timeout); - } } /**