Skip to content

Commit 25d5648

Browse files
Yang Yinglianggregkh
authored andcommitted
w1: fix deadloop in __w1_remove_master_device()
I got a deadloop report while doing device(ds2482) add/remove test: [ 162.241881] w1_master_driver w1_bus_master1: Waiting for w1_bus_master1 to become free: refcnt=1. [ 163.272251] w1_master_driver w1_bus_master1: Waiting for w1_bus_master1 to become free: refcnt=1. [ 164.296157] w1_master_driver w1_bus_master1: Waiting for w1_bus_master1 to become free: refcnt=1. ... __w1_remove_master_device() can't return, because the dev->refcnt is not zero. w1_add_master_device() | w1_alloc_dev() | atomic_set(&dev->refcnt, 2) | kthread_run() | |__w1_remove_master_device() | kthread_stop() // KTHREAD_SHOULD_STOP is set, | // threadfn(w1_process) won't be | // called. | kthread() | | // refcnt will never be 0, it's deadloop. | while (atomic_read(&dev->refcnt)) {...} After calling w1_add_master_device(), w1_process() is not really invoked, before w1_process() starting, if kthread_stop() is called in __w1_remove_master_device(), w1_process() will never be called, the refcnt can not be decreased, then it causes deadloop in remove function because of non-zero refcnt. We need to make sure w1_process() is really started, so move the set refcnt into w1_process() to fix this problem. Fixes: 1da177e ("Linux-2.6.12-rc2") Signed-off-by: Yang Yingliang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2efb6ed commit 25d5648

File tree

2 files changed

+4
-3
lines changed

2 files changed

+4
-3
lines changed

drivers/w1/w1.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,6 +1166,8 @@ int w1_process(void *data)
11661166
/* remainder if it woke up early */
11671167
unsigned long jremain = 0;
11681168

1169+
atomic_inc(&dev->refcnt);
1170+
11691171
for (;;) {
11701172

11711173
if (!jremain && dev->search_count) {

drivers/w1/w1_int.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,9 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
5151
dev->search_count = w1_search_count;
5252
dev->enable_pullup = w1_enable_pullup;
5353

54-
/* 1 for w1_process to decrement
55-
* 1 for __w1_remove_master_device to decrement
54+
/* For __w1_remove_master_device to decrement
5655
*/
57-
atomic_set(&dev->refcnt, 2);
56+
atomic_set(&dev->refcnt, 1);
5857

5958
INIT_LIST_HEAD(&dev->slist);
6059
INIT_LIST_HEAD(&dev->async_list);

0 commit comments

Comments
 (0)