]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.15/nfsd-fix-a-write-performance-regression.patch
Fixes for 5.15
[thirdparty/kernel/stable-queue.git] / queue-5.15 / nfsd-fix-a-write-performance-regression.patch
1 From aed1ad3984d82255ba7da43d0030a2ee43ae4607 Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Thu, 31 Mar 2022 09:54:01 -0400
4 Subject: nfsd: Fix a write performance regression
5
6 From: Trond Myklebust <trond.myklebust@hammerspace.com>
7
8 [ Upstream commit 6b8a94332ee4f7d9a8ae0cbac7609f79c212f06c ]
9
10 The call to filemap_flush() in nfsd_file_put() is there to ensure that
11 we clear out any writes belonging to a NFSv3 client relatively quickly
12 and avoid situations where the file can't be evicted by the garbage
13 collector. It also ensures that we detect write errors quickly.
14
15 The problem is this causes a regression in performance for some
16 workloads.
17
18 So try to improve matters by deferring writeback until we're ready to
19 close the file, and need to detect errors so that we can force the
20 client to resend.
21
22 Tested-by: Jan Kara <jack@suse.cz>
23 Fixes: b6669305d35a ("nfsd: Reduce the number of calls to nfsd_file_gc()")
24 Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
25 Link: https://lore.kernel.org/all/20220330103457.r4xrhy2d6nhtouzk@quack3.lan
26 Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
27 ---
28 fs/nfsd/filecache.c | 18 +++++++++++++++---
29 1 file changed, 15 insertions(+), 3 deletions(-)
30
31 diff --git a/fs/nfsd/filecache.c b/fs/nfsd/filecache.c
32 index 94157b82b60e1..6cde6ef68996e 100644
33 --- a/fs/nfsd/filecache.c
34 +++ b/fs/nfsd/filecache.c
35 @@ -229,6 +229,13 @@ nfsd_file_check_write_error(struct nfsd_file *nf)
36 return filemap_check_wb_err(file->f_mapping, READ_ONCE(file->f_wb_err));
37 }
38
39 +static void
40 +nfsd_file_flush(struct nfsd_file *nf)
41 +{
42 + if (nf->nf_file && vfs_fsync(nf->nf_file, 1) != 0)
43 + nfsd_reset_write_verifier(net_generic(nf->nf_net, nfsd_net_id));
44 +}
45 +
46 static void
47 nfsd_file_do_unhash(struct nfsd_file *nf)
48 {
49 @@ -296,11 +303,14 @@ nfsd_file_put(struct nfsd_file *nf)
50 return;
51 }
52
53 - filemap_flush(nf->nf_file->f_mapping);
54 is_hashed = test_bit(NFSD_FILE_HASHED, &nf->nf_flags) != 0;
55 - nfsd_file_put_noref(nf);
56 - if (is_hashed)
57 + if (!is_hashed) {
58 + nfsd_file_flush(nf);
59 + nfsd_file_put_noref(nf);
60 + } else {
61 + nfsd_file_put_noref(nf);
62 nfsd_file_schedule_laundrette();
63 + }
64 if (atomic_long_read(&nfsd_filecache_count) >= NFSD_FILE_LRU_LIMIT)
65 nfsd_file_gc();
66 }
67 @@ -321,6 +331,7 @@ nfsd_file_dispose_list(struct list_head *dispose)
68 while(!list_empty(dispose)) {
69 nf = list_first_entry(dispose, struct nfsd_file, nf_lru);
70 list_del(&nf->nf_lru);
71 + nfsd_file_flush(nf);
72 nfsd_file_put_noref(nf);
73 }
74 }
75 @@ -334,6 +345,7 @@ nfsd_file_dispose_list_sync(struct list_head *dispose)
76 while(!list_empty(dispose)) {
77 nf = list_first_entry(dispose, struct nfsd_file, nf_lru);
78 list_del(&nf->nf_lru);
79 + nfsd_file_flush(nf);
80 if (!refcount_dec_and_test(&nf->nf_ref))
81 continue;
82 if (nfsd_file_free(nf))
83 --
84 2.43.0
85