From: Jeff Layton <jlayton@kernel.org>
To: Chuck Lever <cel@kernel.org>,
Chuck Lever <chuck.lever@oracle.com>,
NeilBrown <neil@brown.name>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
"J. Bruce Fields" <bfields@fieldses.org>,
Scott Mayhew <smayhew@redhat.com>,
Trond Myklebust <Trond.Myklebust@netapp.com>,
Andreas Gruenbacher <agruen@suse.de>,
Mike Snitzer <snitzer@kernel.org>,
Rick Macklem <rmacklem@uoguelph.ca>
Cc: Chris Mason <clm@meta.com>,
linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 08/10] nfsd: fix partial-write detection in nfsd_direct_write
Date: Fri, 29 May 2026 13:06:19 -0400 [thread overview]
Message-ID: <c44f1ab33041c297510117903a9e48ae92bd118f.camel@kernel.org> (raw)
In-Reply-To: <0f23fe53-3796-4102-ab62-f28fd53afaf7@kernel.org>
On Fri, 2026-05-29 at 13:03 -0400, Chuck Lever wrote:
> On 5/29/26 1:01 PM, Jeff Layton wrote:
> > On Fri, 2026-05-29 at 12:57 -0400, Chuck Lever wrote:
> > >
> > > On Thu, May 28, 2026, at 5:55 PM, Jeff Layton wrote:
> > > > From: Chris Mason <clm@meta.com>
> > > >
> > > > nfsd_direct_write() walks a list of write segments and, after each
> > > > vfs_iocb_iter_write(), tries to detect a short write so the loop can
> > > > stop before placing the next segment at a wrong file offset:
> > > >
> > > > host_err = vfs_iocb_iter_write(file, kiocb, &segments[i].iter);
> > > > if (host_err < 0)
> > > > return host_err;
> > > > *cnt += host_err;
> > > > if (host_err < segments[i].iter.count)
> > > > break; /* partial write */
> > > >
> > > > vfs_iocb_iter_write() runs the iter through ->write_iter(), which
> > > > advances the iter by the number of bytes written. By the time the
> > > > check runs, segments[i].iter.count is the residual, not the original
> > > > request length:
> > > >
> > > > before write_iter: iter.count == original_len
> > > > after write_iter: iter.count == original_len - host_err
> > > >
> > > > The condition then reduces to host_err < original_len - host_err, so
> > > > the break fires only when less than half of the segment was written.
> > > > Any short write completing between 50% and 99% of the segment slips
> > > > through; the loop advances to the next segment with kiocb->ki_pos
> > > > only bumped by the short amount, writing the next segment's payload
> > > > at the wrong offset and over-reporting *cnt to the NFS client.
> > > >
> > > > Snapshot the segment's byte count before the write and compare
> > > > host_err against that snapshot so any short write breaks the loop.
> > > >
> > > > Fixes: 06c5c97293e3 ("NFSD: Implement NFSD_IO_DIRECT for NFS WRITE")
> > > > Assisted-by: kres:claude-opus-4-7
> > > > Signed-off-by: Chris Mason <clm@meta.com>
> > > > ---
> > > > fs/nfsd/vfs.c | 5 ++++-
> > > > 1 file changed, 4 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
> > > > index 980217f755b7..619f252af4d1 100644
> > > > --- a/fs/nfsd/vfs.c
> > > > +++ b/fs/nfsd/vfs.c
> > > > @@ -1380,6 +1380,7 @@ nfsd_direct_write(struct svc_rqst *rqstp, struct
> > > > svc_fh *fhp,
> > > > struct file *file = nf->nf_file;
> > > > unsigned int nsegs, i;
> > > > ssize_t host_err;
> > > > + size_t expected;
> > > >
> > > > nsegs = nfsd_write_dio_iters_init(nf, rqstp->rq_bvec, nvecs,
> > > > kiocb, *cnt, segments);
> > > > @@ -1401,11 +1402,13 @@ nfsd_direct_write(struct svc_rqst *rqstp,
> > > > struct svc_fh *fhp,
> > > > kiocb->ki_flags |= IOCB_DONTCACHE;
> > > > }
> > > >
> > > > + expected = iov_iter_count(&segments[i].iter);
> > > > +
> > > > host_err = vfs_iocb_iter_write(file, kiocb, &segments[i].iter);
> > > > if (host_err < 0)
> > > > return host_err;
> > > > *cnt += host_err;
> > > > - if (host_err < segments[i].iter.count)
> > > > + if (host_err < (ssize_t)expected)
> > > > break; /* partial write */
> > > > }
> > > >
> > > >
> > > > --
> > > > 2.54.0
> > >
> > > How many filesystems can return a short write in this case?
> > > My impression was that only the NFS client can do that.
> > >
> >
> > No idea right offhand, but NFS is exportable. Since
> > vfs_iocb_iter_write() is allowed to return a short write, I think we
> > have to deal with that properly here.
>
> NFSD_IO_DIRECT is experimental, and doesn't make sense (to me)
> to use with an NFS re-export.
>
> If we can find another filesystem that might return a short write
> with NFSD_IO_DIRECT, I might consider this a higher priority.
>
I'm fairly sure Ceph and CIFS can and they're exportable. For local
filesystems, I'm not even sure how to audit that.
Given that the potential effect is data corruption, omitting this patch
based on guesswork about what filesystems are being exported seems
unwise.
--
Jeff Layton <jlayton@kernel.org>
next prev parent reply other threads:[~2026-05-29 17:06 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-28 21:55 [PATCH 00/10] nfsd: a pile of fixes for random bugs Jeff Layton
2026-05-28 21:55 ` [PATCH 01/10] nfsd: fix BUG_ON in nfsd4_alloc_layout_stateid on racing delegation revoke Jeff Layton
2026-05-28 23:40 ` NeilBrown
2026-05-29 14:44 ` Jeff Layton
2026-05-28 21:55 ` [PATCH 02/10] nfsd: drain callbacks and clear cl_cb_session Jeff Layton
2026-05-29 15:13 ` Chuck Lever
2026-05-29 17:31 ` Jeff Layton
2026-05-28 21:55 ` [PATCH 03/10] nfsd: serialize nfsd4_end_grace() with atomic test-and-set Jeff Layton
2026-05-29 15:38 ` Chuck Lever
2026-05-29 15:57 ` Jeff Layton
2026-05-29 16:05 ` Chuck Lever
2026-05-29 17:02 ` Jeff Layton
2026-05-28 21:55 ` [PATCH 04/10] nfsd: dedup nfs4_client_to_reclaim inserts Jeff Layton
2026-05-29 16:22 ` Chuck Lever
2026-05-28 21:55 ` [PATCH 05/10] nfsd: gate nfs3 setacl by argp->mask Jeff Layton
2026-05-28 21:55 ` [PATCH 06/10] NFSD: Enable return of an updated stable_how to NFS clients Jeff Layton
2026-05-29 10:56 ` Jeff Layton
2026-05-30 7:58 ` NFSv4.1 COMMIT of all changed areas only on flush? " Cedric Blancher
2026-05-30 10:24 ` Jeff Layton
2026-05-28 21:55 ` [PATCH 07/10] NFSD: check truncate permission under inode lock Jeff Layton
2026-05-28 21:55 ` [PATCH 08/10] nfsd: fix partial-write detection in nfsd_direct_write Jeff Layton
2026-05-29 16:57 ` Chuck Lever
2026-05-29 17:01 ` Jeff Layton
2026-05-29 17:03 ` Chuck Lever
2026-05-29 17:06 ` Jeff Layton [this message]
2026-05-29 17:09 ` Chuck Lever
2026-05-28 21:55 ` [PATCH 09/10] nfsd: cap decoded POSIX ACL count to bound sort cost Jeff Layton
2026-05-28 22:11 ` Rick Macklem
2026-05-28 23:11 ` Chuck Lever
2026-05-29 0:07 ` Chuck Lever
2026-05-29 10:48 ` Jeff Layton
2026-05-29 13:20 ` Chuck Lever
2026-05-29 7:34 ` Cedric Blancher
2026-05-29 10:50 ` Jeff Layton
2026-05-29 18:34 ` Chuck Lever
2026-05-29 18:41 ` Jeff Layton
2026-05-29 18:48 ` Chuck Lever
2026-05-29 23:04 ` Rick Macklem
2026-05-28 21:55 ` [PATCH 10/10] nfsd: validate symlink target length in NFSv4 CREATE Jeff Layton
2026-05-29 18:55 ` 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=c44f1ab33041c297510117903a9e48ae92bd118f.camel@kernel.org \
--to=jlayton@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=Trond.Myklebust@netapp.com \
--cc=agruen@suse.de \
--cc=bfields@fieldses.org \
--cc=cel@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=clm@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=okorniev@redhat.com \
--cc=rmacklem@uoguelph.ca \
--cc=smayhew@redhat.com \
--cc=snitzer@kernel.org \
--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
Powered by JetHome