svn commit: r360514 - head/sys/fs/nfs

Rick Macklem rmacklem at FreeBSD.org
Fri May 1 00:36:15 UTC 2020


Author: rmacklem
Date: Fri May  1 00:36:14 2020
New Revision: 360514
URL: https://svnweb.freebsd.org/changeset/base/360514

Log:
  Factor some code out of nfsm_dissct() into separate functions.
  
  Factoring some of the code in nfsm_dissct() out into separate functions
  allows these functions to be used elsewhere in the NFS mbuf handling code.
  Other uses of these functions will be done in future commits.
  It also makes it easier to add support for ext_pgs mbufs, which is needed
  for nfs-over-tls under development in base/projects/nfs-over-tls.
  
  Although the algorithm in nfsm_dissct() is somewhat re-written by this
  patch, the semantics of nfsm_dissct() should not have changed.

Modified:
  head/sys/fs/nfs/nfs_commonsubs.c
  head/sys/fs/nfs/nfs_var.h

Modified: head/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- head/sys/fs/nfs/nfs_commonsubs.c	Thu Apr 30 23:41:22 2020	(r360513)
+++ head/sys/fs/nfs/nfs_commonsubs.c	Fri May  1 00:36:14 2020	(r360514)
@@ -229,6 +229,8 @@ static void nfsrv_removeuser(struct nfsusrgrp *usrp, i
 static int nfsrv_getrefstr(struct nfsrv_descript *, u_char **, u_char **,
     int *, int *);
 static void nfsrv_refstrbigenough(int, u_char **, u_char **, int *);
+static int nfsm_copyfrommbuf(struct nfsrv_descript *, char *, enum uio_seg,
+    int);
 
 static struct {
 	int	op;
@@ -701,52 +703,49 @@ nfsm_dissct(struct nfsrv_descript *nd, int siz, int ho
 	caddr_t retp;
 
 	retp = NULL;
-	left = mtod(nd->nd_md, caddr_t) + nd->nd_md->m_len - nd->nd_dpos;
+	left = mtod(nd->nd_md, char *) + nd->nd_md->m_len -
+	    nd->nd_dpos;
 	while (left == 0) {
-		nd->nd_md = nd->nd_md->m_next;
-		if (nd->nd_md == NULL)
-			return (retp);
-		left = nd->nd_md->m_len;
-		nd->nd_dpos = mtod(nd->nd_md, caddr_t);
+		if (!nfsm_shiftnext(nd, &left))
+			return (NULL);
 	}
 	if (left >= siz) {
 		retp = nd->nd_dpos;
 		nd->nd_dpos += siz;
-	} else if (nd->nd_md->m_next == NULL) {
-		return (retp);
 	} else if (siz > ncl_mbuf_mhlen) {
 		panic("nfs S too big");
 	} else {
+		/* Allocate a new mbuf for the "siz" bytes of data. */
 		MGET(mp2, MT_DATA, how);
 		if (mp2 == NULL)
 			return (NULL);
+
+		/*
+		 * Link the new mp2 mbuf into the list then copy left
+		 * bytes from the mbuf before it and siz - left bytes
+		 * from the mbuf(s) after it.
+		 */
 		mp2->m_next = nd->nd_md->m_next;
 		nd->nd_md->m_next = mp2;
 		nd->nd_md->m_len -= left;
-		nd->nd_md = mp2;
-		retp = p = mtod(mp2, caddr_t);
-		NFSBCOPY(nd->nd_dpos, p, left);	/* Copy what was left */
+		retp = p = mtod(mp2, char *);
+		memcpy(p, nd->nd_dpos, left);	/* Copy what was left */
 		siz2 = siz - left;
 		p += left;
-		mp2 = mp2->m_next;
+		mp2->m_len = siz;
+		nd->nd_md = mp2->m_next;
 		/* Loop around copying up the siz2 bytes */
 		while (siz2 > 0) {
-			if (mp2 == NULL)
+			if (nd->nd_md == NULL)
 				return (NULL);
-			xfer = (siz2 > mp2->m_len) ? mp2->m_len : siz2;
-			if (xfer > 0) {
-				NFSBCOPY(mtod(mp2, caddr_t), p, xfer);
-				mp2->m_data += xfer;
-				mp2->m_len -= xfer;
-				p += xfer;
-				siz2 -= xfer;
-			}
+			nfsm_set(nd, 0, false);
+			xfer = nfsm_copyfrommbuf(nd, p,
+			    UIO_SYSSPACE, siz2);
+			p += xfer;
+			siz2 -= xfer;
 			if (siz2 > 0)
-				mp2 = mp2->m_next;
+				nd->nd_md = nd->nd_md->m_next;
 		}
-		nd->nd_md->m_len = siz;
-		nd->nd_md = mp2;
-		nd->nd_dpos = mtod(mp2, caddr_t);
 	}
 	return (retp);
 }
@@ -4825,5 +4824,76 @@ nfsv4_findmirror(struct nfsmount *nmp)
 		}
 	}
 	return (ds);
