View | Details | Raw Unified | Return to bug 219550
Collapse All | Expand All

(-)sys/fs/nfs/nfsport.h (-2 / +4 lines)
Lines 357-367 Link Here
357
#define	NFSPROC_WRITEDS		51
357
#define	NFSPROC_WRITEDS		51
358
#define	NFSPROC_READDS		52
358
#define	NFSPROC_READDS		52
359
#define	NFSPROC_COMMITDS	53
359
#define	NFSPROC_COMMITDS	53
360
#define	NFSPROC_OPENLAYGET	54
361
#define	NFSPROC_CREATELAYGET	55
360
362
361
/*
363
/*
362
 * Must be defined as one higher than the last NFSv4.1 Proc# above.
364
 * Must be defined as one higher than the last NFSv4.1 Proc# above.
363
 */
365
 */
364
#define	NFSV41_NPROCS		54
366
#define	NFSV41_NPROCS		56
365
367
366
#endif	/* NFS_V3NPROCS */
368
#endif	/* NFS_V3NPROCS */
367
369
Lines 390-396 struct nfsstatsv1 { Link Here
390
	uint64_t	readlink_bios;
392
	uint64_t	readlink_bios;
391
	uint64_t	biocache_readdirs;
393
	uint64_t	biocache_readdirs;
392
	uint64_t	readdir_bios;
394
	uint64_t	readdir_bios;
393
	uint64_t	rpccnt[NFSV41_NPROCS + 15];
395
	uint64_t	rpccnt[NFSV41_NPROCS + 13];
394
	uint64_t	rpcretries;
396
	uint64_t	rpcretries;
395
	uint64_t	srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS];
397
	uint64_t	srvrpccnt[NFSV42_NOPS + NFSV4OP_FAKENOPS];
396
	uint64_t	srvrpc_errs;
398
	uint64_t	srvrpc_errs;
(-)sys/fs/nfs/nfsproto.h (-1 / +3 lines)
Lines 346-356 Link Here
346
#define	NFSPROC_WRITEDS		51
346
#define	NFSPROC_WRITEDS		51
347
#define	NFSPROC_READDS		52
347
#define	NFSPROC_READDS		52
348
#define	NFSPROC_COMMITDS	53
348
#define	NFSPROC_COMMITDS	53
349
#define	NFSPROC_OPENLAYGET	54
350
#define	NFSPROC_CREATELAYGET	55
349
351
350
/*
352
/*
351
 * Must be defined as one higher than the last NFSv4.1 Proc# above.
353
 * Must be defined as one higher than the last NFSv4.1 Proc# above.
352
 */
354
 */
353
#define	NFSV41_NPROCS		54
355
#define	NFSV41_NPROCS		56
354
356
355
#endif	/* NFS_V3NPROCS */
357
#endif	/* NFS_V3NPROCS */
356
358
(-)sys/fs/nfs/nfs_commonsubs.c (-1 / +1 lines)
Lines 177-183 static struct nfsrv_lughash *nfsgroupnam Link Here
177
 */
177
 */
178
int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
178
int nfs_bigreply[NFSV41_NPROCS] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0,
179
    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,
179
    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,
180
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
180
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 };
181
181
182
/* local functions */
182
/* local functions */
183
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
183
static int nfsrv_skipace(struct nfsrv_descript *nd, int *acesizep);
(-)sys/fs/nfsclient/nfs_clcomsubs.c (-1 / +3 lines)
Lines 112-117 static struct { Link Here
112
	{ NFSV4OP_WRITE, 1, "WriteDS", 7, },
112
	{ NFSV4OP_WRITE, 1, "WriteDS", 7, },
113
	{ NFSV4OP_READ, 1, "ReadDS", 6, },
113
	{ NFSV4OP_READ, 1, "ReadDS", 6, },
114
	{ NFSV4OP_COMMIT, 1, "CommitDS", 8, },
114
	{ NFSV4OP_COMMIT, 1, "CommitDS", 8, },
115
	{ NFSV4OP_OPEN, 3, "OpenLayoutGet", 13, },
116
	{ NFSV4OP_OPEN, 8, "CreateLayGet", 12, },
115
};
117
};
116
118
117
/*
119
/*
Lines 120-126 static struct { Link Here
120
static int nfs_bigrequest[NFSV41_NPROCS] = {
122
static int nfs_bigrequest[NFSV41_NPROCS] = {
121
	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123
	0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124
	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123
	0, 0, 0, 0, 0, 0, 1, 0, 0
125
	0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0
124
};
126
};
125
127
126
/*
128
/*
(-)sys/fs/nfsclient/nfs_clrpcops.c (-172 / +819 lines)
Lines 127-132 static enum nfsclds_state nfscl_getsames Link Here
127
static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
127
static int nfsrpc_commitds(vnode_t, uint64_t, int, struct nfsclds *,
128
    struct nfsfh *, struct ucred *, NFSPROC_T *, void *);
128
    struct nfsfh *, struct ucred *, NFSPROC_T *, void *);
129
#endif
129
#endif
130
static void nfsrv_setuplayoutget(struct nfsrv_descript *, int, uint64_t,
131
    uint64_t, uint64_t, nfsv4stateid_t *, int, int);
132
static int nfsrv_parselayoutget(struct nfsrv_descript *, nfsv4stateid_t *,
133
    int *, struct nfsclflayouthead *);
134
static int nfsrpc_getopenlayout(struct nfsmount *, vnode_t, u_int8_t *,
135
    int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int,
136
    struct nfscldeleg **, struct ucred *, NFSPROC_T *);
137
static int nfsrpc_getcreatelayout(vnode_t, char *, int, struct vattr *,
138
    nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **,
139
    struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *,
140
    struct nfsfh **, int *, int *, void *, int *);
141
static int nfsrpc_openlayoutrpc(struct nfsmount *, vnode_t, u_int8_t *,
142
    int, uint8_t *, int, uint32_t, struct nfsclopen *, uint8_t *, int,
143
    struct nfscldeleg **, nfsv4stateid_t *, int, int, int *,
144
    struct nfsclflayouthead *, int *, struct ucred *, NFSPROC_T *);
145
static int nfsrpc_createlayout(vnode_t, char *, int, struct vattr *,
146
    nfsquad_t, int, struct nfsclowner *, struct nfscldeleg **,
147
    struct ucred *, NFSPROC_T *, struct nfsvattr *, struct nfsvattr *,
148
    struct nfsfh **, int *, int *, void *, int *, nfsv4stateid_t *,
149
    int, int, int *, struct nfsclflayouthead *, int *);
150
static int nfsrpc_layoutgetres(struct nfsmount *, vnode_t, uint8_t *,
151
    int, nfsv4stateid_t *, int, uint32_t *, struct nfscllayout **,
152
    struct nfsclflayouthead *, int, int *, struct ucred *, NFSPROC_T *);
130
153
131
/*
154
/*
132
 * nfs null call from vfs.
155
 * nfs null call from vfs.
Lines 301-311 else printf(" fhl=0\n"); Link Here
301
		clidrev = 0;
324
		clidrev = 0;
302
	    if (ret == NFSCLOPEN_DOOPEN) {
325
	    if (ret == NFSCLOPEN_DOOPEN) {
303
		if (np->n_v4 != NULL) {
326
		if (np->n_v4 != NULL) {
304
			error = nfsrpc_openrpc(nmp, vp, np->n_v4->n4_data,
327
			/*
305
			   np->n_v4->n4_fhlen, np->n_fhp->nfh_fh,
328
			 * For the first attempt, try and get a layout, if
306
			   np->n_fhp->nfh_len, mode, op,
329
			 * pNFS is enabled for the mount.
307
			   NFS4NODENAME(np->n_v4), np->n_v4->n4_namelen, &dp,
330
			 */
308
			   0, 0x0, cred, p, 0, 0);
331
			if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 ||
332
			    nfs_numnfscbd == 0 ||
333
			    (np->n_flag & NNOLAYOUT) != 0 || retrycnt > 0)
