Thread (9 messages) read the whole thread 9 messages, 4 authors, 2021-06-23

Re: [PATCH] nfsd: Reduce contention for the nfsd_file nf_rwsem

From: Trond Myklebust <hidden>
Date: 2021-06-21 19:35:33

On Mon, 2021-06-21 at 15:06 -0400, Trond Myklebust wrote:
On Mon, 2021-06-21 at 18:27 +0000, Chuck Lever III wrote:
quoted
quoted
On Jun 21, 2021, at 2:00 PM, Trond Myklebust
[off-list ref] wrote:

On Mon, 2021-06-21 at 16:49 +0000, Chuck Lever III wrote:
quoted
Hi-
quoted
On Jun 17, 2021, at 7:26 PM, trondmy@kernel.org wrote:

From: Trond Myklebust <redacted>

When flushing out the unstable file writes as part of a
COMMIT
call, try
to perform most of of the data writes and waits outside the
semaphore.

This means that if the client is sending the COMMIT as part
of
a
memory
reclaim operation, then it can continue performing I/O, with
contention
for the lock occurring only once the data sync is finished.

Fixes: 5011af4c698a ("nfsd: Fix stable writes")
Signed-off-by: Trond Myklebust
[off-list ref]
The good news is I've found no functional regressions. The bad
news is I haven't seen any difference in performance. Is there
a particular test that I can run to observe improvement?
I'd expect that re-exported NFS would be the best test since
fsync() is
a high latency operation when the page cache is loaded. You also
want
to use a client with relatively limited memory so that it will
try
to
reclaim memory by pushing out dirty pages and doing COMMIT.
I thought I was hitting those low-memory cases with direct I/O
testing. <shrug>
If you do O_DIRECT with 100MB write() calls, then maybe. If you use <
1MB write()s then you'll rarely if ever hit any COMMIT calls.
Let me correct myself: You'd need to do aio/dio with 100MB write system
calls so that the flush part of the COMMIT operation takes significant
time on the server, and can interfere with other COMMIT operations.
quoted
quoted
quoted
I wonder about adding a Fixes: tag for a change that the patch
description describes as an optimization.
I've occasionally hit OOM situations in the re-export case when
the
r/w
lock contention causes softerr failure to be serialised.
i.e. if the server is down, and you're essentially hoping that
the
nfsd
threads will give up and return EJUKEBOX/NFS4ERR_DELAY to the
client,
then that lock ensures that threads fail one-by-one (grab lock,
write,
timeout, release lock) instead of being able to all fail at once
(write, timeout).
quoted
quoted
---
fs/nfsd/vfs.c | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 15adf1f6ab21..46485c04740d 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -1123,6 +1123,19 @@ nfsd_write(struct svc_rqst *rqstp,
struct
svc_fh *fhp, loff_t offset,
}

#ifdef CONFIG_NFSD_V3
+static int
+nfsd_filemap_write_and_wait_range(struct nfsd_file *nf,
loff_t
offset,
+                                 loff_t end)
+{
+       struct address_space *mapping = nf->nf_file-
quoted
f_mapping;
+       int ret = filemap_fdatawrite_range(mapping, offset,
end);
+
+       if (ret)
+               return ret;
+       filemap_fdatawait_range_keep_errors(mapping, offset,
end);
+       return 0;
+}
+
/*
 * Commit all pending writes to stable storage.
 *
@@ -1153,10 +1166,11 @@ nfsd_commit(struct svc_rqst *rqstp,
struct
svc_fh *fhp,
        if (err)
                goto out;
        if (EX_ISSYNC(fhp->fh_export)) {
-               int err2;
+               int err2 =
nfsd_filemap_write_and_wait_range(nf,
offset, end);

                down_write(&nf->nf_rwsem);
-               err2 = vfs_fsync_range(nf->nf_file, offset,
end,
0);
+               if (!err2)
+                       err2 = vfs_fsync_range(nf->nf_file,
offset,
end, 0);
                switch (err2) {
                case 0:
                        nfsd_copy_boot_verifier(verf,
net_generic(nf->nf_net,
-- 
2.31.1
--
Chuck Lever

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com
--
Chuck Lever

-- 
Trond Myklebust
Linux NFS client maintainer, Hammerspace
trond.myklebust@hammerspace.com

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help