Linux NFS development
 help / color / mirror / Atom feed
From: Chuck Lever <cel@kernel.org>
To: NeilBrown <neil@brown.name>, Jeff Layton <jlayton@kernel.org>,
	Olga Kornievskaia <okorniev@redhat.com>,
	Dai Ngo <dai.ngo@oracle.com>, Tom Talpey <tom@talpey.com>
Cc: <linux-nfs@vger.kernel.org>
Subject: [PATCH v1 1/7] nfsd: use direct I/O only for the last operation in a COMPOUND
Date: Sun,  4 Oct 2026 15:40:23 -0400	[thread overview]
Message-ID: <20261004194029.10714-2-cel@kernel.org> (raw)
In-Reply-To: <20261004194029.10714-1-cel@kernel.org>

A direct read widens the requested byte range to the file system's
alignment and leaves the payload at a nonzero rq_res.page_base. The
xdr_stream encoder does not account for page_base:
xdr_reserve_space_vec() sizes each chunk from page_len alone, and
xdr_get_next_encode_buffer() opens each new page at its first byte.
The stream's position lags the end of the payload by page_base
bytes.

An NFSv4 operation encoded after such a READ overwrites the tail of
the payload, and the transport sends alignment padding in place of
that operation's result. The client sees corrupted file data
followed by an undecodable reply. NFSv2 and NFSv3 are unaffected:
their READ encoders pass page_base explicitly, and nothing is
encoded into the pages after the payload.

Fall back to buffered or DONTCACHE I/O when the READ is not the last
operation in its COMPOUND, as nfsd4_read() already does for splice
reads.

Fixes: d686e64e931c ("NFSD: Implement NFSD_IO_DIRECT for NFS READ")
Signed-off-by: Chuck Lever <cel@kernel.org>
---
 fs/nfsd/vfs.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 4584d5b94fee..e052b9163692 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -37,6 +37,7 @@
 #ifdef CONFIG_NFSD_V4
 #include "acl.h"
 #include "idmap.h"
+#include "xdr4.h"
 #endif /* CONFIG_NFSD_V4 */
 
 #include "nfsd.h"
@@ -1164,6 +1165,24 @@ nfsd_direct_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
 				eof, host_err);
 }
 
+static bool nfsd_direct_read_ok(struct svc_rqst *rqstp, struct nfsd_file *nf)
+{
+	/* When dio_read_offset_align is zero, dio is not supported */
+	if (!nf->nf_dio_read_offset_align)
+		return false;
+	if (rqstp->rq_res.page_len)
+		return false;
+#ifdef CONFIG_NFSD_V4
+	/*
+	 * The xdr_stream encoder ignores rq_res.page_base, so an operation
+	 * encoded after a direct read would overwrite the payload's tail.
+	 */
+	if (rqstp->rq_vers == 4 && !nfsd4_last_compound_op(rqstp))
+		return false;
+#endif
+	return true;
+}
+
 /**
  * nfsd_iter_read - Perform a VFS read using an iterator
  * @rqstp: RPC transaction context
@@ -1197,8 +1216,7 @@ __be32 nfsd_iter_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
 	case NFSD_IO_BUFFERED:
 		break;
 	case NFSD_IO_DIRECT:
-		/* When dio_read_offset_align is zero, dio is not supported */
-		if (nf->nf_dio_read_offset_align && !rqstp->rq_res.page_len)
+		if (nfsd_direct_read_ok(rqstp, nf))
 			return nfsd_direct_read(rqstp, fhp, nf, offset,
 						count, eof);
 		fallthrough;
-- 
2.55.0


  reply	other threads:[~2026-10-04 19:40 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-04 19:40 [PATCH v1 0/7] NFSD short subjects Chuck Lever
2026-10-04 19:40 ` Chuck Lever [this message]
2026-10-04 19:40 ` [PATCH v1 2/7] nfsd: account for page_base when advancing rq_next_page Chuck Lever
2026-10-04 19:40 ` [PATCH v1 3/7] nfsd: locate the READ sink page from the reply buffer Chuck Lever
2026-10-04 19:40 ` [PATCH v1 4/7] nfsd: keep spliced pages below rq_next_page when a READ fails Chuck Lever
2026-10-04 19:40 ` [PATCH v1 5/7] nfsd: remove unreachable cancel of the layout fence work Chuck Lever
2026-10-04 19:40 ` [PATCH v1 6/7] sunrpc: preserve rq_daddrlen across request deferral Chuck Lever
2026-10-04 19:40 ` [PATCH v1 7/7] sunrpc: assign RQ_LOCAL from the transport on every receive Chuck Lever

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=20261004194029.10714-2-cel@kernel.org \
    --to=cel@kernel.org \
    --cc=dai.ngo@oracle.com \
    --cc=jlayton@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --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