提交 8a301eb1 编写于 作者: T Tejun Heo 提交者: Miklos Szeredi

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 26c36791 ("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: NTejun Heo <tj@kernel.org>
Reported-by: NJoshua Miller <joshmiller@fb.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: stable@vger.kernel.org # v2.6.29+
Acked-by: NJan Kara <jack@suse.cz>
Signed-off-by: NMiklos Szeredi <mszeredi@redhat.com>
上级 4ad769f3
...@@ -385,8 +385,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) ...@@ -385,8 +385,7 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req)
if (!fc->blocked && waitqueue_active(&fc->blocked_waitq)) if (!fc->blocked && waitqueue_active(&fc->blocked_waitq))
wake_up(&fc->blocked_waitq); wake_up(&fc->blocked_waitq);
if (fc->num_background == fc->congestion_threshold && if (fc->num_background == fc->congestion_threshold && fc->sb) {
fc->connected && fc->sb) {
clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC); clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC); clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册