334
				error = nfsrpc_openrpc(nmp, vp,
335
				    np->n_v4->n4_data,
336
				    np->n_v4->n4_fhlen, np->n_fhp->nfh_fh,
337
				    np->n_fhp->nfh_len, mode, op,
338
				    NFS4NODENAME(np->n_v4),
339
				    np->n_v4->n4_namelen,
340
				    &dp, 0, 0x0, cred, p, 0, 0);
341
			else
342
				error = nfsrpc_getopenlayout(nmp, vp,
343
				    np->n_v4->n4_data,
344
				    np->n_v4->n4_fhlen, np->n_fhp->nfh_fh,
345
				    np->n_fhp->nfh_len, mode, op,
346
				    NFS4NODENAME(np->n_v4),
347
				    np->n_v4->n4_namelen, &dp, cred, p);
309
			if (dp != NULL) {
348
			if (dp != NULL) {
310
#ifdef APPLE
349
#ifdef APPLE
311
				OSBitAndAtomic((int32_t)~NDELEGMOD, (UInt32 *)&np->n_flag);
350
				OSBitAndAtomic((int32_t)~NDELEGMOD, (UInt32 *)&np->n_flag);
Lines 1894-1902 nfsrpc_create(vnode_t dvp, char *name, i Link Here
1894
			clidrev = nmp->nm_clp->nfsc_clientidrev;
1933
			clidrev = nmp->nm_clp->nfsc_clientidrev;
1895
		else
1934
		else
1896
			clidrev = 0;
1935
			clidrev = 0;
1897
		error = nfsrpc_createv4(dvp, name, namelen, vap, cverf, fmode,
1936
		if (!NFSHASPNFS(nmp) || nfscl_enablecallb == 0 ||
1898
		  owp, &dp, cred, p, dnap, nnap, nfhpp, attrflagp, dattrflagp,
1937
		    nfs_numnfscbd == 0 || retrycnt > 0)
1899
		  dstuff, &unlocked);
1938
			error = nfsrpc_createv4(dvp, name, namelen, vap, cverf,
1939
			  fmode, owp, &dp, cred, p, dnap, nnap, nfhpp,
1940
			  attrflagp, dattrflagp, dstuff, &unlocked);
1941
		else
1942
			error = nfsrpc_getcreatelayout(dvp, name, namelen, vap,
1943
			  cverf, fmode, owp, &dp, cred, p, dnap, nnap, nfhpp,
1944
			  attrflagp, dattrflagp, dstuff, &unlocked);
1900
		/*
1945
		/*
1901
		 * There is no need to invalidate cached attributes here,
1946
		 * There is no need to invalidate cached attributes here,
1902
		 * since new post-delegation issue attributes are always
1947
		 * since new post-delegation issue attributes are always
Lines 4766-4914 nfsrpc_layoutget(struct nfsmount *nmp, u Link Here
4766
    nfsv4stateid_t *stateidp, int *retonclosep, struct nfsclflayouthead *flhp,
4811
    nfsv4stateid_t *stateidp, int *retonclosep, struct nfsclflayouthead *flhp,
4767
    struct ucred *cred, NFSPROC_T *p, void *stuff)
4812
    struct ucred *cred, NFSPROC_T *p, void *stuff)
4768
{
4813
{
4769
	uint32_t *tl;
4770
	struct nfsrv_descript nfsd, *nd = &nfsd;
4814
	struct nfsrv_descript nfsd, *nd = &nfsd;
4771
	struct nfsfh *nfhp;
4815
	int error;
4772
	struct nfsclflayout *flp, *prevflp, *tflp;
4773
	int cnt, error, gotiomode, fhcnt, nfhlen, i, j;
4774
	uint8_t *cp;
4775
	uint64_t retlen;
4776
4816
4777
	flp = NULL;
4778
	gotiomode = -1;
4779
	nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL);
4817
	nfscl_reqstart(nd, NFSPROC_LAYOUTGET, nmp, fhp, fhlen, NULL, NULL);
4780
	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
4818
	nfsrv_setuplayoutget(nd, iomode, offset, len, minlen, stateidp,
4781
	    NFSX_STATEID);
4819
	    layoutlen, 0);
4782
	*tl++ = newnfs_false;		/* Don't signal availability. */
4783
	*tl++ = txdr_unsigned(NFSLAYOUT_NFSV4_1_FILES);
4784
	*tl++ = txdr_unsigned(iomode);
4785
	txdr_hyper(offset, tl);
4786
	tl += 2;
4787
	txdr_hyper(len, tl);
4788
	tl += 2;
4789
	txdr_hyper(minlen, tl);
4790
	tl += 2;
4791
	*tl++ = txdr_unsigned(stateidp->seqid);
4792
	NFSCL_DEBUG(4, "layget seq=%d\n", (int)stateidp->seqid);
4793
	*tl++ = stateidp->other[0];
4794
	*tl++ = stateidp->other[1];
4795
	*tl++ = stateidp->other[2];
4796
	*tl = txdr_unsigned(layoutlen);
4797
	nd->nd_flag |= ND_USEGSSNAME;
4820
	nd->nd_flag |= ND_USEGSSNAME;
4798
	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
4821
	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, NULL, p, cred,
4799
	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
4822
	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
4823
	NFSCL_DEBUG(4, "layget err=%d st=%d\n", error, nd->nd_repstat);
4800
	if (error != 0)
4824
	if (error != 0)
4801
		return (error);
4825
		return (error);
4802
	if (nd->nd_repstat == 0) {
4826
	if (nd->nd_repstat == 0)
4803
		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_STATEID);
4827
		error = nfsrv_parselayoutget(nd, stateidp, retonclosep, flhp);
4804
		if (*tl++ != 0)
4828
	if (error == 0 && nd->nd_repstat != 0)
4805
			*retonclosep = 1;
4806
		else
4807
			*retonclosep = 0;
4808
		stateidp->seqid = fxdr_unsigned(uint32_t, *tl++);
4809
		NFSCL_DEBUG(4, "retoncls=%d stseq=%d\n", *retonclosep,
4810
		    (int)stateidp->seqid);
4811
		stateidp->other[0] = *tl++;
4812
		stateidp->other[1] = *tl++;
4813
		stateidp->other[2] = *tl++;
4814
		cnt = fxdr_unsigned(int, *tl);
4815
		NFSCL_DEBUG(4, "layg cnt=%d\n", cnt);
4816
		if (cnt <= 0 || cnt > 10000) {
4817
			/* Don't accept more than 10000 layouts in reply. */
4818
			error = NFSERR_BADXDR;
4819
			goto nfsmout;
4820
		}
4821
		for (i = 0; i < cnt; i++) {
4822
			/* Dissect all the way to the file handle cnt. */
4823
			NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_HYPER +
4824
			    6 * NFSX_UNSIGNED + NFSX_V4DEVICEID);
4825
			fhcnt = fxdr_unsigned(int, *(tl + 11 +
4826
			    NFSX_V4DEVICEID / NFSX_UNSIGNED));
4827
			NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt);
4828
			if (fhcnt < 0 || fhcnt > 100) {
4829
				/* Don't accept more than 100 file handles. */
4830
				error = NFSERR_BADXDR;
4831
				goto nfsmout;
4832
			}
4833
			if (fhcnt > 1)
4834
				flp = malloc(sizeof(*flp) + (fhcnt - 1) *
4835
				    sizeof(struct nfsfh *),
4836
				    M_NFSFLAYOUT, M_WAITOK);
4837
			else
4838
				flp = malloc(sizeof(*flp),
4839
				    M_NFSFLAYOUT, M_WAITOK);
4840
			flp->nfsfl_flags = 0;
4841
			flp->nfsfl_fhcnt = 0;
4842
			flp->nfsfl_devp = NULL;
4843
			flp->nfsfl_off = fxdr_hyper(tl); tl += 2;
4844
			retlen = fxdr_hyper(tl); tl += 2;
4845
			if (flp->nfsfl_off + retlen < flp->nfsfl_off)
4846
				flp->nfsfl_end = UINT64_MAX - flp->nfsfl_off;
4847
			else
4848
				flp->nfsfl_end = flp->nfsfl_off + retlen;
4849
			flp->nfsfl_iomode = fxdr_unsigned(int, *tl++);
4850
			if (gotiomode == -1)
4851
				gotiomode = flp->nfsfl_iomode;
4852
			NFSCL_DEBUG(4, "layg reqiom=%d retiom=%d\n", iomode,
4853
			    (int)flp->nfsfl_iomode);
4854
			if (fxdr_unsigned(int, *tl++) !=
4855
			    NFSLAYOUT_NFSV4_1_FILES) {
4856
				printf("NFSv4.1: got non-files layout\n");
4857
				error = NFSERR_BADXDR;
4858
				goto nfsmout;
4859
			}
4860
			NFSBCOPY(++tl, flp->nfsfl_dev, NFSX_V4DEVICEID);
4861
			tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
4862
			flp->nfsfl_util = fxdr_unsigned(uint32_t, *tl++);
4863
			NFSCL_DEBUG(4, "flutil=0x%x\n", flp->nfsfl_util);
4864
			flp->nfsfl_stripe1 = fxdr_unsigned(uint32_t, *tl++);
4865
			flp->nfsfl_patoff = fxdr_hyper(tl); tl += 2;
4866
			if (fxdr_unsigned(int, *tl) != fhcnt) {
4867
				printf("EEK! bad fhcnt\n");
4868
				error = NFSERR_BADXDR;
4869
				goto nfsmout;
4870
			}
4871
			for (j = 0; j < fhcnt; j++) {
4872
				NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
4873
				nfhlen = fxdr_unsigned(int, *tl);
4874
				if (nfhlen <= 0 || nfhlen > NFSX_V4FHMAX) {
4875
					error = NFSERR_BADXDR;
4876
					goto nfsmout;
4877
				}
4878
				nfhp = malloc(sizeof(*nfhp) + nfhlen - 1,
4879
				    M_NFSFH, M_WAITOK);
4880
				flp->nfsfl_fh[j] = nfhp;
4881
				flp->nfsfl_fhcnt++;
4882
				nfhp->nfh_len = nfhlen;
4883
				NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(nfhlen));
4884
				NFSBCOPY(cp, nfhp->nfh_fh, nfhlen);
4885
			}
4886
			if (flp->nfsfl_iomode == gotiomode) {
4887
				/* Keep the list in increasing offset order. */
4888
				tflp = LIST_FIRST(flhp);
4889
				prevflp = NULL;
4890
				while (tflp != NULL &&
4891
				    tflp->nfsfl_off < flp->nfsfl_off) {
4892
					prevflp = tflp;
4893
					tflp = LIST_NEXT(tflp, nfsfl_list);
4894
				}
4895
				if (prevflp == NULL)
4896
					LIST_INSERT_HEAD(flhp, flp, nfsfl_list);
4897
				else
4898
					LIST_INSERT_AFTER(prevflp, flp,
4899
					    nfsfl_list);
4900
			} else {
4901
				printf("nfscl_layoutget(): got wrong iomode\n");
4902
				nfscl_freeflayout(flp);
4903
			}
4904
			flp = NULL;
4905
		}
