Skip to content

Commit

Permalink
fuse: fix congested state leak on aborted connections
Browse files Browse the repository at this point in the history
If a connection gets aborted while congested, FUSE can leave
nr_wb_congested[] stuck until reboot causing wait_iff_congested() to
wait spuriously which can lead to severe performance degradation.

The leak is caused by gating congestion state clearing with
fc->connected test in request_end().  This was added way back in 2009
by 26c3679 ("fuse: destroy bdi on umount").  While the commit
description doesn't explain why the test was added, it most likely was
to avoid dereferencing bdi after it got destroyed.

Since then, bdi lifetime rules have changed many times and now we're
always guaranteed to have access to the bdi while the superblock is
alive (fc->sb).

Drop fc->connected conditional to avoid leaking congestion states.

Signed-off-by: Tejun Heo <[email protected]>
Reported-by: Joshua Miller <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: [email protected] # v2.6.29+
Acked-by: Jan Kara <[email protected]>
Signed-off-by: Miklos Szeredi <[email protected]>
  • Loading branch information
htejun authored and Miklos Szeredi committed May 31, 2018
1 parent 4ad769f commit 8a301eb
Showing 1 changed file with 1 addition and 2 deletions.
3 changes: 1 addition & 2 deletions fs/fuse/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,8 +385,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
if (!fc->blocked && waitqueue_active(&fc->blocked_waitq))
wake_up(&fc->blocked_waitq);

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

0 comments on commit 8a301eb

Please sign in to comment.