git: d516e52373e1 - main - nfsd: Optionally enable use of M_EXTPG mbufs for read replies
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 07 Jul 2026 00:11:40 UTC
The branch main has been updated by rmacklem:
URL: https://cgit.FreeBSD.org/src/commit/?id=d516e52373e1768ea84bf1ca220671a44f413abe
commit d516e52373e1768ea84bf1ca220671a44f413abe
Author: Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2026-07-07 00:10:11 +0000
Commit: Rick Macklem <rmacklem@FreeBSD.org>
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 <becker.greg@att.net>
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;
/*