4906
	}
4907
	if (nd->nd_repstat != 0 && error == 0)
4908
		error = nd->nd_repstat;
4829
		error = nd->nd_repstat;
4909
nfsmout:
4910
	if (error != 0 && flp != NULL)
4911
		nfscl_freeflayout(flp);
4912
	mbuf_freem(nd->nd_mrep);
4830
	mbuf_freem(nd->nd_mrep);
4913
	return (error);
4831
	return (error);
4914
}
4832
}
Lines 5209-5216 nfsrpc_getlayout(struct nfsmount *nmp, v Link Here
5209
    struct nfscllayout **lypp, struct ucred *cred, NFSPROC_T *p)
5127
    struct nfscllayout **lypp, struct ucred *cred, NFSPROC_T *p)
5210
{
5128
{
5211
	struct nfscllayout *lyp;
5129
	struct nfscllayout *lyp;
5212
	struct nfsclflayout *flp, *tflp;
5130
	struct nfsclflayout *flp;
5213
	struct nfscldevinfo *dip;
5214
	struct nfsclflayouthead flh;
5131
	struct nfsclflayouthead flh;
5215
	int error = 0, islocked, layoutlen, recalled, retonclose;
5132
	int error = 0, islocked, layoutlen, recalled, retonclose;
5216
	nfsv4stateid_t stateid;
5133
	nfsv4stateid_t stateid;
Lines 5252-5286 nfsrpc_getlayout(struct nfsmount *nmp, v Link Here
5252
			    (uint64_t)0, layoutlen, &stateid, &retonclose,
5169
			    (uint64_t)0, layoutlen, &stateid, &retonclose,
5253
			    &flh, cred, p, NULL);
5170
			    &flh, cred, p, NULL);
5254
		}
5171
		}
5172
		error = nfsrpc_layoutgetres(nmp, vp, nfhp->nfh_fh,
5173
		    nfhp->nfh_len, &stateid, retonclose, notifybitsp, &lyp,
5174
		    &flh, error, NULL, cred, p);
5255
		if (error == 0)
5175
		if (error == 0)
5256
			LIST_FOREACH(tflp, &flh, nfsfl_list) {
5176
			*lypp = lyp;
5257
				error = nfscl_adddevinfo(nmp, NULL, tflp);
5177
		else if (islocked != 0)
5258
				if (error != 0) {
5178
			nfscl_rellayout(lyp, 1);
5259
					error = nfsrpc_getdeviceinfo(nmp,
5260
					    tflp->nfsfl_dev,
5261
					    NFSLAYOUT_NFSV4_1_FILES,
5262
					    notifybitsp, &dip, cred, p);
5263
					if (error != 0)
5264
						break;
5265
					error = nfscl_adddevinfo(nmp, dip,
5266
					    tflp);
5267
					if (error != 0)
5268
						printf(
5269
						    "getlayout: cannot add\n");
5270
				}
5271
			}
5272
		if (error == 0) {
5273
			/*
5274
			 * nfscl_layout() always returns with the nfsly_lock
5275
			 * set to a refcnt (shared lock).
5276
			 */
5277
			error = nfscl_layout(nmp, vp, nfhp->nfh_fh,
5278
			    nfhp->nfh_len, &stateid, retonclose, &flh, &lyp,
5279
			    cred, p);
5280
			if (error == 0)
5281
				*lypp = lyp;
5282
		} else if (islocked != 0)
5283
			nfsv4_unlock(&lyp->nfsly_lock, 0);
5284
	} else
5179
	} else
5285
		*lypp = lyp;
5180
		*lypp = lyp;
5286
	return (error);
5181
	return (error);
Lines 6003-6005 nfsmout: Link Here
6003
}
5898
}
6004
#endif
5899
#endif
6005
5900
5901
/*
5902
 * Set up the XDR arguments for the LayoutGet operation.
5903
 */
5904
static void
5905
nfsrv_setuplayoutget(struct nfsrv_descript *nd, int iomode, uint64_t offset,
5906
    uint64_t len, uint64_t minlen, nfsv4stateid_t *stateidp, int layoutlen,
5907
    int usecurstateid)
5908
{
5909
	uint32_t *tl;
5910
5911
	NFSM_BUILD(tl, uint32_t *, 4 * NFSX_UNSIGNED + 3 * NFSX_HYPER +
5912
	    NFSX_STATEID);
5913
	*tl++ = newnfs_false;		/* Don't signal availability. */
5914
	*tl++ = txdr_unsigned(NFSLAYOUT_NFSV4_1_FILES);
5915
	*tl++ = txdr_unsigned(iomode);
5916
	txdr_hyper(offset, tl);
5917
	tl += 2;
5918
	txdr_hyper(len, tl);
5919
	tl += 2;
5920
	txdr_hyper(minlen, tl);
5921
	tl += 2;
5922
	if (usecurstateid != 0) {
5923
		/* Special stateid for Current stateid. */
5924
		*tl++ = txdr_unsigned(1);
5925
		*tl++ = 0;
5926
		*tl++ = 0;
5927
		*tl++ = 0;
5928
	} else {
5929
		*tl++ = txdr_unsigned(stateidp->seqid);
5930
		NFSCL_DEBUG(4, "layget seq=%d\n", (int)stateidp->seqid);
5931
		*tl++ = stateidp->other[0];
5932
		*tl++ = stateidp->other[1];
5933
		*tl++ = stateidp->other[2];
5934
	}
5935
	*tl = txdr_unsigned(layoutlen);
5936
}
5937
5938
/*
5939
 * Parse the reply for a successful LayoutGet operation.
5940
 */
