Btrfs: fix async worker startup race
After a new worker thread starts, it is placed into the list of idle threads. But, this may race with a check for idle done by the worker thread itself, resulting in a double list_add operation. This fix adds a check to make sure the idle thread addition is done properly. Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
83ebade34b
commit
3e99d8eb34
|
@ -74,7 +74,12 @@ static void check_idle_worker(struct btrfs_worker_thread *worker)
|
|||
unsigned long flags;
|
||||
spin_lock_irqsave(&worker->workers->lock, flags);
|
||||
worker->idle = 1;
|
||||
list_move(&worker->worker_list, &worker->workers->idle_list);
|
||||
|
||||
/* the list may be empty if the worker is just starting */
|
||||
if (!list_empty(&worker->worker_list)) {
|
||||
list_move(&worker->worker_list,
|
||||
&worker->workers->idle_list);
|
||||
}
|
||||
spin_unlock_irqrestore(&worker->workers->lock, flags);
|
||||
}
|
||||
}
|
||||
|
@ -90,8 +95,11 @@ static void check_busy_worker(struct btrfs_worker_thread *worker)
|
|||
unsigned long flags;
|
||||
spin_lock_irqsave(&worker->workers->lock, flags);
|
||||
worker->idle = 0;
|
||||
list_move_tail(&worker->worker_list,
|
||||
&worker->workers->worker_list);
|
||||
|
||||
if (!list_empty(&worker->worker_list)) {
|
||||
list_move_tail(&worker->worker_list,
|
||||
&worker->workers->worker_list);
|
||||
}
|
||||
spin_unlock_irqrestore(&worker->workers->lock, flags);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue