NFSD: Implement NFSD_IO_DIRECT for NFS WRITE
Subsystems (3)
Chuck Lever
maintainerv4 cover NFSD: Implement NFSD_IO_DIRECT for NFS WRITE
From: Chuck Lever <[email protected]>
Following on https://lore.kernel.org/linux-nfs/[email protected]/
this series applies on the nfsd-testing testing branch and includes both patches needed to make NFSD Direct WRITE work.
Changes since v3:
* Address checkpatch.pl nits in 2/3
* Add an untested patch to mark ingress RDMA Read chunks
Chuck Lever (2):
NFSD: Enable return of an updated stable_how to NFS clients
svcrdma: Mark Read chunks
Mike Snitzer (1):
NFSD: Implement NFSD_IO_DIRECT for NFS WRITE
fs/nfsd/debugfs.c | 1 + fs/nfsd/nfs3proc.c | 2 +- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfsproc.c | 3 +- fs/nfsd/trace.h | 1 + fs/nfsd/vfs.c | 233 +++++++++++++++++++++++- fs/nfsd/vfs.h | 6 +- fs/nfsd/xdr3.h | 2 +- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 5 + 9 files changed, 239 insertions(+), 16 deletions(-)
Signature · 1 line
2.51.0
Chuck Lever
maintainerPATCH v4 1/3 NFSD: Enable return of an updated stable_how to NFS clients
From: Chuck Lever <[email protected]>
In a subsequent patch, nfsd_vfs_write() will promote an UNSTABLE WRITE to be a FILE_SYNC WRITE. This indicates that the client does not need a subsequent COMMIT operation, saving a round trip and allowing the client to dispense with cached dirty data as soon as it receives the server's WRITE response.
This patch refactors nfsd_vfs_write() to return a possibly modified stable_how value to its callers. No behavior change is expected.
--- fs/nfsd/nfs3proc.c | 2 +- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfsproc.c | 3 ++- fs/nfsd/vfs.c | 11 ++++++----- fs/nfsd/vfs.h | 6 ++++-- fs/nfsd/xdr3.h | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-)
fs/nfsd/nfs3proc.c +1 -1
@@ -236,7 +236,7 @@ nfsd3_proc_write(struct svc_rqst *rqstp) resp->committed = argp->stable; resp->status =nfsd_write (rqstp, &resp->fh, argp->offset, &argp->payload, &cnt, - resp->committed, resp->verf); + &resp->committed, resp->verf); resp->count = cnt; resp->status =nfsd3_map_status (resp->status);return rpc_success;
fs/nfsd/nfs4proc.c +1 -1
@@ -1285,7 +1285,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, write->wr_how_written = write->wr_stable_how; status =nfsd_vfs_write (rqstp, &cstate->current_fh, nf, write->wr_offset, &write->wr_payload, - &cnt, write->wr_how_written, + &cnt, &write->wr_how_written, (__be32 *)write->wr_verifier.data);nfsd_file_put (nf);
fs/nfsd/nfsproc.c +2 -1
@@ -251,6 +251,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)struct nfsd_writeargs *argp = rqstp->rq_argp;struct nfsd_attrstat *resp = rqstp->rq_resp;unsigned long cnt = argp->len; +u32 committed =NFS_DATA_SYNC ; dprintk("nfsd: WRITE %s %u bytes at %d\n", SVCFH_fmt(&argp->fh),
@@ -258,7 +259,7 @@ nfsd_proc_write(struct svc_rqst *rqstp)fh_copy (&resp->fh, &argp->fh); resp->status =nfsd_write (rqstp, &resp->fh, argp->offset, - &argp->payload, &cnt,NFS_DATA_SYNC ,NULL ); + &argp->payload, &cnt, &committed,NULL );if (resp->status == nfs_ok) resp->status =fh_getattr (&resp->fh, &resp->stat);else if (resp->status == nfserr_jukebox)
fs/nfsd/vfs.c +6 -5
@@ -1262,7 +1262,7 @@ static int wait_for_concurrent_writes(struct file *file)* @offset: Byte offset of start * @payload: xdr_buf containing the write payload * @cnt: IN: number of bytes to write, OUT: number of bytes actually written -* @stable: An NFS stable_how value +* @stable_how: IN: Client's requested stable_how, OUT: Actual stable_how * @verf: NFS WRITE verifier * * Upon return, caller must invoke fh_put on @fhp.
@@ -1274,11 +1274,12 @@ __be32 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct nfsd_file *nf, loff_t offset, const struct xdr_buf *payload, unsigned long *cnt, - int stable, __be32 *verf) + u32 *stable_how, __be32 *verf) { struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);struct file *file = nf->nf_file;struct super_block *sb =file_inode (file)->i_sb; +u32 stable = *stable_how;struct kiocb kiocb;struct svc_export *exp;struct iov_iter iter;
@@ -1434,7 +1435,7 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,* @offset: Byte offset of start * @payload: xdr_buf containing the write payload * @cnt: IN: number of bytes to write, OUT: number of bytes actually written -* @stable: An NFS stable_how value +* @stable_how: IN: Client's requested stable_how, OUT: Actual stable_how * @verf: NFS WRITE verifier * * Upon return, caller must invoke fh_put on @fhp.
@@ -1444,7 +1445,7 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,*/ __be32 nfsd_write (struct svc_rqst *rqstp,struct svc_fh *fhp,loff_t offset, -const struct xdr_buf *payload,unsigned long *cnt,int stable, +const struct xdr_buf *payload,unsigned long *cnt,u32 *stable_how,__be32 *verf) {struct nfsd_file *nf;
@@ -1457,7 +1458,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, goto out; err =nfsd_vfs_write (rqstp, fhp, nf, offset, payload, cnt, - stable, verf); + stable_how, verf);nfsd_file_put (nf); out:trace_nfsd_write_done (rqstp, fhp, offset, *cnt);
fs/nfsd/vfs.h +4 -2
@@ -130,11 +130,13 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *eof);__be32 nfsd_write (struct svc_rqst *rqstp,struct svc_fh *fhp,loff_t offset,const struct xdr_buf *payload, -unsigned long *cnt,int stable,__be32 *verf); +unsigned long *cnt,u32 *stable_how, +__be32 *verf);__be32 nfsd_vfs_write (struct svc_rqst *rqstp,struct svc_fh *fhp,struct nfsd_file *nf,loff_t offset,const struct xdr_buf *payload, -unsigned long *cnt,int stable,__be32 *verf); +unsigned long *cnt,u32 *stable_how, +__be32 *verf);__be32 nfsd_readlink (struct svc_rqst *,struct svc_fh *,char *,int *); __be32 nfsd_symlink(struct svc_rqst *, struct svc_fh *,
fs/nfsd/xdr3.h +1 -1
@@ -152,7 +152,7 @@ struct nfsd3_writeres {__be32 status;struct svc_fh fh;unsigned long count; -int committed; +u32 committed;__be32 verf[2 ]; };
Signature · 1 line
2.51.0
Re: [PATCH v4 1/3] NFSD: Enable return of an updated stable_how to NFS clients
Quoted 4 lines · Chuck Lever
From: Chuck Lever <[email protected]>
In a subsequent patch,
nfsd_vfs_write()will promote an UNSTABLE WRITE to be aFILE_SYNCWRITE. This indicates that the client does
I'd much prefer you'd mention why that subsequen patch needs to update it instead of being so vague. That really helps when trying to understand the change when finding it in a bisect or blame.
Chuck Lever
maintainerPATCH v4 2/3 NFSD: Implement NFSD_IO_DIRECT for NFS WRITE
In reply to Chuck LeverFrom: Mike Snitzer <[email protected]>
If NFSD_IO_DIRECT is used, split any misaligned WRITE into a start, middle and end as needed. The large middle extent is DIO-aligned and the start and/or end are misaligned. Synchronous buffered IO (with preference towards using DONTCACHE) is used for the misaligned extents and O_DIRECT is used for the middle DIO-aligned extent.
nfsd_issue_write_dio() promotes @stable_how to NFS_FILE_SYNC, which allows the client to drop its dirty data and avoid needing an extra COMMIT operation.
If vfs_iocb_iter_write() returns -ENOTBLK, due to its inability to invalidate the page cache on behalf of the DIO WRITE, then nfsd_issue_write_dio() will fall back to using buffered IO.
These changes served as the original starting point for the NFS client's misaligned O_DIRECT support that landed with commit c817248fc831 ("nfs/localio: add proper O_DIRECT support for READ and WRITE"). But NFSD's support is simpler because it currently doesn't use AIO completion.
--- fs/nfsd/debugfs.c | 1 + fs/nfsd/trace.h | 1 + fs/nfsd/vfs.c | 222 ++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 219 insertions(+), 5 deletions(-)
fs/nfsd/debugfs.c +1 -0
@@ -108,6 +108,7 @@ static int nfsd_io_cache_write_set(void *data, u64 val)switch (val) {case NFSD_IO_BUFFERED :case NFSD_IO_DONTCACHE : +case NFSD_IO_DIRECT : nfsd_io_cache_write = val;break ;default :
fs/nfsd/trace.h +1 -0
@@ -469,6 +469,7 @@ DEFINE_NFSD_IO_EVENT(read_io_done);DEFINE_NFSD_IO_EVENT (read_done);DEFINE_NFSD_IO_EVENT (write_start);DEFINE_NFSD_IO_EVENT (write_opened); +DEFINE_NFSD_IO_EVENT (write_direct);DEFINE_NFSD_IO_EVENT (write_io_done);DEFINE_NFSD_IO_EVENT (write_done);DEFINE_NFSD_IO_EVENT (commit_start);
fs/nfsd/vfs.c +217 -5
255 lines not on this page · raw message
Signature · 1 line
2.51.0
Quoted 7 lines · Chuck Lever
From: Mike Snitzer <[email protected]>
If
NFSD_IO_DIRECTis used, split any misaligned WRITE into a start, middle and end as needed. The large middle extent is DIO-aligned and the start and/or end are misaligned. Synchronous buffered IO (with preference towards using DONTCACHE) is used for the misaligned extents andO_DIRECTis used for the middle DIO-aligned extent.
Can you define synchronous better here? The term is unfortunately overloaded between synchronous syscalls vs aio/io_uring and O_(D)SYNC style I/O. As of now I don't understand which one you mean, especially with the DONTCACHE reference thrown in, but I guess I'll figure it out reading the patch.
Quoted 3 lines
If
vfs_iocb_iter_write()returns-ENOTBLK, due to its inability to invalidate the page cache on behalf of the DIO WRITE, thennfsd_issue_write_dio()will fall back to using buffered IO.
Did you see -ENOTBLK leaking out of the file systems? Because at least for iomap it is supposed to be an indication that the file system ->write_iter handler needs to retry using buffered I/O and never leak to the caller.
Quoted 5 lines
These changes served as the original starting point for the NFS client's misaligned
O_DIRECTsupport that landed with commitc817248fc831("nfs/localio: add properO_DIRECTsupport for READ and WRITE"). But NFSD's support is simpler because it currently doesn't use AIO completion.
I don't understand this paragraph. What does starting point mean here? How does it matter for the patch description?
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1261
Quoted 5 lines
fs/nfsd/vfs.c +5
-0+struct nfsd_write_dio { +ssize_t start_len;/* Length for misaligned first extent */ +ssize_t middle_len;/* Length for DIO-aligned middle extent */ +ssize_t end_len;/* Length for misaligned last extent */ +};
Looking at how the code is structured later on, it seems like it would work much better if each of these sections had it's own object with the len, iov_iter, flag if it's aligned, etc. Otherwise we have this structure and lots of arrays of three items passed around.
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1291
Quoted 3 lines
fs/nfsd/vfs.c +3
-0+static bool +nfsd_iov_iter_aligned_bvec (const struct iov_iter *i,unsigned int addr_mask, +unsigned int len_mask)
Wouldn't it make sense to track the alignment when building the bio_vec array instead of doing another walk here touching all cache lines?
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (unlikely(dio_blocksize > PAGE_SIZE)) + return false;
Why does this matter? Can you add a comment explaining it?
Quoted 5 lines
fs/nfsd/vfs.c +5
-0+static int +nfsd_buffered_write (struct svc_rqst *rqstp,struct file *file, +unsigned int nvecs,unsigned long *cnt, +struct kiocb *kiocb) +{
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1374
Quoted 10 lines
fs/nfsd/vfs.c +10
-0+struct iov_iter iter; +int host_err; + +iov_iter_bvec (&iter,ITER_SOURCE , rqstp->rq_bvec, nvecs, *cnt); + host_err =vfs_iocb_iter_write (file, kiocb, &iter); +if (host_err <0 ) +return host_err; + *cnt = host_err; + +return 0 ;
Nothing really buffered here per se, it's just a small wrapper around vfs_iocb_iter_write.
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1404
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+/* +* Any buffered IO issued here will be misaligned, use +* sync IO to ensure it has completed before returning. +* Also update @stable_how to avoid need for COMMIT. +*/ + kiocb->ki_flags |= (IOCB_DSYNC |IOCB_SYNC );
What do you mean with completed before returning? I guess you mean writeback actually happening, right? Why do you need that, why do you also force it for the direct I/O?
Also IOCB_SYNC is wrong here, as the only thing it does over IOCB_DSYNC is also forcing back of metadata not needed to find data (aka timestamps), which I can't see any need for here.
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+ *stable_how =NFS_FILE_SYNC ; + + *cnt =0 ; +for (int i =0 ; i < n_iters; i++) { +if (iter_is_dio_aligned[i]) + kiocb->ki_flags |=IOCB_DIRECT ;
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1420
Quoted 10 lines
fs/nfsd/vfs.c +10
-0+else + kiocb->ki_flags &= ~IOCB_DIRECT ; + + host_err =vfs_iocb_iter_write (file, kiocb, &iter[i]); +if (host_err <0 ) { +/* +* VFS will return -ENOTBLK if DIO WRITE fails to +* invalidate the page cache. Retry using buffered IO. +*/ +if (unlikely (host_err == -ENOTBLK )) {
The VFS certainly does not, and if it leaks out of a specific file system we need to fix that.
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1431
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+ }else if (unlikely (host_err == -EINVAL )) { +struct inode *inode =d_inode (fhp->fh_dentry); + +pr_info_ratelimited ("nfsd: Direct I/O alignment failure on %s/%ld\n" , + inode->i_sb->s_id, inode->i_ino); + host_err = -ESERVERFAULT ;
-EINVAL can be lot more things than alignment failure. And more
importantly alignment failures should not happen with the proper checks in place.
Chuck Lever
maintainerQuoted 14 lines · Christoph Hellwig
Quoted 13 lines · Chuck Lever
From: Mike Snitzer <[email protected]>
fs/nfsd/vfs.c +11
-0+static int +nfsd_buffered_write (struct svc_rqst *rqstp,struct file *file, +unsigned int nvecs,unsigned long *cnt, +struct kiocb *kiocb) +{ +struct iov_iter iter; +int host_err; + +iov_iter_bvec (&iter,ITER_SOURCE , rqstp->rq_bvec, nvecs, *cnt); + host_err =vfs_iocb_iter_write (file, kiocb, &iter); +if (host_err <0 )
Quoted 8 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1374
Quoted 4 lines
fs/nfsd/vfs.c +4
-0+return host_err; + *cnt = host_err; + +return 0 ;Nothing really buffered here per se, it's just a small wrapper around
vfs_iocb_iter_write.
This is the original NFSD_IO_BUFFERED code, refactored out of nfsd_vfs_write(). IMO it might be more clear what's going on if the refactoring was done in a separate prerequisite patch.
Quoted 10 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1431
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+ }else if (unlikely (host_err == -EINVAL )) { +struct inode *inode =d_inode (fhp->fh_dentry); + +pr_info_ratelimited ("nfsd: Direct I/O alignment failure on %s/%ld\n" , + inode->i_sb->s_id, inode->i_ino); + host_err = -ESERVERFAULT ;
-EINVALcan be lot more things than alignment failure. And more
importantly alignment failures should not happen with the proper checks in place.
I tend to agree that I expect an alignment failure will rarely if ever happen if we've done our job well.
Signature · 1 line
Chuck Lever
Quoted 2 lines · Chuck Lever
I tend to agree that I expect an alignment failure will rarely if ever happen if we've done our job well.
It should never happen if the job was done properly. But when -EINVAL happens it can be just as likely any other mismatched condition.
Quoted 9 lines · Christoph Hellwig
Quoted 7 lines · Chuck Lever
From: Mike Snitzer <[email protected]>
If
NFSD_IO_DIRECTis used, split any misaligned WRITE into a start, middle and end as needed. The large middle extent is DIO-aligned and the start and/or end are misaligned. Synchronous buffered IO (with preference towards using DONTCACHE) is used for the misaligned extents andO_DIRECTis used for the middle DIO-aligned extent.
Quoted 5 lines
Can you define synchronous better here? The term is unfortunately overloaded between synchronous syscalls vs aio/io_uring and O_(D)SYNC style I/O. As of now I don't understand which one you mean, especially with the DONTCACHE reference thrown in, but I guess I'll figure it out reading the patch.
It clearly talks about synchronous IO. DONTCACHE just happens to be the buffered IO that'll be used if supported.
I don't see anything that needs changing here.
Quoted 8 lines
Quoted 3 lines
If
vfs_iocb_iter_write()returns-ENOTBLK, due to its inability to invalidate the page cache on behalf of the DIO WRITE, thennfsd_issue_write_dio()will fall back to using buffered IO.Did you see
-ENOTBLKleaking out of the file systems? Because at least for iomap it is supposed to be an indication that the file system ->write_iter handler needs to retry using buffered I/O and never leak to the caller.
fs/iomap/direct-io.c:__iomap_dio_rw() will return -ENOTBLK on its own.
Quoted 8 lines
Quoted 5 lines
These changes served as the original starting point for the NFS client's misaligned
O_DIRECTsupport that landed with commitc817248fc831("nfs/localio: add properO_DIRECTsupport for READ and WRITE"). But NFSD's support is simpler because it currently doesn't use AIO completion.I don't understand this paragraph. What does starting point mean here? How does it matter for the patch description?
This patch's NFSD changes were starting point for NFS commit c817248fc831
How does it matter that this NFSD code served as the basis for NFS code that has been merged? I thought it useful context.
Quoted 10 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1261
Quoted 5 lines
fs/nfsd/vfs.c +5
-0+struct nfsd_write_dio { +ssize_t start_len;/* Length for misaligned first extent */ +ssize_t middle_len;/* Length for DIO-aligned middle extent */ +ssize_t end_len;/* Length for misaligned last extent */ +};Looking at how the code is structured later on, it seems like it would work much better if each of these sections had it's own object with the len,
iov_iter, flag if it's aligned, etc. Otherwise we have this structure and lots of arrays of three items passed around.
I did look at doing that, really isn't much better. And 2 isn't lots.
But not opposed to revisiting it.
Would prefer that cleanup, if done, to happen with an incremental follow-up patch.
Quoted 6 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1291
Quoted 3 lines
fs/nfsd/vfs.c +3
-0+static bool +nfsd_iov_iter_aligned_bvec (const struct iov_iter *i,unsigned int addr_mask, +unsigned int len_mask)Wouldn't it make sense to track the alignment when building the
bio_vecarray instead of doing another walk here touching all cache lines?
Yes, that is the conventional wisdom that justified Keith removing iov_iter_aligned. But for NFSD's WRITE payload the bio_vec is built outside of the fs/nfsd/vfs.c code. Could be there is a natural way to clean this up (to make the sunrpc layer to conditionally care about alignment) but I didn't confront that yet.
Room for follow-on improvement to be sure.
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (unlikely(dio_blocksize > PAGE_SIZE)) + return false;Why does this matter? Can you add a comment explaining it?
I did/do have concerns that a bug in the storage driver could expose dio_offset_align that is far too large and so bounded dio_blocksize to a conservative size. What is a better constant to check?
But... for trusted storage and drivers, probably doesn't matter and could be removed.
I split the check out:
if (unlikely(dio_blocksize > PAGE_SIZE))
return false;
if (unlikely(len < dio_blocksize))
return false;
could've been:
if (unlikely(dio_blocksize > PAGE_SIZE || len < dio_blocksize))
return false;physical blocksizes larger than PAGE_SIZE are coming (or here?) but overall this initial NFSD O_DIRECT support isn't meant to concern itself with such exotics at this point.
Quoted 11 lines
Quoted 11 lines
fs/nfsd/vfs.c +11
-0+static int +nfsd_buffered_write (struct svc_rqst *rqstp,struct file *file, +unsigned int nvecs,unsigned long *cnt, +struct kiocb *kiocb) +{ +struct iov_iter iter; +int host_err; + +iov_iter_bvec (&iter,ITER_SOURCE , rqstp->rq_bvec, nvecs, *cnt); + host_err =vfs_iocb_iter_write (file, kiocb, &iter); +if (host_err <0 )
Quoted 8 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1374
Quoted 4 lines
fs/nfsd/vfs.c +4
-0+return host_err; + *cnt = host_err; + +return 0 ;Nothing really buffered here per se, it's just a small wrapper around
vfs_iocb_iter_write.
Its factored out code with in a named function. Name fit its purpose.
Quoted 10 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1404
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+/* +* Any buffered IO issued here will be misaligned, use +* sync IO to ensure it has completed before returning. +* Also update @stable_how to avoid need for COMMIT. +*/ + kiocb->ki_flags |= (IOCB_DSYNC |IOCB_SYNC );What do you mean with completed before returning? I guess you mean writeback actually happening, right? Why do you need that, why do you also force it for the direct I/O?
The IO needs to have reached stable storage.
Changing these flags when IOCB_DIRECT used doesn't seem needed.
Open to suggestions, could be I'm being too heavy but the goal is to ensure the misaligned ends (head and tail) have hit the storage.
Quoted 3 lines
Also
IOCB_SYNCis wrong here, as the only thing it does overIOCB_DSYNCis also forcing back of metadata not needed to find data (aka timestamps), which I can't see any need for here.
Well, we're eliding any followup SYNC from the NFS client by setting stable_how to NFS_FILE_SYNC, so I made sure to use SYNC:
Quoted 11 lines
Quoted 11 lines
fs/nfsd/vfs.c +11
-0+ *stable_how =NFS_FILE_SYNC ; + + *cnt =0 ; +for (int i =0 ; i < n_iters; i++) { +if (iter_is_dio_aligned[i]) + kiocb->ki_flags |=IOCB_DIRECT ; +else + kiocb->ki_flags &= ~IOCB_DIRECT ; + + host_err =vfs_iocb_iter_write (file, kiocb, &iter[i]); +if (host_err <0 ) {
Quoted 8 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1420
Quoted 5 lines
fs/nfsd/vfs.c +5
-0+/* +* VFS will return -ENOTBLK if DIO WRITE fails to +* invalidate the page cache. Retry using buffered IO. +*/ +if (unlikely (host_err == -ENOTBLK )) {The VFS certainly does not, and if it leaks out of a specific file system we need to fix that.
As I said above, fs/iomap/direct-io.c:__iomap_dio_rw() does.
Quoted 10 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1431
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+ }else if (unlikely (host_err == -EINVAL )) { +struct inode *inode =d_inode (fhp->fh_dentry); + +pr_info_ratelimited ("nfsd: Direct I/O alignment failure on %s/%ld\n" , + inode->i_sb->s_id, inode->i_ino); + host_err = -ESERVERFAULT ;
-EINVALcan be lot more things than alignment failure. And more
importantly alignment failures should not happen with the proper checks in place.
Regardless, the most likely outcome from issing what should be aligned DIO only to get -EINVAL is exactly what is addressed with this _unlikely_ error handling: misaligned IO.. should happen but bugs happen (or optimization happens, e.g. in the future to fold alignment checking into sunrpc's WRITE bio_vec creation, and in turn bugs could happen).
Not submitting a new version of this patch until/unless there is clear feedback there is something in this v4 that really cannot stand.
Thanks for your review!
Quoted 10 lines · Mike Snitzer
Quoted 5 lines
Can you define synchronous better here? The term is unfortunately overloaded between synchronous syscalls vs aio/io_uring and O_(D)SYNC style I/O. As of now I don't understand which one you mean, especially with the DONTCACHE reference thrown in, but I guess I'll figure it out reading the patch.
It clearly talks about synchronous IO. DONTCACHE just happens to be the buffered IO that'll be used if supported.
I don't see anything that needs changing here.
Again, what synchronous? O_(D)SYNC, or !async?
Quoted 11 lines
Quoted 9 lines
Quoted 4 lines
If
vfs_iocb_iter_write()returns-ENOTBLK, due to its inability to invalidate the page cache on behalf of the DIO WRITE, thennfsd_issue_write_dio()will fall back to using buffered IO.Did you see
-ENOTBLKleaking out of the file systems? Because at least for iomap it is supposed to be an indication that the file system ->write_iter handler needs to retry using buffered I/O and never leak to the caller.fs/iomap/direct-io.c:__iomap_dio_rw() will return
-ENOTBLKon its own.
Yes, and the callers in the file system methods are supposed to handle that and fall back to buffered I/O. Take a look at xfs_file_write_iter.
If this leaks out of ->write_iter we have a problem that needs fixing in the affected file system.
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
These changes served as the original starting point for the NFS client's misaligned
O_DIRECTsupport that landed with commitc817248fc831("nfs/localio: add properO_DIRECTsupport for READ and WRITE"). But NFSD's support is simpler because it currently doesn't use AIO completion.
Quoted 5 lines
Quoted 2 lines
I don't understand this paragraph. What does starting point mean here? How does it matter for the patch description?
This patch's NFSD changes were starting point for NFS commit
c817248fc831
But that commit is already in? This sentence really confuses me.
Quoted 2 lines
Would prefer that cleanup, if done, to happen with an incremental follow-up patch.
Starting out with well structured code is generally a good idea :(
Quoted 8 lines
Quoted 7 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1291
Quoted 4 lines
fs/nfsd/vfs.c +3
-0+static bool +nfsd_iov_iter_aligned_bvec (const struct iov_iter *i,unsigned int addr_mask, +unsigned int len_mask)Wouldn't it make sense to track the alignment when building the
bio_vecarray instead of doing another walk here touching all cache lines?
Quoted 5 lines
Yes, that is the conventional wisdom that justified Keith removing
iov_iter_aligned. But for NFSD's WRITE payload thebio_vecis built outside of thefs/nfsd/vfs.ccode. Could be there is a natural way to clean this up (to make the sunrpc layer to conditionally care about alignment) but I didn't confront that yet.
Well, for the block code it's also build outside the layer consuming it. But Keith showed that you can easily communicate that information and avoid extra loops touching the cache lines.
Quoted 11 lines
Room for follow-on improvement to be sure.
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (unlikely(dio_blocksize > PAGE_SIZE)) + return false;Why does this matter? Can you add a comment explaining it?
I did/do have concerns that a bug in the storage driver could expose
dio_offset_alignthat is far too large and so boundeddio_blocksizeto a conservative size. What is a better constant to check?
I don't think there is a good upper limit, we not do supper LBA sizes larger than PAGE_SIZE, although I don't think there's any shipping devices that do that. But the most important thing is to always add a comment with the rationale for such non-obvious checks so that someone who has to lift it later can understand why it is done.
Quoted 9 lines
Quoted 7 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1404
Quoted 3 lines
fs/nfsd/vfs.c +3
-0+* Also update @stable_how to avoid need for COMMIT. +*/ + kiocb->ki_flags |= (IOCB_DSYNC |IOCB_SYNC );What do you mean with completed before returning? I guess you mean writeback actually happening, right? Why do you need that, why do you also force it for the direct I/O?
The IO needs to have reached stable storage.
Please spell that out. Because that's different from how completed is generally used in file systems and storage protocols.
Quoted 6 lines
Quoted 3 lines
Also
IOCB_SYNCis wrong here, as the only thing it does overIOCB_DSYNCis also forcing back of metadata not needed to find data (aka timestamps), which I can't see any need for here.Well, we're eliding any followup SYNC from the NFS client by setting
stable_howtoNFS_FILE_SYNC, so I made sure to use SYNC:
Why do you care about timestamps reaching stable storage? Which is the only practical extra thing IOCB_SYNC will give you. If there is a good reason for that, add a comment because that's a bit unexpected (and in general IOCB_SYNC / O_SYNC is just a sign that someone does not know about SYNC vs DSYNC semantics).
Quoted 4 lines
Quoted 2 lines
The VFS certainly does not, and if it leaks out of a specific file system we need to fix that.
As I said above, fs/iomap/direct-io.c:__iomap_dio_rw() does.
As stated above that's an internal helper and the code is supposed to be handled by the file system and never leak out.
Quoted 3 lines
Regardless, the most likely outcome from issing what should be aligned DIO only to get
-EINVALis exactly what is addressed with this _unlikely_ error handling: misaligned IO..
No. There is no reason why this is any more likely than any of the other -EINVAL cases.
Chuck Lever
maintainerQuoted 24 lines · Christoph Hellwig
Quoted 10 lines · Mike Snitzer
Quoted 5 lines
Can you define synchronous better here? The term is unfortunately overloaded between synchronous syscalls vs aio/io_uring and O_(D)SYNC style I/O. As of now I don't understand which one you mean, especially with the DONTCACHE reference thrown in, but I guess I'll figure it out reading the patch.
It clearly talks about synchronous IO. DONTCACHE just happens to be the buffered IO that'll be used if supported.
I don't see anything that needs changing here.
Again, what synchronous? O_(D)SYNC, or !async?
Quoted 10 lines
Quoted 9 lines
Quoted 4 lines
If
vfs_iocb_iter_write()returns-ENOTBLK, due to its inability to invalidate the page cache on behalf of the DIO WRITE, thennfsd_issue_write_dio()will fall back to using buffered IO.Did you see
-ENOTBLKleaking out of the file systems? Because at least for iomap it is supposed to be an indication that the file system ->write_iter handler needs to retry using buffered I/O and never leak to the caller.
Quoted 7 lines
Quoted 1 line
fs/iomap/direct-io.c:__iomap_dio_rw() will return
-ENOTBLKon its own.Yes, and the callers in the file system methods are supposed to handle that and fall back to buffered I/O. Take a look at
xfs_file_write_iter.If this leaks out of ->write_iter we have a problem that needs fixing in the affected file system.
What I'm hearing is that nfsd_vfs_write() should never see -ENOTBLK, so this check is essentially dead code.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 5 lines
These changes served as the original starting point for the NFS client's misaligned
O_DIRECTsupport that landed with commitc817248fc831("nfs/localio: add properO_DIRECTsupport for READ and WRITE"). But NFSD's support is simpler because it currently doesn't use AIO completion.
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
I don't understand this paragraph. What does starting point mean here? How does it matter for the patch description?
This patch's NFSD changes were starting point for NFS commit
c817248fc831But that commit is already in? This sentence really confuses me.
I'm not convinced this paragraph in the patch description is needed. Can it be removed?
Quoted 2 lines
Quoted 2 lines
Would prefer that cleanup, if done, to happen with an incremental follow-up patch.
I'm not following. What clean-up? And why push it out to a later merge?
Quoted 1 line
Starting out with well structured code is generally a good idea :(
That is my preference as well, though I recognize that some subsystems do not mind merging incomplete features and moving forward from there.
Let's remember, upstream does not target specific kernel releases when developing new features. You might want your feature to hit the next LTS kernel, and even that is frowned upon. Let's focus on getting this as right as we know how to, rather than hitting a delivery date.
Quoted 13 lines
Quoted 7 lines
Quoted 6 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1291
Quoted 3 lines
fs/nfsd/vfs.c +3
-0+static bool +nfsd_iov_iter_aligned_bvec (const struct iov_iter *i,unsigned int addr_mask, +unsigned int len_mask)Wouldn't it make sense to track the alignment when building the
bio_vecarray instead of doing another walk here touching all cache lines?Quoted 5 lines
Yes, that is the conventional wisdom that justified Keith removing
iov_iter_aligned. But for NFSD's WRITE payload thebio_vecis built outside of thefs/nfsd/vfs.ccode. Could be there is a natural way to clean this up (to make the sunrpc layer to conditionally care about alignment) but I didn't confront that yet.
Quoted 3 lines
Well, for the block code it's also build outside the layer consuming it. But Keith showed that you can easily communicate that information and avoid extra loops touching the cache lines.
Again, is there a reason to push this suggestion out to a later merge window? It seems reasonable to tackle it now.
(Perhaps to get us started, Christoph, do you know of specific code that shows how this code could be reorganized?)
Quoted 25 lines
Quoted 10 lines
Room for follow-on improvement to be sure.
Quoted 4 lines
Review
Quoted 2 lines
(quoted diff) +2
-0+ if (unlikely(dio_blocksize > PAGE_SIZE)) + return false;Why does this matter? Can you add a comment explaining it?
I did/do have concerns that a bug in the storage driver could expose
dio_offset_alignthat is far too large and so boundeddio_blocksizeto a conservative size. What is a better constant to check?I don't think there is a good upper limit, we not do supper LBA sizes larger than
PAGE_SIZE, although I don't think there's any shipping devices that do that. But the most important thing is to always add a comment with the rationale for such non-obvious checks so that someone who has to lift it later can understand why it is done.Quoted 8 lines
Quoted 7 lines
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1404
Quoted 3 lines
fs/nfsd/vfs.c +3
-0+* Also update @stable_how to avoid need for COMMIT. +*/ + kiocb->ki_flags |= (IOCB_DSYNC |IOCB_SYNC );What do you mean with completed before returning? I guess you mean writeback actually happening, right? Why do you need that, why do you also force it for the direct I/O?
Quoted 4 lines
Quoted 1 line
The IO needs to have reached stable storage.
Please spell that out. Because that's different from how completed is generally used in file systems and storage protocols.
It's sensible to add a comment that cites the NFS protocol compliance mandate that states a data durability requirement.
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Also
IOCB_SYNCis wrong here, as the only thing it does overIOCB_DSYNCis also forcing back of metadata not needed to find data (aka timestamps), which I can't see any need for here.
Quoted 8 lines
Quoted 2 lines
Well, we're eliding any followup SYNC from the NFS client by setting
stable_howtoNFS_FILE_SYNC, so I made sure to use SYNC:Why do you care about timestamps reaching stable storage? Which is the only practical extra thing
IOCB_SYNCwill give you. If there is a good reason for that, add a comment because that's a bit unexpected (and in generalIOCB_SYNC/O_SYNCis just a sign that someone does not know about SYNC vs DSYNC semantics).
If NFSD responds with NFS_FILE_SYNC here, then timestamps need to be persisted as well as data. As discussed in other threads, currently nfsd_vfs_write() seems to miss that mark.
So either: return NFS_DATA_SYNC (which means we've persisted only the data) or make this path persist the timestamps too.
I haven't seen any existing code that convinces me that setting both IOCB_SYNC and IOCB_DSYNC is necessary.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
The VFS certainly does not, and if it leaks out of a specific file system we need to fix that.
As I said above, fs/iomap/direct-io.c:__iomap_dio_rw() does.
As stated above that's an internal helper and the code is supposed to be handled by the file system and never leak out.
Quoted 6 lines
Quoted 3 lines
Regardless, the most likely outcome from issing what should be aligned DIO only to get
-EINVALis exactly what is addressed with this _unlikely_ error handling: misaligned IO..No. There is no reason why this is any more likely than any of the other
-EINVALcases.
Agreed, the likelihood of getting an -EINVAL here due to a block alignment issue is much lower than getting -EINVAL due to other problems.
Signature · 1 line
Chuck Lever
Quoted 2 lines · Chuck Lever
What I'm hearing is that
nfsd_vfs_write()should never see-ENOTBLK, so this check is essentially dead code.
That's how iomap_dio_rw is designed to work. If it ever leaks out, that is a file system bug because no other caller of ->write_iter handles -ENOTBLK.
Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Quoted 5 lines
These changes served as the original starting point for the NFS client's misaligned
O_DIRECTsupport that landed with commitc817248fc831("nfs/localio: add properO_DIRECTsupport for READ and WRITE"). But NFSD's support is simpler because it currently doesn't use AIO completion.I don't understand this paragraph. What does starting point mean here? How does it matter for the patch description?
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
This patch's NFSD changes were starting point for NFS commit
c817248fc831But that commit is already in? This sentence really confuses me.
I'm not convinced this paragraph in the patch description is needed. Can it be removed?
I guess Mike wants to say the two are based on the concept. But given that c817248fc831 is already in I'd expect to word it as "these changes are similar to the direct I/O writes implemented for the NFS client local I/O feature in commit c817248fc831 <insert subject line here>. But I'm not really sure there is much of a point in that.
Quoted 3 lines
(Perhaps to get us started, Christoph, do you know of specific code that shows how this code could be reorganized?)
This is what I had in mind:
https://lore.kernel.org/linux-block/[email protected]/T/#m3588b5824b7fa76f001d57e54664889b73471422
It records the alignment while building (or iterating for another reason), and then just checking a mask later. For nfsd this would be a bit different as you'd also record the boundaries of the aligned segments, but the idea is the same.
Quoted 9 lines
If NFSD responds with
NFS_FILE_SYNChere, then timestamps need to be persisted as well as data. As discussed in other threads, currentlynfsd_vfs_write()seems to miss that mark.So either: return
NFS_DATA_SYNC(which means we've persisted only the data) or make this path persist the timestamps too.I haven't seen any existing code that convinces me that setting both
IOCB_SYNCandIOCB_DSYNCis necessary.
iocb_flags is the canonical place. IOCB_DSYNC is the main path driving the syncing, and IOCB_SYNC drivers the additional syncing of the timestamps.
This is all a bit odd, because Linux historically only supposed the O_SYNC flag, but used it for O_DSYNC semantics. When I fixed that, I had to do a few non-standard things so that we could keep existing binaries work as expected despite renaming the flags. See commit 6b2f3d1f769b ("vfs: Implement proper O_SYNC semantics") for details.
Jeff Layton
maintainerQuoted 87 lines · Christoph Hellwig
Quoted 7 lines · Chuck Lever
From: Mike Snitzer <[email protected]>
If
NFSD_IO_DIRECTis used, split any misaligned WRITE into a start, middle and end as needed. The large middle extent is DIO-aligned and the start and/or end are misaligned. Synchronous buffered IO (with preference towards using DONTCACHE) is used for the misaligned extents andO_DIRECTis used for the middle DIO-aligned extent.Can you define synchronous better here? The term is unfortunately overloaded between synchronous syscalls vs aio/io_uring and O_(D)SYNC style I/O. As of now I don't understand which one you mean, especially with the DONTCACHE reference thrown in, but I guess I'll figure it out reading the patch.
Quoted 3 lines
If
vfs_iocb_iter_write()returns-ENOTBLK, due to its inability to invalidate the page cache on behalf of the DIO WRITE, thennfsd_issue_write_dio()will fall back to using buffered IO.Did you see
-ENOTBLKleaking out of the file systems? Because at least for iomap it is supposed to be an indication that the file system ->write_iter handler needs to retry using buffered I/O and never leak to the caller.Quoted 5 lines
These changes served as the original starting point for the NFS client's misaligned
O_DIRECTsupport that landed with commitc817248fc831("nfs/localio: add properO_DIRECTsupport for READ and WRITE"). But NFSD's support is simpler because it currently doesn't use AIO completion.I don't understand this paragraph. What does starting point mean here? How does it matter for the patch description?
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1261
Quoted 5 lines
fs/nfsd/vfs.c +5
-0+struct nfsd_write_dio { +ssize_t start_len;/* Length for misaligned first extent */ +ssize_t middle_len;/* Length for DIO-aligned middle extent */ +ssize_t end_len;/* Length for misaligned last extent */ +};Looking at how the code is structured later on, it seems like it would work much better if each of these sections had it's own object with the len,
iov_iter, flag if it's aligned, etc. Otherwise we have this structure and lots of arrays of three items passed around.fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1291
Quoted 3 lines
fs/nfsd/vfs.c +3
-0+static bool +nfsd_iov_iter_aligned_bvec (const struct iov_iter *i,unsigned int addr_mask, +unsigned int len_mask)Wouldn't it make sense to track the alignment when building the
bio_vecarray instead of doing another walk here touching all cache lines?Review
Quoted 2 lines
(quoted diff) +2
-0+ if (unlikely(dio_blocksize > PAGE_SIZE)) + return false;Why does this matter? Can you add a comment explaining it?
Quoted 5 lines
fs/nfsd/vfs.c +5
-0+static int +nfsd_buffered_write (struct svc_rqst *rqstp,struct file *file, +unsigned int nvecs,unsigned long *cnt, +struct kiocb *kiocb) +{fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1374
Quoted 10 lines
fs/nfsd/vfs.c +10
-0+struct iov_iter iter; +int host_err; + +iov_iter_bvec (&iter,ITER_SOURCE , rqstp->rq_bvec, nvecs, *cnt); + host_err =vfs_iocb_iter_write (file, kiocb, &iter); +if (host_err <0 ) +return host_err; + *cnt = host_err; + +return 0 ;Nothing really buffered here per se, it's just a small wrapper around
vfs_iocb_iter_write.fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1404
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+/* +* Any buffered IO issued here will be misaligned, use +* sync IO to ensure it has completed before returning. +* Also update @stable_how to avoid need for COMMIT. +*/ + kiocb->ki_flags |= (IOCB_DSYNC |IOCB_SYNC );What do you mean with completed before returning? I guess you mean writeback actually happening, right? Why do you need that, why do you also force it for the direct I/O?
Quoted 4 lines
Also
IOCB_SYNCis wrong here, as the only thing it does overIOCB_DSYNCis also forcing back of metadata not needed to find data (aka timestamps), which I can't see any need for here.
Responding to a WRITE with NFS_FILE_SYNC flag set means that the data the client wrote is now on stable storage (and hence the client doesn't need to follow up with a COMMIT). This patch is using DIO for the aligned middle section but any unaligned ends use buffered I/O. If we want to return NFS_FILE_SYNC here then all of the data and metadata need to be on disk when the reply goes out.
Don't we need IOCB_SYNC here in this case? Otherwise, the server could crash while the metadata is still in memory. When it comes back up, the client could see stale timestamps. Maybe that's not fatal, but it seems pretty sketchy.
Quoted 30 lines
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+ *stable_how =NFS_FILE_SYNC ; + + *cnt =0 ; +for (int i =0 ; i < n_iters; i++) { +if (iter_is_dio_aligned[i]) + kiocb->ki_flags |=IOCB_DIRECT ;fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1420
Quoted 10 lines
fs/nfsd/vfs.c +10
-0+else + kiocb->ki_flags &= ~IOCB_DIRECT ; + + host_err =vfs_iocb_iter_write (file, kiocb, &iter[i]); +if (host_err <0 ) { +/* +* VFS will return -ENOTBLK if DIO WRITE fails to +* invalidate the page cache. Retry using buffered IO. +*/ +if (unlikely (host_err == -ENOTBLK )) {The VFS certainly does not, and if it leaks out of a specific file system we need to fix that.
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1431
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+ }else if (unlikely (host_err == -EINVAL )) { +struct inode *inode =d_inode (fhp->fh_dentry); + +pr_info_ratelimited ("nfsd: Direct I/O alignment failure on %s/%ld\n" , + inode->i_sb->s_id, inode->i_ino); + host_err = -ESERVERFAULT ;
-EINVALcan be lot more things than alignment failure. And more
importantly alignment failures should not happen with the proper checks in place.
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 11 lines · Jeff Layton
Responding to a WRITE with
NFS_FILE_SYNCflag set means that the data the client wrote is now on stable storage (and hence the client doesn't need to follow up with a COMMIT). This patch is using DIO for the aligned middle section but any unaligned ends use buffered I/O. If we want to returnNFS_FILE_SYNChere then all of the data and metadata need to be on disk when the reply goes out.Don't we need
IOCB_SYNChere in this case? Otherwise, the server could crash while the metadata is still in memory. When it comes back up, the client could see stale timestamps. Maybe that's not fatal, but it seems pretty sketchy.
Why do you care about the timestamps which in NFS AFAIK aren't tied to the data writeback in any way?
Jeff Layton
maintainerQuoted 8 lines · Christoph Hellwig
Quoted 7 lines · Jeff Layton
Responding to a WRITE with
NFS_FILE_SYNCflag set means that the data the client wrote is now on stable storage (and hence the client doesn't need to follow up with a COMMIT). This patch is using DIO for the aligned middle section but any unaligned ends use buffered I/O. If we want to returnNFS_FILE_SYNChere then all of the data and metadata need to be on disk when the reply goes out.
Quoted 7 lines
Quoted 4 lines
Don't we need
IOCB_SYNChere in this case? Otherwise, the server could crash while the metadata is still in memory. When it comes back up, the client could see stale timestamps. Maybe that's not fatal, but it seems pretty sketchy.Why do you care about the timestamps which in NFS AFAIK aren't tied to the data writeback in any way?
Cache coherency. If the timestamps roll back, some clients may not notice that data has changed after a write.
It's not the end of the world -- non-evident timestamp changes were typical prior to the multigrain timestamp patches going in, but it's not ideal.
Signature · 1 line
Jeff Layton <[email protected]>
Quoted 6 lines · Jeff Layton
Cache coherency. If the timestamps roll back, some clients may not notice that data has changed after a write.
It's not the end of the world -- non-evident timestamp changes were typical prior to the multigrain timestamp patches going in, but it's not ideal.
Well, in that case nfsd_vfs_write needs to use IOCB_SYNC as well. And both that and this code need a big fat comment about it.
Jeff Layton
maintainerQuoted 10 lines · Christoph Hellwig
Quoted 6 lines · Jeff Layton
Cache coherency. If the timestamps roll back, some clients may not notice that data has changed after a write.
It's not the end of the world -- non-evident timestamp changes were typical prior to the multigrain timestamp patches going in, but it's not ideal.
Well, in that case
nfsd_vfs_writeneeds to useIOCB_SYNCas well. And both that and this code need a big fat comment about it.
That was my thinking too, but Chuck pointed out that nfsd has been violating this basically since forever. Given that, I think using IOCB_DSYNC is probably fine, and it would certainly be less costly.
Signature · 1 line
Jeff Layton <[email protected]>
Chuck Lever
maintainerQuoted 10 lines · Christoph Hellwig
Quoted 6 lines · Jeff Layton
Cache coherency. If the timestamps roll back, some clients may not notice that data has changed after a write.
It's not the end of the world -- non-evident timestamp changes were typical prior to the multigrain timestamp patches going in, but it's not ideal.
Well, in that case
nfsd_vfs_writeneeds to useIOCB_SYNCas well. And both that and this code need a big fat comment about it.
NFSD's historical behavior doesn't match the spec, so yes, I'd like a comment or two that calls this out if we agree that's something we do not want to change.
Otherwise, I'm not opposed to bringing NFSD into compliance. But that might need patches that can be backported. Not technically difficult, but some planning is necessary.
Signature · 1 line
Chuck Lever
Quoted 11 lines · Chuck Lever
Quoted 10 lines · Christoph Hellwig
Quoted 6 lines · Jeff Layton
Cache coherency. If the timestamps roll back, some clients may not notice that data has changed after a write.
It's not the end of the world -- non-evident timestamp changes were typical prior to the multigrain timestamp patches going in, but it's not ideal.
Well, in that case
nfsd_vfs_writeneeds to useIOCB_SYNCas well. And both that and this code need a big fat comment about it.
Quoted 7 lines
NFSD's historical behavior doesn't match the spec, so yes, I'd like a comment or two that calls this out if we agree that's something we do not want to change.
Otherwise, I'm not opposed to bringing NFSD into compliance. But that might need patches that can be backported. Not technically difficult, but some planning is necessary.
It's basically just adding IOCB_SYNC in nfsd_vfs_write. If you do that before this series it should be fairly easily backportable.
Chuck Lever
maintainerQuoted 9 lines · Christoph Hellwig
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1404
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+/* +* Any buffered IO issued here will be misaligned, use +* sync IO to ensure it has completed before returning. +* Also update @stable_how to avoid need for COMMIT. +*/ + kiocb->ki_flags |= (IOCB_DSYNC |IOCB_SYNC );What do you mean with completed before returning? I guess you mean writeback actually happening, right? Why do you need that, why do you also force it for the direct I/O?
This is the only comment where I'm not clear on what corrective action to take.
I think IOCB_SYNC would be needed with O_DIRECT to force timestamp updates. Otherwise, IOCB_SYNC is relevant only when the function is forced to fall back to some form of write through the page cache.
Is that correct?
Signature · 1 line
Chuck Lever
Quoted 11 lines · Chuck Lever
Quoted 9 lines · Christoph Hellwig
fs/nfsd/vfs.c static int wait_for_concurrent_writes(struct file *file) · line 1404
Quoted 6 lines
fs/nfsd/vfs.c +6
-0+/* +* Any buffered IO issued here will be misaligned, use +* sync IO to ensure it has completed before returning. +* Also update @stable_how to avoid need for COMMIT. +*/ + kiocb->ki_flags |= (IOCB_DSYNC |IOCB_SYNC );What do you mean with completed before returning? I guess you mean writeback actually happening, right? Why do you need that, why do you also force it for the direct I/O?
Quoted 2 lines
This is the only comment where I'm not clear on what corrective action to take.
I have multiple issues with the comment. One is that it really should talk about commiting data to stable storage instead of completing, as that seems to be the main point (and also what IOCB_DSYNC / IOCB_SYNC) does. If we stick to using IOCB_SYNC it should also mention metadata or more specifically timestamps.
But I also really don't get the "Any buffered IO issued here will be misaligned, ..." part. What does buffered I/O and/or misalignment have to do with not wanting to do a COMMIT?
Quoted 3 lines
I think
IOCB_SYNCwould be needed withO_DIRECTto force timestamp updates. Otherwise,IOCB_SYNCis relevant only when the function is forced to fall back to some form of write through the page cache.
Well, IOCB_SYNC is only needed to commit timestamps. O_DSYNC is always required if you want to commit to stable storage. As said above I don't really understand from the patch why we want to do that, but IFF we want to do that, we need IOCB_DSYNC bother for direct and buffered I/O.
Chuck Lever
maintainerPATCH v4 3/3 svcrdma: Mark Read chunks
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
The upper layer may want to know when the receive buffer's .pages array is guaranteed to contain only an opaque payload. This permits the upper layer to optimize its buffer handling.
NB: Since svc_rdma_recvfrom.c is under net/, we use the comment style that is preferred in the networking layer.
--- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 5 +++++ 1 file changed, 5 insertions(+)
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +5 -0
@@ -815,6 +815,11 @@ static void svc_rdma_read_complete_one(struct svc_rqst *rqstp, buf->page_len = length; buf->len += length; buf->buflen += length; + +/* Transport guarantees that only the chunk payload +* appears in buf->pages. +*/ + buf->flags |=XDRBUF_READ ; }/* Finish constructing the RPC Call message in rqstp::rq_arg.
Signature · 1 line
2.51.0