5941
static int
5942
nfsrv_parselayoutget(struct nfsrv_descript *nd, nfsv4stateid_t *stateidp,
5943
    int *retonclosep, struct nfsclflayouthead *flhp)
5944
{
5945
	uint32_t *tl;
5946
	struct nfsclflayout *flp, *prevflp, *tflp;
5947
	int cnt, error, gotiomode, fhcnt, nfhlen, i, j;
5948
	uint64_t retlen;
5949
	struct nfsfh *nfhp;
5950
	uint8_t *cp;
5951
5952
	error = 0;
5953
	flp = NULL;
5954
	gotiomode = -1;
5955
	NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED + NFSX_STATEID);
5956
	if (*tl++ != 0)
5957
		*retonclosep = 1;
5958
	else
5959
		*retonclosep = 0;
5960
	stateidp->seqid = fxdr_unsigned(uint32_t, *tl++);
5961
	NFSCL_DEBUG(4, "retoncls=%d stseq=%d\n", *retonclosep,
5962
	    (int)stateidp->seqid);
5963
	stateidp->other[0] = *tl++;
5964
	stateidp->other[1] = *tl++;
5965
	stateidp->other[2] = *tl++;
5966
	cnt = fxdr_unsigned(int, *tl);
5967
	NFSCL_DEBUG(4, "layg cnt=%d\n", cnt);
5968
	if (cnt <= 0 || cnt > 10000) {
5969
		/* Don't accept more than 10000 layouts in reply. */
5970
		error = NFSERR_BADXDR;
5971
		goto nfsmout;
5972
	}
5973
	for (i = 0; i < cnt; i++) {
5974
		/* Dissect all the way to the file handle cnt. */
5975
		NFSM_DISSECT(tl, uint32_t *, 3 * NFSX_HYPER +
5976
		    6 * NFSX_UNSIGNED + NFSX_V4DEVICEID);
5977
		fhcnt = fxdr_unsigned(int, *(tl + 11 +
5978
		    NFSX_V4DEVICEID / NFSX_UNSIGNED));
5979
		NFSCL_DEBUG(4, "fhcnt=%d\n", fhcnt);
5980
		if (fhcnt < 0 || fhcnt > 100) {
5981
			/* Don't accept more than 100 file handles. */
5982
			error = NFSERR_BADXDR;
5983
			goto nfsmout;
5984
		}
5985
		if (fhcnt > 1)
5986
			flp = malloc(sizeof(*flp) + (fhcnt - 1) *
5987
			    sizeof(struct nfsfh *), M_NFSFLAYOUT, M_WAITOK);
5988
		else
5989
			flp = malloc(sizeof(*flp), M_NFSFLAYOUT, M_WAITOK);
5990
		flp->nfsfl_flags = 0;
5991
		flp->nfsfl_fhcnt = 0;
5992
		flp->nfsfl_devp = NULL;
5993
		flp->nfsfl_off = fxdr_hyper(tl); tl += 2;
5994
		retlen = fxdr_hyper(tl); tl += 2;
5995
		if (flp->nfsfl_off + retlen < flp->nfsfl_off)
5996
			flp->nfsfl_end = UINT64_MAX - flp->nfsfl_off;
5997
		else
5998
			flp->nfsfl_end = flp->nfsfl_off + retlen;
5999
		flp->nfsfl_iomode = fxdr_unsigned(int, *tl++);
6000
		if (gotiomode == -1)
6001
			gotiomode = flp->nfsfl_iomode;
6002
		if (fxdr_unsigned(int, *tl++) != NFSLAYOUT_NFSV4_1_FILES) {
6003
			printf("NFSv4.1: got non-files layout\n");
6004
			error = NFSERR_BADXDR;
6005
			goto nfsmout;
6006
		}
6007
		NFSBCOPY(++tl, flp->nfsfl_dev, NFSX_V4DEVICEID);
6008
		tl += (NFSX_V4DEVICEID / NFSX_UNSIGNED);
6009
		flp->nfsfl_util = fxdr_unsigned(uint32_t, *tl++);
6010
		NFSCL_DEBUG(4, "flutil=0x%x\n", flp->nfsfl_util);
6011
		flp->nfsfl_stripe1 = fxdr_unsigned(uint32_t, *tl++);
6012
		flp->nfsfl_patoff = fxdr_hyper(tl); tl += 2;
6013
		if (fxdr_unsigned(int, *tl) != fhcnt) {
6014
			printf("EEK! bad fhcnt\n");
6015
			error = NFSERR_BADXDR;
6016
			goto nfsmout;
6017
		}
6018
		for (j = 0; j < fhcnt; j++) {
6019
			NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
6020
			nfhlen = fxdr_unsigned(int, *tl);
6021
			if (nfhlen <= 0 || nfhlen > NFSX_V4FHMAX) {
6022
				error = NFSERR_BADXDR;
6023
				goto nfsmout;
6024
			}
6025
			nfhp = malloc(sizeof(*nfhp) + nfhlen - 1, M_NFSFH,
6026
			    M_WAITOK);
6027
			flp->nfsfl_fh[j] = nfhp;
6028
			flp->nfsfl_fhcnt++;
6029
			nfhp->nfh_len = nfhlen;
6030
			NFSM_DISSECT(cp, uint8_t *, NFSM_RNDUP(nfhlen));
6031
			NFSBCOPY(cp, nfhp->nfh_fh, nfhlen);
6032
		}
6033
		if (flp->nfsfl_iomode == gotiomode) {
6034
			/* Keep the list in increasing offset order. */
6035
			tflp = LIST_FIRST(flhp);
6036
			prevflp = NULL;
6037
			while (tflp != NULL &&
6038
			    tflp->nfsfl_off < flp->nfsfl_off) {
6039
				prevflp = tflp;
6040
				tflp = LIST_NEXT(tflp, nfsfl_list);
6041
			}
6042
			if (prevflp == NULL)
6043
				LIST_INSERT_HEAD(flhp, flp, nfsfl_list);
6044
			else
6045
				LIST_INSERT_AFTER(prevflp, flp,
6046
				    nfsfl_list);
6047
		} else {
6048
			printf("nfscl_layoutget(): got wrong iomode\n");
6049
			nfscl_freeflayout(flp);
6050
		}
6051
		flp = NULL;
6052
	}
6053
nfsmout:
6054
	if (error != 0 && flp != NULL)
6055
		nfscl_freeflayout(flp);
6056
	return (error);
6057
}
6058
6059
/*
6060
 * Similar to nfsrpc_getlayout(), except that it uses nfsrpc_openlayget(),
6061
 * so that it does both an Open and a Layoutget.
6062
 */
6063
static int
6064
nfsrpc_getopenlayout(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp,
6065
    int fhlen, uint8_t *newfhp, int newfhlen, uint32_t mode,
6066
    struct nfsclopen *op, uint8_t *name, int namelen, struct nfscldeleg **dpp,
6067
    struct ucred *cred, NFSPROC_T *p)