+}
+
+/*
+ * Fill in the fields of "struct nfsrv_descript" for a new ext_pgs mbuf.
+ * The build argument is true for build and false for dissect.
+ */
+int
+nfsm_set(struct nfsrv_descript *nd, u_int offs, bool build)
+{
+	struct mbuf *m;
+	int rlen;
+
+	if (build)
+		m = nd->nd_mb;
+	else
+		m = nd->nd_md;
+	if (build) {
+		nd->nd_bpos = mtod(m, char *) + offs;
+		rlen = m->m_len - offs;
+	} else {
+		nd->nd_dpos = mtod(m, char *);
+		rlen = m->m_len;
+	}
+	return (rlen);
+}
+
+/*
+ * Copy up to "len" bytes from the mbuf into "cp" and adjust the
+ * mbuf accordingly.
+ * If cp == NULL, do not do the actual copy, but adjust the mbuf.
+ * Return the number of bytes actually copied.
+ * Adjust m_data and m_len so that a future calculation of what
+ * is left using mtod() will work correctly.
+ */
+static int
+nfsm_copyfrommbuf(struct nfsrv_descript *nd, char *cp, enum uio_seg segflg,
+    int len)
+{
+	struct mbuf *m;
+	int xfer;
+
+	m = nd->nd_md;
+	xfer = mtod(m, char *) + m->m_len - nd->nd_dpos;
+	xfer = min(xfer, len);
+	if (xfer > 0) {
+		if (cp != NULL) {
+			if (segflg == UIO_SYSSPACE)
+				memcpy(cp, nd->nd_dpos, xfer);
+			else
+				copyout(nd->nd_dpos, cp, xfer);
+		}
+		nd->nd_dpos += xfer;
+		m->m_data += xfer;
+		m->m_len -= xfer;
+	}
+	return (xfer);
+}
+
+/*
+ * Shift to the next mbuf in the list list and update the nd fields.
+ * Return true if successful, false otherwise.
+ */
+bool
+nfsm_shiftnext(struct nfsrv_descript *nd, int *leftp)
+{
+
+	nd->nd_md = nd->nd_md->m_next;
+	if (nd->nd_md == NULL)
+		return (false);
+	*leftp = nfsm_set(nd, 0, false);
+	return (true);
 }
 

Modified: head/sys/fs/nfs/nfs_var.h
==============================================================================
--- head/sys/fs/nfs/nfs_var.h	Thu Apr 30 23:41:22 2020	(r360513)
+++ head/sys/fs/nfs/nfs_var.h	Fri May  1 00:36:14 2020	(r360514)
@@ -361,6 +361,8 @@ int nfsv4_sequencelookup(struct nfsmount *, struct nfs
 void nfsv4_freeslot(struct nfsclsession *, int);
 struct ucred *nfsrv_getgrpscred(struct ucred *);
 struct nfsdevice *nfsv4_findmirror(struct nfsmount *);
+int nfsm_set(struct nfsrv_descript *, u_int, bool);
+bool nfsm_shiftnext(struct nfsrv_descript *, int *);
 
 /* nfs_clcomsubs.c */
 void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);


More information about the svn-src-all mailing list