svn commit: r358051 - projects/nfs-over-tls/sys/fs/nfsserver
Rick Macklem
rmacklem at FreeBSD.org
Mon Feb 17 20:58:34 UTC 2020
Author: rmacklem
Date: Mon Feb 17 20:58:33 2020
New Revision: 358051
URL: https://svnweb.freebsd.org/changeset/base/358051
Log:
Update sys/fs/nfsserver sources so that they handle ext_pgs mbufs.
Modified:
projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdkrpc.c
projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c
projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdserv.c
projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdsubs.c
Modified: projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdkrpc.c
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdkrpc.c Mon Feb 17 20:35:25 2020 (r358050)
+++ projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdkrpc.c Mon Feb 17 20:58:33 2020 (r358051)
@@ -38,6 +38,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet6.h"
#include "opt_kgssapi.h"
+#include "opt_kern_tls.h"
#include <fs/nfs/nfsport.h>
@@ -110,6 +111,9 @@ extern time_t nfsdev_time;
extern int nfsrv_writerpc[NFS_NPROCS];
extern volatile int nfsrv_devidcnt;
extern struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS];
+#ifdef KERN_TLS
+extern u_int ktls_maxlen;
+#endif
/*
* NFS server system calls
@@ -158,9 +162,11 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
*/
nd.nd_mrep = rqst->rq_args;
rqst->rq_args = NULL;
+#ifdef notnow
newnfs_realign(&nd.nd_mrep, M_WAITOK);
+#endif
nd.nd_md = nd.nd_mrep;
- nd.nd_dpos = mtod(nd.nd_md, caddr_t);
+ nfsm_set(&nd, false);
nd.nd_nam = svc_getrpccaller(rqst);
nd.nd_nam2 = rqst->rq_addr;
nd.nd_mreq = NULL;
@@ -269,6 +275,14 @@ nfssvc_program(struct svc_req *rqst, SVCXPRT *xprt)
}
}
+ if (xprt->xp_tls)
+ nd.nd_flag |= ND_TLS;
+ nd.nd_maxextsiz = 16384;
+#ifdef KERN_TLS
+ if (xprt->xp_tls)
+ nd.nd_maxextsiz = min(TLS_MAX_MSG_SIZE_V10_2,
+ ktls_maxlen);
+#endif
cacherep = nfs_proc(&nd, rqst->rq_xid, xprt, &rp);
NFSLOCKV4ROOTMUTEX();
nfsv4_relref(&nfsd_suspend_lock);
Modified: projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c Mon Feb 17 20:35:25 2020 (r358050)
+++ projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c Mon Feb 17 20:58:33 2020 (r358051)
@@ -76,6 +76,7 @@ extern struct nfsdontlisthead nfsrv_dontlisthead;
extern volatile int nfsrv_dontlistlen;
extern volatile int nfsrv_devidcnt;
extern int nfsrv_maxpnfsmirror;
+extern bool nfs_use_ext_pgs;
struct vfsoptlist nfsv4root_opt, nfsv4root_newopt;
NFSDLOCKMUTEX;
NFSSTATESPINLOCK;
@@ -108,8 +109,12 @@ extern struct nfsdevicehead nfsrv_devidhead;
static int nfsrv_createiovec(int, struct mbuf **, struct mbuf **,
struct iovec **);
+static int nfsrv_createiovec_extpgs(int, int, struct mbuf **,
+ struct mbuf **, struct iovec **);
static int nfsrv_createiovecw(int, struct mbuf *, char *, struct iovec **,
int *);
+static int nfsrv_createiovecw_extpgs(int, struct mbuf *, char *, int,
+ int, struct iovec **, int *);
static void nfsrv_pnfscreate(struct vnode *, struct vattr *, struct ucred *,
NFSPROC_T *);
static void nfsrv_pnfsremovesetup(struct vnode *, NFSPROC_T *, struct vnode **,
@@ -730,8 +735,8 @@ nfsvno_relpathbuf(struct nameidata *ndp)
* Readlink vnode op into an mbuf list.
*/
int
-nfsvno_readlink(struct vnode *vp, struct ucred *cred, struct thread *p,
- struct mbuf **mpp, struct mbuf **mpendp, int *lenp)
+nfsvno_readlink(struct vnode *vp, struct ucred *cred, int maxextsiz,
+ struct thread *p, struct mbuf **mpp, struct mbuf **mpendp, int *lenp)
{
struct iovec *iv;
struct uio io, *uiop = &io;
@@ -739,7 +744,11 @@ nfsvno_readlink(struct vnode *vp, struct ucred *cred,
int len, tlen, error = 0;
len = NFS_MAXPATHLEN;
- uiop->uio_iovcnt = nfsrv_createiovec(len, &mp3, &mp, &iv);
+ if (maxextsiz > 0)
+ uiop->uio_iovcnt = nfsrv_createiovec_extpgs(len, maxextsiz,
+ &mp3, &mp, &iv);
+ else
+ uiop->uio_iovcnt = nfsrv_createiovec(len, &mp3, &mp, &iv);
uiop->uio_iov = iv;
uiop->uio_offset = 0;
uiop->uio_resid = len;
@@ -756,7 +765,12 @@ nfsvno_readlink(struct vnode *vp, struct ucred *cred,
if (uiop->uio_resid > 0) {
len -= uiop->uio_resid;
tlen = NFSM_RNDUP(len);
- nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen, tlen - len);
+ if (tlen == 0) {
+ m_freem(mp3);
+ mp3 = mp = NULL;
+ } else if (tlen != NFS_MAXPATHLEN || tlen != len)
+ mp = nfsrv_adj(mp3, NFS_MAXPATHLEN - tlen,
+ tlen - len);
}
*lenp = len;
*mpp = mp3;
@@ -824,11 +838,80 @@ nfsrv_createiovec(int len, struct mbuf **mpp, struct m
}
/*
+ * Create an mbuf chain and an associated iovec that can be used to Read
+ * or Getextattr of data.
+ * Upon success, return pointers to the first and last mbufs in the chain
+ * plus the malloc'd iovec and its iovlen.
+ * Same as above, but creates ext_pgs mbuf(s).
+ */
+static int
+nfsrv_createiovec_extpgs(int len, int maxextsiz, struct mbuf **mpp,
+ struct mbuf **mpendp, struct iovec **ivp)
+{
+ struct mbuf *m, *m2 = NULL, *m3;
+ struct mbuf_ext_pgs *pgs;
+ struct iovec *iv;
+ int i, left, pgno, siz;
+
+ left = len;
+ m3 = NULL;
+ /*
+ * Generate the mbuf list with the uio_iov ref. to it.
+ */
+ i = 0;
+ while (left > 0) {
+ siz = min(left, maxextsiz);
+ m = mb_alloc_ext_plus_pages(siz, M_WAITOK, false,
+ mb_free_mext_pgs);
+ left -= siz;
+ i += m->m_ext.ext_pgs->npgs;
+ if (m3 != NULL)
+ m2->m_next = m;
+ else
+ m3 = m;
+ m2 = m;
+ }
+ *ivp = iv = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK);
+ m = m3;
+ left = len;
+ i = 0;
+ pgno = 0;
+ pgs = m->m_ext.ext_pgs;
+ while (left > 0) {
+ if (m == NULL)
+ panic("nfsvno_createiovec_extpgs iov");
+ siz = min(PAGE_SIZE, left);
+ if (siz > 0) {
+ iv->iov_base = (void *)PHYS_TO_DMAP(pgs->pa[pgno]);
+ iv->iov_len = siz;
+ m->m_len += siz;
+ if (pgno == pgs->npgs - 1)
+ pgs->last_pg_len = siz;
+ left -= siz;
+ iv++;
+ i++;
+ pgno++;
+ }
+ if (pgno == pgs->npgs && left > 0) {
+ m = m->m_next;
+ if (m == NULL)
+ panic("nfsvno_createiovec_extpgs iov");
+ pgs = m->m_ext.ext_pgs;
+ pgno = 0;
+ }
+ }
+ *mpp = m3;
+ *mpendp = m2;
+ return (i);
+}
+
+/*
* Read vnode op call into mbuf list.
*/
int
nfsvno_read(struct vnode *vp, off_t off, int cnt, struct ucred *cred,
- struct thread *p, struct mbuf **mpp, struct mbuf **mpendp)
+ int maxextsiz, struct thread *p, struct mbuf **mpp,
+ struct mbuf **mpendp)
{
struct mbuf *m;
struct iovec *iv;
@@ -847,7 +930,11 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, stru
return (error);
len = NFSM_RNDUP(cnt);
- uiop->uio_iovcnt = nfsrv_createiovec(len, &m3, &m, &iv);
+ if (maxextsiz > 0)
+ uiop->uio_iovcnt = nfsrv_createiovec_extpgs(len, maxextsiz,
+ &m3, &m, &iv);
+ else
+ uiop->uio_iovcnt = nfsrv_createiovec(len, &m3, &m, &iv);
uiop->uio_iov = iv;
uiop->uio_offset = off;
uiop->uio_resid = len;
@@ -871,9 +958,9 @@ nfsvno_read(struct vnode *vp, off_t off, int cnt, stru
tlen = NFSM_RNDUP(cnt);
if (tlen == 0) {
m_freem(m3);
- m3 = NULL;
+ m3 = m = NULL;
} else if (len != tlen || tlen != cnt)
- nfsrv_adj(m3, len - tlen, tlen - cnt);
+ m = nfsrv_adj(m3, len - tlen, tlen - cnt);
*mpp = m3;
*mpendp = m;
@@ -943,11 +1030,98 @@ nfsrv_createiovecw(int retlen, struct mbuf *m, char *c
}
/*
+ * Create the iovec for the mbuf chain passed in as an argument.
+ * The "cp" argument is where the data starts within the first mbuf in
+ * the chain. It returns the iovec and the iovcnt.
+ * Same as above, but for ext_pgs mbufs.
+ */
+static int
+nfsrv_createiovecw_extpgs(int retlen, struct mbuf *m, char *cp, int dextpg,
+ int dextpgsiz, struct iovec **ivpp, int *iovcntp)
+{
+ struct mbuf *mp;
+ struct mbuf_ext_pgs *pgs;
+ struct iovec *ivp;
+ int cnt, i, len, pgno;
+
+ /*
+ * Loop through the mbuf chain, counting how many pages are
+ * part of this write oepration, so the iovec size is known.
+ */
+ cnt = 0;
+ len = retlen;
+ mp = m;
+ pgs = mp->m_ext.ext_pgs;
+ i = dextpgsiz;
+ pgno = dextpg;
+ while (len > 0) {
+ if (i > 0) {
+ len -= i;
+ cnt++;
+ }
+ if (len > 0) {
+ if (pgno == pgs->npgs - 1) {
+ mp = mp->m_next;
+ if (mp == NULL)
+ return (EBADRPC);
+ pgno = 0;
+ pgs = mp->m_ext.ext_pgs;
+ } else
+ pgno++;
+ if (pgno == 0)
+ i = mbuf_ext_pg_len(pgs, 0,
+ pgs->first_pg_off);
+ else
+ i = mbuf_ext_pg_len(pgs, pgno, 0);
+ }
+ }
+
+ /* Now, create the iovec. */
+ mp = m;
+ *ivpp = ivp = malloc(cnt * sizeof (struct iovec), M_TEMP,
+ M_WAITOK);
+ *iovcntp = cnt;
+ len = retlen;
+ pgs = mp->m_ext.ext_pgs;
+ i = dextpgsiz;
+ pgno = dextpg;
+ while (len > 0) {
+ if (i > 0) {
+ i = min(i, len);
+ ivp->iov_base = cp;
+ ivp->iov_len = i;
+ ivp++;
+ len -= i;
+ }
+ if (len > 0) {
+ if (pgno == pgs->npgs - 1) {
+ mp = mp->m_next;
+ if (mp == NULL)
+ return (EBADRPC);
+ pgno = 0;
+ pgs = mp->m_ext.ext_pgs;
+ } else
+ pgno++;
+ cp = (char *)(void *)
+ PHYS_TO_DMAP(pgs->pa[pgno]);
+ if (pgno == 0) {
+ cp += pgs->first_pg_off;
+ i = mbuf_ext_pg_len(pgs, 0,
+ pgs->first_pg_off);
+ } else
+ i = mbuf_ext_pg_len(pgs, pgno, 0);
+ }
+ }
+ return (0);
+}
+
+/*
* Write vnode op from an mbuf list.
*/
int
nfsvno_write(struct vnode *vp, off_t off, int retlen, int *stable,
- struct mbuf *mp, char *cp, struct ucred *cred, struct thread *p)
+ struct mbuf *mp, char *cp, int dextpg, int dextpgsiz,
+ struct ucred *cred, struct thread *p)
{
struct iovec *iv;
int cnt, ioflags, error;
@@ -970,7 +1144,11 @@ nfsvno_write(struct vnode *vp, off_t off, int retlen,
ioflags = IO_NODELOCKED;
else
ioflags = (IO_SYNC | IO_NODELOCKED);
- error = nfsrv_createiovecw(retlen, mp, cp, &iv, &cnt);
+ if ((mp->m_flags & (M_EXT | M_NOMAP)) == (M_EXT | M_NOMAP))
+ error = nfsrv_createiovecw_extpgs(retlen, mp, cp, dextpg,
+ dextpgsiz, &iv, &cnt);
+ else
+ error = nfsrv_createiovecw(retlen, mp, cp, &iv, &cnt);
if (error != 0)
return (error);
uiop->uio_iov = iv;
@@ -2135,6 +2313,7 @@ nfsrvd_readdirplus(struct nfsrv_descript *nd, int isdg
struct mount *mp, *new_mp;
uint64_t mounted_on_fileno;
struct thread *p = curthread;
+ int bextpg0, bextpg1, bextpgsiz0, bextpgsiz1;
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &at);
@@ -2353,6 +2532,8 @@ again:
*/
mb0 = nd->nd_mb;
bpos0 = nd->nd_bpos;
+ bextpg0 = nd->nd_bextpg;
+ bextpgsiz0 = nd->nd_bextpgsiz;
/*
* Fill in the first part of the reply.
@@ -2374,6 +2555,8 @@ again:
*/
mb1 = nd->nd_mb;
bpos1 = nd->nd_bpos;
+ bextpg1 = nd->nd_bextpg;
+ bextpgsiz1 = nd->nd_bextpgsiz;
/* Loop through the records and build reply */
entrycnt = 0;
@@ -2390,6 +2573,8 @@ again:
*/
mb1 = nd->nd_mb;
bpos1 = nd->nd_bpos;
+ bextpg1 = nd->nd_bextpg;
+ bextpgsiz1 = nd->nd_bextpgsiz;
/*
* For readdir_and_lookup get the vnode using
@@ -2615,11 +2800,11 @@ invalid:
if (!nd->nd_repstat && entrycnt == 0)
nd->nd_repstat = NFSERR_TOOSMALL;
if (nd->nd_repstat) {
- newnfs_trimtrailing(nd, mb0, bpos0);
+ nfsm_trimtrailing(nd, mb0, bpos0, bextpg0, bextpgsiz0);
if (nd->nd_flag & ND_NFSV3)
nfsrv_postopattr(nd, getret, &at);
} else
- newnfs_trimtrailing(nd, mb1, bpos1);
+ nfsm_trimtrailing(nd, mb1, bpos1, bextpg1, bextpgsiz1);
eofflag = 0;
} else if (cpos < cend)
eofflag = 0;
@@ -4928,7 +5113,7 @@ nfsrv_readdsrpc(fhandle_t *fhp, off_t off, int len, st
st.other[2] = 0x55555555;
st.seqid = 0xffffffff;
nfscl_reqstart(nd, NFSPROC_READDS, nmp, (u_int8_t *)fhp, sizeof(*fhp),
- NULL, NULL, 0, 0);
+ NULL, NULL, 0, 0, false);
nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED * 3);
txdr_hyper(off, tl);
@@ -4963,10 +5148,15 @@ nfsrv_readdsrpc(fhandle_t *fhp, off_t off, int len, st
* Now, adjust first mbuf so that any XDR before the
* read data is skipped over.
*/
- trimlen = nd->nd_dpos - mtod(m, char *);
- if (trimlen > 0) {
- m->m_len -= trimlen;
- NFSM_DATAP(m, trimlen);
+ if ((nd->nd_md->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP))
+ nfsm_trimatpos_extpgs(nd);
+ else {
+ trimlen = nd->nd_dpos - mtod(m, char *);
+ if (trimlen > 0) {
+ m->m_len -= trimlen;
+ NFSM_DATAP(m, trimlen);
+ }
}
/*
@@ -4977,7 +5167,11 @@ nfsrv_readdsrpc(fhandle_t *fhp, off_t off, int len, st
tlen = NFSM_RNDUP(retlen);
do {
if (m->m_len >= tlen) {
- m->m_len = tlen;
+ if ((m->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP))
+ nfsm_trimback_extpgs(m, tlen);
+ else
+ m->m_len = tlen;
tlen = 0;
m2 = m->m_next;
m->m_next = NULL;
@@ -5036,7 +5230,7 @@ nfsrv_writedsdorpc(struct nfsmount *nmp, fhandle_t *fh
nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
nfscl_reqstart(nd, NFSPROC_WRITE, nmp, (u_int8_t *)fhp,
- sizeof(fhandle_t), NULL, NULL, 0, 0);
+ sizeof(fhandle_t), NULL, NULL, 0, 0, false);
/*
* Use a stateid where other is an alternating 01010 pattern and
@@ -5258,7 +5452,7 @@ nfsrv_allocatedsdorpc(struct nfsmount *nmp, fhandle_t
nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
nfscl_reqstart(nd, NFSPROC_ALLOCATE, nmp, (u_int8_t *)fhp,
- sizeof(fhandle_t), NULL, NULL, 0, 0);
+ sizeof(fhandle_t), NULL, NULL, 0, 0, false);
/*
* Use a stateid where other is an alternating 01010 pattern and
@@ -5412,7 +5606,7 @@ nfsrv_setattrdsdorpc(fhandle_t *fhp, struct ucred *cre
st.other[2] = 0x55555555;
st.seqid = 0xffffffff;
nfscl_reqstart(nd, NFSPROC_SETATTR, nmp, (u_int8_t *)fhp, sizeof(*fhp),
- NULL, NULL, 0, 0);
+ NULL, NULL, 0, 0, false);
nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
nfscl_fillsattr(nd, &nap->na_vattr, vp, NFSSATTR_FULL, 0);
@@ -5597,7 +5791,7 @@ nfsrv_setacldsdorpc(fhandle_t *fhp, struct ucred *cred
st.other[2] = 0x55555555;
st.seqid = 0xffffffff;
nfscl_reqstart(nd, NFSPROC_SETACL, nmp, (u_int8_t *)fhp, sizeof(*fhp),
- NULL, NULL, 0, 0);
+ NULL, NULL, 0, 0, false);
nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
NFSZERO_ATTRBIT(&attrbits);
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_ACL);
@@ -5732,7 +5926,7 @@ nfsrv_getattrdsrpc(fhandle_t *fhp, struct ucred *cred,
NFSD_DEBUG(4, "in nfsrv_getattrdsrpc\n");
nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, (u_int8_t *)fhp,
- sizeof(fhandle_t), NULL, NULL, 0, 0);
+ sizeof(fhandle_t), NULL, NULL, 0, 0, false);
NFSZERO_ATTRBIT(&attrbits);
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_SIZE);
NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
@@ -5800,7 +5994,7 @@ nfsrv_seekdsrpc(fhandle_t *fhp, off_t *offp, int conte
st.seqid = 0xffffffff;
nd = malloc(sizeof(*nd), M_TEMP, M_WAITOK | M_ZERO);
nfscl_reqstart(nd, NFSPROC_SEEKDS, nmp, (u_int8_t *)fhp,
- sizeof(fhandle_t), NULL, NULL, 0, 0);
+ sizeof(fhandle_t), NULL, NULL, 0, 0, false);
nfsm_stateidtom(nd, &st, NFSSTATEID_PUTSTATEID);
NFSM_BUILD(tl, uint32_t *, NFSX_HYPER + NFSX_UNSIGNED);
txdr_hyper(*offp, tl); tl += 2;
@@ -6140,8 +6334,8 @@ nfsvno_allocate(struct vnode *vp, off_t off, off_t len
*/
int
nfsvno_getxattr(struct vnode *vp, char *name, uint32_t maxresp,
- struct ucred *cred, struct thread *p, struct mbuf **mpp,
- struct mbuf **mpendp, int *lenp)
+ struct ucred *cred, uint64_t flag, int maxextsiz, struct thread *p,
+ struct mbuf **mpp, struct mbuf **mpendp, int *lenp)
{
struct iovec *iv;
struct uio io, *uiop = &io;
@@ -6158,7 +6352,17 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t
return (NFSERR_XATTR2BIG);
len = siz;
tlen = NFSM_RNDUP(len);
- uiop->uio_iovcnt = nfsrv_createiovec(tlen, &m, &m2, &iv);
+ /*
+ * If the cnt is larger than MCLBYTES, use ext_pgs if
+ * possible.
+ * Always use ext_pgs if ND_EXTPG is set.
+ */
+ if ((flag & ND_EXTPG) != 0 || (tlen > MCLBYTES &&
+ PMAP_HAS_DMAP != 0 && ((flag & ND_TLS) != 0 || nfs_use_ext_pgs)))
+ uiop->uio_iovcnt = nfsrv_createiovec_extpgs(tlen, maxextsiz,
+ &m, &m2, &iv);
+ else
+ uiop->uio_iovcnt = nfsrv_createiovec(tlen, &m, &m2, &iv);
uiop->uio_iov = iv;
uiop->uio_offset = 0;
uiop->uio_resid = tlen;
@@ -6182,7 +6386,11 @@ nfsvno_getxattr(struct vnode *vp, char *name, uint32_t
tlen = NFSM_RNDUP(len);
if (alen != tlen)
printf("nfsvno_getxattr: weird size read\n");
- nfsrv_adj(m, alen - tlen, tlen - len);
+ if (tlen == 0) {
+ m_freem(m);
+ m = m2 = NULL;
+ } else if (alen != tlen || tlen != len)
+ m2 = nfsrv_adj(m, alen - tlen, tlen - len);
}
*lenp = len;
*mpp = m;
@@ -6203,7 +6411,8 @@ out:
*/
int
nfsvno_setxattr(struct vnode *vp, char *name, int len, struct mbuf *m,
- char *cp, struct ucred *cred, struct thread *p)
+ char *cp, int dextpg, int dextpgsiz, struct ucred *cred,
+ struct thread *p)
{
struct iovec *iv;
struct uio uio, *uiop = &uio;
@@ -6222,7 +6431,11 @@ nfsvno_setxattr(struct vnode *vp, char *name, int len,
uiop->uio_td = p;
uiop->uio_offset = 0;
uiop->uio_resid = len;
- error = nfsrv_createiovecw(len, m, cp, &iv, &cnt);
+ if ((m->m_flags & (M_EXT | M_NOMAP)) == (M_EXT | M_NOMAP))
+ error = nfsrv_createiovecw_extpgs(len, m, cp, dextpg,
+ dextpgsiz, &iv, &cnt);
+ else
+ error = nfsrv_createiovecw(len, m, cp, &iv, &cnt);
uiop->uio_iov = iv;
uiop->uio_iovcnt = cnt;
if (error == 0) {
Modified: projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdserv.c
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdserv.c Mon Feb 17 20:35:25 2020 (r358050)
+++ projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdserv.c Mon Feb 17 20:58:33 2020 (r358051)
@@ -68,6 +68,7 @@ extern u_long sb_max_adj;
extern int nfsrv_pnfsatime;
extern int nfsrv_maxpnfsmirror;
extern int nfs_maxcopyrange;
+extern bool nfs_use_ext_pgs;
#endif /* !APPLEKEXT */
static int nfs_async = 0;
@@ -665,6 +666,8 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused in
int getret = 1, len;
struct nfsvattr nva;
struct thread *p = curthread;
+ struct mbuf_ext_pgs *pgs;
+ uint16_t off;
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &nva);
@@ -676,9 +679,14 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused in
else
nd->nd_repstat = EINVAL;
}
- if (!nd->nd_repstat)
- nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred, p,
- &mp, &mpend, &len);
+ if (nd->nd_repstat == 0) {
+ if ((nd->nd_flag & ND_EXTPG) != 0)
+ nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred,
+ nd->nd_maxextsiz, p, &mp, &mpend, &len);
+ else
+ nd->nd_repstat = nfsvno_readlink(vp, nd->nd_cred,
+ 0, p, &mp, &mpend, &len);
+ }
if (nd->nd_flag & ND_NFSV3)
getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
vput(vp);
@@ -688,9 +696,21 @@ nfsrvd_readlink(struct nfsrv_descript *nd, __unused in
goto out;
NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(len);
- mbuf_setnext(nd->nd_mb, mp);
- nd->nd_mb = mpend;
- nd->nd_bpos = NFSMTOD(mpend, caddr_t) + mbuf_len(mpend);
+ if (mp != NULL) {
+ nd->nd_mb->m_next = mp;
+ nd->nd_mb = mpend;
+ if ((mpend->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP)) {
+ pgs = mpend->m_ext.ext_pgs;
+ nd->nd_bextpg = pgs->npgs - 1;
+ nd->nd_bpos = (char *)(void *)
+ PHYS_TO_DMAP(pgs->pa[nd->nd_bextpg]);
+ off = (nd->nd_bextpg == 0) ? pgs->first_pg_off : 0;
+ nd->nd_bpos += off + pgs->last_pg_len;
+ nd->nd_bextpgsiz = PAGE_SIZE - pgs->last_pg_len - off;
+ } else
+ nd->nd_bpos = mtod(mpend, char *) + mpend->m_len;
+ }
out:
NFSEXITCODE2(0, nd);
@@ -714,6 +734,8 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is
nfsv4stateid_t stateid;
nfsquad_t clientid;
struct thread *p = curthread;
+ struct mbuf_ext_pgs *pgs;
+ uint16_t poff;
if (nd->nd_repstat) {
nfsrv_postopattr(nd, getret, &nva);
@@ -835,8 +857,18 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is
cnt = reqlen;
m3 = NULL;
if (cnt > 0) {
- nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred, p,
- &m3, &m2);
+ /*
+ * If the cnt is larger than MCLBYTES, use ext_pgs if
+ * possible.
+ * Always use ext_pgs if ND_EXTPG is set.
+ */
+ if ((nd->nd_flag & ND_EXTPG) != 0 || (PMAP_HAS_DMAP != 0 &&
+ ((nd->nd_flag & ND_TLS) != 0 || nfs_use_ext_pgs)))
+ nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred,
+ nd->nd_maxextsiz, p, &m3, &m2);
+ else
+ nd->nd_repstat = nfsvno_read(vp, off, cnt, nd->nd_cred,
+ 0, p, &m3, &m2);
if (!(nd->nd_flag & ND_NFSV4)) {
getret = nfsvno_getattr(vp, &nva, nd, p, 1, NULL);
if (!nd->nd_repstat)
@@ -869,9 +901,20 @@ nfsrvd_read(struct nfsrv_descript *nd, __unused int is
}
*tl = txdr_unsigned(cnt);
if (m3) {
- mbuf_setnext(nd->nd_mb, m3);
+ nd->nd_mb->m_next = m3;
nd->nd_mb = m2;
- nd->nd_bpos = NFSMTOD(m2, caddr_t) + mbuf_len(m2);
+ if ((m2->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP)) {
+ nd->nd_flag |= ND_EXTPG;
+ pgs = m2->m_ext.ext_pgs;
+ nd->nd_bextpg = pgs->npgs - 1;
+ nd->nd_bpos = (char *)(void *)
+ PHYS_TO_DMAP(pgs->pa[nd->nd_bextpg]);
+ poff = (nd->nd_bextpg == 0) ? pgs->first_pg_off : 0;
+ nd->nd_bpos += poff + pgs->last_pg_len;
+ nd->nd_bextpgsiz = PAGE_SIZE - pgs->last_pg_len - poff;
+ } else
+ nd->nd_bpos = mtod(m2, char *) + m2->m_len;
}
out:
@@ -1014,7 +1057,8 @@ nfsrvd_write(struct nfsrv_descript *nd, __unused int i
*/
if (retlen > 0) {
nd->nd_repstat = nfsvno_write(vp, off, retlen, &stable,
- nd->nd_md, nd->nd_dpos, nd->nd_cred, p);
+ nd->nd_md, nd->nd_dpos, nd->nd_dextpg, nd->nd_dextpgsiz,
+ nd->nd_cred, p);
error = nfsm_advance(nd, NFSM_RNDUP(retlen), -1);
if (error)
goto nfsmout;
@@ -5509,6 +5553,8 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused in
int error, len;
char *name;
struct thread *p = curthread;
+ struct mbuf_ext_pgs *pgs;
+ uint16_t off;
error = 0;
if (nfs_rootfhset == 0 || nfsd_checkrootexp(nd) != 0) {
@@ -5528,8 +5574,9 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused in
name = malloc(len + 1, M_TEMP, M_WAITOK);
nd->nd_repstat = nfsrv_mtostr(nd, name, len);
if (nd->nd_repstat == 0)
- nd->nd_repstat = nfsvno_getxattr(vp, name, nd->nd_maxresp,
- nd->nd_cred, p, &mp, &mpend, &len);
+ nd->nd_repstat = nfsvno_getxattr(vp, name,
+ nd->nd_maxresp, nd->nd_cred, nd->nd_flag,
+ nd->nd_maxextsiz, p, &mp, &mpend, &len);
if (nd->nd_repstat == ENOATTR)
nd->nd_repstat = NFSERR_NOXATTR;
else if (nd->nd_repstat == EOPNOTSUPP)
@@ -5537,9 +5584,22 @@ nfsrvd_getxattr(struct nfsrv_descript *nd, __unused in
if (nd->nd_repstat == 0) {
NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
*tl = txdr_unsigned(len);
- mbuf_setnext(nd->nd_mb, mp);
- nd->nd_mb = mpend;
- nd->nd_bpos = NFSMTOD(mpend, caddr_t) + mbuf_len(mpend);
+ if (mp != NULL) {
+ nd->nd_mb->m_next = mp;
+ nd->nd_mb = mpend;
+ if ((mpend->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP)) {
+ nd->nd_flag |= ND_EXTPG;
+ pgs = mpend->m_ext.ext_pgs;
+ nd->nd_bextpg = pgs->npgs - 1;
+ nd->nd_bpos = (char *)(void *)
+ PHYS_TO_DMAP(pgs->pa[nd->nd_bextpg]);
+ off = (nd->nd_bextpg == 0) ? pgs->first_pg_off : 0;
+ nd->nd_bpos += off + pgs->last_pg_len;
+ nd->nd_bextpgsiz = PAGE_SIZE - pgs->last_pg_len - off;
+ } else
+ nd->nd_bpos = mtod(mpend, char *) + mpend->m_len;
+ }
}
free(name, M_TEMP);
@@ -5621,7 +5681,8 @@ nfsrvd_setxattr(struct nfsrv_descript *nd, __unused in
nd->nd_repstat = nfsvno_getattr(vp, &ova, nd, p, 1, &attrbits);
if (nd->nd_repstat == 0) {
nd->nd_repstat = nfsvno_setxattr(vp, name, len, nd->nd_md,
- nd->nd_dpos, nd->nd_cred, p);
+ nd->nd_dpos, nd->nd_dextpg, nd->nd_dextpgsiz, nd->nd_cred,
+ p);
if (nd->nd_repstat == ENXIO)
nd->nd_repstat = NFSERR_XATTR2BIG;
}
Modified: projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdsubs.c
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdsubs.c Mon Feb 17 20:35:25 2020 (r358050)
+++ projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdsubs.c Mon Feb 17 20:58:33 2020 (r358051)
@@ -1270,62 +1270,96 @@ static short *nfsrv_v4errmap[] = {
};
/*
- * A fiddled version of m_adj() that ensures null fill to a long
- * boundary and only trims off the back end
+ * Trim tlen bytes off the end of the mbuf list and then ensure
+ * the end of the last mbuf is nul filled to a long boundary,
+ * as indicated by the value of "nul".
+ * Return the last mbuf in the updated list and free and mbufs
+ * that follow it in the original list.
+ * This is somewhat different than the old nfsrv_adj() with
+ * support for ext_pgs mbufs. It frees the remaining mbufs
+ * instead of setting them 0 length, since lists of ext_pgs
+ * mbufs are all expected to be non-empty.
*/
-APPLESTATIC void
-nfsrv_adj(mbuf_t mp, int len, int nul)
+struct mbuf *
+nfsrv_adj(struct mbuf *mp, int len, int nul)
{
- mbuf_t m;
- int count, i;
+ struct mbuf *m, *m2;
+ struct mbuf_ext_pgs *pgs;
+ vm_page_t pg;
+ int i, lastlen, pgno, plen, tlen, trim;
+ uint16_t off;
char *cp;
/*
- * Trim from tail. Scan the mbuf chain,
- * calculating its length and finding the last mbuf.
- * If the adjustment only affects this mbuf, then just
- * adjust and return. Otherwise, rescan and truncate
- * after the remaining size.
+ * Find the last mbuf after adjustment and
+ * how much it needs to be adjusted by.
*/
- count = 0;
+ tlen = 0;
m = mp;
for (;;) {
- count += mbuf_len(m);
- if (mbuf_next(m) == NULL)
+ tlen += m->m_len;
+ if (m->m_next == NULL)
break;
- m = mbuf_next(m);
+ m = m->m_next;
}
- if (mbuf_len(m) > len) {
- mbuf_setlen(m, mbuf_len(m) - len);
- if (nul > 0) {
- cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
+
+ /* m is now the last mbuf and tlen the total length. */
+ if (len >= m->m_len) {
+ /* Need to trim away the last mbuf(s). */
+ i = tlen - len;
+ m = mp;
+ for (;;) {
+ if (m->m_len >= i)
+ break;
+ i -= m->m_len;
+ m = m->m_next;
}
- return;
- }
- count -= len;
- if (count < 0)
- count = 0;
- /*
- * Correct length for chain is "count".
- * Find the mbuf with last data, adjust its length,
- * and toss data from remaining mbufs on chain.
- */
- for (m = mp; m; m = mbuf_next(m)) {
- if (mbuf_len(m) >= count) {
- mbuf_setlen(m, count);
- if (nul > 0) {
- cp = NFSMTOD(m, caddr_t) + mbuf_len(m) - nul;
- for (i = 0; i < nul; i++)
- *cp++ = '\0';
+ lastlen = i;
+ } else
+ lastlen = m->m_len - len;
+
+ /* Adjust the last mbuf. */
+ if ((m->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP)) {
+ pgs = m->m_ext.ext_pgs;
+ pgno = pgs->npgs - 1;
+ off = (pgno == 0) ? pgs->first_pg_off : 0;
+ plen = mbuf_ext_pg_len(pgs, pgno, off);
+ if (m->m_len > lastlen) {
+ /* Trim this mbuf. */
+ trim = m->m_len - lastlen;
+ while (trim >= plen) {
+ /* Free page. */
+ pg = PHYS_TO_VM_PAGE(pgs->pa[pgno]);
+ vm_page_unwire_noq(pg);
+ vm_page_free(pg);
+ trim -= plen;
+ pgs->npgs--;
+ pgno--;
+ off = (pgno == 0) ? pgs->first_pg_off : 0;
+ plen = mbuf_ext_pg_len(pgs, pgno, off);
}
- break;
+ plen -= trim;
+ pgs->last_pg_len = plen;
+ m->m_len = lastlen;
}
- count -= mbuf_len(m);
+ cp = (char *)(void *)PHYS_TO_DMAP(pgs->pa[pgno]);
+ cp += off + plen - nul;
+ } else {
+ m->m_len = lastlen;
+ cp = mtod(m, char *) + m->m_len - nul;
}
- for (m = mbuf_next(m); m; m = mbuf_next(m))
- mbuf_setlen(m, 0);
+
+ /* Write the nul bytes. */
+ for (i = 0; i < nul; i++)
+ *cp++ = '\0';
+
+ /* Free up any mbufs past "m". */
+ m2 = m->m_next;
+ m->m_next = NULL;
+ if (m2 != NULL)
+ m_freem(m2);
+ return (m);
}
/*
@@ -1837,8 +1871,9 @@ APPLESTATIC int
nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, u_long *hashp,
NFSPATHLEN_T *outlenp)
{
+ struct mbuf_ext_pgs *pgs;
+ vm_page_t pg;
char *fromcp, *tocp, val = '\0';
- mbuf_t md;
int i;
int rem, len, error = 0, pubtype = 0, outlen = 0, percent = 0;
char digit;
@@ -1853,177 +1888,194 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp,
* Otherwise, get the component name.
*/
if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) {
- *tocp++ = '.';
- hash += ((u_char)'.');
- *tocp++ = '.';
- hash += ((u_char)'.');
- outlen = 2;
+ *tocp++ = '.';
+ hash += ((u_char)'.');
+ *tocp++ = '.';
+ hash += ((u_char)'.');
+ outlen = 2;
} else {
- /*
- * First, get the name length.
- */
- NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
- len = fxdr_unsigned(int, *tl);
- if (len > NFS_MAXNAMLEN) {
- nd->nd_repstat = NFSERR_NAMETOL;
- error = 0;
- goto nfsmout;
- } else if (len <= 0) {
- nd->nd_repstat = NFSERR_INVAL;
- error = 0;
- goto nfsmout;
- }
-
- /*
- * Now, copy the component name into the buffer.
- */
- fromcp = nd->nd_dpos;
- md = nd->nd_md;
- rem = NFSMTOD(md, caddr_t) + mbuf_len(md) - fromcp;
- for (i = 0; i < len; i++) {
- while (rem == 0) {
- md = mbuf_next(md);
- if (md == NULL) {
- error = EBADRPC;
- goto nfsmout;
- }
- fromcp = NFSMTOD(md, caddr_t);
- rem = mbuf_len(md);
- }
- if (*fromcp == '\0') {
- nd->nd_repstat = EACCES;
+ /*
+ * First, get the name length.
+ */
+ NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
+ len = fxdr_unsigned(int, *tl);
+ if (len > NFS_MAXNAMLEN) {
+ nd->nd_repstat = NFSERR_NAMETOL;
error = 0;
goto nfsmout;
+ } else if (len <= 0) {
+ nd->nd_repstat = NFSERR_INVAL;
+ error = 0;
+ goto nfsmout;
}
+
/*
- * For lookups on the public filehandle, do some special
- * processing on the name. (The public file handle is the
- * root of the public file system for this server.)
+ * Now, copy the component name into the buffer.
*/
- if (nd->nd_flag & ND_PUBLOOKUP) {
- /*
- * If the first char is ASCII, it is a canonical
- * path, otherwise it is a native path. (RFC2054
- * doesn't actually state what it is if the first
- * char isn't ASCII or 0x80, so I assume native.)
- * pubtype == 1 -> native path
- * pubtype == 2 -> canonical path
- */
- if (i == 0) {
- if (*fromcp & 0x80) {
- /*
- * Since RFC2054 doesn't indicate
- * that a native path of just 0x80
- * isn't allowed, I'll replace the
- * 0x80 with '/' instead of just
- * throwing it away.
- */
- *fromcp = '/';
- pubtype = 1;
+ fromcp = nd->nd_dpos;
+ if ((nd->nd_md->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP))
+ rem = nd->nd_dextpgsiz;
+ else
+ rem = mtod(nd->nd_md, char *) + nd->nd_md->m_len -
+ fromcp;
+ for (i = 0; i < len; i++) {
+ while (rem == 0) {
+ if ((nd->nd_md->m_flags & (M_EXT | M_NOMAP)) ==
+ (M_EXT | M_NOMAP) && nd->nd_dextpg <
+ nd->nd_md->m_ext.ext_pgs->npgs - 1) {
+ pgs = nd->nd_md->m_ext.ext_pgs;
+ pg = PHYS_TO_VM_PAGE(
+ pgs->pa[nd->nd_dextpg]);
+ vm_page_unwire_noq(pg);
+ vm_page_free(pg);
+ for (i = nd->nd_bextpg;
+ i < pgs->npgs - 1; i++)
+ pgs->pa[i] = pgs->pa[i + 1];
+ pgs->npgs--;
+ if (nd->nd_dextpg == 0)
+ pgs->first_pg_off = 0;
+ fromcp = nd->nd_dpos = (char *)(void *)
+ PHYS_TO_DMAP(pgs->pa[nd->nd_dextpg]);
+ rem = nd->nd_dextpgsiz =
+ mbuf_ext_pg_len(pgs, nd->nd_dextpg, 0);
} else {
- pubtype = 2;
+ if (!nfsm_shiftnext(nd, &rem)) {
+ error = EBADRPC;
+ goto nfsmout;
+ }
+ fromcp = nd->nd_dpos;
}
}
- /*
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list