6068
{
6069
	struct nfscllayout *lyp;
6070
	struct nfsclflayout *flp;
6071
	struct nfsclflayouthead flh;
6072
	int error, islocked, layoutlen, recalled, retonclose, usecurstateid;
6073
	int laystat;
6074
	nfsv4stateid_t stateid;
6075
	struct nfsclsession *tsep;
6076
6077
	error = 0;
6078
	/*
6079
	 * If lyp is returned non-NULL, there will be a refcnt (shared lock)
6080
	 * on it, iff flp != NULL or a lock (exclusive lock) on it iff
6081
	 * flp == NULL.
6082
	 */
6083
	lyp = nfscl_getlayout(nmp->nm_clp, newfhp, newfhlen, 0, &flp,
6084
	    &recalled);
6085
	NFSCL_DEBUG(4, "nfsrpc_getopenlayout nfscl_getlayout lyp=%p\n", lyp);
6086
	if (lyp == NULL)
6087
		islocked = 0;
6088
	else if (flp != NULL)
6089
		islocked = 1;
6090
	else
6091
		islocked = 2;
6092
	if ((lyp == NULL || flp == NULL) && recalled == 0) {
6093
		LIST_INIT(&flh);
6094
		tsep = nfsmnt_mdssession(nmp);
6095
		layoutlen = tsep->nfsess_maxcache - (NFSX_STATEID +
6096
		    3 * NFSX_UNSIGNED);
6097
		if (lyp == NULL)
6098
			usecurstateid = 1;
6099
		else {
6100
			usecurstateid = 0;
6101
			stateid.seqid = lyp->nfsly_stateid.seqid;
6102
			stateid.other[0] = lyp->nfsly_stateid.other[0];
6103
			stateid.other[1] = lyp->nfsly_stateid.other[1];
6104
			stateid.other[2] = lyp->nfsly_stateid.other[2];
6105
		}
6106
		error = nfsrpc_openlayoutrpc(nmp, vp, nfhp, fhlen,
6107
		    newfhp, newfhlen, mode, op, name, namelen,
6108
		    dpp, &stateid, usecurstateid, layoutlen,
6109
		    &retonclose, &flh, &laystat, cred, p);
6110
		NFSCL_DEBUG(4, "aft nfsrpc_openlayoutrpc laystat=%d err=%d\n",
6111
		    laystat, error);
6112
		laystat = nfsrpc_layoutgetres(nmp, vp, newfhp, newfhlen,
6113
		    &stateid, retonclose, NULL, &lyp, &flh, laystat, &islocked,
6114
		    cred, p);
6115
	} else
6116
		error = nfsrpc_openrpc(nmp, vp, nfhp, fhlen, newfhp, newfhlen,
6117
		    mode, op, name, namelen, dpp, 0, 0, cred, p, 0, 0);
6118
	if (islocked == 2)
6119
		nfscl_rellayout(lyp, 1);
6120
	else if (islocked == 1)
6121
		nfscl_rellayout(lyp, 0);
6122
	return (error);
6123
}
6124
6125
/*
6126
 * This function does an Open+LayoutGet for an NFSv4.1 mount with pNFS
6127
 * enabled, only for the CLAIM_NULL case.  All other NFSv4 Opens are
6128
 * handled by nfsrpc_openrpc().
6129
 * For the case where op == NULL, dvp is the directory.  When op != NULL, it
6130
 * can be NULL.
6131
 */
6132
static int
6133
nfsrpc_openlayoutrpc(struct nfsmount *nmp, vnode_t vp, u_int8_t *nfhp,
6134
    int fhlen, uint8_t *newfhp, int newfhlen, uint32_t mode,
6135
    struct nfsclopen *op, uint8_t *name, int namelen, struct nfscldeleg **dpp,
6136
    nfsv4stateid_t *stateidp, int usecurstateid,
6137
    int layoutlen, int *retonclosep, struct nfsclflayouthead *flhp,
6138
    int *laystatp, struct ucred *cred, NFSPROC_T *p)
6139
{
6140
	uint32_t *tl;
6141
	struct nfsrv_descript nfsd, *nd = &nfsd;
6142
	struct nfscldeleg *ndp = NULL;
6143
	struct nfsvattr nfsva;
6144
	struct nfsclsession *tsep;
6145
	uint32_t rflags, deleg;
6146
	nfsattrbit_t attrbits;
6147
	int error, ret, acesize, limitby, iomode;
6148
6149
	*dpp = NULL;
6150
	*laystatp = ENXIO;
6151
	nfscl_reqstart(nd, NFSPROC_OPENLAYGET, nmp, nfhp, fhlen, NULL, NULL);
6152
	NFSM_BUILD(tl, uint32_t *, 5 * NFSX_UNSIGNED);
6153
	*tl++ = txdr_unsigned(op->nfso_own->nfsow_seqid);
6154
	*tl++ = txdr_unsigned(mode & NFSV4OPEN_ACCESSBOTH);
6155
	*tl++ = txdr_unsigned((mode >> NFSLCK_SHIFT) & NFSV4OPEN_DENYBOTH);
6156
	tsep = nfsmnt_mdssession(nmp);
6157
	*tl++ = tsep->nfsess_clientid.lval[0];
6158
	*tl = tsep->nfsess_clientid.lval[1];
6159
	nfsm_strtom(nd, op->nfso_own->nfsow_owner, NFSV4CL_LOCKNAMELEN);
6160
	NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
6161
	*tl++ = txdr_unsigned(NFSV4OPEN_NOCREATE);
6162
	*tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
6163
	nfsm_strtom(nd, name, namelen);
6164
	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
6165
	*tl = txdr_unsigned(NFSV4OP_GETATTR);
6166
	NFSZERO_ATTRBIT(&attrbits);
6167
	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_CHANGE);
6168
	NFSSETBIT_ATTRBIT(&attrbits, NFSATTRBIT_TIMEMODIFY);
6169
	nfsrv_putattrbit(nd, &attrbits);
6170
	NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
6171
	*tl = txdr_unsigned(NFSV4OP_LAYOUTGET);
6172
	if ((mode & NFSV4OPEN_ACCESSWRITE) != 0)
6173
		iomode = NFSLAYOUTIOMODE_RW;
6174
	else
6175
		iomode = NFSLAYOUTIOMODE_READ;
6176
	nfsrv_setuplayoutget(nd, iomode, 0, UINT64_MAX, 0, stateidp,
6177
	    layoutlen, usecurstateid);
6178
	error = newnfs_request(nd, nmp, NULL, &nmp->nm_sockreq, vp, p, cred,
6179
	    NFS_PROG, NFS_VER4, NULL, 1, NULL, NULL);
6180
	if (error != 0)
6181
		return (error);
6182
	NFSCL_INCRSEQID(op->nfso_own->nfsow_seqid, nd);
6183
	if (nd->nd_repstat != 0)
6184
		*laystatp = nd->nd_repstat;
6185
	if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
6186
		/* ND_NOMOREDATA will be set if the Open operation failed. */
6187
		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
6188
		    6 * NFSX_UNSIGNED);
6189
		op->nfso_stateid.seqid = *tl++;
6190
		op->nfso_stateid.other[0] = *tl++;
6191
		op->nfso_stateid.other[1] = *tl++;
6192
		op->nfso_stateid.other[2] = *tl;
6193
		rflags = fxdr_unsigned(u_int32_t, *(tl + 6));
6194
		error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
6195
		if (error != 0)
6196
			goto nfsmout;
6197
		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
6198
		deleg = fxdr_unsigned(u_int32_t, *tl);
