From: Jeff Layton <jlayton@kernel.org>
To: Chuck Lever <chuck.lever@oracle.com>, Neil Brown <neilb@suse.de>,
Olga Kornievskaia <kolga@netapp.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org,
Jeff Layton <jlayton@kernel.org>
Subject: [PATCH v2] nfsd: don't hand out write delegations on O_WRONLY opens
Date: Tue, 01 Aug 2023 09:33:06 -0400 [thread overview]
Message-ID: <20230801-wdeleg-v2-1-20c14252bab4@kernel.org> (raw)
I noticed that xfstests generic/001 was failing against linux-next nfsd.
The client would request a OPEN4_SHARE_ACCESS_WRITE open, and the server
would hand out a write delegation. The client would then try to use that
write delegation as the source stateid in a COPY or CLONE operation, and
the server would respond with NFS4ERR_STALE.
The problem is that the struct file associated with the delegation does
not necessarily have read permissions. It's handing out a write
delegation on what is effectively an O_WRONLY open. RFC 8881 states:
"An OPEN_DELEGATE_WRITE delegation allows the client to handle, on its
own, all opens."
Given that the client didn't request any read permissions, and that nfsd
didn't check for any, it seems wrong to give out a write delegation.
Only hand out a write delegation if we have a O_RDWR descriptor
available. If it fails to find an appropriate write descriptor, go
ahead and try for a read delegation if NFS4_SHARE_ACCESS_READ was
requested.
This fixes xfstest generic/001.
Closes: https://bugzilla.linux-nfs.org/show_bug.cgi?id=412
Signed-off-by: Jeff Layton <jlayton@kernel.org>
---
Changes in v2:
- Rework the logic when finding struct file for the delegation. The
earlier patch might still have attached a O_WRONLY file to the deleg
in some cases, and could still have handed out a write delegation on
an O_WRONLY OPEN request in some cases.
---
fs/nfsd/nfs4state.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index ef7118ebee00..e79d82fd05e7 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -5449,7 +5449,7 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
struct nfs4_file *fp = stp->st_stid.sc_file;
struct nfs4_clnt_odstate *odstate = stp->st_clnt_odstate;
struct nfs4_delegation *dp;
- struct nfsd_file *nf;
+ struct nfsd_file *nf = NULL;
struct file_lock *fl;
u32 dl_type;
@@ -5461,21 +5461,28 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
if (fp->fi_had_conflict)
return ERR_PTR(-EAGAIN);
- if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) {
- nf = find_writeable_file(fp);
+ /*
+ * Try for a write delegation first. We need an O_RDWR file
+ * since a write delegation allows the client to perform any open
+ * from its cache.
+ */
+ if ((open->op_share_access & NFS4_SHARE_ACCESS_BOTH) == NFS4_SHARE_ACCESS_BOTH) {
+ nf = nfsd_file_get(fp->fi_fds[O_RDWR]);
dl_type = NFS4_OPEN_DELEGATE_WRITE;
- } else {
+ }
+
+ /*
+ * If the file is being opened O_RDONLY or we couldn't get a O_RDWR
+ * file for some reason, then try for a read deleg instead.
+ */
+ if (!nf && (open->op_share_access & NFS4_SHARE_ACCESS_READ)) {
nf = find_readable_file(fp);
dl_type = NFS4_OPEN_DELEGATE_READ;
}
- if (!nf) {
- /*
- * We probably could attempt another open and get a read
- * delegation, but for now, don't bother until the
- * client actually sends us one.
- */
+
+ if (!nf)
return ERR_PTR(-EAGAIN);
- }
+
spin_lock(&state_lock);
spin_lock(&fp->fi_lock);
if (nfs4_delegation_exists(clp, fp))
---
base-commit: a734662572708cf062e974f659ae50c24fc1ad17
change-id: 20230731-wdeleg-bbdb6b25a3c6
Best regards,
--
Jeff Layton <jlayton@kernel.org>
next reply other threads:[~2023-08-01 13:33 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-01 13:33 Jeff Layton [this message]
2023-08-01 22:26 ` [PATCH v2] nfsd: don't hand out write delegations on O_WRONLY opens NeilBrown
2023-08-01 22:51 ` Chuck Lever
2023-08-02 0:07 ` Jeff Layton
2023-08-02 16:29 ` dai.ngo
2023-08-02 18:15 ` Jeff Layton
2023-08-02 18:25 ` Chuck Lever III
2023-08-02 20:15 ` dai.ngo
2023-08-02 20:48 ` Jeff Layton
2023-08-02 20:57 ` Chuck Lever III
2023-08-02 21:13 ` Jeff Layton
2023-08-02 21:26 ` dai.ngo
2023-08-02 21:22 ` dai.ngo
2023-08-02 21:32 ` dai.ngo
2023-08-02 21:52 ` Jeff Layton
[not found] ` <3dad0420-11b5-6e6a-a1ae-72970fbfdb34@oracle.com>
2023-08-03 11:27 ` Jeff Layton
2023-08-03 17:01 ` dai.ngo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230801-wdeleg-v2-1-20c14252bab4@kernel.org \
--to=jlayton@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=chuck.lever@oracle.com \
--cc=kolga@netapp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neilb@suse.de \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox