Blame view

fs/nfsd/nfs4proc.c 48.1 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   *  Server-side procedures for NFSv4.
   *
   *  Copyright (c) 2002 The Regents of the University of Michigan.
   *  All rights reserved.
   *
   *  Kendrick Smith <kmsmith@umich.edu>
   *  Andy Adamson   <andros@umich.edu>
   *
   *  Redistribution and use in source and binary forms, with or without
   *  modification, are permitted provided that the following conditions
   *  are met:
   *
   *  1. Redistributions of source code must retain the above copyright
   *     notice, this list of conditions and the following disclaimer.
   *  2. Redistributions in binary form must reproduce the above copyright
   *     notice, this list of conditions and the following disclaimer in the
   *     documentation and/or other materials provided with the distribution.
   *  3. Neither the name of the University nor the names of its
   *     contributors may be used to endorse or promote products derived
   *     from this software without specific prior written permission.
   *
   *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
   *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
   */
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
35
  #include <linux/file.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
36
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
37

58e7b33a5   Mi Jinlong   nfsd41: try to ch...
38
  #include "idmap.h"
9a74af213   Boaz Harrosh   nfsd: Move privat...
39
40
  #include "cache.h"
  #include "xdr4.h"
0a3adadee   J. Bruce Fields   nfsd: make fs/nfs...
41
  #include "vfs.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
  
  #define NFSDDBG_FACILITY		NFSDDBG_PROC
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  static u32 nfsd_attrmask[] = {
  	NFSD_WRITEABLE_ATTRS_WORD0,
  	NFSD_WRITEABLE_ATTRS_WORD1,
  	NFSD_WRITEABLE_ATTRS_WORD2
  };
  
  static u32 nfsd41_ex_attrmask[] = {
  	NFSD_SUPPATTR_EXCLCREAT_WORD0,
  	NFSD_SUPPATTR_EXCLCREAT_WORD1,
  	NFSD_SUPPATTR_EXCLCREAT_WORD2
  };
  
  static __be32
  check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  		   u32 *bmval, u32 *writable)
  {
  	struct dentry *dentry = cstate->current_fh.fh_dentry;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
61
62
63
64
65
66
67
68
69
70
71
  
  	/*
  	 * Check about attributes are supported by the NFSv4 server or not.
  	 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP.
  	 */
  	if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) ||
  	    (bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) ||
  	    (bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
  		return nfserr_attrnotsupp;
  
  	/*
a06b1261b   Trond Myklebust   NFSD: Fix a bug i...
72
  	 * Check FATTR4_WORD0_ACL can be supported
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
73
74
75
76
77
78
  	 * in current environment or not.
  	 */
  	if (bmval[0] & FATTR4_WORD0_ACL) {
  		if (!IS_POSIXACL(dentry->d_inode))
  			return nfserr_attrnotsupp;
  	}
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
  
  	/*
  	 * According to spec, read-only attributes return ERR_INVAL.
  	 */
  	if (writable) {
  		if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
  		    (bmval[2] & ~writable[2]))
  			return nfserr_inval;
  	}
  
  	return nfs_ok;
  }
  
  static __be32
  nfsd4_check_open_attributes(struct svc_rqst *rqstp,
  	struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
  {
  	__be32 status = nfs_ok;
  
  	if (open->op_create == NFS4_OPEN_CREATE) {
  		if (open->op_createmode == NFS4_CREATE_UNCHECKED
  		    || open->op_createmode == NFS4_CREATE_GUARDED)
  			status = check_attr_support(rqstp, cstate,
  					open->op_bmval, nfsd_attrmask);
  		else if (open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1)
  			status = check_attr_support(rqstp, cstate,
  					open->op_bmval, nfsd41_ex_attrmask);
  	}
  
  	return status;
  }
9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  static int
  is_create_with_attrs(struct nfsd4_open *open)
  {
  	return open->op_create == NFS4_OPEN_CREATE
  		&& (open->op_createmode == NFS4_CREATE_UNCHECKED
  		    || open->op_createmode == NFS4_CREATE_GUARDED
  		    || open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1);
  }
  
  /*
   * if error occurs when setting the acl, just clear the acl bit
   * in the returned attr bitmap.
   */
  static void
  do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
  		struct nfs4_acl *acl, u32 *bmval)
  {
  	__be32 status;
  
  	status = nfsd4_set_nfs4_acl(rqstp, fhp, acl);
  	if (status)
  		/*
  		 * We should probably fail the whole open at this point,
  		 * but we've already created the file, so it's too late;
  		 * So this seems the least of evils:
  		 */
  		bmval[0] &= ~FATTR4_WORD0_ACL;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
138
139
140
141
142
143
144
145
146
  static inline void
  fh_dup2(struct svc_fh *dst, struct svc_fh *src)
  {
  	fh_put(dst);
  	dget(src->fh_dentry);
  	if (src->fh_export)
  		cache_get(&src->fh_export->h);
  	*dst = *src;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
147
  static __be32
dc730e173   J. Bruce Fields   [PATCH] knfsd: nf...
148
  do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
150
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151
152
153
154
  
  	if (open->op_truncate &&
  		!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
  		return nfserr_inval;
a043226bc   J. Bruce Fields   nfsd4: permit rea...
155
  	accmode |= NFSD_MAY_READ_IF_EXEC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
156
  	if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
157
  		accmode |= NFSD_MAY_READ;
9801d8a39   J. Bruce Fields   [PATCH] knfsd: nf...
158
  	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
159
  		accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
57ecb34fe   J. Bruce Fields   nfsd4: fix share ...
160
  	if (open->op_share_deny & NFS4_SHARE_DENY_READ)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
161
  		accmode |= NFSD_MAY_WRITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162
163
164
165
166
  
  	status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
  
  	return status;
  }
aadab6c6f   J. Bruce Fields   nfsd4: return nfs...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
  static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
  {
  	umode_t mode = fh->fh_dentry->d_inode->i_mode;
  
  	if (S_ISREG(mode))
  		return nfs_ok;
  	if (S_ISDIR(mode))
  		return nfserr_isdir;
  	/*
  	 * Using err_symlink as our catch-all case may look odd; but
  	 * there's no other obvious error for this case in 4.0, and we
  	 * happen to know that it will cause the linux v4 client to do
  	 * the right thing on attempts to open something other than a
  	 * regular file.
  	 */
  	return nfserr_symlink;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
184
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
  do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  {
  	struct svc_fh resfh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
188
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
189
190
191
192
193
  
  	fh_init(&resfh, NFS4_FHSIZE);
  	open->op_truncate = 0;
  
  	if (open->op_create) {
79fb54abd   Benny Halevy   nfsd41: CREATE_EX...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  		/* FIXME: check session persistence and pnfs flags.
  		 * The nfsv4.1 spec requires the following semantics:
  		 *
  		 * Persistent   | pNFS   | Server REQUIRED | Client Allowed
  		 * Reply Cache  | server |                 |
  		 * -------------+--------+-----------------+--------------------
  		 * no           | no     | EXCLUSIVE4_1    | EXCLUSIVE4_1
  		 *              |        |                 | (SHOULD)
  		 *              |        | and EXCLUSIVE4  | or EXCLUSIVE4
  		 *              |        |                 | (SHOULD NOT)
  		 * no           | yes    | EXCLUSIVE4_1    | EXCLUSIVE4_1
  		 * yes          | no     | GUARDED4        | GUARDED4
  		 * yes          | yes    | GUARDED4        | GUARDED4
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
  		/*
  		 * Note: create modes (UNCHECKED,GUARDED...) are the same
ac6721a13   Mi Jinlong   nfsd41: make sure...
210
  		 * in NFSv4 as in v3 except EXCLUSIVE4_1.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
211
  		 */
ac6721a13   Mi Jinlong   nfsd41: make sure...
212
  		status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
  					open->op_fname.len, &open->op_iattr,
  					&resfh, open->op_createmode,
749997e51   Jeff Layton   knfsd: set the re...
215
  					(u32 *)open->op_verf.data,
856121b2e   J. Bruce Fields   nfsd4: warn on op...
216
  					&open->op_truncate, &open->op_created);
749997e51   Jeff Layton   knfsd: set the re...
217

99f887263   J. Bruce Fields   nfsd: clarify exc...
218
219
220
221
  		/*
  		 * Following rfc 3530 14.2.16, use the returned bitmask
  		 * to indicate which attributes we used to store the
  		 * verifier:
749997e51   Jeff Layton   knfsd: set the re...
222
223
  		 */
  		if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
99f887263   J. Bruce Fields   nfsd: clarify exc...
224
  			open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
749997e51   Jeff Layton   knfsd: set the re...
225
  						FATTR4_WORD1_TIME_MODIFY);
af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
226
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
229
  		status = nfsd_lookup(rqstp, current_fh,
  				     open->op_fname.data, open->op_fname.len, &resfh);
  		fh_unlock(current_fh);
aadab6c6f   J. Bruce Fields   nfsd4: return nfs...
230
231
232
  		if (status)
  			goto out;
  		status = nfsd_check_obj_isreg(&resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
  	}
af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
234
235
  	if (status)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
236

9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
237
238
  	if (is_create_with_attrs(open) && open->op_acl != NULL)
  		do_set_nfs4_acl(rqstp, &resfh, open->op_acl, open->op_bmval);
af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
239
  	set_change_info(&open->op_cinfo, current_fh);
13024b7b4   J. Bruce Fields   nfsd4: fix mispla...
240
  	fh_dup2(current_fh, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
242
  	/* set reply cache */
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
243
  	fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
a4773c08f   J. Bruce Fields   nfsd4: use helper...
244
  			&resfh.fh_handle);
856121b2e   J. Bruce Fields   nfsd4: warn on op...
245
  	if (!open->op_created)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
246
247
  		status = do_open_permission(rqstp, current_fh, open,
  					    NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
248

af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
249
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
250
251
252
  	fh_put(&resfh);
  	return status;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
253
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
  do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
256
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
259
260
261
262
263
264
  	/* We don't know the target directory, and therefore can not
  	* set the change info
  	*/
  
  	memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
  
  	/* set replay cache */
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
265
  	fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
a4773c08f   J. Bruce Fields   nfsd4: use helper...
266
  			&current_fh->fh_handle);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
267
268
269
  
  	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
  		(open->op_iattr.ia_size == 0);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
270
271
  	status = do_open_permission(rqstp, current_fh, open,
  				    NFSD_MAY_OWNER_OVERRIDE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
273
274
  
  	return status;
  }
60adfc50d   Andy Adamson   nfsd41: clientid ...
275
276
277
278
279
280
281
282
283
  static void
  copy_clientid(clientid_t *clid, struct nfsd4_session *session)
  {
  	struct nfsd4_sessionid *sid =
  			(struct nfsd4_sessionid *)session->se_sessionid.data;
  
  	clid->cl_boot = sid->clientid.cl_boot;
  	clid->cl_id = sid->clientid.cl_id;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284

7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
285
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
286
  nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
287
  	   struct nfsd4_open *open)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
289
  	__be32 status;
6668958fa   Andy Adamson   nfsd41: stateid h...
290
  	struct nfsd4_compoundres *resp;
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
291
292
  	dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
293
  		(int)open->op_fname.len, open->op_fname.data,
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
294
  		open->op_openowner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
  	/* This check required by spec. */
  	if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
  		return nfserr_inval;
b6d2f1ca3   J. Bruce Fields   nfsd4: more robus...
299
300
  	/* We don't yet support WANT bits: */
  	open->op_share_access &= NFS4_SHARE_ACCESS_MASK;
856121b2e   J. Bruce Fields   nfsd4: warn on op...
301
  	open->op_created = 0;
ab1350b2b   Mi Jinlong   nfsd41: Deny new ...
302
303
304
305
306
307
308
309
  	/*
  	 * RFC5661 18.51.3
  	 * Before RECLAIM_COMPLETE done, server should deny new lock
  	 */
  	if (nfsd4_has_session(cstate) &&
  	    !cstate->session->se_client->cl_firststate &&
  	    open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
  		return nfserr_grace;
60adfc50d   Andy Adamson   nfsd41: clientid ...
310
311
  	if (nfsd4_has_session(cstate))
  		copy_clientid(&open->op_clientid, cstate->session);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
  	nfs4_lock_state();
  
  	/* check seqid for replay. set nfs4_owner */
6668958fa   Andy Adamson   nfsd41: stateid h...
315
316
  	resp = rqstp->rq_resp;
  	status = nfsd4_process_open1(&resp->cstate, open);
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
317
  	if (status == nfserr_replay_me) {
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
318
  		struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
319
  		fh_put(&cstate->current_fh);
a4773c08f   J. Bruce Fields   nfsd4: use helper...
320
321
  		fh_copy_shallow(&cstate->current_fh.fh_handle,
  				&rp->rp_openfh);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
322
  		status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
326
327
  		if (status)
  			dprintk("nfsd4_open: replay failed"
  				" restoring previous filehandle
  ");
  		else
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
328
  			status = nfserr_replay_me;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
329
330
331
  	}
  	if (status)
  		goto out;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
332

3c8e03166   Yu Zhiguo   NFSv4: do exact c...
333
334
335
  	status = nfsd4_check_open_attributes(rqstp, cstate, open);
  	if (status)
  		goto out;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
336
337
  	/* Openowner is now set, so sequence id will get bumped.  Now we need
  	 * these checks before we do any creates: */
cbd0d51a3   J. Bruce Fields   [PATCH] knfsd: fi...
338
  	status = nfserr_grace;
af558e33b   J. Bruce Fields   nfsd: common grac...
339
  	if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
cbd0d51a3   J. Bruce Fields   [PATCH] knfsd: fi...
340
341
  		goto out;
  	status = nfserr_no_grace;
af558e33b   J. Bruce Fields   nfsd: common grac...
342
  	if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
cbd0d51a3   J. Bruce Fields   [PATCH] knfsd: fi...
343
  		goto out;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
344

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
345
  	switch (open->op_claim_type) {
0dd3c1921   NeilBrown   [PATCH] nfsd4: su...
346
  		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
  		case NFS4_OPEN_CLAIM_NULL:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
348
349
  			status = do_open_lookup(rqstp, &cstate->current_fh,
  						open);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
353
  			if (status)
  				goto out;
  			break;
  		case NFS4_OPEN_CLAIM_PREVIOUS:
dad1c067e   J. Bruce Fields   nfsd4: replace oo...
354
  			open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
0cf99b91c   Mi Jinlong   nfsd41: allow non...
355
356
357
  			status = nfs4_check_open_reclaim(&open->op_clientid);
  			if (status)
  				goto out;
8b289b2c2   J. Bruce Fields   nfsd4: implement ...
358
359
  		case NFS4_OPEN_CLAIM_FH:
  		case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
360
361
  			status = do_open_fhandle(rqstp, &cstate->current_fh,
  						 open);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362
363
364
  			if (status)
  				goto out;
  			break;
8b289b2c2   J. Bruce Fields   nfsd4: implement ...
365
  		case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366
               	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
dad1c067e   J. Bruce Fields   nfsd4: replace oo...
367
  			open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
2fdada03b   J. Bruce Fields   knfsd: demote som...
368
369
  			dprintk("NFSD: unsupported OPEN claim type %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
370
371
372
373
  				open->op_claim_type);
  			status = nfserr_notsupp;
  			goto out;
  		default:
2fdada03b   J. Bruce Fields   knfsd: demote som...
374
375
  			dprintk("NFSD: Invalid OPEN claim type %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
378
379
380
381
382
383
384
  				open->op_claim_type);
  			status = nfserr_inval;
  			goto out;
  	}
  	/*
  	 * nfsd4_process_open2() does the actual opening of the file.  If
  	 * successful, it (1) truncates the file if open->op_truncate was
  	 * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
  	 */
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
385
  	status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
856121b2e   J. Bruce Fields   nfsd4: warn on op...
386
  	WARN_ON(status && open->op_created);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
387
  out:
d29b20cd5   J. Bruce Fields   nfsd4: clean up o...
388
  	nfsd4_cleanup_open_state(open, status);
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
389
390
  	if (open->op_openowner)
  		cstate->replay_owner = &open->op_openowner->oo_owner;
7c13f344c   J. Bruce Fields   nfsd4: drop most ...
391
  	else
5ec094c10   J. Bruce Fields   nfsd4: extend sta...
392
  		nfs4_unlock_state();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
393
394
395
396
397
398
  	return status;
  }
  
  /*
   * filehandle-manipulating ops.
   */
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
399
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
400
401
  nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	    struct svc_fh **getfh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
402
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
403
  	if (!cstate->current_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404
  		return nfserr_nofilehandle;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
405
  	*getfh = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406
407
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
408
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
409
410
  nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	    struct nfsd4_putfh *putfh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
411
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
412
413
414
415
  	fh_put(&cstate->current_fh);
  	cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
  	memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
  	       putfh->pf_fhlen);
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
416
  	return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
417
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
418
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
419
420
  nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  		void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
421
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
422
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
424
  	fh_put(&cstate->current_fh);
df547efb0   J. Bruce Fields   knfsd: nfsd4: sim...
425
  	status = exp_pseudoroot(rqstp, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
426
427
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
428
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
429
430
  nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  		void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
432
  	if (!cstate->save_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
  		return nfserr_restorefh;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
434
  	fh_dup2(&cstate->current_fh, &cstate->save_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
437
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
438
439
  nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
440
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
441
  	if (!cstate->current_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
442
  		return nfserr_nofilehandle;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
443
  	fh_dup2(&cstate->save_fh, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
446
447
448
449
  	return nfs_ok;
  }
  
  /*
   * misc nfsv4 ops
   */
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
450
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
451
452
  nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_access *access)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
454
455
456
457
  {
  	if (access->ac_req_access & ~NFS3_ACCESS_FULL)
  		return nfserr_inval;
  
  	access->ac_resp_access = access->ac_req_access;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
458
459
  	return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
  			   &access->ac_supported);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
460
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
461
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
462
463
  nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_commit *commit)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
465
466
467
  	u32 *p = (u32 *)commit->co_verf.data;
  	*p++ = nfssvc_boot.tv_sec;
  	*p++ = nfssvc_boot.tv_usec;
75c096f75   J. Bruce Fields   nfsd4: it's OK to...
468
  	return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
469
  			     commit->co_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
471
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
472
473
  nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_create *create)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
474
475
  {
  	struct svc_fh resfh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
476
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
477
478
479
  	dev_t rdev;
  
  	fh_init(&resfh, NFS4_FHSIZE);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
480
481
  	status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
  			   NFSD_MAY_CREATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
483
  	if (status)
  		return status;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
484
485
486
487
  	status = check_attr_support(rqstp, cstate, create->cr_bmval,
  				    nfsd_attrmask);
  	if (status)
  		return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
488
489
490
491
492
493
494
495
496
497
  	switch (create->cr_type) {
  	case NF4LNK:
  		/* ugh! we have to null-terminate the linktext, or
  		 * vfs_symlink() will choke.  it is always safe to
  		 * null-terminate by brute force, since at worst we
  		 * will overwrite the first byte of the create namelen
  		 * in the XDR buffer, which has already been extracted
  		 * during XDR decode.
  		 */
  		create->cr_linkname[create->cr_linklen] = 0;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
498
499
500
501
  		status = nfsd_symlink(rqstp, &cstate->current_fh,
  				      create->cr_name, create->cr_namelen,
  				      create->cr_linkname, create->cr_linklen,
  				      &resfh, &create->cr_iattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
502
503
504
505
506
507
508
  		break;
  
  	case NF4BLK:
  		rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  		if (MAJOR(rdev) != create->cr_specdata1 ||
  		    MINOR(rdev) != create->cr_specdata2)
  			return nfserr_inval;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
509
510
511
  		status = nfsd_create(rqstp, &cstate->current_fh,
  				     create->cr_name, create->cr_namelen,
  				     &create->cr_iattr, S_IFBLK, rdev, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
512
513
514
515
516
517
518
  		break;
  
  	case NF4CHR:
  		rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  		if (MAJOR(rdev) != create->cr_specdata1 ||
  		    MINOR(rdev) != create->cr_specdata2)
  			return nfserr_inval;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
519
520
521
  		status = nfsd_create(rqstp, &cstate->current_fh,
  				     create->cr_name, create->cr_namelen,
  				     &create->cr_iattr,S_IFCHR, rdev, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
522
523
524
  		break;
  
  	case NF4SOCK:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
525
526
527
  		status = nfsd_create(rqstp, &cstate->current_fh,
  				     create->cr_name, create->cr_namelen,
  				     &create->cr_iattr, S_IFSOCK, 0, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
528
529
530
  		break;
  
  	case NF4FIFO:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
531
532
533
  		status = nfsd_create(rqstp, &cstate->current_fh,
  				     create->cr_name, create->cr_namelen,
  				     &create->cr_iattr, S_IFIFO, 0, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
535
536
537
  		break;
  
  	case NF4DIR:
  		create->cr_iattr.ia_valid &= ~ATTR_SIZE;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
538
539
540
  		status = nfsd_create(rqstp, &cstate->current_fh,
  				     create->cr_name, create->cr_namelen,
  				     &create->cr_iattr, S_IFDIR, 0, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
541
542
543
544
545
  		break;
  
  	default:
  		status = nfserr_badtype;
  	}
9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
546
547
  	if (status)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
548

9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
549
550
551
552
553
554
555
556
  	if (create->cr_acl != NULL)
  		do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
  				create->cr_bmval);
  
  	fh_unlock(&cstate->current_fh);
  	set_change_info(&create->cr_cinfo, &cstate->current_fh);
  	fh_dup2(&cstate->current_fh, &resfh);
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
  	fh_put(&resfh);
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
560
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
561
562
  nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_getattr *getattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
563
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
564
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
565

8837abcab   Miklos Szeredi   nfsd: rename MAY_...
566
  	status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567
568
569
570
571
  	if (status)
  		return status;
  
  	if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  		return nfserr_inval;
7e7057064   Andy Adamson   nfsd41: support f...
572
573
574
  	getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
  	getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
  	getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
575

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
576
  	getattr->ga_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
577
578
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
579
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
580
581
  nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	   struct nfsd4_link *link)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
582
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
583
  	__be32 status = nfserr_nofilehandle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
584

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
585
  	if (!cstate->save_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
  		return status;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
587
588
  	status = nfsd_link(rqstp, &cstate->current_fh,
  			   link->li_name, link->li_namelen, &cstate->save_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
  	if (!status)
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
590
  		set_change_info(&link->li_cinfo, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
591
592
  	return status;
  }
0ff7ab467   J. Bruce Fields   nfsd4: move guts ...
593
  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
  {
  	struct svc_fh tmp_fh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
596
  	__be32 ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
597
598
  
  	fh_init(&tmp_fh, NFS4_FHSIZE);
df547efb0   J. Bruce Fields   knfsd: nfsd4: sim...
599
600
  	ret = exp_pseudoroot(rqstp, &tmp_fh);
  	if (ret)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
601
  		return ret;
0ff7ab467   J. Bruce Fields   nfsd4: move guts ...
602
  	if (tmp_fh.fh_dentry == fh->fh_dentry) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
603
604
605
606
  		fh_put(&tmp_fh);
  		return nfserr_noent;
  	}
  	fh_put(&tmp_fh);
0ff7ab467   J. Bruce Fields   nfsd4: move guts ...
607
608
609
610
611
612
613
614
  	return nfsd_lookup(rqstp, fh, "..", 2, fh);
  }
  
  static __be32
  nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      void *arg)
  {
  	return nfsd4_do_lookupp(rqstp, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
615
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
616
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
617
618
  nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_lookup *lookup)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
620
621
622
  	return nfsd_lookup(rqstp, &cstate->current_fh,
  			   lookup->lo_name, lookup->lo_len,
  			   &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
623
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
624
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
625
626
  nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	   struct nfsd4_read *read)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
628
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
630
  
  	/* no need to check permission - this will be done in nfsd_read() */
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
631
  	read->rd_filp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
632
633
634
635
636
  	if (read->rd_offset >= OFFSET_MAX)
  		return nfserr_inval;
  
  	nfs4_lock_state();
  	/* check stateid */
dd453dfd7   Benny Halevy   nfsd: pass nfsd4_...
637
638
  	if ((status = nfs4_preprocess_stateid_op(cstate, &read->rd_stateid,
  						 RD_STATE, &read->rd_filp))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
639
640
641
642
  		dprintk("NFSD: nfsd4_read: couldn't process stateid!
  ");
  		goto out;
  	}
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
643
644
  	if (read->rd_filp)
  		get_file(read->rd_filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
646
647
648
  	status = nfs_ok;
  out:
  	nfs4_unlock_state();
  	read->rd_rqstp = rqstp;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
649
  	read->rd_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
650
651
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
652
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
653
654
  nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_readdir *readdir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
657
658
659
660
661
662
  {
  	u64 cookie = readdir->rd_cookie;
  	static const nfs4_verifier zeroverf;
  
  	/* no need to check permission - this will be done in nfsd_readdir() */
  
  	if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  		return nfserr_inval;
7e7057064   Andy Adamson   nfsd41: support f...
663
664
665
  	readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
  	readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
  	readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666

832023bff   Bernd Schubert   nfsd4: Remove che...
667
  	if ((cookie == 1) || (cookie == 2) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
668
669
670
671
  	    (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
  		return nfserr_bad_cookie;
  
  	readdir->rd_rqstp = rqstp;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
672
  	readdir->rd_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
675
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
676
677
  nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	       struct nfsd4_readlink *readlink)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
  {
  	readlink->rl_rqstp = rqstp;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
680
  	readlink->rl_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
681
682
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
683
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
684
685
  nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_remove *remove)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
686
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
687
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688

af558e33b   J. Bruce Fields   nfsd: common grac...
689
  	if (locks_in_grace())
c815afc73   NeilBrown   [PATCH] nfsd4: bl...
690
  		return nfserr_grace;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
691
692
  	status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
  			     remove->rm_name, remove->rm_namelen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
693
  	if (!status) {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
694
695
  		fh_unlock(&cstate->current_fh);
  		set_change_info(&remove->rm_cinfo, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
696
697
698
  	}
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
699
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
700
701
  nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_rename *rename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
703
  	__be32 status = nfserr_nofilehandle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
705
  	if (!cstate->save_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
  		return status;
af558e33b   J. Bruce Fields   nfsd: common grac...
707
  	if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags
c815afc73   NeilBrown   [PATCH] nfsd4: bl...
708
709
  					& NFSEXP_NOSUBTREECHECK))
  		return nfserr_grace;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
710
711
  	status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
  			     rename->rn_snamelen, &cstate->current_fh,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
713
714
715
716
717
718
  			     rename->rn_tname, rename->rn_tnamelen);
  
  	/* the underlying filesystem returns different error's than required
  	 * by NFSv4. both save_fh and current_fh have been verified.. */
  	if (status == nfserr_isdir)
  		status = nfserr_exist;
  	else if ((status == nfserr_notdir) &&
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
719
720
                    (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
                     S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
721
  		status = nfserr_exist;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
722
723
  
  	if (!status) {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
724
725
  		set_change_info(&rename->rn_sinfo, &cstate->current_fh);
  		set_change_info(&rename->rn_tinfo, &cstate->save_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
726
727
728
  	}
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
729
  static __be32
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
730
731
732
733
734
735
736
737
738
  nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_secinfo *secinfo)
  {
  	struct svc_fh resfh;
  	struct svc_export *exp;
  	struct dentry *dentry;
  	__be32 err;
  
  	fh_init(&resfh, NFS4_FHSIZE);
29a78a3ed   J. Bruce Fields   nfsd4: make fh_ve...
739
740
741
  	err = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_EXEC);
  	if (err)
  		return err;
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
742
743
744
745
746
747
748
749
750
751
752
  	err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
  				    secinfo->si_name, secinfo->si_namelen,
  				    &exp, &dentry);
  	if (err)
  		return err;
  	if (dentry->d_inode == NULL) {
  		exp_put(exp);
  		err = nfserr_noent;
  	} else
  		secinfo->si_exp = exp;
  	dput(dentry);
56560b9ae   J. Bruce Fields   nfsd4: 4.1 SECINF...
753
754
755
  	if (cstate->minorversion)
  		/* See rfc 5661 section 2.6.3.1.1.8 */
  		fh_put(&cstate->current_fh);
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
756
757
758
759
  	return err;
  }
  
  static __be32
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
  nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_secinfo_no_name *sin)
  {
  	__be32 err;
  
  	switch (sin->sin_style) {
  	case NFS4_SECINFO_STYLE4_CURRENT_FH:
  		break;
  	case NFS4_SECINFO_STYLE4_PARENT:
  		err = nfsd4_do_lookupp(rqstp, &cstate->current_fh);
  		if (err)
  			return err;
  		break;
  	default:
  		return nfserr_inval;
  	}
  	exp_get(cstate->current_fh.fh_export);
  	sin->sin_exp = cstate->current_fh.fh_export;
  	fh_put(&cstate->current_fh);
  	return nfs_ok;
  }
  
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
783
784
  nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_setattr *setattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
786
  	__be32 status = nfs_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
787

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
788
789
  	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
  		nfs4_lock_state();
dd453dfd7   Benny Halevy   nfsd: pass nfsd4_...
790
  		status = nfs4_preprocess_stateid_op(cstate,
6150ef0dc   J. Bruce Fields   nfsd4: remove unu...
791
  			&setattr->sa_stateid, WR_STATE, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
792
  		nfs4_unlock_state();
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
793
  		if (status) {
3e3b48009   Greg Banks   [PATCH] knfsd: ad...
794
795
  			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!
  ");
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
796
797
  			return status;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
798
  	}
bad0dcffc   Al Viro   new helpers: fh_{...
799
  	status = fh_want_write(&cstate->current_fh);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
800
801
  	if (status)
  		return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
  	status = nfs_ok;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
803
804
805
806
807
  
  	status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
  				    nfsd_attrmask);
  	if (status)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
808
  	if (setattr->sa_acl != NULL)
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
809
810
  		status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
  					    setattr->sa_acl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
811
  	if (status)
18f335aff   Dave Hansen   [PATCH] r/o bind ...
812
  		goto out;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
813
  	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
814
  				0, (time_t)0);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
815
  out:
bad0dcffc   Al Viro   new helpers: fh_{...
816
  	fh_drop_write(&cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
817
818
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
819
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
820
821
  nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	    struct nfsd4_write *write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
822
823
824
825
  {
  	stateid_t *stateid = &write->wr_stateid;
  	struct file *filp = NULL;
  	u32 *p;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
826
  	__be32 status = nfs_ok;
31dec2538   David Shaw   Short write in nf...
827
  	unsigned long cnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
828
829
830
831
832
833
834
  
  	/* no need to check permission - this will be done in nfsd_write() */
  
  	if (write->wr_offset >= OFFSET_MAX)
  		return nfserr_inval;
  
  	nfs4_lock_state();
dd453dfd7   Benny Halevy   nfsd: pass nfsd4_...
835
  	status = nfs4_preprocess_stateid_op(cstate, stateid, WR_STATE, &filp);
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
836
837
  	if (filp)
  		get_file(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
838
  	nfs4_unlock_state();
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
839
840
841
842
843
  	if (status) {
  		dprintk("NFSD: nfsd4_write: couldn't process stateid!
  ");
  		return status;
  	}
31dec2538   David Shaw   Short write in nf...
844
  	cnt = write->wr_buflen;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
845
846
847
848
  	write->wr_how_written = write->wr_stable_how;
  	p = (u32 *)write->wr_verifier.data;
  	*p++ = nfssvc_boot.tv_sec;
  	*p++ = nfssvc_boot.tv_usec;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
849
850
  	status =  nfsd_write(rqstp, &cstate->current_fh, filp,
  			     write->wr_offset, rqstp->rq_vec, write->wr_vlen,
31dec2538   David Shaw   Short write in nf...
851
  			     &cnt, &write->wr_how_written);
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
852
853
  	if (filp)
  		fput(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
854

31dec2538   David Shaw   Short write in nf...
855
  	write->wr_bytes_written = cnt;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
  	return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
857
858
859
860
861
862
863
  }
  
  /* This routine never returns NFS_OK!  If there are no other errors, it
   * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the
   * attributes matched.  VERIFY is implemented by mapping NFSERR_SAME
   * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
   */
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
864
  static __be32
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
865
  _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
866
  	     struct nfsd4_verify *verify)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
867
  {
2ebbc012a   Al Viro   [PATCH] xdr annot...
868
  	__be32 *buf, *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
869
  	int count;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
870
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
871

8837abcab   Miklos Szeredi   nfsd: rename MAY_...
872
  	status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
873
874
  	if (status)
  		return status;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
875
876
877
  	status = check_attr_support(rqstp, cstate, verify->ve_bmval, NULL);
  	if (status)
  		return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
878
879
880
881
882
883
884
885
886
887
888
889
  	if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
  	    || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
  		return nfserr_inval;
  	if (verify->ve_attrlen & 3)
  		return nfserr_inval;
  
  	/* count in words:
  	 *   bitmap_len(1) + bitmap(2) + attr_len(1) = 4
  	 */
  	count = 4 + (verify->ve_attrlen >> 2);
  	buf = kmalloc(count << 2, GFP_KERNEL);
  	if (!buf)
3e7724639   J. Bruce Fields   nfsd4: stop using...
890
  		return nfserr_jukebox;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
891

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
892
893
894
  	status = nfsd4_encode_fattr(&cstate->current_fh,
  				    cstate->current_fh.fh_export,
  				    cstate->current_fh.fh_dentry, buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
895
  				    &count, verify->ve_bmval,
406a7ea97   Frank Filz   nfsd: Allow AIX c...
896
  				    rqstp, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
897
898
899
900
901
902
  
  	/* this means that nfsd4_encode_fattr() ran out of space */
  	if (status == nfserr_resource && count == 0)
  		status = nfserr_not_same;
  	if (status)
  		goto out_kfree;
95ec28cda   Benny Halevy   nfsd: dynamically...
903
904
  	/* skip bitmap */
  	p = buf + 1 + ntohl(buf[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
905
906
907
908
909
910
911
912
913
914
  	status = nfserr_not_same;
  	if (ntohl(*p++) != verify->ve_attrlen)
  		goto out_kfree;
  	if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen))
  		status = nfserr_same;
  
  out_kfree:
  	kfree(buf);
  	return status;
  }
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
  static __be32
  nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_verify *verify)
  {
  	__be32 status;
  
  	status = _nfsd4_verify(rqstp, cstate, verify);
  	return status == nfserr_not_same ? nfs_ok : status;
  }
  
  static __be32
  nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_verify *verify)
  {
  	__be32 status;
  
  	status = _nfsd4_verify(rqstp, cstate, verify);
  	return status == nfserr_same ? nfs_ok : status;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
934
935
936
  /*
   * NULL call.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
937
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
938
939
940
941
  nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  {
  	return nfs_ok;
  }
e2b209509   Shankar Anand   [PATCH] knfsd: nf...
942
943
944
945
946
  static inline void nfsd4_increment_op_stats(u32 opnum)
  {
  	if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
  		nfsdstats.nfs4_opcount[opnum]++;
  }
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
947
948
  typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
  			      void *);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
949
  typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op);
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
950
951
  enum nfsd4_op_flags {
  	ALLOWED_WITHOUT_FH = 1 << 0,	/* No current filehandle required */
5ece3cafb   Mi Jinlong   nfsd41: modify th...
952
953
  	ALLOWED_ON_ABSENT_FS = 1 << 1,	/* ops processed on absent fs */
  	ALLOWED_AS_FIRST_OP = 1 << 2,	/* ops reqired first in compound */
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
954
955
956
  	/* For rfc 5661 section 2.6.3.1.1: */
  	OP_HANDLES_WRONGSEC = 1 << 3,
  	OP_IS_PUTFH_LIKE = 1 << 4,
1091006c5   J. Bruce Fields   nfsd: turn on rep...
957
  	/*
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
958
959
960
961
962
963
964
965
  	 * These are the ops whose result size we estimate before
  	 * encoding, to avoid performing an op then not being able to
  	 * respond or cache a response.  This includes writes and setattrs
  	 * as well as the operations usually called "nonidempotent":
  	 */
  	OP_MODIFIES_SOMETHING = 1 << 5,
  	/*
  	 * Cache compounds containing these ops in the xid-based drc:
1091006c5   J. Bruce Fields   nfsd: turn on rep...
966
967
968
969
970
971
972
  	 * We use the DRC for compounds containing non-idempotent
  	 * operations, *except* those that are 4.1-specific (since
  	 * sessions provide their own EOS), and except for stateful
  	 * operations other than setclientid and setclientid_confirm
  	 * (since sequence numbers provide EOS for open, lock, etc in
  	 * the v4.0 case).
  	 */
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
973
974
975
976
977
978
979
  	OP_CACHEME = 1 << 6,
  };
  
  struct nfsd4_operation {
  	nfsd4op_func op_func;
  	u32 op_flags;
  	char *op_name;
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
980
981
  	/* Try to get response size before operation */
  	nfsd4op_rsize op_rsize_bop;
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
982
983
984
  };
  
  static struct nfsd4_operation nfsd4_ops[];
f1c7f79b6   Adrian Bunk   [NFSD] uninline n...
985
  static const char *nfsd4_op_name(unsigned opnum);
b001a1b6a   Benny Halevy   nfsd: dprint oper...
986

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
987
  /*
577163559   J. Bruce Fields   nfsd4: complete e...
988
   * Enforce NFSv4.1 COMPOUND ordering rules:
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
989
   *
577163559   J. Bruce Fields   nfsd4: complete e...
990
991
992
   * Also note, enforced elsewhere:
   *	- SEQUENCE other than as first op results in
   *	  NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().)
1d1bc8f20   J. Bruce Fields   nfsd4: support BI...
993
994
   *	- BIND_CONN_TO_SESSION must be the only op in its compound.
   *	  (Enforced in nfsd4_bind_conn_to_session().)
577163559   J. Bruce Fields   nfsd4: complete e...
995
996
997
   *	- DESTROY_SESSION must be the final operation in a compound, if
   *	  sessionid's in SEQUENCE and DESTROY_SESSION are the same.
   *	  (Enforced in nfsd4_destroy_session().)
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
998
   */
577163559   J. Bruce Fields   nfsd4: complete e...
999
  static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
1000
  {
577163559   J. Bruce Fields   nfsd4: complete e...
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  	struct nfsd4_op *op = &args->ops[0];
  
  	/* These ordering requirements don't apply to NFSv4.0: */
  	if (args->minorversion == 0)
  		return nfs_ok;
  	/* This is weird, but OK, not our problem: */
  	if (args->opcnt == 0)
  		return nfs_ok;
  	if (op->status == nfserr_op_illegal)
  		return nfs_ok;
  	if (!(nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
  		return nfserr_op_not_in_session;
  	if (op->opnum == OP_SEQUENCE)
  		return nfs_ok;
  	if (args->opcnt != 1)
  		return nfserr_not_only_op;
  	return nfs_ok;
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
1018
  }
22b032149   J. Bruce Fields   nfsd4: introduce ...
1019
1020
1021
1022
  static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
  {
  	return &nfsd4_ops[op->opnum];
  }
1091006c5   J. Bruce Fields   nfsd: turn on rep...
1023
1024
  bool nfsd4_cache_this_op(struct nfsd4_op *op)
  {
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1025
  	return OPDESC(op)->op_flags & OP_CACHEME;
1091006c5   J. Bruce Fields   nfsd: turn on rep...
1026
  }
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  static bool need_wrongsec_check(struct svc_rqst *rqstp)
  {
  	struct nfsd4_compoundres *resp = rqstp->rq_resp;
  	struct nfsd4_compoundargs *argp = rqstp->rq_argp;
  	struct nfsd4_op *this = &argp->ops[resp->opcnt - 1];
  	struct nfsd4_op *next = &argp->ops[resp->opcnt];
  	struct nfsd4_operation *thisd;
  	struct nfsd4_operation *nextd;
  
  	thisd = OPDESC(this);
  	/*
  	 * Most ops check wronsec on our own; only the putfh-like ops
  	 * have special rules.
  	 */
  	if (!(thisd->op_flags & OP_IS_PUTFH_LIKE))
  		return false;
  	/*
  	 * rfc 5661 2.6.3.1.1.6: don't bother erroring out a
  	 * put-filehandle operation if we're not going to use the
  	 * result:
  	 */
  	if (argp->opcnt == resp->opcnt)
  		return false;
  
  	nextd = OPDESC(next);
  	/*
  	 * Rest of 2.6.3.1.1: certain operations will return WRONGSEC
  	 * errors themselves as necessary; others should check for them
  	 * now:
  	 */
  	return !(nextd->op_flags & OP_HANDLES_WRONGSEC);
  }
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
1059
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1060
1061
   * COMPOUND call.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
1062
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1063
1064
1065
1066
1067
  nfsd4_proc_compound(struct svc_rqst *rqstp,
  		    struct nfsd4_compoundargs *args,
  		    struct nfsd4_compoundres *resp)
  {
  	struct nfsd4_op	*op;
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1068
  	struct nfsd4_operation *opdesc;
e354d571b   Andy Adamson   nfsd: embed nfsd4...
1069
  	struct nfsd4_compound_state *cstate = &resp->cstate;
e57101991   J.Bruce Fields   [PATCH] knfsd: nf...
1070
  	int		slack_bytes;
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1071
  	u32		plen = 0;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
1072
  	__be32		status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1073

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1074
  	resp->xbuf = &rqstp->rq_res;
e354d571b   Andy Adamson   nfsd: embed nfsd4...
1075
1076
  	resp->p = rqstp->rq_res.head[0].iov_base +
  						rqstp->rq_res.head[0].iov_len;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1077
1078
1079
1080
1081
1082
1083
1084
  	resp->tagp = resp->p;
  	/* reserve space for: taglen, tag, and opcnt */
  	resp->p += 2 + XDR_QUADLEN(args->taglen);
  	resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
  	resp->taglen = args->taglen;
  	resp->tag = args->tag;
  	resp->opcnt = 0;
  	resp->rqstp = rqstp;
d87a8ade9   Andy Adamson   nfsd41: access_valid
1085
  	resp->cstate.minorversion = args->minorversion;
e354d571b   Andy Adamson   nfsd: embed nfsd4...
1086
  	resp->cstate.replay_owner = NULL;
26c0c75e6   J. Bruce Fields   nfsd4: fix unlike...
1087
  	resp->cstate.session = NULL;
e354d571b   Andy Adamson   nfsd: embed nfsd4...
1088
1089
  	fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
  	fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
8ff30fa4e   NeilBrown   nfsd: disable def...
1090
1091
1092
1093
1094
  	/*
  	 * Don't use the deferral mechanism for NFSv4; compounds make it
  	 * too hard to avoid non-idempotency problems.
  	 */
  	rqstp->rq_usedeferral = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1095
1096
1097
1098
1099
  
  	/*
  	 * According to RFC3010, this takes precedence over all other errors.
  	 */
  	status = nfserr_minor_vers_mismatch;
8daf220a6   Benny Halevy   nfsd41: control n...
1100
  	if (args->minorversion > nfsd_supported_minorversion)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1101
  		goto out;
577163559   J. Bruce Fields   nfsd4: complete e...
1102
1103
  	status = nfs41_check_op_ordering(args);
  	if (status) {
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
1104
  		op = &args->ops[0];
577163559   J. Bruce Fields   nfsd4: complete e...
1105
  		op->status = status;
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
1106
1107
  		goto encode_op;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1108
1109
  	while (!status && resp->opcnt < args->opcnt) {
  		op = &args->ops[resp->opcnt++];
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1110
1111
1112
1113
  		dprintk("nfsv4 compound op #%d/%d: %d (%s)
  ",
  			resp->opcnt, args->opcnt, op->opnum,
  			nfsd4_op_name(op->opnum));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
  		/*
  		 * The XDR decode routines may have pre-set op->status;
  		 * for example, if there is a miscellaneous XDR error
  		 * it will be set to nfserr_bad_xdr.
  		 */
  		if (op->status)
  			goto encode_op;
  
  		/* We must be able to encode a successful response to
  		 * this operation, with enough room left over to encode a
  		 * failed response to the next operation.  If we don't
  		 * have enough room, fail with ERR_RESOURCE.
  		 */
e57101991   J.Bruce Fields   [PATCH] knfsd: nf...
1127
1128
1129
1130
  		slack_bytes = (char *)resp->end - (char *)resp->p;
  		if (slack_bytes < COMPOUND_SLACK_SPACE
  				+ COMPOUND_ERR_SLACK_SPACE) {
  			BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1131
1132
1133
  			op->status = nfserr_resource;
  			goto encode_op;
  		}
22b032149   J. Bruce Fields   nfsd4: introduce ...
1134
  		opdesc = OPDESC(op);
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1135

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
1136
  		if (!cstate->current_fh.fh_dentry) {
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1137
  			if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
42ca09938   J.Bruce Fields   [PATCH] knfsd: nf...
1138
1139
1140
  				op->status = nfserr_nofilehandle;
  				goto encode_op;
  			}
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
1141
1142
  		} else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
  			  !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
42ca09938   J.Bruce Fields   [PATCH] knfsd: nf...
1143
  			op->status = nfserr_moved;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1144
1145
  			goto encode_op;
  		}
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1146

58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1147
1148
1149
1150
1151
1152
1153
1154
  		/* If op is non-idempotent */
  		if (opdesc->op_flags & OP_MODIFIES_SOMETHING) {
  			plen = opdesc->op_rsize_bop(rqstp, op);
  			op->status = nfsd4_check_resp_size(resp, plen);
  		}
  
  		if (op->status)
  			goto encode_op;
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1155
1156
1157
  		if (opdesc->op_func)
  			op->status = opdesc->op_func(rqstp, cstate, &op->u);
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1158
  			BUG_ON(op->status == nfs_ok);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1159

68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1160
1161
  		if (!op->status && need_wrongsec_check(rqstp))
  			op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1162
  encode_op:
49557cc74   Andy Adamson   nfsd41: Use separ...
1163
  		/* Only from SEQUENCE */
da3846a28   Andy Adamson   nfsd41: nfsd DRC ...
1164
1165
1166
  		if (resp->cstate.status == nfserr_replay_cache) {
  			dprintk("%s NFS4.1 replay from cache
  ", __func__);
abfabf8ca   Andy Adamson   nfsd41: encode re...
1167
  			status = op->status;
da3846a28   Andy Adamson   nfsd41: nfsd DRC ...
1168
1169
  			goto out;
  		}
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
1170
  		if (op->status == nfserr_replay_me) {
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
1171
  			op->replay = &cstate->replay_owner->so_replay;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1172
1173
1174
1175
1176
1177
  			nfsd4_encode_replay(resp, op);
  			status = op->status = op->replay->rp_status;
  		} else {
  			nfsd4_encode_operation(resp, op);
  			status = op->status;
  		}
0407717d8   Benny Halevy   nfsd: dprint each...
1178
1179
1180
1181
1182
  
  		dprintk("nfsv4 compound op %p opcnt %d #%d: %d: status %d
  ",
  			args->ops, args->opcnt, resp->opcnt, op->opnum,
  			be32_to_cpu(status));
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
1183
  		if (cstate->replay_owner) {
5ec094c10   J. Bruce Fields   nfsd4: extend sta...
1184
  			nfs4_unlock_state();
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
1185
  			cstate->replay_owner = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1186
  		}
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
1187
1188
1189
  		/* XXX Ugh, we need to get rid of this kind of special case: */
  		if (op->opnum == OP_READ && op->u.read.rd_filp)
  			fput(op->u.read.rd_filp);
e2b209509   Shankar Anand   [PATCH] knfsd: nf...
1190
1191
  
  		nfsd4_increment_op_stats(op->opnum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1192
  	}
da3846a28   Andy Adamson   nfsd41: nfsd DRC ...
1193
  	resp->cstate.status = status;
e354d571b   Andy Adamson   nfsd: embed nfsd4...
1194
1195
1196
  	fh_put(&resp->cstate.current_fh);
  	fh_put(&resp->cstate.save_fh);
  	BUG_ON(resp->cstate.replay_owner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1197
  out:
2f425878b   Andy Adamson   nfsd: don't use t...
1198
1199
  	/* Reset deferral mechanism for RPC deferrals */
  	rqstp->rq_usedeferral = 1;
3b12cd986   J. Bruce Fields   nfsd: add dprintk...
1200
1201
  	dprintk("nfsv4 compound returned %d
  ", ntohl(status));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1202
1203
  	return status;
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
  #define op_encode_hdr_size		(2)
  #define op_encode_stateid_maxsz		(XDR_QUADLEN(NFS4_STATEID_SIZE))
  #define op_encode_verifier_maxsz	(XDR_QUADLEN(NFS4_VERIFIER_SIZE))
  #define op_encode_change_info_maxsz	(5)
  #define nfs4_fattr_bitmap_maxsz		(4)
  
  #define op_encode_lockowner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
  #define op_encode_lock_denied_maxsz	(8 + op_encode_lockowner_maxsz)
  
  #define nfs4_owner_maxsz		(1 + XDR_QUADLEN(IDMAP_NAMESZ))
  
  #define op_encode_ace_maxsz		(3 + nfs4_owner_maxsz)
  #define op_encode_delegation_maxsz	(1 + op_encode_stateid_maxsz + 1 + \
  					 op_encode_ace_maxsz)
  
  #define op_encode_channel_attrs_maxsz	(6 + 1 + 1)
  
  static inline u32 nfsd4_only_status_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_status_stateid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_stateid_maxsz)* sizeof(__be32);
  }
  
  static inline u32 nfsd4_commit_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_create_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_change_info_maxsz
  		+ nfs4_fattr_bitmap_maxsz) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_change_info_maxsz)
  		* sizeof(__be32);
  }
  
  static inline u32 nfsd4_lock_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_lock_denied_maxsz)
  		* sizeof(__be32);
  }
  
  static inline u32 nfsd4_open_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_stateid_maxsz
  		+ op_encode_change_info_maxsz + 1
  		+ nfs4_fattr_bitmap_maxsz
  		+ op_encode_delegation_maxsz) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_read_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	u32 maxcount = 0, rlen = 0;
  
  	maxcount = svc_max_payload(rqstp);
  	rlen = op->u.read.rd_length;
  
  	if (rlen > maxcount)
  		rlen = maxcount;
  
  	return (op_encode_hdr_size + 2) * sizeof(__be32) + rlen;
  }
  
  static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	u32 rlen = op->u.readdir.rd_maxcount;
  
  	if (rlen > PAGE_SIZE)
  		rlen = PAGE_SIZE;
  
  	return (op_encode_hdr_size + op_encode_verifier_maxsz)
  		 * sizeof(__be32) + rlen;
  }
  
  static inline u32 nfsd4_remove_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_change_info_maxsz)
  		* sizeof(__be32);
  }
  
  static inline u32 nfsd4_rename_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_change_info_maxsz
  		+ op_encode_change_info_maxsz) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + nfs4_fattr_bitmap_maxsz) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\
  		1 + 1 + 0 + /* eir_flags, spr_how, SP4_NONE (for now) */\
  		2 + /*eir_server_owner.so_minor_id */\
  		/* eir_server_owner.so_major_id<> */\
  		XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\
  		/* eir_server_scope<> */\
  		XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\
  		1 + /* eir_server_impl_id array length */\
  		0 /* ignored eir_server_impl_id contents */) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_bind_conn_to_session_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + \
  		XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + /* bctsr_sessid */\
  		2 /* bctsr_dir, use_conn_in_rdma_mode */) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_create_session_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + \
  		XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + /* sessionid */\
  		2 + /* csr_sequence, csr_flags */\
  		op_encode_channel_attrs_maxsz + \
  		op_encode_channel_attrs_maxsz) * sizeof(__be32);
  }
207660163   Benny Halevy   nfsd: remove nfsd...
1341
  static struct nfsd4_operation nfsd4_ops[] = {
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1342
1343
  	[OP_ACCESS] = {
  		.op_func = (nfsd4op_func)nfsd4_access,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1344
  		.op_name = "OP_ACCESS",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1345
1346
1347
  	},
  	[OP_CLOSE] = {
  		.op_func = (nfsd4op_func)nfsd4_close,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1348
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1349
  		.op_name = "OP_CLOSE",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1350
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1351
1352
1353
  	},
  	[OP_COMMIT] = {
  		.op_func = (nfsd4op_func)nfsd4_commit,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1354
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1355
  		.op_name = "OP_COMMIT",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1356
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_commit_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1357
1358
1359
  	},
  	[OP_CREATE] = {
  		.op_func = (nfsd4op_func)nfsd4_create,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1360
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1361
  		.op_name = "OP_CREATE",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1362
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1363
1364
1365
  	},
  	[OP_DELEGRETURN] = {
  		.op_func = (nfsd4op_func)nfsd4_delegreturn,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1366
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1367
  		.op_name = "OP_DELEGRETURN",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1368
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1369
1370
1371
  	},
  	[OP_GETATTR] = {
  		.op_func = (nfsd4op_func)nfsd4_getattr,
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
1372
  		.op_flags = ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1373
  		.op_name = "OP_GETATTR",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1374
1375
1376
  	},
  	[OP_GETFH] = {
  		.op_func = (nfsd4op_func)nfsd4_getfh,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1377
  		.op_name = "OP_GETFH",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1378
1379
1380
  	},
  	[OP_LINK] = {
  		.op_func = (nfsd4op_func)nfsd4_link,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1381
1382
  		.op_flags = ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING
  				| OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1383
  		.op_name = "OP_LINK",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1384
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_link_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1385
1386
1387
  	},
  	[OP_LOCK] = {
  		.op_func = (nfsd4op_func)nfsd4_lock,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1388
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1389
  		.op_name = "OP_LOCK",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1390
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1391
1392
1393
  	},
  	[OP_LOCKT] = {
  		.op_func = (nfsd4op_func)nfsd4_lockt,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1394
  		.op_name = "OP_LOCKT",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1395
1396
1397
  	},
  	[OP_LOCKU] = {
  		.op_func = (nfsd4op_func)nfsd4_locku,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1398
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1399
  		.op_name = "OP_LOCKU",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1400
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1401
1402
1403
  	},
  	[OP_LOOKUP] = {
  		.op_func = (nfsd4op_func)nfsd4_lookup,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1404
  		.op_flags = OP_HANDLES_WRONGSEC,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1405
  		.op_name = "OP_LOOKUP",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1406
1407
1408
  	},
  	[OP_LOOKUPP] = {
  		.op_func = (nfsd4op_func)nfsd4_lookupp,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1409
  		.op_flags = OP_HANDLES_WRONGSEC,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1410
  		.op_name = "OP_LOOKUPP",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1411
1412
1413
  	},
  	[OP_NVERIFY] = {
  		.op_func = (nfsd4op_func)nfsd4_nverify,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1414
  		.op_name = "OP_NVERIFY",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1415
1416
1417
  	},
  	[OP_OPEN] = {
  		.op_func = (nfsd4op_func)nfsd4_open,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1418
  		.op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1419
  		.op_name = "OP_OPEN",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1420
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1421
1422
1423
  	},
  	[OP_OPEN_CONFIRM] = {
  		.op_func = (nfsd4op_func)nfsd4_open_confirm,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1424
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1425
  		.op_name = "OP_OPEN_CONFIRM",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1426
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1427
1428
1429
  	},
  	[OP_OPEN_DOWNGRADE] = {
  		.op_func = (nfsd4op_func)nfsd4_open_downgrade,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1430
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1431
  		.op_name = "OP_OPEN_DOWNGRADE",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1432
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1433
1434
1435
  	},
  	[OP_PUTFH] = {
  		.op_func = (nfsd4op_func)nfsd4_putfh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1436
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1437
  				| OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1438
  		.op_name = "OP_PUTFH",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1439
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1440
  	},
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
1441
  	[OP_PUTPUBFH] = {
a1c8c4d1f   J. Bruce Fields   nfsd4: support pu...
1442
  		.op_func = (nfsd4op_func)nfsd4_putrootfh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1443
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1444
  				| OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1445
  		.op_name = "OP_PUTPUBFH",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1446
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
1447
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1448
1449
  	[OP_PUTROOTFH] = {
  		.op_func = (nfsd4op_func)nfsd4_putrootfh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1450
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1451
  				| OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1452
  		.op_name = "OP_PUTROOTFH",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1453
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1454
1455
1456
  	},
  	[OP_READ] = {
  		.op_func = (nfsd4op_func)nfsd4_read,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1457
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1458
  		.op_name = "OP_READ",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1459
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1460
1461
1462
  	},
  	[OP_READDIR] = {
  		.op_func = (nfsd4op_func)nfsd4_readdir,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1463
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1464
  		.op_name = "OP_READDIR",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1465
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_readdir_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1466
1467
1468
  	},
  	[OP_READLINK] = {
  		.op_func = (nfsd4op_func)nfsd4_readlink,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1469
  		.op_name = "OP_READLINK",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1470
1471
1472
  	},
  	[OP_REMOVE] = {
  		.op_func = (nfsd4op_func)nfsd4_remove,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1473
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1474
  		.op_name = "OP_REMOVE",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1475
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_remove_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1476
1477
1478
  	},
  	[OP_RENAME] = {
  		.op_func = (nfsd4op_func)nfsd4_rename,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1479
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1480
  		.op_name = "OP_RENAME",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1481
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_rename_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1482
1483
1484
  	},
  	[OP_RENEW] = {
  		.op_func = (nfsd4op_func)nfsd4_renew,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1485
1486
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
  				| OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1487
  		.op_name = "OP_RENEW",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1488
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1489
1490
1491
  	},
  	[OP_RESTOREFH] = {
  		.op_func = (nfsd4op_func)nfsd4_restorefh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1492
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1493
  				| OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1494
  		.op_name = "OP_RESTOREFH",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1495
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1496
1497
1498
  	},
  	[OP_SAVEFH] = {
  		.op_func = (nfsd4op_func)nfsd4_savefh,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1499
  		.op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1500
  		.op_name = "OP_SAVEFH",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1501
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1502
  	},
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
1503
1504
  	[OP_SECINFO] = {
  		.op_func = (nfsd4op_func)nfsd4_secinfo,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1505
  		.op_flags = OP_HANDLES_WRONGSEC,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1506
  		.op_name = "OP_SECINFO",
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
1507
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1508
1509
  	[OP_SETATTR] = {
  		.op_func = (nfsd4op_func)nfsd4_setattr,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1510
  		.op_name = "OP_SETATTR",
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1511
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1512
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1513
1514
1515
  	},
  	[OP_SETCLIENTID] = {
  		.op_func = (nfsd4op_func)nfsd4_setclientid,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1516
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1517
  				| OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1518
  		.op_name = "OP_SETCLIENTID",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1519
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_setclientid_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1520
1521
1522
  	},
  	[OP_SETCLIENTID_CONFIRM] = {
  		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1523
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1524
  				| OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1525
  		.op_name = "OP_SETCLIENTID_CONFIRM",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1526
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1527
1528
1529
  	},
  	[OP_VERIFY] = {
  		.op_func = (nfsd4op_func)nfsd4_verify,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1530
  		.op_name = "OP_VERIFY",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1531
1532
1533
  	},
  	[OP_WRITE] = {
  		.op_func = (nfsd4op_func)nfsd4_write,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
1534
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1535
  		.op_name = "OP_WRITE",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1536
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1537
1538
1539
  	},
  	[OP_RELEASE_LOCKOWNER] = {
  		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1540
1541
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
  				| OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1542
  		.op_name = "OP_RELEASE_LOCKOWNER",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1543
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1544
  	},
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1545
1546
1547
1548
  
  	/* NFSv4.1 operations */
  	[OP_EXCHANGE_ID] = {
  		.op_func = (nfsd4op_func)nfsd4_exchange_id,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1549
1550
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1551
  		.op_name = "OP_EXCHANGE_ID",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1552
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_exchange_id_rsize,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1553
  	},
1d1bc8f20   J. Bruce Fields   nfsd4: support BI...
1554
1555
  	[OP_BIND_CONN_TO_SESSION] = {
  		.op_func = (nfsd4op_func)nfsd4_bind_conn_to_session,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1556
1557
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
1d1bc8f20   J. Bruce Fields   nfsd4: support BI...
1558
  		.op_name = "OP_BIND_CONN_TO_SESSION",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1559
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_bind_conn_to_session_rsize,
1d1bc8f20   J. Bruce Fields   nfsd4: support BI...
1560
  	},
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1561
1562
  	[OP_CREATE_SESSION] = {
  		.op_func = (nfsd4op_func)nfsd4_create_session,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1563
1564
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1565
  		.op_name = "OP_CREATE_SESSION",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1566
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_create_session_rsize,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1567
1568
1569
  	},
  	[OP_DESTROY_SESSION] = {
  		.op_func = (nfsd4op_func)nfsd4_destroy_session,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1570
1571
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1572
  		.op_name = "OP_DESTROY_SESSION",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1573
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1574
1575
1576
  	},
  	[OP_SEQUENCE] = {
  		.op_func = (nfsd4op_func)nfsd4_sequence,
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
1577
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
1578
1579
  		.op_name = "OP_SEQUENCE",
  	},
094b5d74f   Benny Halevy   NFSD: allow OP_DE...
1580
  	[OP_DESTROY_CLIENTID] = {
345c28429   Mi Jinlong   nfs41: implement ...
1581
  		.op_func = (nfsd4op_func)nfsd4_destroy_clientid,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1582
1583
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
094b5d74f   Benny Halevy   NFSD: allow OP_DE...
1584
  		.op_name = "OP_DESTROY_CLIENTID",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1585
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
094b5d74f   Benny Halevy   NFSD: allow OP_DE...
1586
  	},
4dc6ec00f   J. Bruce Fields   nfsd4: implement ...
1587
1588
  	[OP_RECLAIM_COMPLETE] = {
  		.op_func = (nfsd4op_func)nfsd4_reclaim_complete,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1589
  		.op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
4dc6ec00f   J. Bruce Fields   nfsd4: implement ...
1590
  		.op_name = "OP_RECLAIM_COMPLETE",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1591
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
4dc6ec00f   J. Bruce Fields   nfsd4: implement ...
1592
  	},
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
1593
1594
  	[OP_SECINFO_NO_NAME] = {
  		.op_func = (nfsd4op_func)nfsd4_secinfo_no_name,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
1595
  		.op_flags = OP_HANDLES_WRONGSEC,
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
1596
1597
  		.op_name = "OP_SECINFO_NO_NAME",
  	},
174568045   Bryan Schumaker   NFSD: Added TEST_...
1598
1599
1600
1601
1602
  	[OP_TEST_STATEID] = {
  		.op_func = (nfsd4op_func)nfsd4_test_stateid,
  		.op_flags = ALLOWED_WITHOUT_FH,
  		.op_name = "OP_TEST_STATEID",
  	},
e1ca12dfb   Bryan Schumaker   NFSD: added FREE_...
1603
1604
  	[OP_FREE_STATEID] = {
  		.op_func = (nfsd4op_func)nfsd4_free_stateid,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1605
  		.op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
e1ca12dfb   Bryan Schumaker   NFSD: added FREE_...
1606
  		.op_name = "OP_FREE_STATEID",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
1607
  		.op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
e1ca12dfb   Bryan Schumaker   NFSD: added FREE_...
1608
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1609
  };
f1c7f79b6   Adrian Bunk   [NFSD] uninline n...
1610
  static const char *nfsd4_op_name(unsigned opnum)
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1611
1612
1613
1614
1615
  {
  	if (opnum < ARRAY_SIZE(nfsd4_ops))
  		return nfsd4_ops[opnum].op_name;
  	return "unknown_operation";
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1616
  #define nfsd4_voidres			nfsd4_voidargs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1617
  struct nfsd4_voidargs { int dummy; };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1618
  static struct svc_procedure		nfsd_procedures4[2] = {
0a93a47f0   Yu Zhiguo   NFSv4: kill off c...
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
  	[NFSPROC4_NULL] = {
  		.pc_func = (svc_procfunc) nfsd4_proc_null,
  		.pc_encode = (kxdrproc_t) nfs4svc_encode_voidres,
  		.pc_argsize = sizeof(struct nfsd4_voidargs),
  		.pc_ressize = sizeof(struct nfsd4_voidres),
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = 1,
  	},
  	[NFSPROC4_COMPOUND] = {
  		.pc_func = (svc_procfunc) nfsd4_proc_compound,
  		.pc_decode = (kxdrproc_t) nfs4svc_decode_compoundargs,
  		.pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres,
  		.pc_argsize = sizeof(struct nfsd4_compoundargs),
  		.pc_ressize = sizeof(struct nfsd4_compoundres),
3e98abffd   J. Bruce Fields   nfsd4: call nfsd4...
1633
  		.pc_release = nfsd4_release_compoundargs,
0a93a47f0   Yu Zhiguo   NFSv4: kill off c...
1634
1635
1636
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = NFSD_BUFSIZE/4,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
  };
  
  struct svc_version	nfsd_version4 = {
  		.vs_vers	= 4,
  		.vs_nproc	= 2,
  		.vs_proc	= nfsd_procedures4,
  		.vs_dispatch	= nfsd_dispatch,
  		.vs_xdrsize	= NFS4_SVC_XDRSIZE,
  };
  
  /*
   * Local variables:
   *  c-basic-offset: 8
   * End:
   */