6199
		if (deleg == NFSV4OPEN_DELEGATEREAD ||
6200
		    deleg == NFSV4OPEN_DELEGATEWRITE) {
6201
			if (!(op->nfso_own->nfsow_clp->nfsc_flags &
6202
			      NFSCLFLAGS_FIRSTDELEG))
6203
				op->nfso_own->nfsow_clp->nfsc_flags |=
6204
				  (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
6205
			ndp = malloc(sizeof(struct nfscldeleg) + newfhlen,
6206
			    M_NFSCLDELEG, M_WAITOK);
6207
			LIST_INIT(&ndp->nfsdl_owner);
6208
			LIST_INIT(&ndp->nfsdl_lock);
6209
			ndp->nfsdl_clp = op->nfso_own->nfsow_clp;
6210
			ndp->nfsdl_fhlen = newfhlen;
6211
			NFSBCOPY(newfhp, ndp->nfsdl_fh, newfhlen);
6212
			newnfs_copyincred(cred, &ndp->nfsdl_cred);
6213
			nfscl_lockinit(&ndp->nfsdl_rwlock);
6214
			NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
6215
			    NFSX_UNSIGNED);
6216
			ndp->nfsdl_stateid.seqid = *tl++;
6217
			ndp->nfsdl_stateid.other[0] = *tl++;
6218
			ndp->nfsdl_stateid.other[1] = *tl++;
6219
			ndp->nfsdl_stateid.other[2] = *tl++;
6220
			ret = fxdr_unsigned(int, *tl);
6221
			if (deleg == NFSV4OPEN_DELEGATEWRITE) {
6222
				ndp->nfsdl_flags = NFSCLDL_WRITE;
6223
				/*
6224
				 * Indicates how much the file can grow.
6225
				 */
6226
				NFSM_DISSECT(tl, u_int32_t *,
6227
				    3 * NFSX_UNSIGNED);
6228
				limitby = fxdr_unsigned(int, *tl++);
6229
				switch (limitby) {
6230
				case NFSV4OPEN_LIMITSIZE:
6231
					ndp->nfsdl_sizelimit = fxdr_hyper(tl);
6232
					break;
6233
				case NFSV4OPEN_LIMITBLOCKS:
6234
					ndp->nfsdl_sizelimit =
6235
					    fxdr_unsigned(u_int64_t, *tl++);
6236
					ndp->nfsdl_sizelimit *=
6237
					    fxdr_unsigned(u_int64_t, *tl);
6238
					break;
6239
				default:
6240
					error = NFSERR_BADXDR;
6241
					goto nfsmout;
6242
				};
6243
			} else
6244
				ndp->nfsdl_flags = NFSCLDL_READ;
6245
			if (ret != 0)
6246
				ndp->nfsdl_flags |= NFSCLDL_RECALL;
6247
			error = nfsrv_dissectace(nd, &ndp->nfsdl_ace, &ret,
6248
			    &acesize, p);
6249
			if (error != 0)
6250
				goto nfsmout;
6251
		} else if (deleg != NFSV4OPEN_DELEGATENONE) {
6252
			error = NFSERR_BADXDR;
6253
			goto nfsmout;
6254
		}
6255
		if ((rflags & NFSV4OPEN_LOCKTYPEPOSIX) != 0 ||
6256
		    nfscl_assumeposixlocks)
6257
			op->nfso_posixlock = 1;
6258
		else
6259
			op->nfso_posixlock = 0;
6260
		NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
6261
		/* If the 2nd element == NFS_OK, the Getattr succeeded. */
6262
		if (*++tl == 0) {
6263
			error = nfsv4_loadattr(nd, NULL, &nfsva, NULL,
6264
			    NULL, 0, NULL, NULL, NULL, NULL, NULL, 0,
6265
			    NULL, NULL, NULL, p, cred);
6266
			if (error != 0)
6267
				goto nfsmout;
6268
			if (ndp != NULL) {
6269
				ndp->nfsdl_change = nfsva.na_filerev;
6270
				ndp->nfsdl_modtime = nfsva.na_mtime;
6271
				ndp->nfsdl_flags |= NFSCLDL_MODTIMESET;
6272
				*dpp = ndp;
6273
				ndp = NULL;
6274
			}
6275
			/*
6276
			 * At this point, the Open has succeeded, so set
6277
			 * nd_repstat = NFS_OK.  If the Layoutget failed,
6278
			 * this function just won't return a layout.
6279
			 */
6280
			if (nd->nd_repstat == 0) {
6281
				NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
6282
				*laystatp = fxdr_unsigned(int, *++tl);
6283
				if (*laystatp == 0) {
6284
					error = nfsrv_parselayoutget(nd,
6285
					    stateidp, retonclosep, flhp);
6286
					if (error != 0)
6287
						*laystatp = error;
6288
				}
6289
			} else
6290
				nd->nd_repstat = 0;	/* Return 0 for Open. */
6291
		}
6292
	}
6293
	if (nd->nd_repstat != 0 && error == 0)
6294
		error = nd->nd_repstat;
6295
nfsmout:
6296
	free(ndp, M_NFSCLDELEG);
6297
	mbuf_freem(nd->nd_mrep);
6298
	return (error);
6299
}
6300
6301
/*
6302
 * Similar nfsrpc_createv4(), but also does the LayoutGet operation.
6303
 * Used only for mounts with pNFS enabled.
6304
 */
6305
static int
6306
nfsrpc_createlayout(vnode_t dvp, char *name, int namelen, struct vattr *vap,
6307
    nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp,
6308
    struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
6309
    struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
6310
    int *dattrflagp, void *dstuff, int *unlockedp, nfsv4stateid_t *stateidp,
6311
    int usecurstateid, int layoutlen, int *retonclosep,
6312
    struct nfsclflayouthead *flhp, int *laystatp)
