]>
Commit | Line | Data |
---|---|---|
52761858 SL |
1 | From caf85d1492a720e447dfe84e7396041e59a71672 Mon Sep 17 00:00:00 2001 |
2 | From: Sasha Levin <sashal@kernel.org> | |
3 | Date: Thu, 8 Sep 2022 18:14:19 -0400 | |
4 | Subject: NFSD: Make nfsd4_rename() wait before returning NFS4ERR_DELAY | |
5 | ||
6 | From: Chuck Lever <chuck.lever@oracle.com> | |
7 | ||
8 | [ Upstream commit 68c522afd0b1936b48a03a4c8b81261e7597c62d ] | |
9 | ||
10 | nfsd_rename() can kick off a CB_RECALL (via | |
11 | vfs_rename() -> leases_conflict()) if a delegation is present. | |
12 | Before returning NFS4ERR_DELAY, give the client holding that | |
13 | delegation a chance to return it and then retry the nfsd_rename() | |
14 | again, once. | |
15 | ||
16 | This version of the patch handles renaming an existing file, | |
17 | but does not deal with renaming onto an existing file. That | |
18 | case will still always trigger an NFS4ERR_DELAY. | |
19 | ||
20 | Link: https://bugzilla.linux-nfs.org/show_bug.cgi?id=354 | |
21 | Tested-by: Igor Mammedov <imammedo@redhat.com> | |
22 | Signed-off-by: Chuck Lever <chuck.lever@oracle.com> | |
23 | Reviewed-by: Jeff Layton <jlayton@kernel.org> | |
24 | Signed-off-by: Chuck Lever <chuck.lever@oracle.com> | |
25 | --- | |
26 | fs/nfsd/vfs.c | 10 +++++++++- | |
27 | 1 file changed, 9 insertions(+), 1 deletion(-) | |
28 | ||
29 | diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c | |
30 | index e8329051dde01..4c5cc142562b2 100644 | |
31 | --- a/fs/nfsd/vfs.c | |
32 | +++ b/fs/nfsd/vfs.c | |
33 | @@ -1698,7 +1698,15 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, | |
34 | .new_dir = tdir, | |
35 | .new_dentry = ndentry, | |
36 | }; | |
37 | - host_err = vfs_rename(&rd); | |
38 | + int retries; | |
39 | + | |
40 | + for (retries = 1;;) { | |
41 | + host_err = vfs_rename(&rd); | |
42 | + if (host_err != -EAGAIN || !retries--) | |
43 | + break; | |
44 | + if (!nfsd_wait_for_delegreturn(rqstp, d_inode(odentry))) | |
45 | + break; | |
46 | + } | |
47 | if (!host_err) { | |
48 | host_err = commit_metadata(tfhp); | |
49 | if (!host_err) | |
50 | -- | |
51 | 2.43.0 | |
52 |