The branch main has been updated by rmacklem: URL: https://cgit.FreeBSD.org/src/commit/?id=d516e52373e1768ea84bf1ca220671a44f413abe
commit d516e52373e1768ea84bf1ca220671a44f413abe Author: Rick Macklem <[email protected]> AuthorDate: 2026-07-07 00:10:11 +0000 Commit: Rick Macklem <[email protected]> CommitDate: 2026-07-07 00:10:11 +0000 nfsd: Optionally enable use of M_EXTPG mbufs for read replies A test site determined that, for a Mellanox NIC which can handle M_EXTPG mbufs, an improvement of 5-15% for read rate could be achieved if the read reply was in M_EXTPG mbufs. A patch that tried to determine if the outbound NIC supported M_EXTPG mbufs (IFCAP_MEXTPG) did not pass review. However, it does appear that this can be useful for NFS-over-RDMA. (Which just happen to use NICs that do support M_EXTPG mbufs.) As such, this patch enables them is xp_extpg is set to true, which is never for now, but might be set true for RDMA or when vfs.nfsd.enable_mextpg is set non-zero. (It is 0 by default, so this is never enabled by default at this time.) Tested by: Greg Becker <[email protected]> MFC after: 2 weeks --- sys/fs/nfs/nfs.h | 1 + sys/fs/nfsserver/nfs_nfsdkrpc.c | 18 +++++++++++++++++- sys/fs/nfsserver/nfs_nfsdport.c | 16 ++++++++++------ sys/fs/nfsserver/nfs_nfsdserv.c | 7 +++++-- sys/rpc/svc.h | 1 + 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/sys/fs/nfs/nfs.h b/sys/fs/nfs/nfs.h index 1056595e8cde..4e79d3afbd2f 100644 --- a/sys/fs/nfs/nfs.h +++ b/sys/fs/nfs/nfs.h @@ -746,6 +746,7 @@ struct nfsrv_descript { #define ND_EXTLSCERTUSER 0x20000000000 #define ND_ERELOOKUP 0x40000000000 #define ND_MACHCRED 0x80000000000 +#define ND_CANEXTPG 0x100000000000 /* * ND_GSS should be the "or" of all GSS type authentications. diff --git a/sys/fs/nfsserver/nfs_nfsdkrpc.c b/sys/fs/nfsserver/nfs_nfsdkrpc.c index 8c557143efbd..16c21b4e1607 100644 --- a/sys/fs/nfsserver/nfs_nfsdkrpc.c +++ b/sys/fs/nfsserver/nfs_nfsdkrpc.c @@ -97,6 +97,10 @@ SYSCTL_INT(_vfs_nfsd, OID_AUTO, server_max_nfsvers, CTLFLAG_VNET | CTLFLAG_RWTUN, &VNET_NAME(nfs_maxvers), 0, "The highest version of NFS handled by the server"); +static bool nfsrv_mextpg = false; +SYSCTL_BOOL(_vfs_nfsd, OID_AUTO, enable_mextpg, CTLFLAG_RW, + &nfsrv_mextpg, 0, "Enable use of M_EXTPG mbufs"); + static int nfs_proc(struct nfsrv_descript *, u_int32_t, SVCXPRT *xprt, struct nfsrvcache **); @@ -315,7 +319,19 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt) if ((xprt->xp_tls & RPCTLS_FLAGS_CERTUSER) != 0) nd.nd_flag |= ND_TLSCERTUSER; } - nd.nd_maxextsiz = 16384; + nd.nd_maxextsiz = MBUF_PEXT_MAX_PGS * PAGE_SIZE; + /* + * If the NIC can handle M_EXTPG mbufs, they can be used + * only if the reply will not be copied into the DRC. + * This implies NFSv3 over TCP and NFSv4.n, but not NFSv4.0. + * (NFSv4.n will set ND_SAVEREPLY if the reply is going + * to be copied into the session slot.) + * Check for TCP transport (UDP uses the DRC) and a direct + * map. + */ + if ((nfsrv_mextpg || xprt->xp_extpg) && nd.nd_nam2 == NULL && + PMAP_HAS_DMAP != 0) + nd.nd_flag |= ND_CANEXTPG; #ifdef MAC mac_cred_associate_nfsd(nd.nd_cred); #endif diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c index 543c43295b20..cfc0cea2195e 100644 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -3018,12 +3018,13 @@ again: /* * If cnt > MCLBYTES and the reply will not be saved, use - * ext_pgs mbufs for TLS. + * ext_pgs mbufs for TLS or if enabled via vfs.nfsd.enable_mextpg. * For NFSv4.0, we do not know for sure if the reply will * be saved, so do not use ext_pgs mbufs for NFSv4.0. */ if (cnt > MCLBYTES && siz > MCLBYTES && - (nd->nd_flag & (ND_TLS | ND_EXTPG | ND_SAVEREPLY)) == ND_TLS && + ((nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS || + (nd->nd_flag & (ND_CANEXTPG | ND_SAVEREPLY)) == ND_CANEXTPG) && (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4) nd->nd_flag |= ND_EXTPG; @@ -3364,7 +3365,8 @@ ateof: /* * If the reply is likely to exceed MCLBYTES and the reply will - * not be saved, use ext_pgs mbufs for TLS. + * not be saved, use ext_pgs mbufs for TLS or if enabled via + * vfs.nfsd.enable_mextpg. * It is difficult to predict how large each entry will be and * how many entries have been read, so just assume the directory * entries grow by a factor of 4 when attributes are included. @@ -3372,7 +3374,8 @@ ateof: * be saved, so do not use ext_pgs mbufs for NFSv4.0. */ if (cnt > MCLBYTES && siz > MCLBYTES / 4 && - (nd->nd_flag & (ND_TLS | ND_EXTPG | ND_SAVEREPLY)) == ND_TLS && + ((nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS || + (nd->nd_flag & (ND_CANEXTPG | ND_SAVEREPLY)) == ND_CANEXTPG) && (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4) nd->nd_flag |= ND_EXTPG; @@ -8213,13 +8216,14 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t maxresp, if (tlen > 0) { /* * If cnt > MCLBYTES and the reply will not be saved, use - * ext_pgs mbufs for TLS. + * ext_pgs mbufs for TLS or enabled via vfs.nfsd.enable_mextpg. * For NFSv4.0, we do not know for sure if the reply will * be saved, so do not use ext_pgs mbufs for NFSv4.0. * Always use ext_pgs mbufs if ND_EXTPG is set. */ if ((flag & ND_EXTPG) != 0 || (tlen > MCLBYTES && - (flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS && + ((flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS || + (flag & (ND_CANEXTPG | ND_SAVEREPLY)) == ND_CANEXTPG) && (flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4)) uiop->uio_iovcnt = nfsrv_createiovec_extpgs(tlen, maxextsiz, &m, &m2, &iv); diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c index fe7f0e217a74..704667bd27b6 100644 --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -1028,13 +1028,16 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int isdgram, if (cnt > 0) { /* * If cnt > MCLBYTES and the reply will not be saved, use - * ext_pgs mbufs for TLS. + * ext_pgs mbufs for TLS of if enabled via + * vfs.nfsd.enable_mextpg. * For NFSv4.0, we do not know for sure if the reply will * be saved, so do not use ext_pgs mbufs for NFSv4.0. * Always use ext_pgs mbufs if ND_EXTPG is set. */ if ((nd->nd_flag & ND_EXTPG) != 0 || (cnt > MCLBYTES && - (nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS && + ((nd->nd_flag & (ND_TLS | ND_SAVEREPLY)) == ND_TLS || + (nd->nd_flag & (ND_CANEXTPG | ND_SAVEREPLY)) == + ND_CANEXTPG) && (nd->nd_flag & (ND_NFSV4 | ND_NFSV41)) != ND_NFSV4)) nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, nd->nd_maxextsiz, p, &m3, &m2); diff --git a/sys/rpc/svc.h b/sys/rpc/svc.h index b0fc78d4d044..e73e61e5ac93 100644 --- a/sys/rpc/svc.h +++ b/sys/rpc/svc.h @@ -155,6 +155,7 @@ typedef struct __rpc_svcxprt { uid_t xp_uid; gid_t *xp_gidp; int xp_doneddp; + bool_t xp_extpg; /* Can use M_EXTPG mbufs. */ } SVCXPRT; /*