6313
{
6314
	uint32_t *tl;
6315
	int error = 0, deleg, newone, ret, acesize, limitby;
6316
	struct nfsrv_descript nfsd, *nd = &nfsd;
6317
	struct nfsclopen *op;
6318
	struct nfscldeleg *dp = NULL;
6319
	struct nfsnode *np;
6320
	struct nfsfh *nfhp;
6321
	struct nfsclsession *tsep;
6322
	nfsattrbit_t attrbits;
6323
	nfsv4stateid_t stateid;
6324
	uint32_t rflags;
6325
	struct nfsmount *nmp;
6326
6327
	nmp = VFSTONFS(dvp->v_mount);
6328
	np = VTONFS(dvp);
6329
	*laystatp = ENXIO;
6330
	*unlockedp = 0;
6331
	*nfhpp = NULL;
6332
	*dpp = NULL;
6333
	*attrflagp = 0;
6334
	*dattrflagp = 0;
6335
	if (namelen > NFS_MAXNAMLEN)
6336
		return (ENAMETOOLONG);
6337
	NFSCL_REQSTART(nd, NFSPROC_CREATELAYGET, dvp);
6338
	/*
6339
	 * For V4, this is actually an Open op.
6340
	 */
6341
	NFSM_BUILD(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
6342
	*tl++ = txdr_unsigned(owp->nfsow_seqid);
6343
	*tl++ = txdr_unsigned(NFSV4OPEN_ACCESSWRITE |
6344
	    NFSV4OPEN_ACCESSREAD);
6345
	*tl++ = txdr_unsigned(NFSV4OPEN_DENYNONE);
6346
	tsep = nfsmnt_mdssession(nmp);
6347
	*tl++ = tsep->nfsess_clientid.lval[0];
6348
	*tl = tsep->nfsess_clientid.lval[1];
6349
	nfsm_strtom(nd, owp->nfsow_owner, NFSV4CL_LOCKNAMELEN);
6350
	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
6351
	*tl++ = txdr_unsigned(NFSV4OPEN_CREATE);
6352
	if ((fmode & O_EXCL) != 0) {
6353
		if (NFSHASSESSPERSIST(nmp)) {
6354
			/* Use GUARDED for persistent sessions. */
6355
			*tl = txdr_unsigned(NFSCREATE_GUARDED);
6356
			nfscl_fillsattr(nd, vap, dvp, 0, 0);
6357
		} else {
6358
			/* Otherwise, use EXCLUSIVE4_1. */
6359
			*tl = txdr_unsigned(NFSCREATE_EXCLUSIVE41);
6360
			NFSM_BUILD(tl, u_int32_t *, NFSX_VERF);
6361
			*tl++ = cverf.lval[0];
6362
			*tl = cverf.lval[1];
6363
			nfscl_fillsattr(nd, vap, dvp, 0, 0);
6364
		}
6365
	} else {
6366
		*tl = txdr_unsigned(NFSCREATE_UNCHECKED);
6367
		nfscl_fillsattr(nd, vap, dvp, 0, 0);
6368
	}
6369
	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
6370
	*tl = txdr_unsigned(NFSV4OPEN_CLAIMNULL);
6371
	nfsm_strtom(nd, name, namelen);
6372
	/* Get the new file's handle and attributes, plus save the FH. */
6373
	NFSM_BUILD(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
6374
	*tl++ = txdr_unsigned(NFSV4OP_SAVEFH);
6375
	*tl++ = txdr_unsigned(NFSV4OP_GETFH);
6376
	*tl = txdr_unsigned(NFSV4OP_GETATTR);
6377
	NFSGETATTR_ATTRBIT(&attrbits);
6378
	nfsrv_putattrbit(nd, &attrbits);
6379
	/* Get the directory's post-op attributes. */
6380
	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
6381
	*tl = txdr_unsigned(NFSV4OP_PUTFH);
6382
	nfsm_fhtom(nd, np->n_fhp->nfh_fh, np->n_fhp->nfh_len, 0);
6383
	NFSM_BUILD(tl, u_int32_t *, NFSX_UNSIGNED);
6384
	*tl = txdr_unsigned(NFSV4OP_GETATTR);
6385
	nfsrv_putattrbit(nd, &attrbits);
6386
	NFSM_BUILD(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
6387
	*tl++ = txdr_unsigned(NFSV4OP_RESTOREFH);
6388
	*tl = txdr_unsigned(NFSV4OP_LAYOUTGET);
6389
	nfsrv_setuplayoutget(nd, NFSLAYOUTIOMODE_RW, 0, UINT64_MAX, 0, stateidp,
6390
	    layoutlen, usecurstateid);
6391
	error = nfscl_request(nd, dvp, p, cred, dstuff);
6392
	if (error != 0)
6393
		return (error);
6394
	NFSCL_DEBUG(4, "nfsrpc_createlayout stat=%d err=%d\n", nd->nd_repstat,
6395
	    error);
6396
	if (nd->nd_repstat != 0)
6397
		*laystatp = nd->nd_repstat;
6398
	NFSCL_INCRSEQID(owp->nfsow_seqid, nd);
6399
	if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
6400
		NFSCL_DEBUG(4, "nfsrpc_createlayout open succeeded\n");
6401
		NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
6402
		    6 * NFSX_UNSIGNED);
6403
		stateid.seqid = *tl++;
6404
		stateid.other[0] = *tl++;
6405
		stateid.other[1] = *tl++;
6406
		stateid.other[2] = *tl;
6407
		rflags = fxdr_unsigned(u_int32_t, *(tl + 6));
6408
		nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
6409
		NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
6410
		deleg = fxdr_unsigned(int, *tl);
6411
		if (deleg == NFSV4OPEN_DELEGATEREAD ||
6412
		    deleg == NFSV4OPEN_DELEGATEWRITE) {
6413
			if (!(owp->nfsow_clp->nfsc_flags &
6414
			      NFSCLFLAGS_FIRSTDELEG))
6415
				owp->nfsow_clp->nfsc_flags |=
6416
				  (NFSCLFLAGS_FIRSTDELEG | NFSCLFLAGS_GOTDELEG);
6417
			dp = malloc(sizeof(struct nfscldeleg) + NFSX_V4FHMAX,
6418
			    M_NFSCLDELEG, M_WAITOK);
6419
			LIST_INIT(&dp->nfsdl_owner);
6420
			LIST_INIT(&dp->nfsdl_lock);
6421
			dp->nfsdl_clp = owp->nfsow_clp;
6422
			newnfs_copyincred(cred, &dp->nfsdl_cred);
6423
			nfscl_lockinit(&dp->nfsdl_rwlock);
6424
			NFSM_DISSECT(tl, u_int32_t *, NFSX_STATEID +
6425
			    NFSX_UNSIGNED);
6426
			dp->nfsdl_stateid.seqid = *tl++;
6427
			dp->nfsdl_stateid.other[0] = *tl++;
6428
			dp->nfsdl_stateid.other[1] = *tl++;
6429
			dp->nfsdl_stateid.other[2] = *tl++;
6430
			ret = fxdr_unsigned(int, *tl);
6431
			if (deleg == NFSV4OPEN_DELEGATEWRITE) {
6432
				dp->nfsdl_flags = NFSCLDL_WRITE;
6433
				/*
6434
				 * Indicates how much the file can grow.
6435
				 */
6436
				NFSM_DISSECT(tl, u_int32_t *,
6437
				    3 * NFSX_UNSIGNED);
6438
				limitby = fxdr_unsigned(int, *tl++);
6439
				switch (limitby) {
6440
				case NFSV4OPEN_LIMITSIZE:
6441
					dp->nfsdl_sizelimit = fxdr_hyper(tl);
6442
					break;
6443
				case NFSV4OPEN_LIMITBLOCKS:
6444
					dp->nfsdl_sizelimit =
6445
					    fxdr_unsigned(u_int64_t, *tl++);
6446
					dp->nfsdl_sizelimit *=
6447
					    fxdr_unsigned(u_int64_t, *tl);
6448
					break;
6449
				default:
6450
					error = NFSERR_BADXDR;
6451
					goto nfsmout;
6452
				};
6453
			} else {
6454
				dp->nfsdl_flags = NFSCLDL_READ;
6455
			}
6456
			if (ret != 0)
6457
				dp->nfsdl_flags |= NFSCLDL_RECALL;
6458
			error = nfsrv_dissectace(nd, &dp->nfsdl_ace, &ret,
6459
			    &acesize, p);
6460
			if (error != 0)
6461
				goto nfsmout;
6462
		} else if (deleg != NFSV4OPEN_DELEGATENONE) {
6463
			error = NFSERR_BADXDR;
6464
			goto nfsmout;
6465
		}
6466
6467
		/* Now, we should have the status for the SaveFH. */
6468
		NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
6469
		if (*++tl == 0) {
6470
			NFSCL_DEBUG(4, "nfsrpc_createlayout SaveFH ok\n");
6471
			/*
6472
			 * Now, process the GetFH and Getattr for the newly
6473
			 * created file. nfscl_mtofh() will set
6474
			 * ND_NOMOREDATA if these weren't successful.
6475
			 */
6476
			error = nfscl_mtofh(nd, nfhpp, nnap, attrflagp);
6477
			NFSCL_DEBUG(4, "aft nfscl_mtofh err=%d\n", error);
6478
			if (error != 0)
6479
				goto nfsmout;
6480
		} else
6481
			nd->nd_flag |= ND_NOMOREDATA;
6482
		/* Now we have the PutFH and Getattr for the directory. */
6483
		if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
6484
			NFSM_DISSECT(tl, uint32_t *, 2 * NFSX_UNSIGNED);
6485
			if (*++tl != 0)
6486
				nd->nd_flag |= ND_NOMOREDATA;
6487
			else {
6488
				NFSM_DISSECT(tl, uint32_t *, 2 *
6489
				    NFSX_UNSIGNED);
6490
				if (*++tl != 0)
6491
					nd->nd_flag |= ND_NOMOREDATA;
6492
			}
6493
		}
6494
		if ((nd->nd_flag & ND_NOMOREDATA) == 0) {
6495
			/* Load the directory attributes. */
6496
			error = nfsm_loadattr(nd, dnap);
6497
			NFSCL_DEBUG(4, "aft nfsm_loadattr err=%d\n", error);
6498
			if (error != 0)
6499
				goto nfsmout;
6500
			*dattrflagp = 1;
6501
			if (dp != NULL && *attrflagp != 0) {
6502
				dp->nfsdl_change = nnap->na_filerev;
6503
				dp->nfsdl_modtime = nnap->na_mtime;
6504
				dp->nfsdl_flags |= NFSCLDL_MODTIMESET;
6505
			}
6506
			/*
6507
			 * We can now complete the Open state.
6508
			 */
6509
			nfhp = *nfhpp;
6510
			if (dp != NULL) {
6511
				dp->nfsdl_fhlen = nfhp->nfh_len;
6512
				NFSBCOPY(nfhp->nfh_fh, dp->nfsdl_fh,
6513
				    nfhp->nfh_len);
6514
			}
6515
			/*
6516
			 * Get an Open structure that will be
6517
			 * attached to the OpenOwner, acquired already.
6518
			 */
6519
			error = nfscl_open(dvp, nfhp->nfh_fh, nfhp->nfh_len, 
6520
			    (NFSV4OPEN_ACCESSWRITE | NFSV4OPEN_ACCESSREAD), 0,
6521
			    cred, p, NULL, &op, &newone, NULL, 0);
6522
			if (error != 0)
6523
				goto nfsmout;
6524
			op->nfso_stateid = stateid;
6525
			newnfs_copyincred(cred, &op->nfso_cred);
6526
	
6527
			nfscl_openrelease(nmp, op, error, newone);
6528
			*unlockedp = 1;
6529
6530
			/* Now, handle the RestoreFH and LayoutGet. */
6531
			if (nd->nd_repstat == 0) {
6532
				NFSM_DISSECT(tl, uint32_t *, 4 * NFSX_UNSIGNED);
6533
				*laystatp = fxdr_unsigned(int, *(tl + 3));
6534
				if (*laystatp == 0) {
6535
					error = nfsrv_parselayoutget(nd,
6536
					    stateidp, retonclosep, flhp);
6537
					if (error != 0)
6538
						*laystatp = error;
6539
				}
6540
				NFSCL_DEBUG(4, "aft nfsrv_parselayout err=%d\n",
6541
				    error);
6542
			} else
6543
				nd->nd_repstat = 0;
6544
		}
6545
	}
6546
	if (nd->nd_repstat != 0 && error == 0)
6547
		error = nd->nd_repstat;
6548
	if (error == NFSERR_STALECLIENTID || error == NFSERR_BADSESSION)
6549
		nfscl_initiate_recovery(owp->nfsow_clp);
6550
nfsmout:
6551
	NFSCL_DEBUG(4, "eo nfsrpc_createlayout err=%d\n", error);
6552
	if (error == 0)
6553
		*dpp = dp;
6554
	else
6555
		free(dp, M_NFSCLDELEG);
6556
	mbuf_freem(nd->nd_mrep);
6557
	return (error);
6558
}
6559
6560
/*
6561
 * Similar to nfsrpc_getopenlayout(), except that it used for the Create case.
6562
 */
