]> git.baikalelectronics.ru Git - kernel.git/commit
Btrfs: eliminate races in worker stopping code
authorIlya Dryomov <idryomov@gmail.com>
Wed, 2 Oct 2013 16:39:50 +0000 (19:39 +0300)
committerJosef Bacik <jbacik@fusionio.com>
Fri, 4 Oct 2013 20:02:13 +0000 (16:02 -0400)
commit7193dc8fa235ceee9dbf4a5444c5052ccb99eaa5
tree1d8df39327cbfcf2c6543b47b4b66e48a27f4946
parentb7c4313964cea771122aca5a36587772a4ddaa9a
Btrfs: eliminate races in worker stopping code

The current implementation of worker threads in Btrfs has races in
worker stopping code, which cause all kinds of panics and lockups when
running btrfs/011 xfstest in a loop.  The problem is that
btrfs_stop_workers is unsynchronized with respect to check_idle_worker,
check_busy_worker and __btrfs_start_workers.

E.g., check_idle_worker race flow:

       btrfs_stop_workers():            check_idle_worker(aworker):
- grabs the lock
- splices the idle list into the
  working list
- removes the first worker from the
  working list
- releases the lock to wait for
  its kthread's completion
                                  - grabs the lock
                                  - if aworker is on the working list,
                                    moves aworker from the working list
                                    to the idle list
                                  - releases the lock
- grabs the lock
- puts the worker
- removes the second worker from the
  working list
                              ......
        btrfs_stop_workers returns, aworker is on the idle list
                 FS is umounted, memory is freed
                              ......
              aworker is waken up, fireworks ensue

With this applied, I wasn't able to trigger the problem in 48 hours,
whereas previously I could reliably reproduce at least one of these
races within an hour.

Reported-by: David Sterba <dsterba@suse.cz>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Josef Bacik <jbacik@fusionio.com>
fs/btrfs/async-thread.c
fs/btrfs/async-thread.h