FreeBSD Bugzilla – Attachment 182908 Details for
Bug 219550
Add support for Open+LayoutGet RPC to the NFSv4.1/pNFS client
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
add Open+LayoutGet RPCs
openlayout.patch (text/plain), 37.91 KB, created by
Rick Macklem
on 2017-05-25 20:08:58 UTC
(
hide
)
Description:
add Open+LayoutGet RPCs
Filename:
MIME Type:
Creator:
Rick Macklem
Created:
2017-05-25 20:08:58 UTC
Size:
37.91 KB
patch
obsolete
>--- sys/fs/nfs/nfsport.h.orig 2017-04-27 11:51:51.000000000 -0400 >+++ sys/fs/nfs/nfsport.h 2017-05-19 13:22:45.604219000 -0400 >@@ -357,11 +357,13 @@ > #define NFSPROC_WRITEDS 51 > #define NFSPROC_READDS 52 > #define NFSPROC_COMMITDS 53 >+#define NFSPROC_OPENLAYGET 54 >+#define NFSPROC_CREATELAYGET 55 > > /* > * Must be defined as one higher than the last NFSv4.1 Proc# above. > */ >-#define NFSV41_NPROCS 54 >+#define NFSV41_NPROCS 56 > > #endif /* NFS_V3NPROCS */ > >@@ -390,7 +392,7 @@ struct nfsstatsv1 { > uint64_t readlink_bios; > uint64_t biocache_readdirs; > uint64_t readdir_bios; >- uint64_t rpccnt[NFSV41_NPROCS + 15]; >+ uint64_t rpccnt[NFSV41_NPROCS + 13]; > uint64_t rpcretries; > uint64_t srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS]; > uint64_t srvrpc_errs; >--- sys/fs/nfs/nfsproto.h.orig 2017-05-11 11:08:01.681251000 -0400 >+++ sys/fs/nfs/nfsproto.h 2017-05-19 13:23:21.991290000 -0400 >@@ -346,11 +346,13 @@ > #define NFSPROC_WRITEDS 51 > #define NFSPROC_READDS 52 > #define NFSPROC_COMMITDS 53 >+#define NFSPROC_OPENLAYGET 54 >+#define NFSPROC_CREATELAYGET 55 > > /* > * Must be defined as one higher than the last NFSv4.1 Proc# above. > */ >-#define NFSV41_NPROCS 54 >+#define NFSV41_NPROCS 56 > > #endif /* NFS_V3NPROCS */ > >--- sys/fs/nfs/nfs_commonsubs.c.orig 2017-05-16 09:38:21.723163000 -0400 >+++ sys/fs/nfs/nfs_commonsubs.c 2017-05-19 13:21:27.867778000 -0400 >@@ -177,7 +177,7 @@ static struct nfsrv_lughash *nfsgroupnam > */ > int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, > 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 }; >+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }; > > /* local functions */ > static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep); >--- sys/fs/nfsclient/nfs_clcomsubs.c.orig 2017-05-16 12:36:16.098878000 -0400 >+++ sys/fs/nfsclient/nfs_clcomsubs.c 2017-05-19 13:25:59.823092000 -0400 >@@ -112,6 +112,8 @@ static struct { > { NFSV4OP_WRITE, 1, "WriteDS", 7, }, > { NFSV4OP_READ, 1, "ReadDS", 6, }, > { NFSV4OP_COMMIT, 1, "CommitDS", 8, }, >+ { NFSV4OP_OPEN, 3, "OpenLayoutGet", 13, }, >+ { NFSV4OP_OPEN, 8, "CreateLayGet", 12, }, > }; > > /* >@@ -120,7 +122,7 @@ static struct { > static int nfs_bigrequest[NFSV41_NPROCS] = { > 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, > 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >- 0, 0, 0, 0, 0, 0, 1, 0, 0 >+ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 > }; > > /* >--- sys/fs/nfsclient/nfs_clrpcops.c.orig 2017-05-11 10:52:42.168711000 -0400 >+++ sys/fs/nfsclient/nfs_clrpcops.c 2017-05-19 13:29:08.409098000 -0400 >@@ -127,6 +127,29 @@ static enum nfsclds_state nfscl_getsames > static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *, > struct nfsfh *, struct ucred *, NFSPROC_T *, void *); > #endif >+static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t, >+ uint64_t, uint64_t, nfsv4stateid_t *, int, int); >+static int nfsrv_parselayoutget(struct nfsrv_descript *, nfsv4stateid_t *, >+ int *, struct nfsclflayouthead *); >+static int nfsrpc_getopenlayout(struct nfsmount *, vnode_t, u_int8_t *, >+ int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int, >+ struct nfscldeleg **, struct ucred *, NFSPROC_T *); >+static int nfsrpc_getcreatelayout(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 *); >+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 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 *); >+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 *); > > /* > * nfs null call from vfs. >@@ -301,11 +324,27 @@ else printf(" fhl=0\n"); > clidrev = 0; > if (ret == NFSCLOPEN_DOOPEN) { > if (np->n_v4 != NULL) { >- error = nfsrpc_openrpc(nmp, vp, np->n_v4->n4_data, >- np->n_v4->n4_fhlen, np->n_fhp->nfh_fh, >- np->n_fhp->nfh_len, mode, op, >- NFS4NODENAME(np->n_v4), np->n_v4->n4_namelen, &dp, >- 0, 0x0, cred, p, 0, 0); >+ /* >+ * For the first attempt, try and get a layout, if >+ * pNFS is enabled for the mount. >+ */ >+ if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 || >+ nfs_numnfscbd == 0 || >+ (np->n_flag & NNOLAYOUT) != 0 || retrycnt > 0) >+ error = nfsrpc_openrpc(nmp, vp, >+ np->n_v4->n4_data, >+ np->n_v4->n4_fhlen, np->n_fhp->nfh_fh, >+ np->n_fhp->nfh_len, mode, op, >+ NFS4NODENAME(np->n_v4), >+ np->n_v4->n4_namelen, >+ &dp, 0, 0x0, cred, p, 0, 0); >+ else >+ error = nfsrpc_getopenlayout(nmp, vp, >+ np->n_v4->n4_data, >+ np->n_v4->n4_fhlen, np->n_fhp->nfh_fh, >+ np->n_fhp->nfh_len, mode, op, >+ NFS4NODENAME(np->n_v4), >+ np->n_v4->n4_namelen, &dp, cred, p); > if (dp != NULL) { > #ifdef APPLE > OSBitAndAtomic((int32_t)~NDELEGMOD, (UInt32 *)&np->n_flag); >@@ -1894,9 +1933,15 @@ nfsrpc_create(vnode_t dvp, char *name, i > clidrev = nmp->nm_clp->nfsc_clientidrev; > else > clidrev = 0; >- error = nfsrpc_createv4(dvp, name, namelen, vap, cverf, fmode, >- owp, &dp, cred, p, dnap, nnap, nfhpp, attrflagp, dattrflagp, >- dstuff, &unlocked); >+ if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 || >+ nfs_numnfscbd == 0 || retrycnt > 0) >+ error = nfsrpc_createv4(dvp, name, namelen, vap, cverf, >+ fmode, owp, &dp, cred, p, dnap, nnap, nfhpp, >+ attrflagp, dattrflagp, dstuff, &unlocked); >+ else >+ error = nfsrpc_getcreatelayout(dvp, name, namelen, vap, >+ cverf, fmode, owp, &dp, cred, p, dnap, nnap, nfhpp, >+ attrflagp, dattrflagp, dstuff, &unlocked); > /* > * There is no need to invalidate cached attributes here, > * since new post-delegation issue attributes are always >@@ -4766,149 +4811,22 @@ nfsrpc_layoutget(struct nfsmount *nmp, u > nfsv4stateid_t *stateidp, int *retonclosep, struct nfsclflayouthead *flhp, > struct ucred *cred, NFSPROC_T *p, void *stuff) > { >- uint32_t *tl; > struct nfsrv_descript nfsd, *nd = &nfsd; >- struct nfsfh *nfhp; >- struct nfsclflayout *flp, *prevflp, *tflp; >- int cnt, error, gotiomode, fhcnt, nfhlen, i, j; >- uint8_t *cp; >- uint64_t retlen; >+ int error; > >- flp = NULL; >- gotiomode = -1; > nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL); >- NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER + >- NFSX_STATEID); >- *tl++ = newnfs_false; /* Don't signal availability. */ >- *tl++ = txdr_unsigned(NFSLAYOUT_NFSV4_1_FILES); >- *tl++ = txdr_unsigned(iomode); >- txdr_hyper(offset, tl); >- tl += 2; >- txdr_hyper(len, tl); >- tl += 2; >- txdr_hyper(minlen, tl); >- tl += 2; >- *tl++ = txdr_unsigned(stateidp->seqid); >- NFSCL_DEBUG(4, "layget seq=%d\n", (int)stateidp->seqid); >- *tl++ = stateidp->other[0]; >- *tl++ = stateidp->other[1]; >- *tl++ = stateidp->other[2]; >- *tl = txdr_unsigned(layoutlen); >+ nfsrv_setuplayoutget(nd, iomode, offset, len, minlen, stateidp, >+ 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); >+ NFSCL_DEBUG(4, "layget err=%d st=%d\n", error, nd->nd_repstat); > if (error != 0) > return (error); >- if (nd->nd_repstat == 0) { >- NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_STATEID); >- if (*tl++ != 0) >- *retonclosep = 1; >- else >- *retonclosep = 0; >- stateidp->seqid = fxdr_unsigned(uint32_t, *tl++); >- NFSCL_DEBUG(4, "retoncls=%d stseq=%d\n", *retonclosep, >- (int)stateidp->seqid); >- stateidp->other[0] = *tl++; >- stateidp->other[1] = *tl++; >- stateidp->other[2] = *tl++; >- cnt = fxdr_unsigned(int, *tl); >- NFSCL_DEBUG(4, "layg cnt=%d\n", cnt); >- if (cnt <= 0 || cnt > 10000) { >- /* Don't accept more than 10000 layouts in reply. */ >- error = NFSERR_BADXDR; >- goto nfsmout; >- } >- for (i = 0; i < cnt; i++) { >- /* Dissect all the way to the file handle cnt. */ >- NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_HYPER + >- 6 * NFSX_UNSIGNED + NFSX_V4DEVICEID); >- fhcnt = fxdr_unsigned(int, *(tl + 11 + >- NFSX_V4DEVICEID / NFSX_UNSIGNED)); >- NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt); >- if (fhcnt < 0 || fhcnt > 100) { >- /* Don't accept more than 100 file handles. */ >- error = NFSERR_BADXDR; >- goto nfsmout; >- } >- if (fhcnt > 1) >- flp = malloc(sizeof(*flp) + (fhcnt - 1) * >- sizeof(struct nfsfh *), >- M_NFSFLAYOUT, M_WAITOK); >- else >- flp = malloc(sizeof(*flp), >- M_NFSFLAYOUT, M_WAITOK); >- flp->nfsfl_flags = 0; >- flp->nfsfl_fhcnt = 0; >- flp->nfsfl_devp = NULL; >- flp->nfsfl_off = fxdr_hyper(tl); tl += 2; >- retlen = fxdr_hyper(tl); tl += 2; >- if (flp->nfsfl_off + retlen < flp->nfsfl_off) >- flp->nfsfl_end = UINT64_MAX - flp->nfsfl_off; >- else >- flp->nfsfl_end = flp->nfsfl_off + retlen; >- flp->nfsfl_iomode = fxdr_unsigned(int, *tl++); >- if (gotiomode == -1) >- gotiomode = flp->nfsfl_iomode; >- NFSCL_DEBUG(4, "layg reqiom=%d retiom=%d\n", iomode, >- (int)flp->nfsfl_iomode); >- if (fxdr_unsigned(int, *tl++) != >- NFSLAYOUT_NFSV4_1_FILES) { >- printf("NFSv4.1: got non-files layout\n"); >- error = NFSERR_BADXDR; >- goto nfsmout; >- } >- NFSBCOPY(++tl, flp->nfsfl_dev, NFSX_V4DEVICEID); >- tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); >- flp->nfsfl_util = fxdr_unsigned(uint32_t, *tl++); >- NFSCL_DEBUG(4, "flutil=0x%x\n", flp->nfsfl_util); >- flp->nfsfl_stripe1 = fxdr_unsigned(uint32_t, *tl++); >- flp->nfsfl_patoff = fxdr_hyper(tl); tl += 2; >- if (fxdr_unsigned(int, *tl) != fhcnt) { >- printf("EEK! bad fhcnt\n"); >- error = NFSERR_BADXDR; >- goto nfsmout; >- } >- for (j = 0; j < fhcnt; j++) { >- NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); >- nfhlen = fxdr_unsigned(int, *tl); >- if (nfhlen <= 0 || nfhlen > NFSX_V4FHMAX) { >- error = NFSERR_BADXDR; >- goto nfsmout; >- } >- nfhp = malloc(sizeof(*nfhp) + nfhlen - 1, >- M_NFSFH, M_WAITOK); >- flp->nfsfl_fh[j] = nfhp; >- flp->nfsfl_fhcnt++; >- nfhp->nfh_len = nfhlen; >- NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(nfhlen)); >- NFSBCOPY(cp, nfhp->nfh_fh, nfhlen); >- } >- if (flp->nfsfl_iomode == gotiomode) { >- /* Keep the list in increasing offset order. */ >- tflp = LIST_FIRST(flhp); >- prevflp = NULL; >- while (tflp != NULL && >- tflp->nfsfl_off < flp->nfsfl_off) { >- prevflp = tflp; >- tflp = LIST_NEXT(tflp, nfsfl_list); >- } >- if (prevflp == NULL) >- LIST_INSERT_HEAD(flhp, flp, nfsfl_list); >- else >- LIST_INSERT_AFTER(prevflp, flp, >- nfsfl_list); >- } else { >- printf("nfscl_layoutget(): got wrong iomode\n"); >- nfscl_freeflayout(flp); >- } >- flp = NULL; >- } >- } >- if (nd->nd_repstat != 0 && error == 0) >+ if (nd->nd_repstat == 0) >+ error = nfsrv_parselayoutget(nd, stateidp, retonclosep, flhp); >+ if (error == 0 && nd->nd_repstat != 0) > error = nd->nd_repstat; >-nfsmout: >- if (error != 0 && flp != NULL) >- nfscl_freeflayout(flp); > mbuf_freem(nd->nd_mrep); > return (error); > } >@@ -5209,8 +5127,7 @@ nfsrpc_getlayout(struct nfsmount *nmp, v > struct nfscllayout **lypp, struct ucred *cred, NFSPROC_T *p) > { > struct nfscllayout *lyp; >- struct nfsclflayout *flp, *tflp; >- struct nfscldevinfo *dip; >+ struct nfsclflayout *flp; > struct nfsclflayouthead flh; > int error = 0, islocked, layoutlen, recalled, retonclose; > nfsv4stateid_t stateid; >@@ -5252,35 +5169,13 @@ nfsrpc_getlayout(struct nfsmount *nmp, v > (uint64_t)0, layoutlen, &stateid, &retonclose, > &flh, cred, p, NULL); > } >+ error = nfsrpc_layoutgetres(nmp, vp, nfhp->nfh_fh, >+ nfhp->nfh_len, &stateid, retonclose, notifybitsp, &lyp, >+ &flh, error, NULL, cred, p); > if (error == 0) >- LIST_FOREACH(tflp, &flh, nfsfl_list) { >- error = nfscl_adddevinfo(nmp, NULL, tflp); >- if (error != 0) { >- error = nfsrpc_getdeviceinfo(nmp, >- tflp->nfsfl_dev, >- NFSLAYOUT_NFSV4_1_FILES, >- notifybitsp, &dip, cred, p); >- if (error != 0) >- break; >- error = nfscl_adddevinfo(nmp, dip, >- tflp); >- if (error != 0) >- printf( >- "getlayout: cannot add\n"); >- } >- } >- if (error == 0) { >- /* >- * nfscl_layout() always returns with the nfsly_lock >- * set to a refcnt (shared lock). >- */ >- error = nfscl_layout(nmp, vp, nfhp->nfh_fh, >- nfhp->nfh_len, &stateid, retonclose, &flh, &lyp, >- cred, p); >- if (error == 0) >- *lypp = lyp; >- } else if (islocked != 0) >- nfsv4_unlock(&lyp->nfsly_lock, 0); >+ *lypp = lyp; >+ else if (islocked != 0) >+ nfscl_rellayout(lyp, 1); > } else > *lypp = lyp; > return (error); >@@ -6003,3 +5898,755 @@ nfsmout: > } > #endif > >+/* >+ * Set up the XDR arguments for the LayoutGet operation. >+ */ >+static void >+nfsrv_setuplayoutget(struct nfsrv_descript *nd, int iomode, uint64_t offset, >+ uint64_t len, uint64_t minlen, nfsv4stateid_t *stateidp, int layoutlen, >+ int usecurstateid) >+{ >+ uint32_t *tl; >+ >+ NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER + >+ NFSX_STATEID); >+ *tl++ = newnfs_false; /* Don't signal availability. */ >+ *tl++ = txdr_unsigned(NFSLAYOUT_NFSV4_1_FILES); >+ *tl++ = txdr_unsigned(iomode); >+ txdr_hyper(offset, tl); >+ tl += 2; >+ txdr_hyper(len, tl); >+ tl += 2; >+ txdr_hyper(minlen, tl); >+ tl += 2; >+ if (usecurstateid != 0) { >+ /* Special stateid for Current stateid. */ >+ *tl++ = txdr_unsigned(1); >+ *tl++ = 0; >+ *tl++ = 0; >+ *tl++ = 0; >+ } else { >+ *tl++ = txdr_unsigned(stateidp->seqid); >+ NFSCL_DEBUG(4, "layget seq=%d\n", (int)stateidp->seqid); >+ *tl++ = stateidp->other[0]; >+ *tl++ = stateidp->other[1]; >+ *tl++ = stateidp->other[2]; >+ } >+ *tl = txdr_unsigned(layoutlen); >+} >+ >+/* >+ * Parse the reply for a successful LayoutGet operation. >+ */ >+static int >+nfsrv_parselayoutget(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp, >+ int *retonclosep, struct nfsclflayouthead *flhp) >+{ >+ uint32_t *tl; >+ struct nfsclflayout *flp, *prevflp, *tflp; >+ int cnt, error, gotiomode, fhcnt, nfhlen, i, j; >+ uint64_t retlen; >+ struct nfsfh *nfhp; >+ uint8_t *cp; >+ >+ error = 0; >+ flp = NULL; >+ gotiomode = -1; >+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_STATEID); >+ if (*tl++ != 0) >+ *retonclosep = 1; >+ else >+ *retonclosep = 0; >+ stateidp->seqid = fxdr_unsigned(uint32_t, *tl++); >+ NFSCL_DEBUG(4, "retoncls=%d stseq=%d\n", *retonclosep, >+ (int)stateidp->seqid); >+ stateidp->other[0] = *tl++; >+ stateidp->other[1] = *tl++; >+ stateidp->other[2] = *tl++; >+ cnt = fxdr_unsigned(int, *tl); >+ NFSCL_DEBUG(4, "layg cnt=%d\n", cnt); >+ if (cnt <= 0 || cnt > 10000) { >+ /* Don't accept more than 10000 layouts in reply. */ >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ } >+ for (i = 0; i < cnt; i++) { >+ /* Dissect all the way to the file handle cnt. */ >+ NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_HYPER + >+ 6 * NFSX_UNSIGNED + NFSX_V4DEVICEID); >+ fhcnt = fxdr_unsigned(int, *(tl + 11 + >+ NFSX_V4DEVICEID / NFSX_UNSIGNED)); >+ NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt); >+ if (fhcnt < 0 || fhcnt > 100) { >+ /* Don't accept more than 100 file handles. */ >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ } >+ if (fhcnt > 1) >+ flp = malloc(sizeof(*flp) + (fhcnt - 1) * >+ sizeof(struct nfsfh *), M_NFSFLAYOUT, M_WAITOK); >+ else >+ flp = malloc(sizeof(*flp), M_NFSFLAYOUT, M_WAITOK); >+ flp->nfsfl_flags = 0; >+ flp->nfsfl_fhcnt = 0; >+ flp->nfsfl_devp = NULL; >+ flp->nfsfl_off = fxdr_hyper(tl); tl += 2; >+ retlen = fxdr_hyper(tl); tl += 2; >+ if (flp->nfsfl_off + retlen < flp->nfsfl_off) >+ flp->nfsfl_end = UINT64_MAX - flp->nfsfl_off; >+ else >+ flp->nfsfl_end = flp->nfsfl_off + retlen; >+ flp->nfsfl_iomode = fxdr_unsigned(int, *tl++); >+ if (gotiomode == -1) >+ gotiomode = flp->nfsfl_iomode; >+ if (fxdr_unsigned(int, *tl++) != NFSLAYOUT_NFSV4_1_FILES) { >+ printf("NFSv4.1: got non-files layout\n"); >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ } >+ NFSBCOPY(++tl, flp->nfsfl_dev, NFSX_V4DEVICEID); >+ tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED); >+ flp->nfsfl_util = fxdr_unsigned(uint32_t, *tl++); >+ NFSCL_DEBUG(4, "flutil=0x%x\n", flp->nfsfl_util); >+ flp->nfsfl_stripe1 = fxdr_unsigned(uint32_t, *tl++); >+ flp->nfsfl_patoff = fxdr_hyper(tl); tl += 2; >+ if (fxdr_unsigned(int, *tl) != fhcnt) { >+ printf("EEK! bad fhcnt\n"); >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ } >+ for (j = 0; j < fhcnt; j++) { >+ NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED); >+ nfhlen = fxdr_unsigned(int, *tl); >+ if (nfhlen <= 0 || nfhlen > NFSX_V4FHMAX) { >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ } >+ nfhp = malloc(sizeof(*nfhp) + nfhlen - 1, M_NFSFH, >+ M_WAITOK); >+ flp->nfsfl_fh[j] = nfhp; >+ flp->nfsfl_fhcnt++; >+ nfhp->nfh_len = nfhlen; >+ NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(nfhlen)); >+ NFSBCOPY(cp, nfhp->nfh_fh, nfhlen); >+ } >+ if (flp->nfsfl_iomode == gotiomode) { >+ /* Keep the list in increasing offset order. */ >+ tflp = LIST_FIRST(flhp); >+ prevflp = NULL; >+ while (tflp != NULL && >+ tflp->nfsfl_off < flp->nfsfl_off) { >+ prevflp = tflp; >+ tflp = LIST_NEXT(tflp, nfsfl_list); >+ } >+ if (prevflp == NULL) >+ LIST_INSERT_HEAD(flhp, flp, nfsfl_list); >+ else >+ LIST_INSERT_AFTER(prevflp, flp, >+ nfsfl_list); >+ } else { >+ printf("nfscl_layoutget(): got wrong iomode\n"); >+ nfscl_freeflayout(flp); >+ } >+ flp = NULL; >+ } >+nfsmout: >+ if (error != 0 && flp != NULL) >+ nfscl_freeflayout(flp); >+ return (error); >+} >+ >+/* >+ * Similar to nfsrpc_getlayout(), except that it uses nfsrpc_openlayget(), >+ * so that it does both an Open and a Layoutget. >+ */ >+static int >+nfsrpc_getopenlayout(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp, >+ int fhlen, uint8_t *newfhp, int newfhlen, uint32_t mode, >+ struct nfsclopen *op, uint8_t *name, int namelen, struct nfscldeleg **dpp, >+ struct ucred *cred, NFSPROC_T *p) >+{ >+ struct nfscllayout *lyp; >+ struct nfsclflayout *flp; >+ struct nfsclflayouthead flh; >+ int error, islocked, layoutlen, recalled, retonclose, usecurstateid; >+ int laystat; >+ nfsv4stateid_t stateid; >+ struct nfsclsession *tsep; >+ >+ error = 0; >+ /* >+ * If lyp is returned non-NULL, there will be a refcnt (shared lock) >+ * on it, iff flp != NULL or a lock (exclusive lock) on it iff >+ * flp == NULL. >+ */ >+ lyp = nfscl_getlayout(nmp->nm_clp, newfhp, newfhlen, 0, &flp, >+ &recalled); >+ NFSCL_DEBUG(4, "nfsrpc_getopenlayout nfscl_getlayout lyp=%p\n", lyp); >+ if (lyp == NULL) >+ islocked = 0; >+ else if (flp != NULL) >+ islocked = 1; >+ else >+ islocked = 2; >+ if ((lyp == NULL || flp == NULL) && recalled == 0) { >+ LIST_INIT(&flh); >+ tsep = nfsmnt_mdssession(nmp); >+ layoutlen = tsep->nfsess_maxcache - (NFSX_STATEID + >+ 3 * NFSX_UNSIGNED); >+ if (lyp == NULL) >+ usecurstateid = 1; >+ else { >+ usecurstateid = 0; >+ stateid.seqid = lyp->nfsly_stateid.seqid; >+ stateid.other[0] = lyp->nfsly_stateid.other[0]; >+ stateid.other[1] = lyp->nfsly_stateid.other[1]; >+ stateid.other[2] = lyp->nfsly_stateid.other[2]; >+ } >+ error = nfsrpc_openlayoutrpc(nmp, vp, nfhp, fhlen, >+ newfhp, newfhlen, mode, op, name, namelen, >+ dpp, &stateid, usecurstateid, layoutlen, >+ &retonclose, &flh, &laystat, cred, p); >+ NFSCL_DEBUG(4, "aft nfsrpc_openlayoutrpc laystat=%d err=%d\n", >+ laystat, error); >+ laystat = nfsrpc_layoutgetres(nmp, vp, newfhp, newfhlen, >+ &stateid, retonclose, NULL, &lyp, &flh, laystat, &islocked, >+ cred, p); >+ } else >+ error = nfsrpc_openrpc(nmp, vp, nfhp, fhlen, newfhp, newfhlen, >+ mode, op, name, namelen, dpp, 0, 0, cred, p, 0, 0); >+ if (islocked == 2) >+ nfscl_rellayout(lyp, 1); >+ else if (islocked == 1) >+ nfscl_rellayout(lyp, 0); >+ return (error); >+} >+ >+/* >+ * This function does an Open+LayoutGet for an NFSv4.1 mount with pNFS >+ * enabled, only for the CLAIM_NULL case. All other NFSv4 Opens are >+ * handled by nfsrpc_openrpc(). >+ * For the case where op == NULL, dvp is the directory. When op != NULL, it >+ * can be NULL. >+ */ >+static int >+nfsrpc_openlayoutrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp, >+ int fhlen, uint8_t *newfhp, int newfhlen, uint32_t mode, >+ struct nfsclopen *op, uint8_t *name, int namelen, struct nfscldeleg **dpp, >+ nfsv4stateid_t *stateidp, int usecurstateid, >+ int layoutlen, int *retonclosep, struct nfsclflayouthead *flhp, >+ int *laystatp, struct ucred *cred, NFSPROC_T *p) >+{ >+ uint32_t *tl; >+ struct nfsrv_descript nfsd, *nd = &nfsd; >+ struct nfscldeleg *ndp = NULL; >+ struct nfsvattr nfsva; >+ struct nfsclsession *tsep; >+ uint32_t rflags, deleg; >+ nfsattrbit_t attrbits; >+ int error, ret, acesize, limitby, iomode; >+ >+ *dpp = NULL; >+ *laystatp = ENXIO; >+ nfscl_reqstart(nd, NFSPROC_OPENLAYGET, nmp, nfhp, fhlen, NULL, NULL); >+ NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED); >+ *tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid); >+ *tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH); >+ *tl++ = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH); >+ tsep = nfsmnt_mdssession(nmp); >+ *tl++ = tsep->nfsess_clientid.lval[0]; >+ *tl = tsep->nfsess_clientid.lval[1]; >+ nfsm_strtom(nd, op->nfso_own->nfsow_owner, NFSV4CL_LOCKNAMELEN); >+ NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED); >+ *tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE); >+ *tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL); >+ nfsm_strtom(nd, name, namelen); >+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); >+ *tl = txdr_unsigned(NFSV4OP_GETATTR); >+ NFSZERO_ATTRBIT(&attrbits); >+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE); >+ NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY); >+ nfsrv_putattrbit(nd, &attrbits); >+ NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED); >+ *tl = txdr_unsigned(NFSV4OP_LAYOUTGET); >+ if ((mode & NFSV4OPEN_ACCESSWRITE) != 0) >+ iomode = NFSLAYOUTIOMODE_RW; >+ else >+ iomode = NFSLAYOUTIOMODE_READ; >+ nfsrv_setuplayoutget(nd, iomode, 0, UINT64_MAX, 0, stateidp, >+ layoutlen, usecurstateid); >+ error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred, >+ NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL); >+ if (error != 0) >+ return (error); >+ NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd); >+ if (nd->nd_repstat != 0) >+ *laystatp = nd->nd_repstat; >+ if ((nd->nd_flag & ND_NOMOREDATA) == 0) { >+ /* ND_NOMOREDATA will be set if the Open operation failed. */ >+ NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + >+ 6 * NFSX_UNSIGNED); >+ op->nfso_stateid.seqid = *tl++; >+ op->nfso_stateid.other[0] = *tl++; >+ op->nfso_stateid.other[1] = *tl++; >+ op->nfso_stateid.other[2] = *tl; >+ rflags = fxdr_unsigned(u_int32_t, *(tl + 6)); >+ error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL); >+ if (error != 0) >+ goto nfsmout; >+ NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); >+ deleg = fxdr_unsigned(u_int32_t, *tl); >+ if (deleg == NFSV4OPEN_DELEGATEREAD || >+ deleg == NFSV4OPEN_DELEGATEWRITE) { >+ if (!(op->nfso_own->nfsow_clp->nfsc_flags & >+ NFSCLFLAGS_FIRSTDELEG)) >+ op->nfso_own->nfsow_clp->nfsc_flags |= >+ (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG); >+ ndp = malloc(sizeof(struct nfscldeleg) + newfhlen, >+ M_NFSCLDELEG, M_WAITOK); >+ LIST_INIT(&ndp->nfsdl_owner); >+ LIST_INIT(&ndp->nfsdl_lock); >+ ndp->nfsdl_clp = op->nfso_own->nfsow_clp; >+ ndp->nfsdl_fhlen = newfhlen; >+ NFSBCOPY(newfhp, ndp->nfsdl_fh, newfhlen); >+ newnfs_copyincred(cred, &ndp->nfsdl_cred); >+ nfscl_lockinit(&ndp->nfsdl_rwlock); >+ NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + >+ NFSX_UNSIGNED); >+ ndp->nfsdl_stateid.seqid = *tl++; >+ ndp->nfsdl_stateid.other[0] = *tl++; >+ ndp->nfsdl_stateid.other[1] = *tl++; >+ ndp->nfsdl_stateid.other[2] = *tl++; >+ ret = fxdr_unsigned(int, *tl); >+ if (deleg == NFSV4OPEN_DELEGATEWRITE) { >+ ndp->nfsdl_flags = NFSCLDL_WRITE; >+ /* >+ * Indicates how much the file can grow. >+ */ >+ NFSM_DISSECT(tl, u_int32_t *, >+ 3 * NFSX_UNSIGNED); >+ limitby = fxdr_unsigned(int, *tl++); >+ switch (limitby) { >+ case NFSV4OPEN_LIMITSIZE: >+ ndp->nfsdl_sizelimit = fxdr_hyper(tl); >+ break; >+ case NFSV4OPEN_LIMITBLOCKS: >+ ndp->nfsdl_sizelimit = >+ fxdr_unsigned(u_int64_t, *tl++); >+ ndp->nfsdl_sizelimit *= >+ fxdr_unsigned(u_int64_t, *tl); >+ break; >+ default: >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ }; >+ } else >+ ndp->nfsdl_flags = NFSCLDL_READ; >+ if (ret != 0) >+ ndp->nfsdl_flags |= NFSCLDL_RECALL; >+ error = nfsrv_dissectace(nd, &ndp->nfsdl_ace, &ret, >+ &acesize, p); >+ if (error != 0) >+ goto nfsmout; >+ } else if (deleg != NFSV4OPEN_DELEGATENONE) { >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ } >+ if ((rflags & NFSV4OPEN_LOCKTYPEPOSIX) != 0 || >+ nfscl_assumeposixlocks) >+ op->nfso_posixlock = 1; >+ else >+ op->nfso_posixlock = 0; >+ NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED); >+ /* If the 2nd element == NFS_OK, the Getattr succeeded. */ >+ if (*++tl == 0) { >+ error = nfsv4_loadattr(nd, NULL, &nfsva, NULL, >+ NULL, 0, NULL, NULL, NULL, NULL, NULL, 0, >+ NULL, NULL, NULL, p, cred); >+ if (error != 0) >+ goto nfsmout; >+ if (ndp != NULL) { >+ ndp->nfsdl_change = nfsva.na_filerev; >+ ndp->nfsdl_modtime = nfsva.na_mtime; >+ ndp->nfsdl_flags |= NFSCLDL_MODTIMESET; >+ *dpp = ndp; >+ ndp = NULL; >+ } >+ /* >+ * At this point, the Open has succeeded, so set >+ * nd_repstat = NFS_OK. If the Layoutget failed, >+ * this function just won't return a layout. >+ */ >+ if (nd->nd_repstat == 0) { >+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); >+ *laystatp = fxdr_unsigned(int, *++tl); >+ if (*laystatp == 0) { >+ error = nfsrv_parselayoutget(nd, >+ stateidp, retonclosep, flhp); >+ if (error != 0) >+ *laystatp = error; >+ } >+ } else >+ nd->nd_repstat = 0; /* Return 0 for Open. */ >+ } >+ } >+ if (nd->nd_repstat != 0 && error == 0) >+ error = nd->nd_repstat; >+nfsmout: >+ free(ndp, M_NFSCLDELEG); >+ mbuf_freem(nd->nd_mrep); >+ return (error); >+} >+ >+/* >+ * Similar nfsrpc_createv4(), but also does the LayoutGet operation. >+ * Used only for mounts with pNFS enabled. >+ */ >+static int >+nfsrpc_createlayout(vnode_t dvp, char *name, int namelen, struct vattr *vap, >+ nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp, >+ struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap, >+ struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp, >+ int *dattrflagp, void *dstuff, int *unlockedp, nfsv4stateid_t *stateidp, >+ int usecurstateid, int layoutlen, int *retonclosep, >+ struct nfsclflayouthead *flhp, int *laystatp) >+{ >+ uint32_t *tl; >+ int error = 0, deleg, newone, ret, acesize, limitby; >+ struct nfsrv_descript nfsd, *nd = &nfsd; >+ struct nfsclopen *op; >+ struct nfscldeleg *dp = NULL; >+ struct nfsnode *np; >+ struct nfsfh *nfhp; >+ struct nfsclsession *tsep; >+ nfsattrbit_t attrbits; >+ nfsv4stateid_t stateid; >+ uint32_t rflags; >+ struct nfsmount *nmp; >+ >+ nmp = VFSTONFS(dvp->v_mount); >+ np = VTONFS(dvp); >+ *laystatp = ENXIO; >+ *unlockedp = 0; >+ *nfhpp = NULL; >+ *dpp = NULL; >+ *attrflagp = 0; >+ *dattrflagp = 0; >+ if (namelen > NFS_MAXNAMLEN) >+ return (ENAMETOOLONG); >+ NFSCL_REQSTART(nd, NFSPROC_CREATELAYGET, dvp); >+ /* >+ * For V4, this is actually an Open op. >+ */ >+ NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED); >+ *tl++ = txdr_unsigned(owp->nfsow_seqid); >+ *tl++ = txdr_unsigned(NFSV4OPEN_ACCESSWRITE | >+ NFSV4OPEN_ACCESSREAD); >+ *tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE); >+ tsep = nfsmnt_mdssession(nmp); >+ *tl++ = tsep->nfsess_clientid.lval[0]; >+ *tl = tsep->nfsess_clientid.lval[1]; >+ nfsm_strtom(nd, owp->nfsow_owner, NFSV4CL_LOCKNAMELEN); >+ NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); >+ *tl++ = txdr_unsigned(NFSV4OPEN_CREATE); >+ if ((fmode & O_EXCL) != 0) { >+ if (NFSHASSESSPERSIST(nmp)) { >+ /* Use GUARDED for persistent sessions. */ >+ *tl = txdr_unsigned(NFSCREATE_GUARDED); >+ nfscl_fillsattr(nd, vap, dvp, 0, 0); >+ } else { >+ /* Otherwise, use EXCLUSIVE4_1. */ >+ *tl = txdr_unsigned(NFSCREATE_EXCLUSIVE41); >+ NFSM_BUILD(tl, u_int32_t *, NFSX_VERF); >+ *tl++ = cverf.lval[0]; >+ *tl = cverf.lval[1]; >+ nfscl_fillsattr(nd, vap, dvp, 0, 0); >+ } >+ } else { >+ *tl = txdr_unsigned(NFSCREATE_UNCHECKED); >+ nfscl_fillsattr(nd, vap, dvp, 0, 0); >+ } >+ NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); >+ *tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL); >+ nfsm_strtom(nd, name, namelen); >+ /* Get the new file's handle and attributes, plus save the FH. */ >+ NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED); >+ *tl++ = txdr_unsigned(NFSV4OP_SAVEFH); >+ *tl++ = txdr_unsigned(NFSV4OP_GETFH); >+ *tl = txdr_unsigned(NFSV4OP_GETATTR); >+ NFSGETATTR_ATTRBIT(&attrbits); >+ nfsrv_putattrbit(nd, &attrbits); >+ /* Get the directory's post-op attributes. */ >+ NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); >+ *tl = txdr_unsigned(NFSV4OP_PUTFH); >+ nfsm_fhtom(nd, np->n_fhp->nfh_fh, np->n_fhp->nfh_len, 0); >+ NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED); >+ *tl = txdr_unsigned(NFSV4OP_GETATTR); >+ nfsrv_putattrbit(nd, &attrbits); >+ NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED); >+ *tl++ = txdr_unsigned(NFSV4OP_RESTOREFH); >+ *tl = txdr_unsigned(NFSV4OP_LAYOUTGET); >+ nfsrv_setuplayoutget(nd, NFSLAYOUTIOMODE_RW, 0, UINT64_MAX, 0, stateidp, >+ layoutlen, usecurstateid); >+ error = nfscl_request(nd, dvp, p, cred, dstuff); >+ if (error != 0) >+ return (error); >+ NFSCL_DEBUG(4, "nfsrpc_createlayout stat=%d err=%d\n", nd->nd_repstat, >+ error); >+ if (nd->nd_repstat != 0) >+ *laystatp = nd->nd_repstat; >+ NFSCL_INCRSEQID(owp->nfsow_seqid, nd); >+ if ((nd->nd_flag & ND_NOMOREDATA) == 0) { >+ NFSCL_DEBUG(4, "nfsrpc_createlayout open succeeded\n"); >+ NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + >+ 6 * NFSX_UNSIGNED); >+ stateid.seqid = *tl++; >+ stateid.other[0] = *tl++; >+ stateid.other[1] = *tl++; >+ stateid.other[2] = *tl; >+ rflags = fxdr_unsigned(u_int32_t, *(tl + 6)); >+ nfsrv_getattrbits(nd, &attrbits, NULL, NULL); >+ NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED); >+ deleg = fxdr_unsigned(int, *tl); >+ if (deleg == NFSV4OPEN_DELEGATEREAD || >+ deleg == NFSV4OPEN_DELEGATEWRITE) { >+ if (!(owp->nfsow_clp->nfsc_flags & >+ NFSCLFLAGS_FIRSTDELEG)) >+ owp->nfsow_clp->nfsc_flags |= >+ (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG); >+ dp = malloc(sizeof(struct nfscldeleg) + NFSX_V4FHMAX, >+ M_NFSCLDELEG, M_WAITOK); >+ LIST_INIT(&dp->nfsdl_owner); >+ LIST_INIT(&dp->nfsdl_lock); >+ dp->nfsdl_clp = owp->nfsow_clp; >+ newnfs_copyincred(cred, &dp->nfsdl_cred); >+ nfscl_lockinit(&dp->nfsdl_rwlock); >+ NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID + >+ NFSX_UNSIGNED); >+ dp->nfsdl_stateid.seqid = *tl++; >+ dp->nfsdl_stateid.other[0] = *tl++; >+ dp->nfsdl_stateid.other[1] = *tl++; >+ dp->nfsdl_stateid.other[2] = *tl++; >+ ret = fxdr_unsigned(int, *tl); >+ if (deleg == NFSV4OPEN_DELEGATEWRITE) { >+ dp->nfsdl_flags = NFSCLDL_WRITE; >+ /* >+ * Indicates how much the file can grow. >+ */ >+ NFSM_DISSECT(tl, u_int32_t *, >+ 3 * NFSX_UNSIGNED); >+ limitby = fxdr_unsigned(int, *tl++); >+ switch (limitby) { >+ case NFSV4OPEN_LIMITSIZE: >+ dp->nfsdl_sizelimit = fxdr_hyper(tl); >+ break; >+ case NFSV4OPEN_LIMITBLOCKS: >+ dp->nfsdl_sizelimit = >+ fxdr_unsigned(u_int64_t, *tl++); >+ dp->nfsdl_sizelimit *= >+ fxdr_unsigned(u_int64_t, *tl); >+ break; >+ default: >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ }; >+ } else { >+ dp->nfsdl_flags = NFSCLDL_READ; >+ } >+ if (ret != 0) >+ dp->nfsdl_flags |= NFSCLDL_RECALL; >+ error = nfsrv_dissectace(nd, &dp->nfsdl_ace, &ret, >+ &acesize, p); >+ if (error != 0) >+ goto nfsmout; >+ } else if (deleg != NFSV4OPEN_DELEGATENONE) { >+ error = NFSERR_BADXDR; >+ goto nfsmout; >+ } >+ >+ /* Now, we should have the status for the SaveFH. */ >+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); >+ if (*++tl == 0) { >+ NFSCL_DEBUG(4, "nfsrpc_createlayout SaveFH ok\n"); >+ /* >+ * Now, process the GetFH and Getattr for the newly >+ * created file. nfscl_mtofh() will set >+ * ND_NOMOREDATA if these weren't successful. >+ */ >+ error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp); >+ NFSCL_DEBUG(4, "aft nfscl_mtofh err=%d\n", error); >+ if (error != 0) >+ goto nfsmout; >+ } else >+ nd->nd_flag |= ND_NOMOREDATA; >+ /* Now we have the PutFH and Getattr for the directory. */ >+ if ((nd->nd_flag & ND_NOMOREDATA) == 0) { >+ NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED); >+ if (*++tl != 0) >+ nd->nd_flag |= ND_NOMOREDATA; >+ else { >+ NFSM_DISSECT(tl, uint32_t *, 2 * >+ NFSX_UNSIGNED); >+ if (*++tl != 0) >+ nd->nd_flag |= ND_NOMOREDATA; >+ } >+ } >+ if ((nd->nd_flag & ND_NOMOREDATA) == 0) { >+ /* Load the directory attributes. */ >+ error = nfsm_loadattr(nd, dnap); >+ NFSCL_DEBUG(4, "aft nfsm_loadattr err=%d\n", error); >+ if (error != 0) >+ goto nfsmout; >+ *dattrflagp = 1; >+ if (dp != NULL && *attrflagp != 0) { >+ dp->nfsdl_change = nnap->na_filerev; >+ dp->nfsdl_modtime = nnap->na_mtime; >+ dp->nfsdl_flags |= NFSCLDL_MODTIMESET; >+ } >+ /* >+ * We can now complete the Open state. >+ */ >+ nfhp = *nfhpp; >+ if (dp != NULL) { >+ dp->nfsdl_fhlen = nfhp->nfh_len; >+ NFSBCOPY(nfhp->nfh_fh, dp->nfsdl_fh, >+ nfhp->nfh_len); >+ } >+ /* >+ * Get an Open structure that will be >+ * attached to the OpenOwner, acquired already. >+ */ >+ error = nfscl_open(dvp, nfhp->nfh_fh, nfhp->nfh_len, >+ (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), 0, >+ cred, p, NULL, &op, &newone, NULL, 0); >+ if (error != 0) >+ goto nfsmout; >+ op->nfso_stateid = stateid; >+ newnfs_copyincred(cred, &op->nfso_cred); >+ >+ nfscl_openrelease(nmp, op, error, newone); >+ *unlockedp = 1; >+ >+ /* Now, handle the RestoreFH and LayoutGet. */ >+ if (nd->nd_repstat == 0) { >+ NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED); >+ *laystatp = fxdr_unsigned(int, *(tl + 3)); >+ if (*laystatp == 0) { >+ error = nfsrv_parselayoutget(nd, >+ stateidp, retonclosep, flhp); >+ if (error != 0) >+ *laystatp = error; >+ } >+ NFSCL_DEBUG(4, "aft nfsrv_parselayout err=%d\n", >+ error); >+ } else >+ nd->nd_repstat = 0; >+ } >+ } >+ if (nd->nd_repstat != 0 && error == 0) >+ error = nd->nd_repstat; >+ if (error == NFSERR_STALECLIENTID || error == NFSERR_BADSESSION) >+ nfscl_initiate_recovery(owp->nfsow_clp); >+nfsmout: >+ NFSCL_DEBUG(4, "eo nfsrpc_createlayout err=%d\n", error); >+ if (error == 0) >+ *dpp = dp; >+ else >+ free(dp, M_NFSCLDELEG); >+ mbuf_freem(nd->nd_mrep); >+ return (error); >+} >+ >+/* >+ * Similar to nfsrpc_getopenlayout(), except that it used for the Create case. >+ */ >+static int >+nfsrpc_getcreatelayout(vnode_t dvp, char *name, int namelen, struct vattr *vap, >+ nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp, >+ struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap, >+ struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp, >+ int *dattrflagp, void *dstuff, int *unlockedp) >+{ >+ struct nfscllayout *lyp; >+ struct nfsclflayouthead flh; >+ struct nfsfh *nfhp; >+ struct nfsclsession *tsep; >+ struct nfsmount *nmp; >+ nfsv4stateid_t stateid; >+ int error, layoutlen, retonclose, laystat; >+ >+ error = 0; >+ nmp = VFSTONFS(dvp->v_mount); >+ LIST_INIT(&flh); >+ tsep = nfsmnt_mdssession(nmp); >+ layoutlen = tsep->nfsess_maxcache - (NFSX_STATEID + 3 * NFSX_UNSIGNED); >+ error = nfsrpc_createlayout(dvp, name, namelen, vap, cverf, fmode, >+ owp, dpp, cred, p, dnap, nnap, nfhpp, attrflagp, dattrflagp, >+ dstuff, unlockedp, &stateid, 1, layoutlen, &retonclose, &flh, >+ &laystat); >+ NFSCL_DEBUG(4, "aft nfsrpc_createlayoutrpc laystat=%d err=%d\n", >+ laystat, error); >+ lyp = NULL; >+ nfhp = *nfhpp; >+ laystat = nfsrpc_layoutgetres(nmp, dvp, nfhp->nfh_fh, nfhp->nfh_len, >+ &stateid, retonclose, NULL, &lyp, &flh, laystat, NULL, cred, p); >+ if (laystat == 0) >+ nfscl_rellayout(lyp, 0); >+ return (error); >+} >+ >+/* >+ * Process the results of a layoutget() operation. >+ */ >+static int >+nfsrpc_layoutgetres(struct nfsmount *nmp, vnode_t vp, uint8_t *newfhp, >+ int newfhlen, nfsv4stateid_t *stateidp, int retonclose, uint32_t *notifybit, >+ struct nfscllayout **lypp, struct nfsclflayouthead *flhp, >+ int laystat, int *islockedp, struct ucred *cred, NFSPROC_T *p) >+{ >+ struct nfsclflayout *tflp; >+ struct nfscldevinfo *dip; >+ >+ if (laystat == NFSERR_UNKNLAYOUTTYPE) { >+ /* Disable PNFS. */ >+ NFSCL_DEBUG(1, "disable PNFS\n"); >+ NFSLOCKMNT(nmp); >+ nmp->nm_state &= ~NFSSTA_PNFS; >+ NFSUNLOCKMNT(nmp); >+ } >+ if (laystat == 0) { >+ NFSCL_DEBUG(4, "nfsrpc_layoutgetres at FOREACH\n"); >+ LIST_FOREACH(tflp, flhp, nfsfl_list) { >+ laystat = nfscl_adddevinfo(nmp, NULL, tflp); >+ NFSCL_DEBUG(4, "aft adddev=%d\n", laystat); >+ if (laystat != 0) { >+ laystat = nfsrpc_getdeviceinfo(nmp, >+ tflp->nfsfl_dev, NFSLAYOUT_NFSV4_1_FILES, >+ notifybit, &dip, cred, p); >+ NFSCL_DEBUG(4, "aft nfsrpc_gdi=%d\n", >+ laystat); >+ if (laystat != 0) >+ break; >+ laystat = nfscl_adddevinfo(nmp, dip, tflp); >+ if (laystat != 0) >+ printf("getlayout: cannot add\n"); >+ } >+ } >+ } >+ if (laystat == 0) { >+ /* >+ * nfscl_layout() always returns with the nfsly_lock >+ * set to a refcnt (shared lock). >+ * Passing in dvp is sufficient, since it is only used to >+ * get the fsid for the file system. >+ */ >+ laystat = nfscl_layout(nmp, vp, newfhp, newfhlen, stateidp, >+ retonclose, flhp, lypp, cred, p); >+ NFSCL_DEBUG(4, "nfsrpc_layoutgetres: aft nfscl_layout=%d\n", >+ laystat); >+ if (laystat == 0 && islockedp != NULL) >+ *islockedp = 1; >+ } >+ return (laystat); >+} >+ >--- usr.bin/nfsstat/nfsstat.c.orig 2017-05-19 14:02:22.336358000 -0400 >+++ usr.bin/nfsstat/nfsstat.c 2017-05-19 14:02:22.337045000 -0400 >@@ -926,6 +926,13 @@ exp41_intpr(int clientOnly, int serverOn > (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMITDS]); > if (printtitle) > printf( >+ "%12.12s %12.12s\n", >+ "OpenLayout", "CreateLayout"); >+ printf("%12ju %12ju\n", >+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENLAYGET], >+ (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATELAYGET]); >+ if (printtitle) >+ printf( > "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n", > "OpenOwner", "Opens", "LockOwner", "Locks", > "Delegs", "LocalOwn");
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 219550
: 182908