From owner-svn-src-projects@freebsd.org Tue Sep 26 20:26:50 2017 Return-Path: Delivered-To: svn-src-projects@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E8882E208B1 for ; Tue, 26 Sep 2017 20:26:50 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 91BE07500D; Tue, 26 Sep 2017 20:26:50 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v8QKQnMN034585; Tue, 26 Sep 2017 20:26:49 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v8QKQnci034575; Tue, 26 Sep 2017 20:26:49 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201709262026.v8QKQnci034575@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Tue, 26 Sep 2017 20:26:49 +0000 (UTC) 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 X-SVN-Group: projects X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: in projects/pnfs-planb-server-stable11/sys/fs: nfs nfsclient nfsserver X-SVN-Commit-Revision: 324025 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Sep 2017 20:26:51 -0000 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 ***