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
This commit is contained in:
Rick Macklem committed 2026-07-06 17:10:11 -07:00
1 parent ee5d87a3e2
commit d516e52373
5 files changed
+34 -9

No files matched your search

+1
View File
@@ -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.
+17 -1
View File
@@ -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
+10 -6
View File
@@ -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);
+5 -2
View File
@@ -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);
+1
View File
@@ -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;
/*