Skip to content

Commit 2df37ea

Browse files
Zhang Yuweigregkh
authored andcommitted
driver core: Use mod_delayed_work to prevent lost deferred probe work
[ Upstream commit 1137838 ] 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: 2b28a1a ("driver core: Extend deferred probe timeout on driver registration") Signed-off-by: Zhang Yuwei <zhangyuwei20@huawei.com> Link: https://patch.msgid.link/20260410024448.387231-1-zhangyuwei20@huawei.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 62c8cc8 commit 2df37ea

1 file changed

Lines changed: 2 additions & 4 deletions

File tree

drivers/base/dd.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,12 +327,10 @@ void deferred_probe_extend_timeout(void)
327327
* If the work hasn't been queued yet or if the work expired, don't
328328
* start a new one.
329329
*/
330-
if (cancel_delayed_work(&deferred_probe_timeout_work)) {
331-
schedule_delayed_work(&deferred_probe_timeout_work,
332-
driver_deferred_probe_timeout * HZ);
330+
if (mod_delayed_work(system_wq, &deferred_probe_timeout_work,
331+
driver_deferred_probe_timeout))
333332
pr_debug("Extended deferred probe timeout by %d secs\n",
334333
driver_deferred_probe_timeout);
335-
}
336334
}
337335

338336
/**

0 commit comments

Comments
 (0)