Skip to content

Commit

Permalink
fuse: fix blocked_waitq wakeup
Browse files Browse the repository at this point in the history
Using waitqueue_active() is racy.  Make sure we issue a wake_up()
unconditionally after storing into fc->blocked.  After that it's okay to
optimize with waitqueue_active() since the first wake up provides the
necessary barrier for all waiters, not the just the woken one.

Signed-off-by: Miklos Szeredi <[email protected]>
Fixes: 3c18ef8 ("fuse: optimize wake_up")
Cc: <[email protected]> # v3.10
  • Loading branch information
Miklos Szeredi committed Sep 28, 2018
1 parent 4c316f2 commit 908a572
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,12 +391,19 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
if (test_bit(FR_BACKGROUND, &req->flags)) {
spin_lock(&fc->lock);
clear_bit(FR_BACKGROUND, &req->flags);
if (fc->num_background == fc->max_background)
if (fc->num_background == fc->max_background) {
fc->blocked = 0;

/* Wake up next waiter, if any */
if (!fc->blocked && waitqueue_active(&fc->blocked_waitq))
wake_up(&fc->blocked_waitq);
} else if (!fc->blocked) {
/*
* Wake up next waiter, if any. It's okay to use
* waitqueue_active(), as we've already synced up
* fc->blocked with waiters with the wake_up() call
* above.
*/
if (waitqueue_active(&fc->blocked_waitq))
wake_up(&fc->blocked_waitq);
}

if (fc->num_background == fc->congestion_threshold && fc->sb) {
clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
Expand Down

0 comments on commit 908a572

Please sign in to comment.