]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.14.53/fuse-fix-congested-state-leak-on-aborted-connections.patch
5.1-stable patches
[thirdparty/kernel/stable-queue.git] / releases / 4.14.53 / fuse-fix-congested-state-leak-on-aborted-connections.patch
1 From 8a301eb16d99983a4961f884690ec97b92e7dcfe Mon Sep 17 00:00:00 2001
2 From: Tejun Heo <tj@kernel.org>
3 Date: Fri, 2 Feb 2018 09:54:14 -0800
4 Subject: fuse: fix congested state leak on aborted connections
5
6 From: Tejun Heo <tj@kernel.org>
7
8 commit 8a301eb16d99983a4961f884690ec97b92e7dcfe upstream.
9
10 If a connection gets aborted while congested, FUSE can leave
11 nr_wb_congested[] stuck until reboot causing wait_iff_congested() to
12 wait spuriously which can lead to severe performance degradation.
13
14 The leak is caused by gating congestion state clearing with
15 fc->connected test in request_end(). This was added way back in 2009
16 by 26c3679101db ("fuse: destroy bdi on umount"). While the commit
17 description doesn't explain why the test was added, it most likely was
18 to avoid dereferencing bdi after it got destroyed.
19
20 Since then, bdi lifetime rules have changed many times and now we're
21 always guaranteed to have access to the bdi while the superblock is
22 alive (fc->sb).
23
24 Drop fc->connected conditional to avoid leaking congestion states.
25
26 Signed-off-by: Tejun Heo <tj@kernel.org>
27 Reported-by: Joshua Miller <joshmiller@fb.com>
28 Cc: Johannes Weiner <hannes@cmpxchg.org>
29 Cc: stable@vger.kernel.org # v2.6.29+
30 Acked-by: Jan Kara <jack@suse.cz>
31 Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
32 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
33
34 ---
35 fs/fuse/dev.c | 3 +--
36 1 file changed, 1 insertion(+), 2 deletions(-)
37
38 --- a/fs/fuse/dev.c
39 +++ b/fs/fuse/dev.c
40 @@ -381,8 +381,7 @@ static void request_end(struct fuse_conn
41 if (!fc->blocked && waitqueue_active(&fc->blocked_waitq))
42 wake_up(&fc->blocked_waitq);
43
44 - if (fc->num_background == fc->congestion_threshold &&
45 - fc->connected && fc->sb) {
46 + if (fc->num_background == fc->congestion_threshold && fc->sb) {
47 clear_bdi_congested(fc->sb->s_bdi, BLK_RW_SYNC);
48 clear_bdi_congested(fc->sb->s_bdi, BLK_RW_ASYNC);
49 }