Patch "w1: fix deadloop in __w1_remove_master_device()" has been added to the 5.15-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    w1: fix deadloop in __w1_remove_master_device()

to the 5.15-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     w1-fix-deadloop-in-__w1_remove_master_device.patch
and it can be found in the queue-5.15 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit d00ed71b6427884eac15b08d9d475de8b4e7d1b4
Author: Yang Yingliang <yangyingliang@xxxxxxxxxx>
Date:   Mon Dec 5 16:04:34 2022 +0800

    w1: fix deadloop in __w1_remove_master_device()
    
    [ Upstream commit 25d5648802f12ae486076ceca5d7ddf1fef792b2 ]
    
    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: 1da177e4c3f4 ("Linux-2.6.12-rc2")
    Signed-off-by: Yang Yingliang <yangyingliang@xxxxxxxxxx>
    Link: https://lore.kernel.org/r/20221205080434.3149205-1-yangyingliang@xxxxxxxxxx
    Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index f2ae2e563dc5..8b35fae4cd61 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -1166,6 +1166,8 @@ int w1_process(void *data)
 	/* remainder if it woke up early */
 	unsigned long jremain = 0;
 
+	atomic_inc(&dev->refcnt);
+
 	for (;;) {
 
 		if (!jremain && dev->search_count) {
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index b3e1792d9c49..3a71c5eb2f83 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -51,10 +51,9 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
 	dev->search_count	= w1_search_count;
 	dev->enable_pullup	= w1_enable_pullup;
 
-	/* 1 for w1_process to decrement
-	 * 1 for __w1_remove_master_device to decrement
+	/* For __w1_remove_master_device to decrement
 	 */
-	atomic_set(&dev->refcnt, 2);
+	atomic_set(&dev->refcnt, 1);
 
 	INIT_LIST_HEAD(&dev->slist);
 	INIT_LIST_HEAD(&dev->async_list);



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux