NFSD: Implement NFSD_IO_DIRECT for NFS WRITE
Subsystems (3)
Chuck Lever
maintainerv5 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 includes all patches needed to make NFSD Direct WRITE work, plus an experimental follow-on patch.
Mike, just send along any responses to review comments as patch snippets and I will apply them as needed.
Changes since v4:
* Split out refactoring nfsd_buffered_write() into a separate patch
* Expand patch description of 1/4
* Don't set IOCB_SYNC flag
Changes since v3:
* Address checkpatch.pl nits in 2/3
* Add an untested patch to mark ingress RDMA Read chunks
Chuck Lever (3):
NFSD: Enable return of an updated stable_how to NFS clients
NFSD: Refactor nfsd_vfs_write()
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 | 231 +++++++++++++++++++++++- fs/nfsd/vfs.h | 6 +- fs/nfsd/xdr3.h | 2 +- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 5 + 9 files changed, 237 insertions(+), 16 deletions(-)
Signature · 1 line
2.51.0
Chuck Lever
maintainerPATCH v5 1/4 NFSD: Enable return of an updated stable_how to NFS clients
From: Chuck Lever <[email protected]>
NFSv3 and newer protocols enable clients to perform a two-phase WRITE. A client requests an UNSTABLE WRITE, which sends dirty data to the NFS server, but does not persist it. The server replies that it performed the UNSTABLE WRITE, and the client is then obligated to follow up with a COMMIT request before it can remove the dirty data from its own page cache. The COMMIT reply is the client's guarantee that the written data has been persisted on the server.
The purpose of this protocol design is to enable clients to send a large amount of data via multiple WRITE requests to a server, and then wait for persistence just once. The server is able to start persisting the data as soon as it gets it, to shorten the length of time the client has to wait for the final COMMIT to complete.
It's also possible for the server to respond to an UNSTABLE WRITE request in a way that indicates that the data was persisted anyway. In that case, the client can skip the COMMIT and remove the dirty data from its memory immediately. NetApp filers, for example, do this because they have a battery-backed cache and can guarantee that written data is persisted quickly and immediately.
NFSD has never implemented this kind of promotion. UNSTABLE WRITE requests are unconditionally treated as UNSTABLE. However, in a subsequent patch, nfsd_vfs_write() will be able to promote an UNSTABLE WRITE to be a FILE_SYNC WRITE. This will be because NFSD will handle some WRITE requests locally with O_DIRECT, which persists written data immediately. The FILE_SYNC WRITE response indicates to the client that no follow-up COMMIT is necessary.
This patch prepares for that change by enabling the modified stable_how value to be passed along to NFSD's WRITE reply encoder. 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
Chuck Lever
maintainerPATCH v5 2/4 NFSD: Refactor nfsd_vfs_write()
In reply to Chuck LeverFrom: Chuck Lever <[email protected]>
Extract the common code that is to be used in the buffered and dontcache I/O modes. This common code will also be used as the fallback when direct I/O is requested but cannot be used.
--- fs/nfsd/vfs.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
fs/nfsd/vfs.c +20 -6
@@ -1254,6 +1254,22 @@ static int wait_for_concurrent_writes(struct file *file)return err; } +static int +nfsd_iocb_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 ) +return host_err; + *cnt = host_err; + +return 0 ; +} +/** * nfsd_vfs_write - write data to an already-open file * @rqstp: RPC execution context
@@ -1282,7 +1298,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,u32 stable = *stable_how;struct kiocb kiocb;struct svc_export *exp; -struct iov_iter iter;errseq_t since;__be32 nfserr;int host_err;
@@ -1319,25 +1334,24 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, kiocb.ki_flags |=IOCB_DSYNC ; nvecs =xdr_buf_to_bvec (rqstp->rq_bvec, rqstp->rq_maxpages, payload); -iov_iter_bvec (&iter,ITER_SOURCE , rqstp->rq_bvec, nvecs, *cnt); + since =READ_ONCE (file->f_wb_err);if (verf)nfsd_copy_write_verifier (verf, nn);switch (nfsd_io_cache_write) { -case NFSD_IO_BUFFERED : -break ;case NFSD_IO_DONTCACHE :if (file->f_op->fop_flags &FOP_DONTCACHE ) kiocb.ki_flags |=IOCB_DONTCACHE ; + fallthrough; +case NFSD_IO_BUFFERED : + host_err =nfsd_iocb_write (rqstp, file, nvecs, cnt, &kiocb);break ; } - host_err =vfs_iocb_iter_write (file, &kiocb, &iter);if (host_err <0 ) {commit_reset_write_verifier (nn, rqstp, host_err); goto out_nfserr; } - *cnt = host_err;nfsd_stats_io_write_add (nn, exp, *cnt);fsnotify_modify (file); host_err =filemap_check_wb_err (file->f_mapping, since);
Signature · 1 line
2.51.0
Re: [PATCH v5 2/4] NFSD: Refactor nfsd_vfs_write()
Quoted 7 lines · Chuck Lever
From: Chuck Lever <[email protected]>
Extract the common code that is to be used in the buffered and dontcache I/O modes. This common code will also be used as the fallback when direct I/O is requested but cannot be used.
Signed-off-by Chuck Lever <[email protected]>
Looks good, but please keep it attributed to me. Feel free to add Co-developed-by or something to reflect your assist?
Re: [PATCH v5 2/4] NFSD: Refactor nfsd_vfs_write()
In reply to Chuck LeverQuoted 66 lines · Chuck Lever
From: Chuck Lever <[email protected]>
Extract the common code that is to be used in the buffered and dontcache I/O modes. This common code will also be used as the fallback when direct I/O is requested but cannot be used.
Signed-off-by Chuck Lever <[email protected]>--- fs/nfsd/vfs.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)fs/nfsd/vfs.c +20
-4@@ -1254,6 +1254,22 @@ static int wait_for_concurrent_writes(struct file *file)return err; } +static int +nfsd_iocb_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 ) +return host_err; + *cnt = host_err; + +return 0 ; +} +/** * nfsd_vfs_write - write data to an already-open file * @rqstp: RPC execution context @@ -1282,7 +1298,6 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,u32 stable = *stable_how;struct kiocb kiocb;struct svc_export *exp; -struct iov_iter iter;errseq_t since;__be32 nfserr;int host_err;@@ -1319,25 +1334,24 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, kiocb.ki_flags |=IOCB_DSYNC ; nvecs =xdr_buf_to_bvec (rqstp->rq_bvec, rqstp->rq_maxpages, payload); -iov_iter_bvec (&iter,ITER_SOURCE , rqstp->rq_bvec, nvecs, *cnt); + since =READ_ONCE (file->f_wb_err);if (verf)nfsd_copy_write_verifier (verf, nn);switch (nfsd_io_cache_write) { -case NFSD_IO_BUFFERED : -break ;case NFSD_IO_DONTCACHE :if (file->f_op->fop_flags &FOP_DONTCACHE ) kiocb.ki_flags |=IOCB_DONTCACHE ; + fallthrough; +case NFSD_IO_BUFFERED : + host_err =nfsd_iocb_write (rqstp, file, nvecs, cnt, &kiocb);break ;
fs/nfsd/vfs.c nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, · line 1357
Quoted 10 lines
fs/nfsd/vfs.c +0
-2} - host_err =vfs_iocb_iter_write (file, &kiocb, &iter);if (host_err <0 ) {commit_reset_write_verifier (nn, rqstp, host_err); goto out_nfserr; } - *cnt = host_err;nfsd_stats_io_write_add (nn, exp, *cnt);fsnotify_modify (file); host_err =filemap_check_wb_err (file->f_mapping, since);
Chuck Lever
maintainerPATCH v5 3/4 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 | 196 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+)
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 +196 -0
214 lines not on this page · raw message
Signature · 1 line
2.51.0
kernel test robot
build botkernel test robot noticed the following build errors:
Hi Chuck,
kernel test robot noticed the following build errors:
[auto build test ERROR on v6.18-rc2]
[also build test ERROR on linus/master next-20251024] [cannot apply to trondmy-nfs/linux-next brauner-vfs/vfs.all] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Chuck-Lever/NFSD-Enable-return-of-an-updated-stable_how-to-NFS-clients/20251021-002911 base: v6.18-rc2 patch link: https://lore.kernel.org/r/20251020162546.5066-4-cel%40kernel.org patch subject: [PATCH v5 3/4] NFSD: Implement NFSD_IO_DIRECT for NFS WRITE config: x86_64-kexec (https://download.01.org/0day-ci/archive/20251025/[email protected]/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251025/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All errors (new ones prefixed by >>):
>> fs/nfsd/vfs.c:1448:7: error: use of undeclared identifier 'NFSD_IO_DIRECT'
1448 | case NFSD_IO_DIRECT:
| ^
1 error generated.
--
>> fs/nfsd/debugfs.c:109:7: error: use of undeclared identifier 'NFSD_IO_DIRECT'
109 | case NFSD_IO_DIRECT:
| ^
1 error generated.
vim +/NFSD_IO_DIRECT +1448 fs/nfsd/vfs.c
1377
1378 /**
1379 * nfsd_vfs_write - write data to an already-open file
1380 * @rqstp: RPC execution context
1381 * @fhp: File handle of file to write into
1382 * @nf: An open file matching @fhp
1383 * @offset: Byte offset of start
1384 * @payload: xdr_buf containing the write payload
1385 * @cnt: IN: number of bytes to write, OUT: number of bytes actually written
1386 * @stable_how: IN: Client's requested stable_how, OUT: Actual stable_how
1387 * @verf: NFS WRITE verifier
1388 *
1389 * Upon return, caller must invoke fh_put on @fhp.
1390 *
1391 * Return values:
1392 * An nfsstat value in network byte order.
1393 */
1394 __be32
1395 nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp,
1396 struct nfsd_file *nf, loff_t offset,
1397 const struct xdr_buf *payload, unsigned long *cnt,
1398 u32 *stable_how, __be32 *verf)
1399 {
1400 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1401 struct file *file = nf->nf_file;
1402 struct super_block *sb = file_inode(file)->i_sb;
1403 u32 stable = *stable_how;
1404 struct kiocb kiocb;
1405 struct svc_export *exp;
1406 errseq_t since;
1407 __be32 nfserr;
1408 int host_err;
1409 unsigned long exp_op_flags = 0;
1410 unsigned int pflags = current->flags;
1411 bool restore_flags = false;
1412 unsigned int nvecs;
1413
1414 trace_nfsd_write_opened(rqstp, fhp, offset, *cnt);
1415
1416 if (sb->s_export_op)
1417 exp_op_flags = sb->s_export_op->flags;
1418
1419 if (test_bit(RQ_LOCAL, &rqstp->rq_flags) &&
1420 !(exp_op_flags & EXPORT_OP_REMOTE_FS)) {
1421 /*
1422 * We want throttling in balance_dirty_pages()
1423 * and shrink_inactive_list() to only consider
1424 * the backingdev we are writing to, so that nfs to
1425 * localhost doesn't cause nfsd to lock up due to all
1426 * the client's dirty pages or its congested queue.
1427 */
1428 current->flags |= PF_LOCAL_THROTTLE;
1429 restore_flags = true;
1430 }
1431
1432 exp = fhp->fh_export;
1433
1434 if (!EX_ISSYNC(exp))
1435 stable = NFS_UNSTABLE;
1436 init_sync_kiocb(&kiocb, file);
1437 kiocb.ki_pos = offset;
1438 if (stable && !fhp->fh_use_wgather)
1439 kiocb.ki_flags |= IOCB_DSYNC;
1440
1441 nvecs = xdr_buf_to_bvec(rqstp->rq_bvec, rqstp->rq_maxpages, payload);
1442
1443 since = READ_ONCE(file->f_wb_err);
1444 if (verf)
1445 nfsd_copy_write_verifier(verf, nn);
1446
1447 switch (nfsd_io_cache_write) {
> 1448 case NFSD_IO_DIRECT: 1449 host_err = nfsd_direct_write(rqstp, fhp, nf, stable_how,
1450 nvecs, cnt, &kiocb);
1451 stable = *stable_how;
1452 break;
1453 case NFSD_IO_DONTCACHE:
1454 if (file->f_op->fop_flags & FOP_DONTCACHE)
1455 kiocb.ki_flags |= IOCB_DONTCACHE;
1456 fallthrough;
1457 case NFSD_IO_BUFFERED:
1458 host_err = nfsd_iocb_write(rqstp, file, nvecs, cnt, &kiocb);
1459 break;
1460 }
1461 if (host_err < 0) {
1462 commit_reset_write_verifier(nn, rqstp, host_err);
1463 goto out_nfserr;
1464 }
1465 nfsd_stats_io_write_add(nn, exp, *cnt);
1466 fsnotify_modify(file);
1467 host_err = filemap_check_wb_err(file->f_mapping, since);
1468 if (host_err < 0)
1469 goto out_nfserr;
1470
1471 if (stable && fhp->fh_use_wgather) {
1472 host_err = wait_for_concurrent_writes(file);
1473 if (host_err < 0)
1474 commit_reset_write_verifier(nn, rqstp, host_err);
1475 }
1476
1477 out_nfserr:
1478 if (host_err >= 0) {
1479 trace_nfsd_write_io_done(rqstp, fhp, offset, *cnt);
1480 nfserr = nfs_ok;
1481 } else {
1482 trace_nfsd_write_err(rqstp, fhp, offset, host_err);
1483 nfserr = nfserrno(host_err);
1484 }
1485 if (restore_flags)
1486 current_restore_flags(pflags, PF_LOCAL_THROTTLE);
1487 return nfserr;
1488 }
1489
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
Chuck Lever
maintainerPATCH v5 4/4 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
Re: [PATCH v5 4/4] svcrdma: Mark Read chunks
Quoted 20 lines · Chuck Lever
From: 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.cis undernet/, we use the comment style that is preferred in the networking layer.Signed-off-by Chuck Lever <[email protected]>--- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 5 +++++ 1 file changed, 5 insertions(+)net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +0
-0@@ -815,6 +815,11 @@ static void svc_rdma_read_complete_one(struct svc_rqst *rqstp, buf->page_len = length;
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c static void svc_rdma_read_complete_one(struct svc_rqst *rqstp, · line 825
Quoted 10 lines
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +5
-0buf->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.
Quoted 6 lines · Chuck Lever
From: Chuck Lever <[email protected]>
Following on https://lore.kernel.org/linux-nfs/[email protected]/
this series includes all patches needed to make NFSD Direct WRITE work, plus an experimental follow-on patch.
Quoted 7 lines
Mike, just send along any responses to review comments as patch snippets and I will apply them as needed.
Changes since v4:
* Split out refactoringnfsd_buffered_write()into a separate patch
* Expand patch description of 1/4
* Don't setIOCB_SYNCflag
Sure thing. Just a bit concerned about removing IOCB_SYNC in that we're altering stable_how to be NFS_FILE_SYNC.
Mike
Chuck Lever
maintainerQuoted 3 lines · Mike Snitzer
On Mon, Oct 20, 2025 at 12:25:42PM -0400, Chuck Lever wrote:
Just a bit concerned about removingIOCB_SYNCin that we're alteringstable_howto beNFS_FILE_SYNC.
Commit 3f3503adb332 ("NFSD: Use vfs_iocb_iter_write()") introduces the first use of IOCB_ flags in NFSD's write path, and it uses IOCB_DSYNC. The patch has Reviewed-by's from Christoph, Neil, and Jeff.
Should we be concerned that IOCB_DSYNC does not persist time stamp changes that might be lost during an unplanned server boot?
As a reminder to the thread, Section 3.3.7 of RFC 1813 says:
If stable is FILE_SYNC, the server must commit the data written plus all file system metadata to stable storage before returning results.
The text is a bit blurry about whether "file system metadata" means all of the outstanding metadata changes for every file, or just the metadata changes for the target file handle.
NFSD has historically treated DATA_SYNC and FILE_SYNC identically, as the Linux NFS client does not use DATA_SYNC (IIRC).
Signature · 1 line
Chuck Lever
Quoted 11 lines · Chuck Lever
Quoted 3 lines · Mike Snitzer
On Mon, Oct 20, 2025 at 12:25:42PM -0400, Chuck Lever wrote:
Just a bit concerned about removingIOCB_SYNCin that we're alteringstable_howto beNFS_FILE_SYNC.Commit
3f3503adb332("NFSD: Usevfs_iocb_iter_write()") introduces the first use ofIOCB_flags in NFSD's write path, and it usesIOCB_DSYNC. The patch has Reviewed-by's from Christoph, Neil, and Jeff.Should we be concerned that
IOCB_DSYNCdoes not persist time stamp changes that might be lost during an unplanned server boot?
One reason to mention 3f3503adb332 is that if we decide IOCB_SYNC is necessary to correctly implement NFS_FILE_SYNC, then a separate, backport-able, patch will be needed to replace the flag that was used in that patch.
Signature · 1 line
Chuck Lever
Jeff Layton
maintainerQuoted 18 lines · Chuck Lever
Quoted 3 lines · Mike Snitzer
On Mon, Oct 20, 2025 at 12:25:42PM -0400, Chuck Lever wrote:
Just a bit concerned about removingIOCB_SYNCin that we're alteringstable_howto beNFS_FILE_SYNC.Commit
3f3503adb332("NFSD: Usevfs_iocb_iter_write()") introduces the first use ofIOCB_flags in NFSD's write path, and it usesIOCB_DSYNC. The patch has Reviewed-by's from Christoph, Neil, and Jeff.Should we be concerned that
IOCB_DSYNCdoes not persist time stamp changes that might be lost during an unplanned server boot?As a reminder to the thread, Section 3.3.7 of RFC 1813 says:
If stable is
FILE_SYNC, the server must commit the data written plus all file system metadata to stable storage before returning results.
Quoted 7 lines
The text is a bit blurry about whether "file system metadata" means all of the outstanding metadata changes for every file, or just the metadata changes for the target file handle.
NFSD has historically treated
DATA_SYNCandFILE_SYNCidentically, as the Linux NFS client does not useDATA_SYNC(IIRC).
Surely it just meant for the one file. FILE_SYNC is only applicable to WRITE/COMMIT operations and those only deal with a single file at a time. If the client gets back FILE_SYNC on a write, it should _not_ assume that all outstanding dirty data to all files has been sync'ed.
Signature · 1 line
Jeff Layton <[email protected]>
Chuck Lever
maintainerQuoted 23 lines · Jeff Layton
Quoted 22 lines · Chuck Lever
Quoted 3 lines · Mike Snitzer
On Mon, Oct 20, 2025 at 12:25:42PM -0400, Chuck Lever wrote:
Just a bit concerned about removingIOCB_SYNCin that we're alteringstable_howto beNFS_FILE_SYNC.Commit
3f3503adb332("NFSD: Usevfs_iocb_iter_write()") introduces the first use ofIOCB_flags in NFSD's write path, and it usesIOCB_DSYNC. The patch has Reviewed-by's from Christoph, Neil, and Jeff.Should we be concerned that
IOCB_DSYNCdoes not persist time stamp changes that might be lost during an unplanned server boot?As a reminder to the thread, Section 3.3.7 of RFC 1813 says:
If stable is
FILE_SYNC, the server must commit the data written plus all file system metadata to stable storage before returning results.The text is a bit blurry about whether "file system metadata" means all of the outstanding metadata changes for every file, or just the metadata changes for the target file handle.
Quoted 5 lines
Quoted 3 lines
NFSD has historically treated
DATA_SYNCandFILE_SYNCidentically, as the Linux NFS client does not useDATA_SYNC(IIRC).Surely it just meant for the one file.
Well yes that is the traditional understanding. I'm merely pointing out that the actual text is not quite as specific as what we've come to understand.
Quoted 3 lines
FILE_SYNCis only applicable to
WRITE/COMMIT operations and those only deal with a single file at a time.
True but you may recall that NFSD's COMMIT used to ignore the range arguments and flush the whole file. Some file systems used to flush all dirty data in this case, IIRC.
There's always been a bit of a mismatch between the spec and what NFSD has implemented.
Quoted 2 lines
If the client gets back
FILE_SYNCon a write, it should _not_ assume that all outstanding dirty data to all files has been sync'ed.
Agreed.
But back to Mike's point.
- The spec says NFS_DATA_SYNC means persist file data.
- The spec says NFS_FILE_SYNC means persist file data and file attributes.
- After consulting with the section describing COMMIT, I think that COMMIT is supposed to persist both file data and attributes.
And my reading of the code in fs/nfsd/vfs.c is that NFSD does the equivalent of NFS_DATA_SYNC in all of these cases, and has done for as long as I cared to chase the commit log.
Moveover, commit 3f3503adb332 did not introduce this behavior.
Previous to that commit, nfsd_vfs_write() passed RWF_SYNC to vfs_iter_write(). This API uses kiocb_set_rw_flags() to convert the RWF flag into an IOCB flag. kiocb_set_rw_flags does this:
kiocb_flags |= (__force int) (flags & RWF_SUPPORTED);
if (flags & RWF_SYNC)
kiocb_flags |= IOCB_DSYNC;And that's where I copied IOCB_DSYNC from. The use of RWF_SYNC was introduced in 2016 by commit 24368aad47dc ("nfsd: use RWF_SYNC").
So we've tacitly agreed to let NFSD fall short of the specs in this regard for some time. However I don't believe this is documented anywhere.
Based on this reasoning, IOCB_DSYNC is historically correct for the DIRECT WRITE path and its fallbacks. I'm guessing that an O_DIRECT WRITE is going to persist the written data but won't persist file attribute changes either.
I'm open to making NFSD adhere more strictly to the spec language, but I bet there will be a performance impact. Maybe that impact will be unnoticeable on modern storage devices.
Signature · 1 line
Chuck Lever
Jeff Layton
maintainerQuoted 79 lines · Chuck Lever
Quoted 23 lines · Jeff Layton
Quoted 22 lines · Chuck Lever
Quoted 3 lines · Mike Snitzer
On Mon, Oct 20, 2025 at 12:25:42PM -0400, Chuck Lever wrote:
Just a bit concerned about removingIOCB_SYNCin that we're alteringstable_howto beNFS_FILE_SYNC.Commit
3f3503adb332("NFSD: Usevfs_iocb_iter_write()") introduces the first use ofIOCB_flags in NFSD's write path, and it usesIOCB_DSYNC. The patch has Reviewed-by's from Christoph, Neil, and Jeff.Should we be concerned that
IOCB_DSYNCdoes not persist time stamp changes that might be lost during an unplanned server boot?As a reminder to the thread, Section 3.3.7 of RFC 1813 says:
If stable is
FILE_SYNC, the server must commit the data written plus all file system metadata to stable storage before returning results.The text is a bit blurry about whether "file system metadata" means all of the outstanding metadata changes for every file, or just the metadata changes for the target file handle.
Quoted 5 lines
Quoted 3 lines
NFSD has historically treated
DATA_SYNCandFILE_SYNCidentically, as the Linux NFS client does not useDATA_SYNC(IIRC).Surely it just meant for the one file.
Well yes that is the traditional understanding. I'm merely pointing out that the actual text is not quite as specific as what we've come to understand.
Quoted 3 lines
FILE_SYNCis only applicable to
WRITE/COMMIT operations and those only deal with a single file at a time.True but you may recall that NFSD's COMMIT used to ignore the range arguments and flush the whole file. Some file systems used to flush all dirty data in this case, IIRC.
There's always been a bit of a mismatch between the spec and what NFSD has implemented.
Quoted 2 lines
If the client gets back
FILE_SYNCon a write, it should _not_ assume that all outstanding dirty data to all files has been sync'ed.Agreed.
But back to Mike's point.
- The spec says
NFS_DATA_SYNCmeans persist file data.- The spec says
NFS_FILE_SYNCmeans persist file data and file attributes.- After consulting with the section describing COMMIT, I think that COMMIT is supposed to persist both file data and attributes.
And my reading of the code in
fs/nfsd/vfs.cis that NFSD does the equivalent ofNFS_DATA_SYNCin all of these cases, and has done for as long as I cared to chase the commit log.Moveover, commit
3f3503adb332did not introduce this behavior.Previous to that commit,
nfsd_vfs_write()passedRWF_SYNCtovfs_iter_write(). This API useskiocb_set_rw_flags()to convert the RWF flag into an IOCB flag.kiocb_set_rw_flagsdoes this:kiocb_flags |= (__force int) (flags & RWF_SUPPORTED); if (flags & RWF_SYNC) kiocb_flags |= IOCB_DSYNC;And that's where I copied
IOCB_DSYNCfrom. The use ofRWF_SYNCwas introduced in 2016 by commit24368aad47dc("nfsd: useRWF_SYNC").
Quoted 9 lines
So we've tacitly agreed to let NFSD fall short of the specs in this regard for some time. However I don't believe this is documented anywhere.
Based on this reasoning,
IOCB_DSYNCis historically correct for the DIRECT WRITE path and its fallbacks. I'm guessing that anO_DIRECTWRITE is going to persist the written data but won't persist file attribute changes either.
I think that's the case, generally.
Quoted 4 lines
I'm open to making NFSD adhere more strictly to the spec language, but I bet there will be a performance impact. Maybe that impact will be unnoticeable on modern storage devices.
Ok, I had missed the context that we had been doing this all along anyway. In that case, IOCB_DSYNC seems like it's probably acceptable. We likely have bigger cache coherency problems outstanding than potential timestamp rollbacks anyway.
Alternately, we could just return NFS_DATA_SYNC, but then we'd have to deal with follow-on commits.
Signature · 1 line
Jeff Layton <[email protected]>
Chuck Lever
maintainerQuoted 97 lines · Jeff Layton
Quoted 79 lines · Chuck Lever
Quoted 23 lines · Jeff Layton
Quoted 22 lines · Chuck Lever
Quoted 3 lines · Mike Snitzer
On Mon, Oct 20, 2025 at 12:25:42PM -0400, Chuck Lever wrote:
Just a bit concerned about removingIOCB_SYNCin that we're alteringstable_howto beNFS_FILE_SYNC.Commit
3f3503adb332("NFSD: Usevfs_iocb_iter_write()") introduces the first use ofIOCB_flags in NFSD's write path, and it usesIOCB_DSYNC. The patch has Reviewed-by's from Christoph, Neil, and Jeff.Should we be concerned that
IOCB_DSYNCdoes not persist time stamp changes that might be lost during an unplanned server boot?As a reminder to the thread, Section 3.3.7 of RFC 1813 says:
If stable is
FILE_SYNC, the server must commit the data written plus all file system metadata to stable storage before returning results.The text is a bit blurry about whether "file system metadata" means all of the outstanding metadata changes for every file, or just the metadata changes for the target file handle.
Quoted 5 lines
Quoted 3 lines
NFSD has historically treated
DATA_SYNCandFILE_SYNCidentically, as the Linux NFS client does not useDATA_SYNC(IIRC).Surely it just meant for the one file.
Well yes that is the traditional understanding. I'm merely pointing out that the actual text is not quite as specific as what we've come to understand.
Quoted 3 lines
FILE_SYNCis only applicable to
WRITE/COMMIT operations and those only deal with a single file at a time.True but you may recall that NFSD's COMMIT used to ignore the range arguments and flush the whole file. Some file systems used to flush all dirty data in this case, IIRC.
There's always been a bit of a mismatch between the spec and what NFSD has implemented.
Quoted 2 lines
If the client gets back
FILE_SYNCon a write, it should _not_ assume that all outstanding dirty data to all files has been sync'ed.Agreed.
But back to Mike's point.
- The spec says
NFS_DATA_SYNCmeans persist file data.- The spec says
NFS_FILE_SYNCmeans persist file data and file attributes.- After consulting with the section describing COMMIT, I think that COMMIT is supposed to persist both file data and attributes.
And my reading of the code in
fs/nfsd/vfs.cis that NFSD does the equivalent ofNFS_DATA_SYNCin all of these cases, and has done for as long as I cared to chase the commit log.Moveover, commit
3f3503adb332did not introduce this behavior.Previous to that commit,
nfsd_vfs_write()passedRWF_SYNCtovfs_iter_write(). This API useskiocb_set_rw_flags()to convert the RWF flag into an IOCB flag.kiocb_set_rw_flagsdoes this:kiocb_flags |= (__force int) (flags & RWF_SUPPORTED); if (flags & RWF_SYNC) kiocb_flags |= IOCB_DSYNC;And that's where I copied
IOCB_DSYNCfrom. The use ofRWF_SYNCwas introduced in 2016 by commit24368aad47dc("nfsd: useRWF_SYNC").Quoted 9 lines
So we've tacitly agreed to let NFSD fall short of the specs in this regard for some time. However I don't believe this is documented anywhere.
Based on this reasoning,
IOCB_DSYNCis historically correct for the DIRECT WRITE path and its fallbacks. I'm guessing that anO_DIRECTWRITE is going to persist the written data but won't persist file attribute changes either.I think that's the case, generally.
Quoted 4 lines
I'm open to making NFSD adhere more strictly to the spec language, but I bet there will be a performance impact. Maybe that impact will be unnoticeable on modern storage devices.
Quoted 7 lines
Ok, I had missed the context that we had been doing this all along anyway. In that case,
IOCB_DSYNCseems like it's probably acceptable. We likely have bigger cache coherency problems outstanding than potential timestamp rollbacks anyway.Alternately, we could just return
NFS_DATA_SYNC, but then we'd have to deal with follow-on commits.
But what's the point of asking the client to send us a COMMIT if we're still not going to sync the file attributes? ;-)
Signature · 1 line
Chuck Lever
Quoted 83 lines · Chuck Lever
Quoted 23 lines · Jeff Layton
Quoted 22 lines · Chuck Lever
Quoted 3 lines · Mike Snitzer
On Mon, Oct 20, 2025 at 12:25:42PM -0400, Chuck Lever wrote:
Just a bit concerned about removingIOCB_SYNCin that we're alteringstable_howto beNFS_FILE_SYNC.Commit
3f3503adb332("NFSD: Usevfs_iocb_iter_write()") introduces the first use ofIOCB_flags in NFSD's write path, and it usesIOCB_DSYNC. The patch has Reviewed-by's from Christoph, Neil, and Jeff.Should we be concerned that
IOCB_DSYNCdoes not persist time stamp changes that might be lost during an unplanned server boot?As a reminder to the thread, Section 3.3.7 of RFC 1813 says:
If stable is
FILE_SYNC, the server must commit the data written plus all file system metadata to stable storage before returning results.The text is a bit blurry about whether "file system metadata" means all of the outstanding metadata changes for every file, or just the metadata changes for the target file handle.
Quoted 5 lines
Quoted 3 lines
NFSD has historically treated
DATA_SYNCandFILE_SYNCidentically, as the Linux NFS client does not useDATA_SYNC(IIRC).Surely it just meant for the one file.
Well yes that is the traditional understanding. I'm merely pointing out that the actual text is not quite as specific as what we've come to understand.
Quoted 3 lines
FILE_SYNCis only applicable to
WRITE/COMMIT operations and those only deal with a single file at a time.True but you may recall that NFSD's COMMIT used to ignore the range arguments and flush the whole file. Some file systems used to flush all dirty data in this case, IIRC.
There's always been a bit of a mismatch between the spec and what NFSD has implemented.
Quoted 2 lines
If the client gets back
FILE_SYNCon a write, it should _not_ assume that all outstanding dirty data to all files has been sync'ed.Agreed.
But back to Mike's point.
- The spec says
NFS_DATA_SYNCmeans persist file data.- The spec says
NFS_FILE_SYNCmeans persist file data and file attributes.- After consulting with the section describing COMMIT, I think that COMMIT is supposed to persist both file data and attributes.
And my reading of the code in
fs/nfsd/vfs.cis that NFSD does the equivalent ofNFS_DATA_SYNCin all of these cases, and has done for as long as I cared to chase the commit log.Moveover, commit
3f3503adb332did not introduce this behavior.Previous to that commit,
nfsd_vfs_write()passedRWF_SYNCtovfs_iter_write(). This API useskiocb_set_rw_flags()to convert the RWF flag into an IOCB flag.kiocb_set_rw_flagsdoes this:kiocb_flags |= (__force int) (flags & RWF_SUPPORTED); if (flags & RWF_SYNC) kiocb_flags |= IOCB_DSYNC;And that's where I copied
IOCB_DSYNCfrom. The use ofRWF_SYNCwas introduced in 2016 by commit24368aad47dc("nfsd: useRWF_SYNC").So we've tacitly agreed to let NFSD fall short of the specs in this regard for some time. However I don't believe this is documented anywhere.
Quoted 8 lines
Based on this reasoning,
IOCB_DSYNCis historically correct for the DIRECT WRITE path and its fallbacks. I'm guessing that anO_DIRECTWRITE is going to persist the written data but won't persist file attribute changes either.I'm open to making NFSD adhere more strictly to the spec language, but I bet there will be a performance impact. Maybe that impact will be unnoticeable on modern storage devices.
I was able to get NFSD Direct's use of IOCB_DSYNC|IOCB_SYNC tested with Jonathan Flynn last week, there was no performance difference on his modern test cluster (8 "enterprise" NVMe devices in the server).
Was very comforting to learn IOCB_SYNC didn't cause any performance loss.
Mike