Skip to content

Commit 8a301eb

Browse files
htejunMiklos Szeredi
authored andcommitted
fuse: fix congested state leak on aborted connections
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]>
1 parent 4ad769f commit 8a301eb

File tree

1 file changed

+1
-2
lines changed

1 file changed

+1
-2
lines changed

fs/fuse/dev.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
385385
if (!fc->blocked && waitqueue_active(&fc->blocked_waitq))
386386
wake_up(&fc->blocked_waitq);
387387

388-
if (fc->num_background == fc->congestion_threshold &&
389-
fc->connected && fc->sb) {
388+
if (fc->num_background == fc->congestion_threshold && fc->sb) {
390389
clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
391390
clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC);
392391
}

0 commit comments

Comments
 (0)