Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Sep 2017 20:26:49 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r324025 - in projects/pnfs-planb-server-stable11/sys/fs: nfs nfsclient nfsserver
Message-ID:  <201709262026.v8QKQnci034575@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Tue Sep 26 20:26:48 2017
New Revision: 324025
URL: https://svnweb.freebsd.org/changeset/base/324025

Log:
  Add support for Flex File Layout to the client.
  
  This patch does not change the pNFS server, but adds Flex File Layout support
  to the NFSv4.1 client. I have done this to the stable/11 branch so that others
  can test more easily. This patch will go into head/current as a bunch of
  smaller commits. As such, it will eventually be merged from head into
  pnfs-planb-server.

Modified:
  projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs.h
  projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_commonsubs.c
  projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_var.h
  projects/pnfs-planb-server-stable11/sys/fs/nfs/nfscl.h
  projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsclstate.h
  projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsport.h
  projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clcomsubs.c
  projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clrpcops.c
  projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clstate.c
  projects/pnfs-planb-server-stable11/sys/fs/nfsserver/nfs_nfsdport.c

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs.h
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs.h	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs.h	Tue Sep 26 20:26:48 2017	(r324025)
@@ -192,9 +192,11 @@ struct nfsd_nfsd_args {
  * (To support more than 1000 DSs on an MDS, this needs to be increased.)
  * NFSDEV_MAXMIRRORS - Maximum # of mirrors for a DS.
  * (Most will only have a single mirror, but this setting allows up to 3.)
+ * NFSDEV_MAXVERS - maximum number of NFS versions supported by Flex File.
  */
 #define	NFSDEV_MIRRORSTR	3
 #define	NFSDEV_MAXMIRRORS	4
+#define	NFSDEV_MAXVERS		4
 
 /* Old version. */
 struct nfsd_nfsd_oargs {

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_commonsubs.c
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_commonsubs.c	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_commonsubs.c	Tue Sep 26 20:26:48 2017	(r324025)
@@ -4025,14 +4025,13 @@ newnfs_sndunlock(int *flagp)
 }
 
 APPLESTATIC int
-nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_storage *sa,
-    int *isudp)
+nfsv4_getipaddr(struct nfsrv_descript *nd, struct sockaddr_in *sin,
+    struct sockaddr_in6 *sin6, sa_family_t *saf, int *isudp)
 {
-	struct sockaddr_in *sad;
-	struct sockaddr_in6 *sad6;
 	struct in_addr saddr;
 	uint32_t portnum, *tl;
-	int af = 0, i, j, k;
+	int i, j, k;
+	sa_family_t af = AF_UNSPEC;
 	char addr[64], protocol[5], *cp;
 	int cantparse = 0, error = 0;
 	uint16_t portv;
@@ -4110,20 +4109,20 @@ nfsv4_getipaddr(struct nfsrv_descript *nd, struct sock
 			cantparse = 1;
 		if (cantparse == 0) {
 			if (af == AF_INET) {
-				sad = (struct sockaddr_in *)sa;
-				if (inet_pton(af, addr, &sad->sin_addr) == 1) {
-					sad->sin_len = sizeof(*sad);
-					sad->sin_family = AF_INET;
-					sad->sin_port = htons(portv);
+				if (inet_pton(af, addr, &sin->sin_addr) == 1) {
+					sin->sin_len = sizeof(*sin);
+					sin->sin_family = AF_INET;
+					sin->sin_port = htons(portv);
+					*saf = af;
 					return (0);
 				}
 			} else {
-				sad6 = (struct sockaddr_in6 *)sa;
-				if (inet_pton(af, addr, &sad6->sin6_addr)
+				if (inet_pton(af, addr, &sin6->sin6_addr)
 				    == 1) {
-					sad6->sin6_len = sizeof(*sad6);
-					sad6->sin6_family = AF_INET6;
-					sad6->sin6_port = htons(portv);
+					sin6->sin6_len = sizeof(*sin6);
+					sin6->sin6_family = AF_INET6;
+					sin6->sin6_port = htons(portv);
+					*saf = af;
 					return (0);
 				}
 			}

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_var.h
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_var.h	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfs/nfs_var.h	Tue Sep 26 20:26:48 2017	(r324025)
@@ -311,8 +311,8 @@ void nfsrv_cleanusergroup(void);
 int nfsrv_checkutf8(u_int8_t *, int);
 int newnfs_sndlock(int *);
 void newnfs_sndunlock(int *);
-int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_storage *,
-    int *);
+int nfsv4_getipaddr(struct nfsrv_descript *, struct sockaddr_in *,
+    struct sockaddr_in6 *, sa_family_t *, int *);
 int nfsv4_seqsession(uint32_t, uint32_t, uint32_t, struct nfsslot *,
     struct mbuf **, uint16_t);
 void nfsv4_seqsess_cacherep(uint32_t, struct nfsslot *, int, struct mbuf **);
@@ -325,8 +325,9 @@ struct ucred *nfsrv_getgrpscred(struct ucred *);
 
 /* nfs_clcomsubs.c */
 void nfsm_uiombuf(struct nfsrv_descript *, struct uio *, int);
+struct mbuf *nfsm_uiombuflist(struct uio *, int, struct mbuf **, char **);
 void nfscl_reqstart(struct nfsrv_descript *, int, struct nfsmount *,
-    u_int8_t *, int, u_int32_t **, struct nfsclsession *);
+    u_int8_t *, int, u_int32_t **, struct nfsclsession *, int, int);
 nfsuint64 *nfscl_getcookie(struct nfsnode *, off_t off, int);
 void nfscl_fillsattr(struct nfsrv_descript *, struct vattr *,
       vnode_t, int, u_int32_t);
@@ -502,17 +503,14 @@ int nfsrpc_destroysession(struct nfsmount *, struct nf
     struct ucred *, NFSPROC_T *);
 int nfsrpc_destroyclient(struct nfsmount *, struct nfsclclient *,
     struct ucred *, NFSPROC_T *);
-int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t, uint64_t,
-    uint64_t, int, nfsv4stateid_t *, int *, struct nfsclflayouthead *,
-    struct ucred *, NFSPROC_T *, void *);
 int nfsrpc_getdeviceinfo(struct nfsmount *, uint8_t *, int, uint32_t *,
     struct nfscldevinfo **, struct ucred *, NFSPROC_T *);
 int nfsrpc_layoutcommit(struct nfsmount *, uint8_t *, int, int,
-    uint64_t, uint64_t, uint64_t, nfsv4stateid_t *, int, int, uint8_t *,
-    struct ucred *, NFSPROC_T *, void *);
-int nfsrpc_layoutreturn(struct nfsmount *, uint8_t *, int, int, int, uint32_t,
-    int, uint64_t, uint64_t, nfsv4stateid_t *, int, uint32_t *, struct ucred *,
+    uint64_t, uint64_t, uint64_t, nfsv4stateid_t *, int, struct ucred *,
     NFSPROC_T *, void *);
+int nfsrpc_layoutreturn(struct nfsmount *, uint8_t *, int, int, int, uint32_t,
+    int, uint64_t, uint64_t, nfsv4stateid_t *, struct ucred *, NFSPROC_T *,
+    void *);
 int nfsrpc_reclaimcomplete(struct nfsmount *, struct ucred *, NFSPROC_T *);
 int nfscl_doiods(vnode_t, struct uio *, int *, int *, uint32_t, int,
     struct ucred *, NFSPROC_T *);
@@ -581,7 +579,7 @@ int nfscl_tryclose(struct nfsclopen *, struct ucred *,
     struct nfsmount *, NFSPROC_T *);
 void nfscl_cleanup(NFSPROC_T *);
 int nfscl_layout(struct nfsmount *, vnode_t, u_int8_t *, int, nfsv4stateid_t *,
-    int, struct nfsclflayouthead *, struct nfscllayout **, struct ucred *,
+    int, int, struct nfsclflayouthead *, struct nfscllayout **, struct ucred *,
     NFSPROC_T *);
 struct nfscllayout *nfscl_getlayout(struct nfsclclient *, uint8_t *, int,
     uint64_t, struct nfsclflayout **, int *);

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfs/nfscl.h
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfs/nfscl.h	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfs/nfscl.h	Tue Sep 26 20:26:48 2017	(r324025)
@@ -49,7 +49,8 @@ struct nfsv4node {
  */
 #define	NFSCL_REQSTART(n, p, v) 					\
 	nfscl_reqstart((n), (p), VFSTONFS((v)->v_mount), 		\
-	    VTONFS(v)->n_fhp->nfh_fh, VTONFS(v)->n_fhp->nfh_len, NULL, NULL)
+	    VTONFS(v)->n_fhp->nfh_fh, VTONFS(v)->n_fhp->nfh_len, NULL,	\
+	    NULL, 0, 0)
 
 /*
  * These two macros convert between a lease duration and renew interval.

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsclstate.h
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsclstate.h	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsclstate.h	Tue Sep 26 20:26:48 2017	(r324025)
@@ -258,9 +258,24 @@ struct nfscllayout {
 #define	NFSLY_RECALLALL		0x0040
 #define	NFSLY_RETONCLOSE	0x0080
 #define	NFSLY_WRITTEN		0x0100	/* Has been used to write to a DS. */
+#define	NFSLY_FLEXFILE		0x0200
 
 /*
- * MALLOC'd to the correct length to accommodate the file handle list.
+ * Flex file layout mirror specific stuff for nfsclflayout.
+ */
+struct nfsffm {
+	nfsv4stateid_t		st;
+	char			dev[NFSX_V4DEVICEID];
+	uint32_t		eff;
+	uid_t			user;
+	gid_t			group;
+	struct nfsfh		*fh[NFSDEV_MAXVERS];
+	uint16_t		fhcnt;
+};
+
+/*
+ * MALLOC'd to the correct length to accommodate the file handle list for File
+ * layout and the list of mirrors for the Flex File Layout.
  * These hang off of nfsly_flayread and nfsly_flayrw, sorted in increasing
  * offset order.
  * The nfsly_flayread list holds the ones with iomode == NFSLAYOUTIOMODE_READ,
@@ -268,23 +283,49 @@ struct nfscllayout {
  */
 struct nfsclflayout {
 	LIST_ENTRY(nfsclflayout)	nfsfl_list;
-	uint8_t				nfsfl_dev[NFSX_V4DEVICEID];
 	uint64_t			nfsfl_off;
 	uint64_t			nfsfl_end;
-	uint64_t			nfsfl_patoff;
-	struct nfscldevinfo		*nfsfl_devp;
 	uint32_t			nfsfl_iomode;
-	uint32_t			nfsfl_util;
-	uint32_t			nfsfl_stripe1;
+	struct nfscldevinfo		*nfsfl_devp;
 	uint16_t			nfsfl_flags;
-	uint16_t			nfsfl_fhcnt;
-	struct nfsfh			*nfsfl_fh[1];	/* FH list for DS */
+	union {
+		struct {
+			uint64_t	patoff;
+			uint32_t	util;
+			uint32_t	stripe1;
+			uint8_t		dev[NFSX_V4DEVICEID];
+			uint16_t	fhcnt;
+		} fl;
+		struct {
+			uint64_t	stripeunit;
+			uint32_t	fflags;
+			uint32_t	statshint;
+			uint16_t	mirrorcnt;
+		} ff;
+	} nfsfl_un;
+	union {
+		struct nfsfh		*fh[0];	/* FH list for DS File layout */
+		struct nfsffm		ffm[0];	/* Mirror list for Flex File */
+	} nfsfl_un2;	/* Must be last. Malloc'd to correct array length */
 };
+#define	nfsfl_patoff		nfsfl_un.fl.patoff
+#define	nfsfl_util		nfsfl_un.fl.util
+#define	nfsfl_stripe1		nfsfl_un.fl.stripe1
+#define	nfsfl_dev		nfsfl_un.fl.dev
+#define	nfsfl_fhcnt		nfsfl_un.fl.fhcnt
+#define	nfsfl_stripeunit	nfsfl_un.ff.stripeunit
+#define	nfsfl_fflags		nfsfl_un.ff.fflags
+#define	nfsfl_statshint		nfsfl_un.ff.statshint
+#define	nfsfl_mirrorcnt		nfsfl_un.ff.mirrorcnt
+#define	nfsfl_fh		nfsfl_un2.fh
+#define	nfsfl_ffm		nfsfl_un2.ffm
 
 /*
  * Flags for nfsfl_flags.
  */
 #define	NFSFL_RECALL	0x0001		/* File layout has been recalled */
+#define	NFSFL_FILE	0x0002		/* File layout */
+#define	NFSFL_FLEXFILE	0x0004		/* Flex File layout */
 
 /*
  * Structure that is used to store a LAYOUTRECALL.
@@ -306,6 +347,7 @@ struct nfsclrecalllayout {
  * - stripe indices, each stored as one byte, since there can be many
  *   of them. (This implies a limit of 256 on nfsdi_addrcnt, since the
  *   indices select which address.)
+ * For Flex File, the addrcnt is always one and no stripe indices exist.
  */
 struct nfscldevinfo {
 	LIST_ENTRY(nfscldevinfo)	nfsdi_list;
@@ -313,10 +355,33 @@ struct nfscldevinfo {
 	struct nfsclclient		*nfsdi_clp;
 	uint32_t			nfsdi_refcnt;
 	uint32_t			nfsdi_layoutrefs;
-	uint16_t			nfsdi_stripecnt;
+	union {
+		struct {
+			uint16_t	stripecnt;
+		} fl;
+		struct {
+			int		versindex;
+			uint32_t	vers;
+			uint32_t	minorvers;
+			uint32_t	rsize;
+			uint32_t	wsize;
+		} ff;
+	} nfsdi_un;
 	uint16_t			nfsdi_addrcnt;
+	uint16_t			nfsdi_flags;
 	struct nfsclds			*nfsdi_data[0];
 };
+#define	nfsdi_stripecnt	nfsdi_un.fl.stripecnt
+#define	nfsdi_versindex	nfsdi_un.ff.versindex
+#define	nfsdi_vers	nfsdi_un.ff.vers
+#define	nfsdi_minorvers	nfsdi_un.ff.minorvers
+#define	nfsdi_rsize	nfsdi_un.ff.rsize
+#define	nfsdi_wsize	nfsdi_un.ff.wsize
+
+/* Flags for nfsdi_flags. */
+#define	NFSDI_FILELAYOUT	0x0001
+#define	NFSDI_FLEXFILE		0x0002
+#define	NFSDI_TIGHTCOUPLED	0X0004
 
 /* These inline functions return values from nfsdi_data[]. */
 /*

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsport.h
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsport.h	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfs/nfsport.h	Tue Sep 26 20:26:48 2017	(r324025)
@@ -921,6 +921,7 @@ int newnfs_realign(struct mbuf **, int);
 #define	NFSSTA_HASWRITEVERF	0x00040000  /* Has write verifier */
 #define	NFSSTA_GOTFSINFO	0x00100000  /* Got the fsinfo */
 #define	NFSSTA_OPENMODE		0x00200000  /* Must use correct open mode */
+#define	NFSSTA_FLEXFILE		0x00800000  /* Use Flex File Layout */
 #define	NFSSTA_NOLAYOUTCOMMIT	0x04000000  /* Don't do LayoutCommit */
 #define	NFSSTA_SESSPERSIST	0x08000000  /* Has a persistent session */
 #define	NFSSTA_TIMEO		0x10000000  /* Experiencing a timeout */
@@ -951,6 +952,7 @@ int newnfs_realign(struct mbuf **, int);
 #define	NFSHASNOLAYOUTCOMMIT(n)	((n)->nm_state & NFSSTA_NOLAYOUTCOMMIT)
 #define	NFSHASSESSPERSIST(n)	((n)->nm_state & NFSSTA_SESSPERSIST)
 #define	NFSHASPNFS(n)		((n)->nm_state & NFSSTA_PNFS)
+#define	NFSHASFLEXFILE(n)	((n)->nm_state & NFSSTA_FLEXFILE)
 #define	NFSHASOPENMODE(n)	((n)->nm_state & NFSSTA_OPENMODE)
 #define	NFSHASONEOPENOWN(n)	(((n)->nm_flag & NFSMNT_ONEOPENOWN) != 0 &&	\
 				    (n)->nm_minorvers > 0)

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clcomsubs.c
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clcomsubs.c	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clcomsubs.c	Tue Sep 26 20:26:48 2017	(r324025)
@@ -131,7 +131,8 @@ static int nfs_bigrequest[NFSV41_NPROCS] = {
  */
 APPLESTATIC void
 nfscl_reqstart(struct nfsrv_descript *nd, int procnum, struct nfsmount *nmp,
-    u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep)
+    u_int8_t *nfhp, int fhlen, u_int32_t **opcntpp, struct nfsclsession *sep,
+    int vers, int minorvers)
 {
 	struct mbuf *mb;
 	u_int32_t *tl;
@@ -142,14 +143,22 @@ nfscl_reqstart(struct nfsrv_descript *nd, int procnum,
 	 * First, fill in some of the fields of nd.
 	 */
 	nd->nd_slotseq = NULL;
-	if (NFSHASNFSV4(nmp)) {
+	if (vers == NFS_VER4) {
 		nd->nd_flag = ND_NFSV4 | ND_NFSCL;
-		if (NFSHASNFSV4N(nmp))
+		if (minorvers == NFSV41_MINORVERSION)
 			nd->nd_flag |= ND_NFSV41;
-	} else if (NFSHASNFSV3(nmp))
+	} else if (vers == NFS_VER3)
 		nd->nd_flag = ND_NFSV3 | ND_NFSCL;
-	else
-		nd->nd_flag = ND_NFSV2 | ND_NFSCL;
+	else {
+		if (NFSHASNFSV4(nmp)) {
+			nd->nd_flag = ND_NFSV4 | ND_NFSCL;
+			if (NFSHASNFSV4N(nmp))
+				nd->nd_flag |= ND_NFSV41;
+		} else if (NFSHASNFSV3(nmp))
+			nd->nd_flag = ND_NFSV3 | ND_NFSCL;
+		else
+			nd->nd_flag = ND_NFSV2 | ND_NFSCL;
+	}
 	nd->nd_procnum = procnum;
 	nd->nd_repstat = 0;
 
@@ -333,6 +342,77 @@ nfsm_uiombuf(struct nfsrv_descript *nd, struct uio *ui
 	nd->nd_mb = mp;
 }
 #endif	/* !APPLE */
+
+/*
+ * copies a uio scatter/gather list to an mbuf chain.
+ * This version returns the mbuf list and does not use "nd".
+ * NOTE: can ony handle iovcnt == 1
+ */
+struct mbuf *
+nfsm_uiombuflist(struct uio *uiop, int siz, struct mbuf **mbp, char **cpp)
+{
+	char *uiocp;
+	struct mbuf *mp, *mp2, *firstmp;
+	int xfer, left, mlen;
+	int uiosiz, clflg, rem;
+	char *tcp;
+
+	KASSERT(uiop->uio_iovcnt == 1, ("nfsm_uiotombuf: iovcnt != 1"));
+
+	if (siz > ncl_mbuf_mlen)	/* or should it >= MCLBYTES ?? */
+		clflg = 1;
+	else
+		clflg = 0;
+	rem = NFSM_RNDUP(siz) - siz;
+	if (clflg != 0)
+		NFSMCLGET(mp, M_WAITOK);
+	else
+		NFSMGET(mp);
+	mbuf_setlen(mp, 0);
+	firstmp = mp2 = mp;
+	while (siz > 0) {
+		left = uiop->uio_iov->iov_len;
+		uiocp = uiop->uio_iov->iov_base;
+		if (left > siz)
+			left = siz;
+		uiosiz = left;
+		while (left > 0) {
+			mlen = M_TRAILINGSPACE(mp);
+			if (mlen == 0) {
+				if (clflg)
+					NFSMCLGET(mp, M_WAITOK);
+				else
+					NFSMGET(mp);
+				mbuf_setlen(mp, 0);
+				mbuf_setnext(mp2, mp);
+				mp2 = mp;
+				mlen = M_TRAILINGSPACE(mp);
+			}
+			xfer = (left > mlen) ? mlen : left;
+			if (uiop->uio_segflg == UIO_SYSSPACE)
+				NFSBCOPY(uiocp, NFSMTOD(mp, caddr_t) +
+				    mbuf_len(mp), xfer);
+			else
+				copyin(uiocp, NFSMTOD(mp, caddr_t) +
+				    mbuf_len(mp), xfer);
+			mbuf_setlen(mp, mbuf_len(mp) + xfer);
+			left -= xfer;
+			uiocp += xfer;
+			uiop->uio_offset += xfer;
+			uiop->uio_resid -= xfer;
+		}
+		tcp = (char *)uiop->uio_iov->iov_base;
+		tcp += uiosiz;
+		uiop->uio_iov->iov_base = (void *)tcp;
+		uiop->uio_iov->iov_len -= uiosiz;
+		siz -= uiosiz;
+	}
+	if (cpp != NULL)
+		*cpp = NFSMTOD(mp, caddr_t) + mbuf_len(mp);
+	if (mbp != NULL)
+		*mbp = mp;
+	return (firstmp);
+}
 
 /*
  * Load vnode attributes from the xdr file attributes.

Modified: projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clrpcops.c
==============================================================================
--- projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clrpcops.c	Tue Sep 26 20:23:09 2017	(r324024)
+++ projects/pnfs-planb-server-stable11/sys/fs/nfsclient/nfs_clrpcops.c	Tue Sep 26 20:26:48 2017	(r324025)
@@ -109,25 +109,35 @@ static int nfsrpc_setaclrpc(vnode_t, struct ucred *, N
 static int nfsrpc_getlayout(struct nfsmount *, vnode_t, struct nfsfh *, int,
     uint32_t *, nfsv4stateid_t *, uint64_t, struct nfscllayout **,
     struct ucred *, NFSPROC_T *);
-static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_storage *,
-    struct nfsclds **, NFSPROC_T *);
+static int nfsrpc_fillsa(struct nfsmount *, struct sockaddr_in *,
+    struct sockaddr_in6 *, sa_family_t, int, struct nfsclds **, NFSPROC_T *);
 static void nfscl_initsessionslots(struct nfsclsession *);
 static int nfscl_doflayoutio(vnode_t, struct uio *, int *, int *, int *,
     nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
     struct nfsclflayout *, uint64_t, uint64_t, int, struct ucred *,
     NFSPROC_T *);
+static int nfscl_dofflayoutio(vnode_t, struct uio *, int *, int *, int *,
+    nfsv4stateid_t *, int, struct nfscldevinfo *, struct nfscllayout *,
+    struct nfsclflayout *, uint64_t, uint64_t, int, int, struct mbuf *,
+    struct ucred *, NFSPROC_T *);
+static struct mbuf *nfsm_copym(struct mbuf *, int, int);
 static int nfsrpc_readds(vnode_t, struct uio *, nfsv4stateid_t *, int *,
-    struct nfsclds *, uint64_t, int, struct nfsfh *, struct ucred *,
-    NFSPROC_T *);
+    struct nfsclds *, uint64_t, int, struct nfsfh *, int, int, int,
+    struct ucred *, NFSPROC_T *);
 static int nfsrpc_writeds(vnode_t, struct uio *, int *, int *,
     nfsv4stateid_t *, struct nfsclds *, uint64_t, int,
-    struct nfsfh *, int, struct ucred *, NFSPROC_T *);
+    struct nfsfh *, int, int, int, int, struct ucred *, NFSPROC_T *);
+static int nfsrpc_writedsmir(vnode_t, int *, int *, nfsv4stateid_t *,
+    struct nfsclds *, uint64_t, int, struct nfsfh *, struct mbuf *, int, int,
+    struct ucred *, NFSPROC_T *);
 static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
     struct nfsclds *, struct nfsclds **);
 static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
-    struct nfsfh *, struct ucred *, NFSPROC_T *);
+    struct nfsfh *, int, int, struct ucred *, NFSPROC_T *);
 static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t,
-    uint64_t, uint64_t, nfsv4stateid_t *, int, int);
+    uint64_t, uint64_t, nfsv4stateid_t *, int, int, int);
+static int nfsrv_parseug(struct nfsrv_descript *, int, uid_t *, gid_t *,
+    NFSPROC_T *);
 static int nfsrv_parselayoutget(struct nfsrv_descript *, nfsv4stateid_t *,
     int *, struct nfsclflayouthead *);
 static int nfsrpc_getopenlayout(struct nfsmount *, vnode_t, u_int8_t *,
@@ -139,16 +149,19 @@ static int nfsrpc_getcreatelayout(vnode_t, char *, int
     struct nfsfh **, int *, int *, void *, int *);
 static int nfsrpc_openlayoutrpc(struct nfsmount *, vnode_t, u_int8_t *,
     int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int,
-    struct nfscldeleg **, nfsv4stateid_t *, int, int, int *,
+    struct nfscldeleg **, nfsv4stateid_t *, int, int, int, int *,
     struct nfsclflayouthead *, int *, struct ucred *, NFSPROC_T *);
 static int nfsrpc_createlayout(vnode_t, char *, int, struct vattr *,
     nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **,
     struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *,
     struct nfsfh **, int *, int *, void *, int *, nfsv4stateid_t *,
-    int, int, int *, struct nfsclflayouthead *, int *);
+    int, int, int, int *, struct nfsclflayouthead *, int *);
+static int nfsrpc_layoutget(struct nfsmount *, uint8_t *, int, int, uint64_t,
+    uint64_t, uint64_t, int, int, nfsv4stateid_t *, int *,
+    struct nfsclflayouthead *, struct ucred *, NFSPROC_T *, void *);
 static int nfsrpc_layoutgetres(struct nfsmount *, vnode_t, uint8_t *,
     int, nfsv4stateid_t *, int, uint32_t *, struct nfscllayout **,
-    struct nfsclflayouthead *, int, int *, struct ucred *, NFSPROC_T *);
+    struct nfsclflayouthead *, int, int, int *, struct ucred *, NFSPROC_T *);
 
 /*
  * nfs null call from vfs.
@@ -426,7 +439,7 @@ nfsrpc_openrpc(struct nfsmount *nmp, vnode_t vp, u_int
 
 	dp = *dpp;
 	*dpp = NULL;
-	nfscl_reqstart(nd, NFSPROC_OPEN, nmp, nfhp, fhlen, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_OPEN, nmp, nfhp, fhlen, NULL, NULL, 0, 0);
 	NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
 	*tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
@@ -782,7 +795,7 @@ nfsrpc_closerpc(struct nfsrv_descript *nd, struct nfsm
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_CLOSE, nmp, op->nfso_fh,
-	    op->nfso_fhlen, NULL, NULL);
+	    op->nfso_fhlen, NULL, NULL, 0, 0);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
 	*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
 	if (NFSHASNFSV4N(nmp))
@@ -824,7 +837,8 @@ nfsrpc_openconfirm(vnode_t vp, u_int8_t *nfhp, int fhl
 	nmp = VFSTONFS(vnode_mount(vp));
 	if (NFSHASNFSV4N(nmp))
 		return (0);		/* No confirmation for NFSv4.1. */
-	nfscl_reqstart(nd, NFSPROC_OPENCONFIRM, nmp, nfhp, fhlen, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_OPENCONFIRM, nmp, nfhp, fhlen, NULL, NULL,
+	    0, 0);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED + NFSX_STATEID);
 	*tl++ = op->nfso_stateid.seqid;
 	*tl++ = op->nfso_stateid.other[0];
@@ -938,7 +952,7 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclcli
 	tsep = NFSMNT_MDSSESSION(nmp);
 	NFSUNLOCKMNT(nmp);
 
-	nfscl_reqstart(nd, NFSPROC_SETCLIENTID, nmp, NULL, 0, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_SETCLIENTID, nmp, NULL, 0, NULL, NULL, 0, 0);
 	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(nfsboottime.tv_sec);
 	*tl = txdr_unsigned(clp->nfsc_rev);
@@ -1008,7 +1022,7 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclcli
 	     * and confirm it.
 	     */
 	    nfscl_reqstart(nd, NFSPROC_SETCLIENTIDCFRM, nmp, NULL, 0, NULL,
-		NULL);
+		NULL, 0, 0);
 	    NFSM_BUILD(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
 	    *tl++ = tsep->nfsess_clientid.lval[0];
 	    *tl++ = tsep->nfsess_clientid.lval[1];
@@ -1023,7 +1037,7 @@ nfsrpc_setclient(struct nfsmount *nmp, struct nfsclcli
 	    nd->nd_mrep = NULL;
 	    if (nd->nd_repstat == 0) {
 		nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, nmp->nm_fh,
-		    nmp->nm_fhsize, NULL, NULL);
+		    nmp->nm_fhsize, NULL, NULL, 0, 0);
 		NFSZERO_ATTRBIT(&attrbits);
 		NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_LEASETIME);
 		(void) nfsrv_putattrbit(nd, &attrbits);
@@ -1090,7 +1104,7 @@ nfsrpc_getattrnovp(struct nfsmount *nmp, u_int8_t *fhp
 	int error, vers = NFS_VER2;
 	nfsattrbit_t attrbits;
 	
-	nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, fhp, fhlen, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_GETATTR, nmp, fhp, fhlen, NULL, NULL, 0, 0);
 	if (nd->nd_flag & ND_NFSV4) {
 		vers = NFS_VER4;
 		NFSGETATTR_ATTRBIT(&attrbits);
@@ -3996,7 +4010,7 @@ nfsrpc_locku(struct nfsrv_descript *nd, struct nfsmoun
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_LOCKU, nmp, lp->nfsl_open->nfso_fh,
-	    lp->nfsl_open->nfso_fhlen, NULL, NULL);
+	    lp->nfsl_open->nfso_fhlen, NULL, NULL, 0, 0);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID + 6 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(type);
 	*tl = txdr_unsigned(lp->nfsl_seqid);
@@ -4048,7 +4062,7 @@ nfsrpc_lock(struct nfsrv_descript *nd, struct nfsmount
 	uint8_t own[NFSV4CL_LOCKNAMELEN + NFSX_V4FHMAX];
 	struct nfsclsession *tsep;
 
-	nfscl_reqstart(nd, NFSPROC_LOCK, nmp, nfhp, fhlen, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_LOCK, nmp, nfhp, fhlen, NULL, NULL, 0, 0);
 	NFSM_BUILD(tl, u_int32_t *, 7 * NFSX_UNSIGNED);
 	if (type == F_RDLCK)
 		*tl++ = txdr_unsigned(NFSV4LOCKT_READ);
@@ -4321,10 +4335,11 @@ nfsrpc_renew(struct nfsclclient *clp, struct nfsclds *
 	if (nmp == NULL)
 		return (0);
 	if (dsp == NULL)
-		nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL, NULL);
+		nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL, NULL, 0,
+		    0);
 	else
 		nfscl_reqstart(nd, NFSPROC_RENEW, nmp, NULL, 0, NULL,
-		    &dsp->nfsclds_sess);
+		    &dsp->nfsclds_sess, 0, 0);
 	if (!NFSHASNFSV4N(nmp)) {
 		/* NFSv4.1 just uses a Sequence Op and not a Renew. */
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
@@ -4368,11 +4383,11 @@ nfsrpc_rellockown(struct nfsmount *nmp, struct nfscllo
 	if (NFSHASNFSV4N(nmp)) {
 		/* For NFSv4.1, do a FreeStateID. */
 		nfscl_reqstart(nd, NFSPROC_FREESTATEID, nmp, NULL, 0, NULL,
-		    NULL);
+		    NULL, 0, 0);
 		nfsm_stateidtom(nd, &lp->nfsl_stateid, NFSSTATEID_PUTSTATEID);
 	} else {
 		nfscl_reqstart(nd, NFSPROC_RELEASELCKOWN, nmp, NULL, 0, NULL,
-		    NULL);
+		    NULL, 0, 0);
 		NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
 		tsep = nfsmnt_mdssession(nmp);
 		*tl++ = tsep->nfsess_clientid.lval[0];
@@ -4405,7 +4420,8 @@ nfsrpc_getdirpath(struct nfsmount *nmp, u_char *dirpat
 	int error, cnt, len, setnil;
 	u_int32_t *opcntp;
 
-	nfscl_reqstart(nd, NFSPROC_PUTROOTFH, nmp, NULL, 0, &opcntp, NULL);
+	nfscl_reqstart(nd, NFSPROC_PUTROOTFH, nmp, NULL, 0, &opcntp, NULL, 0,
+	    0);
 	cp = dirpath;
 	cnt = 0;
 	do {
@@ -4472,7 +4488,7 @@ nfsrpc_delegreturn(struct nfscldeleg *dp, struct ucred
 	int error;
 
 	nfscl_reqstart(nd, NFSPROC_DELEGRETURN, nmp, dp->nfsdl_fh,
-	    dp->nfsdl_fhlen, NULL, NULL);
+	    dp->nfsdl_fhlen, NULL, NULL, 0, 0);
 	NFSM_BUILD(tl, u_int32_t *, NFSX_STATEID);
 	if (NFSHASNFSV4N(nmp))
 		*tl++ = 0;
@@ -4582,7 +4598,7 @@ nfsrpc_exchangeid(struct nfsmount *nmp, struct nfsclcl
 	int error, len;
 
 	*dspp = NULL;
-	nfscl_reqstart(nd, NFSPROC_EXCHANGEID, nmp, NULL, 0, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_EXCHANGEID, nmp, NULL, 0, NULL, NULL, 0, 0);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	*tl++ = txdr_unsigned(nfsboottime.tv_sec);	/* Client owner */
 	*tl = txdr_unsigned(clp->nfsc_rev);
@@ -4669,7 +4685,8 @@ nfsrpc_createsession(struct nfsmount *nmp, struct nfsc
 		nmp->nm_rsize = NFS_MAXBSIZE;
 	if (nmp->nm_wsize > NFS_MAXBSIZE || nmp->nm_wsize == 0)
 		nmp->nm_wsize = NFS_MAXBSIZE;
-	nfscl_reqstart(nd, NFSPROC_CREATESESSION, nmp, NULL, 0, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_CREATESESSION, nmp, NULL, 0, NULL, NULL, 0,
+	    0);
 	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED);
 	*tl++ = sep->nfsess_clientid.lval[0];
 	*tl++ = sep->nfsess_clientid.lval[1];
@@ -4783,7 +4800,8 @@ nfsrpc_destroysession(struct nfsmount *nmp, struct nfs
 	int error;
 	struct nfsclsession *tsep;
 
-	nfscl_reqstart(nd, NFSPROC_DESTROYSESSION, nmp, NULL, 0, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_DESTROYSESSION, nmp, NULL, 0, NULL, NULL, 0,
+	    0);
 	NFSM_BUILD(tl, uint32_t *, NFSX_V4SESSIONID);
 	tsep = nfsmnt_mdssession(nmp);
 	bcopy(tsep->nfsess_sessionid, tl, NFSX_V4SESSIONID);
@@ -4810,7 +4828,8 @@ nfsrpc_destroyclient(struct nfsmount *nmp, struct nfsc
 	int error;
 	struct nfsclsession *tsep;
 
-	nfscl_reqstart(nd, NFSPROC_DESTROYCLIENT, nmp, NULL, 0, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_DESTROYCLIENT, nmp, NULL, 0, NULL, NULL, 0,
+	    0);
 	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
 	tsep = nfsmnt_mdssession(nmp);
 	*tl++ = tsep->nfsess_clientid.lval[0];
@@ -4828,18 +4847,20 @@ nfsrpc_destroyclient(struct nfsmount *nmp, struct nfsc
 /*
  * Do the NFSv4.1 LayoutGet.
  */
-int
+static int
 nfsrpc_layoutget(struct nfsmount *nmp, uint8_t *fhp, int fhlen, int iomode,
-    uint64_t offset, uint64_t len, uint64_t minlen, int layoutlen,
-    nfsv4stateid_t *stateidp, int *retonclosep, struct nfsclflayouthead *flhp,
-    struct ucred *cred, NFSPROC_T *p, void *stuff)
+    uint64_t offset, uint64_t len, uint64_t minlen, int layouttype,
+    int layoutlen, nfsv4stateid_t *stateidp, int *retonclosep,
+    struct nfsclflayouthead *flhp, struct ucred *cred, NFSPROC_T *p,
+    void *stuff)
 {
 	struct nfsrv_descript nfsd, *nd = &nfsd;
 	int error;
 
-	nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL, 0,
+	    0);
 	nfsrv_setuplayoutget(nd, iomode, offset, len, minlen, stateidp,
-	    layoutlen, 0);
+	    layouttype, layoutlen, 0);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
@@ -4862,18 +4883,22 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de
     uint32_t *notifybitsp, struct nfscldevinfo **ndip, struct ucred *cred,
     NFSPROC_T *p)
 {
-	uint32_t cnt, *tl;
+	uint32_t cnt, *tl, vers, minorvers;
 	struct nfsrv_descript nfsd;
 	struct nfsrv_descript *nd = &nfsd;
-	struct sockaddr_storage ss;
-	struct nfsclds *dsp = NULL, **dspp;
+	struct sockaddr_in sin, ssin;
+	struct sockaddr_in6 sin6, ssin6;
+	struct nfsclds *dsp = NULL, **dspp, **gotdspp;
 	struct nfscldevinfo *ndi;
-	int addrcnt, bitcnt, error, i, isudp, j, pos, safilled, stripecnt;
+	int addrcnt = 0, bitcnt, error, gotvers, i, isudp, j, stripecnt;
 	uint8_t stripeindex;
+	sa_family_t af, safilled;
 
 	*ndip = NULL;
 	ndi = NULL;
-	nfscl_reqstart(nd, NFSPROC_GETDEVICEINFO, nmp, NULL, 0, NULL, NULL);
+	gotdspp = NULL;
+	nfscl_reqstart(nd, NFSPROC_GETDEVICEINFO, nmp, NULL, 0, NULL, NULL, 0,
+	    0);
 	NFSM_BUILD(tl, uint32_t *, NFSX_V4DEVICEID + 3 * NFSX_UNSIGNED);
 	NFSBCOPY(deviceid, tl, NFSX_V4DEVICEID);
 	tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
@@ -4891,55 +4916,72 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de
 	if (error != 0)
 		return (error);
 	if (nd->nd_repstat == 0) {
-		NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_UNSIGNED);
-		if (layouttype != fxdr_unsigned(int, *tl++))
+		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+		if (layouttype != fxdr_unsigned(int, *tl))
 			printf("EEK! devinfo layout type not same!\n");
-		stripecnt = fxdr_unsigned(int, *++tl);
-		NFSCL_DEBUG(4, "stripecnt=%d\n", stripecnt);
-		if (stripecnt < 1 || stripecnt > 4096) {
-			printf("NFS devinfo stripecnt %d: out of range\n",
-			    stripecnt);
-			error = NFSERR_BADXDR;
-			goto nfsmout;
-		}
-		NFSM_DISSECT(tl, uint32_t *, (stripecnt + 1) * NFSX_UNSIGNED);
-		addrcnt = fxdr_unsigned(int, *(tl + stripecnt));
-		NFSCL_DEBUG(4, "addrcnt=%d\n", addrcnt);
-		if (addrcnt < 1 || addrcnt > 128) {
-			printf("NFS devinfo addrcnt %d: out of range\n",
-			    addrcnt);
-			error = NFSERR_BADXDR;
-			goto nfsmout;
-		}
-
-		/*
-		 * Now we know how many stripe indices and addresses, so
-		 * we can allocate the structure the correct size.
-		 */
-		i = (stripecnt * sizeof(uint8_t)) / sizeof(struct nfsclds *)
-		    + 1;
-		NFSCL_DEBUG(4, "stripeindices=%d\n", i);
-		ndi = malloc(sizeof(*ndi) + (addrcnt + i) *
-		    sizeof(struct nfsclds *), M_NFSDEVINFO, M_WAITOK | M_ZERO);
-		NFSBCOPY(deviceid, ndi->nfsdi_deviceid, NFSX_V4DEVICEID);
-		ndi->nfsdi_refcnt = 0;
-		ndi->nfsdi_stripecnt = stripecnt;
-		ndi->nfsdi_addrcnt = addrcnt;
-		/* Fill in the stripe indices. */
-		for (i = 0; i < stripecnt; i++) {
-			stripeindex = fxdr_unsigned(uint8_t, *tl++);
-			NFSCL_DEBUG(4, "stripeind=%d\n", stripeindex);
-			if (stripeindex >= addrcnt) {
-				printf("NFS devinfo stripeindex %d: too big\n",
-				    (int)stripeindex);
+		if (layouttype == NFSLAYOUT_NFSV4_1_FILES) {
+			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+			stripecnt = fxdr_unsigned(int, *tl);
+			NFSCL_DEBUG(4, "stripecnt=%d\n", stripecnt);
+			if (stripecnt < 1 || stripecnt > 4096) {
+				printf("pNFS File layout devinfo stripecnt %d:"
+				    " out of range\n", stripecnt);
 				error = NFSERR_BADXDR;
 				goto nfsmout;
 			}
-			nfsfldi_setstripeindex(ndi, i, stripeindex);
+			NFSM_DISSECT(tl, uint32_t *, (stripecnt + 1) *
+			    NFSX_UNSIGNED);
+			addrcnt = fxdr_unsigned(int, *(tl + stripecnt));
+			NFSCL_DEBUG(4, "addrcnt=%d\n", addrcnt);
+			if (addrcnt < 1 || addrcnt > 128) {
+				printf("NFS devinfo addrcnt %d: out of range\n",
+				    addrcnt);
+				error = NFSERR_BADXDR;
+				goto nfsmout;
+			}
+	
+			/*
+			 * Now we know how many stripe indices and addresses, so
+			 * we can allocate the structure the correct size.
+			 */
+			i = (stripecnt * sizeof(uint8_t)) /
+			    sizeof(struct nfsclds *) + 1;
+			NFSCL_DEBUG(4, "stripeindices=%d\n", i);
+			ndi = malloc(sizeof(*ndi) + (addrcnt + i) *
+			    sizeof(struct nfsclds *), M_NFSDEVINFO, M_WAITOK |
+			    M_ZERO);
+			NFSBCOPY(deviceid, ndi->nfsdi_deviceid,
+			    NFSX_V4DEVICEID);
+			ndi->nfsdi_refcnt = 0;
+			ndi->nfsdi_flags = NFSDI_FILELAYOUT;
+			ndi->nfsdi_stripecnt = stripecnt;
+			ndi->nfsdi_addrcnt = addrcnt;
+			/* Fill in the stripe indices. */
+			for (i = 0; i < stripecnt; i++) {
+				stripeindex = fxdr_unsigned(uint8_t, *tl++);
+				NFSCL_DEBUG(4, "stripeind=%d\n", stripeindex);
+				if (stripeindex >= addrcnt) {
+					printf("pNFS File Layout devinfo"
+					    " stripeindex %d: too big\n",
+					    (int)stripeindex);
+					error = NFSERR_BADXDR;
+					goto nfsmout;
+				}
+				nfsfldi_setstripeindex(ndi, i, stripeindex);
+			}
+		} else if (layouttype == NFSLAYOUT_FLEXFILE) {
+			/* For Flex File, we only get one address list. */
+			ndi = malloc(sizeof(*ndi) + sizeof(struct nfsclds *),
+			    M_NFSDEVINFO, M_WAITOK | M_ZERO);
+			NFSBCOPY(deviceid, ndi->nfsdi_deviceid,
+			    NFSX_V4DEVICEID);
+			ndi->nfsdi_refcnt = 0;
+			ndi->nfsdi_flags = NFSDI_FLEXFILE;
+			addrcnt = ndi->nfsdi_addrcnt = 1;
 		}
 
 		/* Now, dissect the server address(es). */
-		safilled = 0;
+		safilled = AF_UNSPEC;
 		for (i = 0; i < addrcnt; i++) {
 			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
 			cnt = fxdr_unsigned(uint32_t, *tl);
@@ -4949,63 +4991,107 @@ nfsrpc_getdeviceinfo(struct nfsmount *nmp, uint8_t *de
 				goto nfsmout;
 			}
 			dspp = nfsfldi_addr(ndi, i);
-			pos = arc4random() % cnt;	/* Choose one. */
-			safilled = 0;
+			safilled = AF_UNSPEC;
 			for (j = 0; j < cnt; j++) {
-				error = nfsv4_getipaddr(nd, &ss, &isudp);
+				error = nfsv4_getipaddr(nd, &sin, &sin6, &af,
+				    &isudp);
 				if (error != 0 && error != EPERM) {
 					error = NFSERR_BADXDR;
 					goto nfsmout;
 				}
 				if (error == 0 && isudp == 0) {
 					/*
-					 * The algorithm is:
-					 * - use "pos" entry if it is of the
-					 *   same af_family or none of them
-					 *   is of the same af_family
-					 * else
-					 * - use the first one of the same
-					 *   af_family.
+					 * The priority is:
+					 * - Same address family.
+					 * Save the address and dspp, so that
+					 * the connection can be done after
+					 * parsing is complete.
 					 */
-					if ((safilled == 0 && ss.ss_family ==
-					     nmp->nm_nam->sa_family) ||
-					    (j == pos &&
-					     (safilled == 0 || ss.ss_family ==
-					      nmp->nm_nam->sa_family)) ||
-					    (safilled == 1 && ss.ss_family ==
-					     nmp->nm_nam->sa_family)) {
-						error = nfsrpc_fillsa(nmp, &ss,
-						    &dsp, p);
-						if (error == 0) {
-							*dspp = dsp;
-							if (ss.ss_family ==
-							 nmp->nm_nam->sa_family)
-								safilled = 2;
-							else
-								safilled = 1;
-						}
+					if (safilled == AF_UNSPEC ||
+					    (af == nmp->nm_nam->sa_family &&
+					     safilled != nmp->nm_nam->sa_family)
+					   ) {
+						if (af == AF_INET)
+							ssin = sin;
+						else
+							ssin6 = sin6;
+						safilled = af;
+						gotdspp = dspp;
 					}
 				}
 			}
-			if (safilled == 0)
-				break;
 		}
 
+		gotvers = NFS_VER4;	/* Always NFSv4 for File Layout. */
+		/* For Flex File, we will take one of the versions to use. */
+		if (layouttype == NFSLAYOUT_FLEXFILE) {
+			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+			j = fxdr_unsigned(int, *tl);
+			if (j < 1 || j > NFSDEV_MAXVERS) {
+				printf("pNFS: too many versions\n");
+				error = NFSERR_BADXDR;
+				goto nfsmout;
+			}
+			gotvers = 0;
+			for (i = 0; i < j; i++) {
+				NFSM_DISSECT(tl, uint32_t *, 5 * NFSX_UNSIGNED);
+				vers = fxdr_unsigned(uint32_t, *tl++);
+				minorvers = fxdr_unsigned(uint32_t, *tl++);
+				if ((vers == NFS_VER4 && minorvers ==
+				    NFSV41_MINORVERSION) || (vers == NFS_VER3 &&
+				    gotvers == 0)) {
+					gotvers = vers;
+					/* We'll take this one. */
+					ndi->nfsdi_versindex = i;
+					ndi->nfsdi_vers = vers;
+					ndi->nfsdi_minorvers = minorvers;
+					ndi->nfsdi_rsize = fxdr_unsigned(
+					    uint32_t, *tl++);
+					ndi->nfsdi_wsize = fxdr_unsigned(
+					    uint32_t, *tl++);
+					if (*tl == newnfs_true)
+						ndi->nfsdi_flags |=
+						    NFSDI_TIGHTCOUPLED;
+					else
+						ndi->nfsdi_flags &=
+						    ~NFSDI_TIGHTCOUPLED;
+				}
+			}
+			if (gotvers == 0) {
+				printf("pNFS: no NFSv3 or NFSv4.1\n");
+				error = NFSERR_BADXDR;
+				goto nfsmout;
+			}
+		}
+
 		/* And the notify bits. */
 		NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
-		if (safilled != 0) {
-			bitcnt = fxdr_unsigned(int, *tl);
-			if (bitcnt > 0) {
-				NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
-				if (notifybitsp != NULL)
-					*notifybitsp =
-					    fxdr_unsigned(uint32_t, *tl);
-			}
+		bitcnt = fxdr_unsigned(int, *tl);
+		if (bitcnt > 0) {
+			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+			if (notifybitsp != NULL)
+				*notifybitsp =
+				    fxdr_unsigned(uint32_t, *tl);
+		}
+		if (safilled != AF_UNSPEC) {
+			KASSERT(ndi != NULL, ("ndi is NULL"));
 			*ndip = ndi;
 		} else
 			error = EPERM;
+		if (error == 0) {
+			/*
+			 * Now we can do a TCP connection for the correct
+			 * NFS version and IP address.
+			 */
+			error = nfsrpc_fillsa(nmp, &ssin, &ssin6, safilled,
+			    gotvers, &dsp, p);
+		}
+		if (error == 0) {
+			KASSERT(gotdspp != NULL, ("gotdspp is NULL"));
+			*gotdspp = dsp;
+		}
 	}
-	if (nd->nd_repstat != 0)
+	if (nd->nd_repstat != 0 && error == 0)
 		error = nd->nd_repstat;
 nfsmout:
 	if (error != 0 && ndi != NULL)
@@ -5020,15 +5106,14 @@ nfsmout:
 int
 nfsrpc_layoutcommit(struct nfsmount *nmp, uint8_t *fh, int fhlen, int reclaim,
     uint64_t off, uint64_t len, uint64_t lastbyte, nfsv4stateid_t *stateidp,
-    int layouttype, int layoutupdatecnt, uint8_t *layp, struct ucred *cred,
-    NFSPROC_T *p, void *stuff)
+    int layouttype, struct ucred *cred, NFSPROC_T *p, void *stuff)
 {
 	uint32_t *tl;
 	struct nfsrv_descript nfsd, *nd = &nfsd;
-	int error, outcnt, i;
-	uint8_t *cp;
+	int error;
 
-	nfscl_reqstart(nd, NFSPROC_LAYOUTCOMMIT, nmp, fh, fhlen, NULL, NULL);
+	nfscl_reqstart(nd, NFSPROC_LAYOUTCOMMIT, nmp, fh, fhlen, NULL, NULL,
+	    0, 0);
 	NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
 	    NFSX_STATEID);
 	txdr_hyper(off, tl);
@@ -5052,17 +5137,13 @@ nfsrpc_layoutcommit(struct nfsmount *nmp, uint8_t *fh,
 	tl += 2;
 	*tl++ = newnfs_false;
 	*tl++ = txdr_unsigned(layouttype);
-	*tl = txdr_unsigned(layoutupdatecnt);
-	if (layoutupdatecnt > 0) {
-		KASSERT(layouttype != NFSLAYOUT_NFSV4_1_FILES,
-		    ("Must be nil for Files Layout"));
-		outcnt = NFSM_RNDUP(layoutupdatecnt);
-		NFSM_BUILD(cp, uint8_t *, outcnt);
-		NFSBCOPY(layp, cp, layoutupdatecnt);
-		cp += layoutupdatecnt;
-		for (i = 0; i < (outcnt - layoutupdatecnt); i++)
-			*cp++ = 0x0;
-	}
+	/* All supported layouts appear to be 0 length for now. */
+	if (layouttype == NFSLAYOUT_NFSV4_1_FILES)
+		*tl = txdr_unsigned(0);
+	else if (layouttype == NFSLAYOUT_FLEXFILE)
+		*tl = txdr_unsigned(0);
+	else
+		*tl = txdr_unsigned(0);
 	nd->nd_flag |= ND_USEGSSNAME;
 	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
 	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
@@ -5079,15 +5160,15 @@ nfsrpc_layoutcommit(struct nfsmount *nmp, uint8_t *fh,
 int
 nfsrpc_layoutreturn(struct nfsmount *nmp, uint8_t *fh, int fhlen, int reclaim,
     int layouttype, uint32_t iomode, int layoutreturn, uint64_t offset,
-    uint64_t len, nfsv4stateid_t *stateidp, int layoutcnt, uint32_t *layp,
-    struct ucred *cred, NFSPROC_T *p, void *stuff)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201709262026.v8QKQnci034575>