[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250814111023.2693-2-wangwensheng4@huawei.com>
Date: Thu, 14 Aug 2025 19:10:21 +0800
From: Wang Wensheng <wangwensheng4@...wei.com>
To: <gregkh@...uxfoundation.org>, <rafael@...nel.org>, <dakr@...nel.org>,
<tglx@...utronix.de>, <saravanak@...gle.com>, <robh@...nel.org>,
<broonie@...nel.org>, <linux-kernel@...r.kernel.org>
CC: <chenjun102@...wei.com>, <wangwensheng4@...wei.com>
Subject: [PATCH 1/3] driver core: Fix concurrent problem of deferred_probe_extend_timeout()
The deferred_probe_timeout_work may be canceled forever unexpected when
deferred_probe_extend_timeout() executes concurrently. Start with
deferred_probe_timeout_work pending, and the problem would
occur after the following sequence.
CPU0 CPU1
deferred_probe_extend_timeout
-> cancel_delayed_work => true
deferred_probe_extend_timeout
-> cancel_delayed_wrok
-> __cancel_work
-> try_grab_pending
-> schedule_delayed_work
-> queue_delayed_work_on
since pending bit is grabbed,
just return without doing anything
-> set_work_pool_and_clear_pending
this __cancel_work return false and
the work would never be queued again
The root cause is that the PENDING_BIT of the work_struct would be set
temporaily in __cancel_work and this bit could prevent the work_struct
to be queued in another CPU.
Use deferred_probe_mutex to protect the cancel and queue operations for
the deferred_probe_timeout_work to fix this problem.
Fixes: 2b28a1a84a0e ("driver core: Extend deferred probe timeout on driver registration")
Signed-off-by: Wang Wensheng <wangwensheng4@...wei.com>
---
drivers/base/dd.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 13ab98e033ea..1983919917e0 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -323,6 +323,7 @@ static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_
void deferred_probe_extend_timeout(void)
{
+ mutex_lock(&deferred_probe_mutex);
/*
* If the work hasn't been queued yet or if the work expired, don't
* start a new one.
@@ -333,6 +334,7 @@ void deferred_probe_extend_timeout(void)
pr_debug("Extended deferred probe timeout by %d secs\n",
driver_deferred_probe_timeout);
}
+ mutex_unlock(&deferred_probe_mutex);
}
/**
--
2.22.0
Powered by blists - more mailing lists