6563
static int
6564
nfsrpc_getcreatelayout(vnode_t dvp, char *name, int namelen, struct vattr *vap,
6565
    nfsquad_t cverf, int fmode, struct nfsclowner *owp, struct nfscldeleg **dpp,
6566
    struct ucred *cred, NFSPROC_T *p, struct nfsvattr *dnap,
6567
    struct nfsvattr *nnap, struct nfsfh **nfhpp, int *attrflagp,
6568
    int *dattrflagp, void *dstuff, int *unlockedp)
6569
{
6570
	struct nfscllayout *lyp;
6571
	struct nfsclflayouthead flh;
6572
	struct nfsfh *nfhp;
6573
	struct nfsclsession *tsep;
6574
	struct nfsmount *nmp;
6575
	nfsv4stateid_t stateid;
6576
	int error, layoutlen, retonclose, laystat;
6577
6578
	error = 0;
6579
	nmp = VFSTONFS(dvp->v_mount);
6580
	LIST_INIT(&flh);
6581
	tsep = nfsmnt_mdssession(nmp);
6582
	layoutlen = tsep->nfsess_maxcache - (NFSX_STATEID + 3 * NFSX_UNSIGNED);
6583
	error = nfsrpc_createlayout(dvp, name, namelen, vap, cverf, fmode,
6584
	    owp, dpp, cred, p, dnap, nnap, nfhpp, attrflagp, dattrflagp,
6585
	    dstuff, unlockedp, &stateid, 1, layoutlen, &retonclose, &flh,
6586
	    &laystat);
6587
	NFSCL_DEBUG(4, "aft nfsrpc_createlayoutrpc laystat=%d err=%d\n",
6588
	    laystat, error);
6589
	lyp = NULL;
6590
	nfhp = *nfhpp;
6591
	laystat = nfsrpc_layoutgetres(nmp, dvp, nfhp->nfh_fh, nfhp->nfh_len,
6592
	    &stateid, retonclose, NULL, &lyp, &flh, laystat, NULL, cred, p);
6593
	if (laystat == 0)
6594
		nfscl_rellayout(lyp, 0);
6595
	return (error);
6596
}
6597
6598
/*
6599
 * Process the results of a layoutget() operation.
6600
 */
6601
static int
6602
nfsrpc_layoutgetres(struct nfsmount *nmp, vnode_t vp, uint8_t *newfhp,
6603
    int newfhlen, nfsv4stateid_t *stateidp, int retonclose, uint32_t *notifybit,
6604
    struct nfscllayout **lypp, struct nfsclflayouthead *flhp,
6605
    int laystat, int *islockedp, struct ucred *cred, NFSPROC_T *p)
6606
{
6607
	struct nfsclflayout *tflp;
6608
	struct nfscldevinfo *dip;
6609
6610
	if (laystat == NFSERR_UNKNLAYOUTTYPE) {
6611
		/* Disable PNFS. */
6612
		NFSCL_DEBUG(1, "disable PNFS\n");
6613
		NFSLOCKMNT(nmp);
6614
		nmp->nm_state &= ~NFSSTA_PNFS;
6615
		NFSUNLOCKMNT(nmp);
6616
	}
6617
	if (laystat == 0) {
6618
		NFSCL_DEBUG(4, "nfsrpc_layoutgetres at FOREACH\n");
6619
		LIST_FOREACH(tflp, flhp, nfsfl_list) {
6620
			laystat = nfscl_adddevinfo(nmp, NULL, tflp);
6621
			NFSCL_DEBUG(4, "aft adddev=%d\n", laystat);
6622
			if (laystat != 0) {
6623
				laystat = nfsrpc_getdeviceinfo(nmp,
6624
				    tflp->nfsfl_dev, NFSLAYOUT_NFSV4_1_FILES,
6625
				    notifybit, &dip, cred, p);
6626
				NFSCL_DEBUG(4, "aft nfsrpc_gdi=%d\n",
6627
				    laystat);
6628
				if (laystat != 0)
6629
					break;
6630
				laystat = nfscl_adddevinfo(nmp, dip, tflp);
6631
				if (laystat != 0)
6632
					printf("getlayout: cannot add\n");
6633
			}
6634
		}
6635
	}
6636
	if (laystat == 0) {
6637
		/*
6638
		 * nfscl_layout() always returns with the nfsly_lock
6639
		 * set to a refcnt (shared lock).
6640
		 * Passing in dvp is sufficient, since it is only used to
6641
		 * get the fsid for the file system.
6642
		 */
6643
		laystat = nfscl_layout(nmp, vp, newfhp, newfhlen, stateidp,
6644
		    retonclose, flhp, lypp, cred, p);
6645
		NFSCL_DEBUG(4, "nfsrpc_layoutgetres: aft nfscl_layout=%d\n",
6646
		    laystat);
6647
		if (laystat == 0 && islockedp != NULL)
6648
			*islockedp = 1;
6649
	}
6650
	return (laystat);
6651
}
6652
(-)usr.bin/nfsstat/nfsstat.c (+7 lines)
Lines 926-931 exp41_intpr(int clientOnly, int serverOn Link Here
926
		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMITDS]);
926
		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_COMMITDS]);
927
		if (printtitle)
927
		if (printtitle)
928
			printf(
928
			printf(
929
			    "%12.12s %12.12s\n",
930
			    "OpenLayout", "CreateLayout");
931
		printf("%12ju %12ju\n",
932
		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_OPENLAYGET],
933
		    (uintmax_t)ext_nfsstats.rpccnt[NFSPROC_CREATELAYGET]);
934
		if (printtitle)
935
			printf(
929
			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
936
			    "%12.12s %12.12s %12.12s %12.12s %12.12s %12.12s\n",
930
			    "OpenOwner", "Opens", "LockOwner", "Locks",
937
			    "OpenOwner", "Opens", "LockOwner", "Locks",
931
			    "Delegs", "LocalOwn");
938
			    "Delegs", "LocalOwn");

Return to bug 219550