Skip to content

Commit

Permalink
Btrfs: fix async worker startup race
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Chris Mason committed Sep 16, 2009
1 parent 83ebade commit 3e99d8e
Showing 1 changed file with 11 additions and 3 deletions.
14 changes: 11 additions & 3 deletions fs/btrfs/async-thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand All @@ -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);
}
}
Expand Down

0 comments on commit 3e99d8e

Please sign in to comment.