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;
 
 /*

Reply via email to