svn commit: r363499 - in head/sys/fs: nfs nfsclient

Rick Macklem rmacklem at FreeBSD.org
Fri Jul 24 23:17:11 UTC 2020


Author: rmacklem
Date: Fri Jul 24 23:17:09 2020
New Revision: 363499
URL: https://svnweb.freebsd.org/changeset/base/363499

Log:
  Add support for ext_pgs mbufs to nfsm_uiombuflist() and nfsm_split().
  
  This patch uses a slightly different algorithm for nfsm_uiombuflist() for
  the non-ext_pgs case, where a variable called "mcp" is maintained, pointing to
  the current location that mbuf data can be filled into. This avoids use of
  mtod(mp, char *) + mp->m_len to calculate the location, since this does
  not work for ext_pgs mbufs and I think it makes the algorithm more readable.
  This change should not result in semantic changes for the non-ext_pgs case.
  The patch also deletes come unneeded code.
  
  It also adds support for anonymous page ext_pgs mbufs to nfsm_split().
  
  This is another in the series of commits that add support to the NFS client
  and server for building RPC messages in ext_pgs mbufs with anonymous pages.
  This is useful so that the entire mbuf list does not need to be
  copied before calling sosend() when NFS over TLS is enabled.
  At this time for this case, use of ext_pgs mbufs cannot be enabled, since
  ktls_encrypt() replaces the unencrypted data with encrypted data in place.
  
  Until such time as this can be enabled, there should be no semantic change.
  Also, note that this code is only used by the NFS client for a mirrored pNFS
  server.

Modified:
  head/sys/fs/nfs/nfs_var.h
  head/sys/fs/nfsclient/nfs_clcomsubs.c
  head/sys/fs/nfsclient/nfs_clrpcops.c

Modified: head/sys/fs/nfs/nfs_var.h
==============================================================================
--- head/sys/fs/nfs/nfs_var.h	Fri Jul 24 23:15:42 2020	(r363498)
+++ head/sys/fs/nfs/nfs_var.h	Fri Jul 24 23:17:09 2020	(r363499)
@@ -365,7 +365,7 @@ struct mbuf *nfsm_add_ext_pgs(struct mbuf *, int, int 
 
 /* nfs_clcomsubs.c */
 void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);
-struct mbuf *nfsm_uiombuflist(struct uio *, int, struct mbuf **, char **);
+struct mbuf *nfsm_uiombuflist(struct uio *, int, u_int);
 nfsuint64 *nfscl_getcookie(struct nfsnode *, off_t off, int);
 u_int8_t *nfscl_getmyip(struct nfsmount *, struct in6_addr *, int *);
 int nfsm_getfh(struct nfsrv_descript *, struct nfsfh **);

Modified: head/sys/fs/nfsclient/nfs_clcomsubs.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clcomsubs.c	Fri Jul 24 23:15:42 2020	(r363498)
+++ head/sys/fs/nfsclient/nfs_clcomsubs.c	Fri Jul 24 23:17:09 2020	(r363499)
@@ -160,26 +160,33 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *ui
  * NOTE: can ony handle iovcnt == 1
  */
 struct mbuf *
-nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
+nfsm_uiombuflist(struct uio *uiop, int siz, u_int maxext)
 {
 	char *uiocp;
 	struct mbuf *mp, *mp2, *firstmp;
-	int i, left, mlen, rem, xfer;
+	int extpg, extpgsiz = 0, i, left, mlen, rem, xfer;
 	int uiosiz, clflg;
 	char *mcp, *tcp;
 
 	KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
 
-	if (siz > ncl_mbuf_mlen)	/* or should it >= MCLBYTES ?? */
-		clflg = 1;
-	else
-		clflg = 0;
-	if (clflg != 0)
-		NFSMCLGET(mp, M_WAITOK);
-	else
-		NFSMGET(mp);
+	if (maxext > 0) {
+		mp = mb_alloc_ext_plus_pages(PAGE_SIZE, M_WAITOK);
+		mcp = (char *)(void *)PHYS_TO_DMAP(mp->m_epg_pa[0]);
+		extpg = 0;
+		extpgsiz = PAGE_SIZE;
+	} else {
+		if (siz > ncl_mbuf_mlen) /* or should it >= MCLBYTES ?? */
+			clflg = 1;
+		else
+			clflg = 0;
+		if (clflg != 0)
+			NFSMCLGET(mp, M_WAITOK);
+		else
+			NFSMGET(mp);
+		mcp = mtod(mp, char *);
+	}
 	mp->m_len = 0;
-	mcp = mtod(mp, char *);
 	firstmp = mp2 = mp;
 	rem = NFSM_RNDUP(siz) - siz;
 	while (siz > 0) {
@@ -189,17 +196,28 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu
 			left = siz;
 		uiosiz = left;
 		while (left > 0) {
-			mlen = M_TRAILINGSPACE(mp);
-			if (mlen == 0) {
-				if (clflg)
-					NFSMCLGET(mp, M_WAITOK);
-				else
-					NFSMGET(mp);
-				mp->m_len = 0;
-				mcp = mtod(mp, char *);
-				mp2->m_next = mp;
-				mp2 = mp;
+			if (maxext > 0)
+				mlen = extpgsiz;
+			else
 				mlen = M_TRAILINGSPACE(mp);
+			if (mlen == 0) {
+				if (maxext > 0) {
+					mp = nfsm_add_ext_pgs(mp, maxext,
+					    &extpg);
+					mlen = extpgsiz = PAGE_SIZE;
+					mcp = (char *)(void *)PHYS_TO_DMAP(
+					    mp->m_epg_pa[extpg]);
+				} else {
+					if (clflg)
+						NFSMCLGET(mp, M_WAITOK);
+					else
+						NFSMGET(mp);
+					mcp = mtod(mp, char *);
+					mlen = M_TRAILINGSPACE(mp);
+					mp->m_len = 0;
+					mp2->m_next = mp;
+					mp2 = mp;
+				}
 			}
 			xfer = (left > mlen) ? mlen : left;
 			if (uiop->uio_segflg == UIO_SYSSPACE)
@@ -208,6 +226,10 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu
 				copyin(uiocp, mcp, xfer);
 			mp->m_len += xfer;
 			mcp += xfer;
+			if (maxext > 0) {
+				extpgsiz -= xfer;
+				mp->m_epg_last_len += xfer;
+			}
 			left -= xfer;
 			uiocp += xfer;
 			uiop->uio_offset += xfer;
@@ -220,16 +242,15 @@ nfsm_uiombuflist(struct uio *uiop, int siz, struct mbu
 		siz -= uiosiz;
 	}
 	if (rem > 0) {
-		KASSERT(rem <= M_TRAILINGSPACE(mp),
+		KASSERT((mp->m_flags & M_EXTPG) != 0 ||
+		    rem <= M_TRAILINGSPACE(mp),
 		    ("nfsm_uiombuflist: no space for padding"));
 		for (i = 0; i < rem; i++)
 			*mcp++ = '\0';
 		mp->m_len += rem;
+		if (maxext > 0)
+			mp->m_epg_last_len += rem;
 	}
-	if (cpp != NULL)
-		*cpp = mtod(mp, caddr_t) + mp->m_len;
-	if (mbp != NULL)
-		*mbp = mp;
 	return (firstmp);
 }
 

Modified: head/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- head/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jul 24 23:15:42 2020	(r363498)
+++ head/sys/fs/nfsclient/nfs_clrpcops.c	Fri Jul 24 23:17:09 2020	(r363499)
@@ -5862,7 +5862,7 @@ nfscl_doiods(vnode_t vp, struct uio *uiop, int *iomode
 						    uiop->uio_iov->iov_base;
 						iovlen = uiop->uio_iov->iov_len;
 						m = nfsm_uiombuflist(uiop, len,
-						    NULL, NULL);
+						    0);
 					}
 					tdrpc = drpc = malloc(sizeof(*drpc) *
 					    (mirrorcnt - 1), M_TEMP, M_WAITOK |
@@ -6545,12 +6545,6 @@ nfsrpc_writedsmir(vnode_t vp, int *iomode, int *must_c
 	if (len > 0) {
 		/* Put data in mbuf chain. */
 		nd->nd_mb->m_next = m;
-		/* Set nd_mb and nd_bpos to end of data. */
-		while (m->m_next != NULL)
-			m = m->m_next;
-		nd->nd_mb = m;
-		nd->nd_bpos = mtod(m, char *) + m->m_len;
-		NFSCL_DEBUG(4, "nfsrpc_writedsmir: lastmb len=%d\n", m->m_len);
 	}
 	nrp = dsp->nfsclds_sockp;
 	if (nrp == NULL)
@@ -8625,8 +8619,97 @@ nfsmout:
 static struct mbuf *
 nfsm_split(struct mbuf *mp, uint64_t xfer)
 {
-	struct mbuf *m;
+	struct mbuf *m, *m2;
+	vm_page_t pg;
+	int i, j, left, pgno, plen, trim;
+	char *cp, *cp2;
 
-	m = m_split(mp, xfer, M_WAITOK);
-	return (m);
+	if ((mp->m_flags & M_EXTPG) == 0) {
+		m = m_split(mp, xfer, M_WAITOK);
+		return (m);
+	}
+
+	/* Find the correct mbuf to split at. */
+	for (m = mp; m != NULL && xfer > m->m_len; m = m->m_next)
+		xfer -= m->m_len;
+	if (m == NULL)
+		return (NULL);
+
+	/* If xfer == m->m_len, we can just split the mbuf list. */
+	if (xfer == m->m_len) {
+		m2 = m->m_next;
+		m->m_next = NULL;
+		return (m2);
+	}
+
+	/* Find the page to split at. */
+	pgno = 0;
+	left = xfer;
+	do {
+		if (pgno == 0)
+			plen = m_epg_pagelen(m, 0, m->m_epg_1st_off);
+		else
+			plen = m_epg_pagelen(m, pgno, 0);
+		if (left <= plen)
+			break;
+		left -= plen;
+		pgno++;
+	} while (pgno < m->m_epg_npgs);
+	if (pgno == m->m_epg_npgs)
+		panic("nfsm_split: eroneous ext_pgs mbuf");
+
+	m2 = mb_alloc_ext_pgs(M_WAITOK, mb_free_mext_pgs);
+	m2->m_epg_flags |= EPG_FLAG_ANON;
+
+	/*
+	 * If left < plen, allocate a new page for the new mbuf
+	 * and copy the data after left in the page to this new
+	 * page.
+	 */
+	if (left < plen) {
+		do {
+			pg = vm_page_alloc(NULL, 0, VM_ALLOC_NORMAL |
+			    VM_ALLOC_NOOBJ | VM_ALLOC_NODUMP |
+			    VM_ALLOC_WIRED);
+			if (pg == NULL)
+				vm_wait(NULL);
+		} while (pg == NULL);
+		m2->m_epg_pa[0] = VM_PAGE_TO_PHYS(pg);
+		m2->m_epg_npgs = 1;
+
+		/* Copy the data after left to the new page. */
+		trim = plen - left;
+		cp = (char *)(void *)PHYS_TO_DMAP(m->m_epg_pa[pgno]);
+		if (pgno == 0)
+			cp += m->m_epg_1st_off;
+		cp += left;
+		cp2 = (char *)(void *)PHYS_TO_DMAP(m2->m_epg_pa[0]);
+		if (pgno == m->m_epg_npgs - 1)
+			m2->m_epg_last_len = trim;
+		else {
+			cp2 += PAGE_SIZE - trim;
+			m2->m_epg_1st_off = PAGE_SIZE - trim;
+			m2->m_epg_last_len = m->m_epg_last_len;
+		}
+		memcpy(cp2, cp, trim);
+		m2->m_len = trim;
+	} else {
+		m2->m_len = 0;
+		m2->m_epg_last_len = m->m_epg_last_len;
+	}
+
+	/* Move the pages beyond pgno to the new mbuf. */
+	for (i = pgno + 1, j = m2->m_epg_npgs; i < m->m_epg_npgs; i++, j++) {
+		m2->m_epg_pa[j] = m->m_epg_pa[i];
+		/* Never moves page 0. */
+		m2->m_len += m_epg_pagelen(m, i, 0);
+	}
+	m2->m_epg_npgs = j;
+	m->m_epg_npgs = pgno + 1;
+	m->m_epg_last_len = left;
+	m->m_len = xfer;
+
+	m2->m_next = m->m_next;
+	m->m_next = NULL;
+	return (m2);
 }


More information about the svn-src-head mailing list