Blame view

fs/nfsd/nfs4proc.c 89.7 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
   */
880a3a532   J. Bruce Fields   nfsd: fix incorre...
35
  #include <linux/fs_struct.h>
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
36
  #include <linux/file.h>
b0cb90852   Anna Schumaker   nfsd: Add DEALLOC...
37
  #include <linux/falloc.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
38
  #include <linux/slab.h>
e0639dc58   Olga Kornievskaia   NFSD introduce as...
39
  #include <linux/kthread.h>
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
40
  #include <linux/sunrpc/addr.h>
0cfcd405e   Dai Ngo   NFSv4.2: Fix NFS4...
41
  #include <linux/nfs_ssc.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42

58e7b33a5   Mi Jinlong   nfsd41: try to ch...
43
  #include "idmap.h"
9a74af213   Boaz Harrosh   nfsd: Move privat...
44
45
  #include "cache.h"
  #include "xdr4.h"
0a3adadee   J. Bruce Fields   nfsd: make fs/nfs...
46
  #include "vfs.h"
8b70484c6   Tigran Mkrtchyan   nfsd41: handle cu...
47
  #include "current_stateid.h"
3320fef19   Stanislav Kinsbursky   nfsd: use service...
48
  #include "netns.h"
4ac7249ea   Christoph Hellwig   nfsd: use get_acl...
49
  #include "acl.h"
9cf514ccf   Christoph Hellwig   nfsd: implement p...
50
  #include "pnfs.h"
31ef83dc0   Christoph Hellwig   nfsd: add trace e...
51
  #include "trace.h"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52

18032ca06   David Quigley   NFSD: Server impl...
53
54
55
56
57
58
  #ifdef CONFIG_NFSD_V4_SECURITY_LABEL
  #include <linux/security.h>
  
  static inline void
  nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
  {
2b0143b5c   David Howells   VFS: normal files...
59
  	struct inode *inode = d_inode(resfh->fh_dentry);
18032ca06   David Quigley   NFSD: Server impl...
60
  	int status;
5955102c9   Al Viro   wrappers for ->i_...
61
  	inode_lock(inode);
18032ca06   David Quigley   NFSD: Server impl...
62
63
  	status = security_inode_setsecctx(resfh->fh_dentry,
  		label->data, label->len);
5955102c9   Al Viro   wrappers for ->i_...
64
  	inode_unlock(inode);
18032ca06   David Quigley   NFSD: Server impl...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
  
  	if (status)
  		/*
  		 * XXX: We should really fail the whole open, but we may
  		 * already have created a new file, so it may be too
  		 * late.  For now this seems the least of evils:
  		 */
  		bmval[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
  
  	return;
  }
  #else
  static inline void
  nfsd4_security_inode_setsecctx(struct svc_fh *resfh, struct xdr_netobj *label, u32 *bmval)
  { }
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  #define NFSDDBG_FACILITY		NFSDDBG_PROC
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  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;
32ddd944a   J. Bruce Fields   nfsd: opt in to l...
99
  	struct svc_export *exp = cstate->current_fh.fh_export;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
100

916d2d844   J. Bruce Fields   nfsd: clean up su...
101
  	if (!nfsd_attrs_supported(cstate->minorversion, bmval))
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
102
  		return nfserr_attrnotsupp;
916d2d844   J. Bruce Fields   nfsd: clean up su...
103
104
  	if ((bmval[0] & FATTR4_WORD0_ACL) && !IS_POSIXACL(d_inode(dentry)))
  		return nfserr_attrnotsupp;
32ddd944a   J. Bruce Fields   nfsd: opt in to l...
105
106
107
  	if ((bmval[2] & FATTR4_WORD2_SECURITY_LABEL) &&
  			!(exp->ex_flags & NFSEXP_SECURITY_LABEL))
  		return nfserr_attrnotsupp;
916d2d844   J. Bruce Fields   nfsd: clean up su...
108
109
  	if (writable && !bmval_is_subset(bmval, writable))
  		return nfserr_inval;
47057abde   Andreas Gruenbacher   nfsd: add support...
110
111
112
  	if (writable && (bmval[2] & FATTR4_WORD2_MODE_UMASK) &&
  			(bmval[1] & FATTR4_WORD1_MODE))
  		return nfserr_inval;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  	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...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
  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
162
163
164
165
166
167
  static inline void
  fh_dup2(struct svc_fh *dst, struct svc_fh *src)
  {
  	fh_put(dst);
  	dget(src->fh_dentry);
  	if (src->fh_export)
bf18f163e   Kinglong Mee   NFSD: Using exp_g...
168
  		exp_get(src->fh_export);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
170
  	*dst = *src;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
171
  static __be32
dc730e173   J. Bruce Fields   [PATCH] knfsd: nf...
172
  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
173
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
174
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
  
  	if (open->op_truncate &&
  		!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
  		return nfserr_inval;
a043226bc   J. Bruce Fields   nfsd4: permit rea...
179
  	accmode |= NFSD_MAY_READ_IF_EXEC;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
180
  	if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
181
  		accmode |= NFSD_MAY_READ;
9801d8a39   J. Bruce Fields   [PATCH] knfsd: nf...
182
  	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
183
  		accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
57ecb34fe   J. Bruce Fields   nfsd4: fix share ...
184
  	if (open->op_share_deny & NFS4_SHARE_DENY_READ)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
185
  		accmode |= NFSD_MAY_WRITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
187
188
189
190
  
  	status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
  
  	return status;
  }
aadab6c6f   J. Bruce Fields   nfsd4: return nfs...
191
192
  static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
  {
2b0143b5c   David Howells   VFS: normal files...
193
  	umode_t mode = d_inode(fh->fh_dentry)->i_mode;
aadab6c6f   J. Bruce Fields   nfsd4: return nfs...
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  
  	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;
  }
bbc9c36c3   J. Bruce Fields   nfsd4: more sessi...
208
209
210
211
212
213
214
  static void nfsd4_set_open_owner_reply_cache(struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh *resfh)
  {
  	if (nfsd4_has_session(cstate))
  		return;
  	fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
  			&resfh->fh_handle);
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
215
  static __be32
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
216
  do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open, struct svc_fh **resfh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  {
bbc9c36c3   J. Bruce Fields   nfsd4: more sessi...
218
  	struct svc_fh *current_fh = &cstate->current_fh;
7007c90fb   Neil Brown   nfsd: avoid permi...
219
  	int accmode;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
220
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221

c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
222
223
  	*resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
  	if (!*resfh)
59deeb9e5   J. Bruce Fields   nfsd4: reduce do_...
224
  		return nfserr_jukebox;
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
225
  	fh_init(*resfh, NFS4_FHSIZE);
500c24817   zhengbin   nfsd: use true,fa...
226
  	open->op_truncate = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
227
228
  
  	if (open->op_create) {
79fb54abd   Benny Halevy   nfsd41: CREATE_EX...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
  		/* 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
243
244
  		/*
  		 * Note: create modes (UNCHECKED,GUARDED...) are the same
ac6721a13   Mi Jinlong   nfsd41: make sure...
245
  		 * in NFSv4 as in v3 except EXCLUSIVE4_1.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
246
  		 */
880a3a532   J. Bruce Fields   nfsd: fix incorre...
247
  		current->fs->umask = open->op_umask;
ac6721a13   Mi Jinlong   nfsd41: make sure...
248
  		status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
249
  					open->op_fname.len, &open->op_iattr,
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
250
  					*resfh, open->op_createmode,
749997e51   Jeff Layton   knfsd: set the re...
251
  					(u32 *)open->op_verf.data,
856121b2e   J. Bruce Fields   nfsd4: warn on op...
252
  					&open->op_truncate, &open->op_created);
880a3a532   J. Bruce Fields   nfsd: fix incorre...
253
  		current->fs->umask = 0;
749997e51   Jeff Layton   knfsd: set the re...
254

18032ca06   David Quigley   NFSD: Server impl...
255
  		if (!status && open->op_label.len)
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
256
  			nfsd4_security_inode_setsecctx(*resfh, &open->op_label, open->op_bmval);
18032ca06   David Quigley   NFSD: Server impl...
257

99f887263   J. Bruce Fields   nfsd: clarify exc...
258
  		/*
ead8fb8c2   Kinglong Mee   NFSD: Set the att...
259
260
261
  		 * Following rfc 3530 14.2.16, and rfc 5661 18.16.4
  		 * use the returned bitmask to indicate which attributes
  		 * we used to store the verifier:
749997e51   Jeff Layton   knfsd: set the re...
262
  		 */
ead8fb8c2   Kinglong Mee   NFSD: Set the att...
263
264
265
  		if (nfsd_create_is_exclusive(open->op_createmode) && status == 0)
  			open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
  						FATTR4_WORD1_TIME_MODIFY);
4335723e8   J. Bruce Fields   nfsd4: fix delega...
266
267
268
269
270
271
272
  	} else
  		/*
  		 * Note this may exit with the parent still locked.
  		 * We will hold the lock until nfsd4_open's final
  		 * lookup, to prevent renames or unlinks until we've had
  		 * a chance to an acquire a delegation if appropriate.
  		 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
273
  		status = nfsd_lookup(rqstp, current_fh,
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
274
  				     open->op_fname.data, open->op_fname.len, *resfh);
af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
275
276
  	if (status)
  		goto out;
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
277
  	status = nfsd_check_obj_isreg(*resfh);
9dc4e6c4d   J. Bruce Fields   nfsd: don't fail ...
278
279
  	if (status)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
280

9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
281
  	if (is_create_with_attrs(open) && open->op_acl != NULL)
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
282
  		do_set_nfs4_acl(rqstp, *resfh, open->op_acl, open->op_bmval);
9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
283

c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
284
  	nfsd4_set_open_owner_reply_cache(cstate, open, *resfh);
7007c90fb   Neil Brown   nfsd: avoid permi...
285
  	accmode = NFSD_MAY_NOP;
89f6c3362   J. Bruce Fields   nfsd4: delegation...
286
287
  	if (open->op_created ||
  			open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
7007c90fb   Neil Brown   nfsd: avoid permi...
288
  		accmode |= NFSD_MAY_OWNER_OVERRIDE;
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
289
  	status = do_open_permission(rqstp, *resfh, open, accmode);
41fd1e42f   J. Bruce Fields   nfsd4: delay sett...
290
  	set_change_info(&open->op_cinfo, current_fh);
af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
291
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
293
  	return status;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
294
  static __be32
bbc9c36c3   J. Bruce Fields   nfsd4: more sessi...
295
  do_open_fhandle(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
  {
bbc9c36c3   J. Bruce Fields   nfsd4: more sessi...
297
  	struct svc_fh *current_fh = &cstate->current_fh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
298
  	__be32 status;
9f415eb25   J. Bruce Fields   nfsd4: don't allo...
299
  	int accmode = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
302
303
304
305
  	/* 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));
bbc9c36c3   J. Bruce Fields   nfsd4: more sessi...
306
  	nfsd4_set_open_owner_reply_cache(cstate, open, current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
308
309
  
  	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
  		(open->op_iattr.ia_size == 0);
9f415eb25   J. Bruce Fields   nfsd4: don't allo...
310
311
312
313
314
315
316
317
318
319
320
  	/*
  	 * In the delegation case, the client is telling us about an
  	 * open that it *already* performed locally, some time ago.  We
  	 * should let it succeed now if possible.
  	 *
  	 * In the case of a CLAIM_FH open, on the other hand, the client
  	 * may be counting on us to enforce permissions (the Linux 4.1
  	 * client uses this for normal opens, for example).
  	 */
  	if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH)
  		accmode = NFSD_MAY_OWNER_OVERRIDE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321

9f415eb25   J. Bruce Fields   nfsd4: don't allo...
322
  	status = do_open_permission(rqstp, current_fh, open, accmode);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
324
325
  
  	return status;
  }
60adfc50d   Andy Adamson   nfsd41: clientid ...
326
327
328
329
330
331
332
333
334
  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
335

7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
336
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
337
  nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
338
  	   union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
339
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
340
  	struct nfsd4_open *open = &u->open;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
341
  	__be32 status;
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
342
  	struct svc_fh *resfh = NULL;
3320fef19   Stanislav Kinsbursky   nfsd: use service...
343
344
  	struct net *net = SVC_NET(rqstp);
  	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
03f318ca6   J. Bruce Fields   nfsd4: extend rec...
345
  	bool reclaim = false;
6668958fa   Andy Adamson   nfsd41: stateid h...
346

fe0750e5c   J. Bruce Fields   nfsd4: split stat...
347
348
  	dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
349
  		(int)open->op_fname.len, open->op_fname.data,
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
350
  		open->op_openowner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
351

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
352
353
354
  	/* This check required by spec. */
  	if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
  		return nfserr_inval;
500c24817   zhengbin   nfsd: use true,fa...
355
  	open->op_created = false;
ab1350b2b   Mi Jinlong   nfsd41: Deny new ...
356
357
358
359
360
  	/*
  	 * RFC5661 18.51.3
  	 * Before RECLAIM_COMPLETE done, server should deny new lock
  	 */
  	if (nfsd4_has_session(cstate) &&
a52d726bb   Jeff Layton   nfsd: convert nfs...
361
362
  	    !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
  		      &cstate->session->se_client->cl_flags) &&
ab1350b2b   Mi Jinlong   nfsd41: Deny new ...
363
364
  	    open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
  		return nfserr_grace;
60adfc50d   Andy Adamson   nfsd41: clientid ...
365
366
  	if (nfsd4_has_session(cstate))
  		copy_clientid(&open->op_clientid, cstate->session);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
367
  	/* check seqid for replay. set nfs4_owner */
6cd22668e   Kinglong Mee   nfsd: Remove unne...
368
  	status = nfsd4_process_open1(cstate, open, nn);
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
369
  	if (status == nfserr_replay_me) {
fe0750e5c   J. Bruce Fields   nfsd4: split stat...
370
  		struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
371
  		fh_put(&cstate->current_fh);
a4773c08f   J. Bruce Fields   nfsd4: use helper...
372
373
  		fh_copy_shallow(&cstate->current_fh.fh_handle,
  				&rp->rp_openfh);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
374
  		status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
375
376
377
378
379
  		if (status)
  			dprintk("nfsd4_open: replay failed"
  				" restoring previous filehandle
  ");
  		else
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
380
  			status = nfserr_replay_me;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
382
383
  	}
  	if (status)
  		goto out;
9d313b17d   J. Bruce Fields   nfsd4: handle seq...
384
385
386
387
  	if (open->op_xdr_error) {
  		status = open->op_xdr_error;
  		goto out;
  	}
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
388

3c8e03166   Yu Zhiguo   NFSv4: do exact c...
389
390
391
  	status = nfsd4_check_open_attributes(rqstp, cstate, open);
  	if (status)
  		goto out;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
392
393
  	/* 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...
394
  	status = nfserr_grace;
c87fb4a37   J. Bruce Fields   lockd: NLM grace ...
395
  	if (opens_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
cbd0d51a3   J. Bruce Fields   [PATCH] knfsd: fi...
396
397
  		goto out;
  	status = nfserr_no_grace;
c87fb4a37   J. Bruce Fields   lockd: NLM grace ...
398
  	if (!opens_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
cbd0d51a3   J. Bruce Fields   [PATCH] knfsd: fi...
399
  		goto out;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
400

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
401
  	switch (open->op_claim_type) {
0dd3c1921   NeilBrown   [PATCH] nfsd4: su...
402
  		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
403
  		case NFS4_OPEN_CLAIM_NULL:
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
404
  			status = do_open_lookup(rqstp, cstate, open, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
405
406
407
408
  			if (status)
  				goto out;
  			break;
  		case NFS4_OPEN_CLAIM_PREVIOUS:
3320fef19   Stanislav Kinsbursky   nfsd: use service...
409
  			status = nfs4_check_open_reclaim(&open->op_clientid,
0fe492db6   Trond Myklebust   nfsd: Convert nfs...
410
  							 cstate, nn);
0cf99b91c   Mi Jinlong   nfsd41: allow non...
411
412
  			if (status)
  				goto out;
ba5378b66   Jeff Layton   nfsd: fix setting...
413
  			open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
03f318ca6   J. Bruce Fields   nfsd4: extend rec...
414
  			reclaim = true;
df561f668   Gustavo A. R. Silva   treewide: Use fal...
415
  			fallthrough;
8b289b2c2   J. Bruce Fields   nfsd4: implement ...
416
417
  		case NFS4_OPEN_CLAIM_FH:
  		case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
bbc9c36c3   J. Bruce Fields   nfsd4: more sessi...
418
  			status = do_open_fhandle(rqstp, cstate, open);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419
420
  			if (status)
  				goto out;
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
421
  			resfh = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
422
  			break;
8b289b2c2   J. Bruce Fields   nfsd4: implement ...
423
  		case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
424
               	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
2fdada03b   J. Bruce Fields   knfsd: demote som...
425
426
  			dprintk("NFSD: unsupported OPEN claim type %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427
428
429
430
  				open->op_claim_type);
  			status = nfserr_notsupp;
  			goto out;
  		default:
2fdada03b   J. Bruce Fields   knfsd: demote som...
431
432
  			dprintk("NFSD: Invalid OPEN claim type %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433
434
435
436
437
438
439
440
441
  				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.
  	 */
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
442
  	status = nfsd4_process_open2(rqstp, resfh, open);
b3fbfe0e7   Jeff Layton   nfsd: print statu...
443
444
445
446
  	WARN(status && open->op_created,
  	     "nfsd4_process_open2 failed to open newly-created file! status=%u
  ",
  	     be32_to_cpu(status));
03f318ca6   J. Bruce Fields   nfsd4: extend rec...
447
448
  	if (reclaim && !status)
  		nn->somebody_reclaimed = true;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  out:
c0e6bee48   J. Bruce Fields   nfsd4: delay sett...
450
451
452
453
454
  	if (resfh && resfh != &cstate->current_fh) {
  		fh_dup2(&cstate->current_fh, resfh);
  		fh_put(resfh);
  		kfree(resfh);
  	}
422978999   Jeff Layton   nfsd: remove unus...
455
  	nfsd4_cleanup_open_state(cstate, open);
9411b1d4c   J. Bruce Fields   nfsd4: cleanup ha...
456
  	nfsd4_bump_seqid(cstate, status);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
457
458
459
460
  	return status;
  }
  
  /*
9d313b17d   J. Bruce Fields   nfsd4: handle seq...
461
462
463
464
465
466
467
   * OPEN is the only seqid-mutating operation whose decoding can fail
   * with a seqid-mutating error (specifically, decoding of user names in
   * the attributes).  Therefore we have to do some processing to look up
   * the stateowner so that we can bump the seqid.
   */
  static __be32 nfsd4_open_omfg(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_op *op)
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
468
  	struct nfsd4_open *open = &op->u.open;
9d313b17d   J. Bruce Fields   nfsd4: handle seq...
469
470
471
472
473
474
  
  	if (!seqid_mutating_err(ntohl(op->status)))
  		return op->status;
  	if (nfsd4_has_session(cstate))
  		return op->status;
  	open->op_xdr_error = op->status;
eb69853da   Christoph Hellwig   nfsd4: properly t...
475
  	return nfsd4_open(rqstp, cstate, &op->u);
9d313b17d   J. Bruce Fields   nfsd4: handle seq...
476
477
478
  }
  
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
480
   * filehandle-manipulating ops.
   */
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
481
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
482
  nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
483
  	    union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
484
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
485
  	u->getfh = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
487
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
488
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
489
  nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
490
  	    union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
491
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
492
  	struct nfsd4_putfh *putfh = &u->putfh;
b9e8638e3   Olga Kornievskaia   NFSD: allow inter...
493
  	__be32 ret;
eb69853da   Christoph Hellwig   nfsd4: properly t...
494

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
495
496
497
498
  	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);
b9e8638e3   Olga Kornievskaia   NFSD: allow inter...
499
500
501
502
503
504
505
506
  	ret = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
  #ifdef CONFIG_NFSD_V4_2_INTER_SSC
  	if (ret == nfserr_stale && putfh->no_verify) {
  		SET_FH_FLAG(&cstate->current_fh, NFSD4_FH_FOREIGN);
  		ret = 0;
  	}
  #endif
  	return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
507
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
508
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
509
  nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
510
  		union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
511
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
512
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
513

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
514
  	fh_put(&cstate->current_fh);
df547efb0   J. Bruce Fields   knfsd: nfsd4: sim...
515
  	status = exp_pseudoroot(rqstp, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
516
517
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
518
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
519
  nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
520
  		union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
522
  	if (!cstate->save_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  		return nfserr_restorefh;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
524
  	fh_dup2(&cstate->current_fh, &cstate->save_fh);
51100d2b8   Olga Kornievskaia   NFSD generalize n...
525
  	if (HAS_CSTATE_FLAG(cstate, SAVED_STATE_ID_FLAG)) {
37c593c57   Tigran Mkrtchyan   nfsd41: use curre...
526
  		memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t));
51100d2b8   Olga Kornievskaia   NFSD generalize n...
527
  		SET_CSTATE_FLAG(cstate, CURRENT_STATE_ID_FLAG);
37c593c57   Tigran Mkrtchyan   nfsd41: use curre...
528
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
529
530
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
531
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
532
  nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
533
  	     union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
534
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
535
  	fh_dup2(&cstate->save_fh, &cstate->current_fh);
51100d2b8   Olga Kornievskaia   NFSD generalize n...
536
  	if (HAS_CSTATE_FLAG(cstate, CURRENT_STATE_ID_FLAG)) {
37c593c57   Tigran Mkrtchyan   nfsd41: use curre...
537
  		memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t));
51100d2b8   Olga Kornievskaia   NFSD generalize n...
538
  		SET_CSTATE_FLAG(cstate, SAVED_STATE_ID_FLAG);
37c593c57   Tigran Mkrtchyan   nfsd41: use curre...
539
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
540
541
542
543
544
545
  	return nfs_ok;
  }
  
  /*
   * misc nfsv4 ops
   */
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
546
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
547
  nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
548
  	     union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
549
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
550
  	struct nfsd4_access *access = &u->access;
c11d7fd1b   Frank van der Linden   nfsd: take xattr ...
551
  	u32 access_full;
eb69853da   Christoph Hellwig   nfsd4: properly t...
552

c11d7fd1b   Frank van der Linden   nfsd: take xattr ...
553
554
555
556
557
558
  	access_full = NFS3_ACCESS_FULL;
  	if (cstate->minorversion >= 2)
  		access_full |= NFS4_ACCESS_XALIST | NFS4_ACCESS_XAREAD |
  			       NFS4_ACCESS_XAWRITE;
  
  	if (access->ac_req_access & ~access_full)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
559
560
561
  		return nfserr_inval;
  
  	access->ac_resp_access = access->ac_req_access;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
562
563
  	return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
  			   &access->ac_supported);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
564
  }
b9c0ef857   Stanislav Kinsbursky   nfsd: make NFSd s...
565
  static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net)
ab4684d15   Chuck Lever   NFSD: Fix nfs4_ve...
566
  {
27c438f53   Trond Myklebust   nfsd: Support the...
567
  	__be32 *verf = (__be32 *)verifier->data;
ab4684d15   Chuck Lever   NFSD: Fix nfs4_ve...
568

27c438f53   Trond Myklebust   nfsd: Support the...
569
570
571
  	BUILD_BUG_ON(2*sizeof(*verf) != sizeof(verifier->data));
  
  	nfsd_copy_boot_verifier(verf, net_generic(net, nfsd_net_id));
ab4684d15   Chuck Lever   NFSD: Fix nfs4_ve...
572
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
573
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
574
  nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
575
  	     union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
577
  	struct nfsd4_commit *commit = &u->commit;
75c096f75   J. Bruce Fields   nfsd4: it's OK to...
578
  	return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
524ff1af2   Trond Myklebust   nfsd: Ensure samp...
579
580
  			     commit->co_count,
  			     (__be32 *)commit->co_verf.data);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
581
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
582
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
583
  nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
584
  	     union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
585
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
586
  	struct nfsd4_create *create = &u->create;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
  	struct svc_fh resfh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
588
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
589
590
591
  	dev_t rdev;
  
  	fh_init(&resfh, NFS4_FHSIZE);
fa08139d5   J. Bruce Fields   nfsd: drop unnece...
592
  	status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
593
594
  	if (status)
  		return status;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
595
596
597
598
  	status = check_attr_support(rqstp, cstate, create->cr_bmval,
  				    nfsd_attrmask);
  	if (status)
  		return status;
880a3a532   J. Bruce Fields   nfsd: fix incorre...
599
  	current->fs->umask = create->cr_umask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
600
601
  	switch (create->cr_type) {
  	case NF4LNK:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
602
603
  		status = nfsd_symlink(rqstp, &cstate->current_fh,
  				      create->cr_name, create->cr_namelen,
1e444f5bc   Kinglong Mee   NFSD: Remove iatt...
604
  				      create->cr_data, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
605
606
607
  		break;
  
  	case NF4BLK:
880a3a532   J. Bruce Fields   nfsd: fix incorre...
608
  		status = nfserr_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
609
610
611
  		rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  		if (MAJOR(rdev) != create->cr_specdata1 ||
  		    MINOR(rdev) != create->cr_specdata2)
880a3a532   J. Bruce Fields   nfsd: fix incorre...
612
  			goto out_umask;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
613
614
615
  		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
616
617
618
  		break;
  
  	case NF4CHR:
880a3a532   J. Bruce Fields   nfsd: fix incorre...
619
  		status = nfserr_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
621
622
  		rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  		if (MAJOR(rdev) != create->cr_specdata1 ||
  		    MINOR(rdev) != create->cr_specdata2)
880a3a532   J. Bruce Fields   nfsd: fix incorre...
623
  			goto out_umask;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
624
625
626
  		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
627
628
629
  		break;
  
  	case NF4SOCK:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
630
631
632
  		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
633
634
635
  		break;
  
  	case NF4FIFO:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
636
637
638
  		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
639
640
641
642
  		break;
  
  	case NF4DIR:
  		create->cr_iattr.ia_valid &= ~ATTR_SIZE;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
643
644
645
  		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
646
647
648
649
650
  		break;
  
  	default:
  		status = nfserr_badtype;
  	}
9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
651
652
  	if (status)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
653

18032ca06   David Quigley   NFSD: Server impl...
654
655
  	if (create->cr_label.len)
  		nfsd4_security_inode_setsecctx(&resfh, &create->cr_label, create->cr_bmval);
9208faf29   Yu Zhiguo   NFSv4: ACL in ope...
656
657
658
659
660
661
662
663
  	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
664
  	fh_put(&resfh);
880a3a532   J. Bruce Fields   nfsd: fix incorre...
665
666
  out_umask:
  	current->fs->umask = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
667
668
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
669
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
670
  nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
671
  	      union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
673
  	struct nfsd4_getattr *getattr = &u->getattr;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
674
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
675

8837abcab   Miklos Szeredi   nfsd: rename MAY_...
676
  	status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
677
678
679
680
681
  	if (status)
  		return status;
  
  	if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  		return nfserr_inval;
916d2d844   J. Bruce Fields   nfsd: clean up su...
682
683
684
  	getattr->ga_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0];
  	getattr->ga_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1];
  	getattr->ga_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
685

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
686
  	getattr->ga_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687
688
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
689
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
690
  nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
691
  	   union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
693
  	struct nfsd4_link *link = &u->link;
954244604   J. Bruce Fields   nfsd: remove unne...
694
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
695

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
696
697
  	status = nfsd_link(rqstp, &cstate->current_fh,
  			   link->li_name, link->li_namelen, &cstate->save_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
698
  	if (!status)
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
699
  		set_change_info(&link->li_cinfo, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
700
701
  	return status;
  }
0ff7ab467   J. Bruce Fields   nfsd4: move guts ...
702
  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
703
704
  {
  	struct svc_fh tmp_fh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
705
  	__be32 ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
707
  
  	fh_init(&tmp_fh, NFS4_FHSIZE);
df547efb0   J. Bruce Fields   knfsd: nfsd4: sim...
708
709
  	ret = exp_pseudoroot(rqstp, &tmp_fh);
  	if (ret)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710
  		return ret;
0ff7ab467   J. Bruce Fields   nfsd4: move guts ...
711
  	if (tmp_fh.fh_dentry == fh->fh_dentry) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
712
713
714
715
  		fh_put(&tmp_fh);
  		return nfserr_noent;
  	}
  	fh_put(&tmp_fh);
0ff7ab467   J. Bruce Fields   nfsd4: move guts ...
716
717
718
719
720
  	return nfsd_lookup(rqstp, fh, "..", 2, fh);
  }
  
  static __be32
  nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
721
  	      union nfsd4_op_u *u)
0ff7ab467   J. Bruce Fields   nfsd4: move guts ...
722
723
  {
  	return nfsd4_do_lookupp(rqstp, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
724
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
725
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
726
  nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
727
  	     union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
728
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
729
  	return nfsd_lookup(rqstp, &cstate->current_fh,
eb69853da   Christoph Hellwig   nfsd4: properly t...
730
  			   u->lookup.lo_name, u->lookup.lo_len,
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
731
  			   &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
733
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
734
  nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
735
  	   union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
736
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
737
  	struct nfsd4_read *read = &u->read;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
738
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
739

5c4583b2b   Jeff Layton   nfsd: hook up nfs...
740
  	read->rd_nf = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
741
742
  	if (read->rd_offset >= OFFSET_MAX)
  		return nfserr_inval;
87c5942e8   Chuck Lever   nfsd: Add I/O tra...
743
744
  	trace_nfsd_read_start(rqstp, &cstate->current_fh,
  			      read->rd_offset, read->rd_length);
9b3234b92   J. Bruce Fields   nfsd4: disable ze...
745
746
747
748
749
750
751
752
753
  	/*
  	 * If we do a zero copy read, then a client will see read data
  	 * that reflects the state of the file *after* performing the
  	 * following compound.
  	 *
  	 * To ensure proper ordering, we therefore turn off zero copy if
  	 * the client wants us to do more in this compound:
  	 */
  	if (!nfsd4_last_compound_op(rqstp))
779fb0f3a   Jeff Layton   sunrpc: move rq_s...
754
  		clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
9b3234b92   J. Bruce Fields   nfsd4: disable ze...
755

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
756
  	/* check stateid */
aa0d6aed4   Anna Schumaker   nfsd: Pass fileha...
757
758
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
  					&read->rd_stateid, RD_STATE,
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
759
  					&read->rd_nf, NULL);
af90f707f   Christoph Hellwig   nfsd: take struct...
760
  	if (status) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
761
762
763
764
765
766
  		dprintk("NFSD: nfsd4_read: couldn't process stateid!
  ");
  		goto out;
  	}
  	status = nfs_ok;
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
767
  	read->rd_rqstp = rqstp;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
768
  	read->rd_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
  	return status;
  }
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
771
772
773
774
  
  static void
  nfsd4_read_release(union nfsd4_op_u *u)
  {
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
775
776
  	if (u->read.rd_nf)
  		nfsd_file_put(u->read.rd_nf);
87c5942e8   Chuck Lever   nfsd: Add I/O tra...
777
778
  	trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp,
  			     u->read.rd_offset, u->read.rd_length);
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
779
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
780
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
781
  nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
782
  	      union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
783
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
784
  	struct nfsd4_readdir *readdir = &u->readdir;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
785
786
787
788
789
790
791
  	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;
916d2d844   J. Bruce Fields   nfsd: clean up su...
792
793
794
  	readdir->rd_bmval[0] &= nfsd_suppattrs[cstate->minorversion][0];
  	readdir->rd_bmval[1] &= nfsd_suppattrs[cstate->minorversion][1];
  	readdir->rd_bmval[2] &= nfsd_suppattrs[cstate->minorversion][2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
795

832023bff   Bernd Schubert   nfsd4: Remove che...
796
  	if ((cookie == 1) || (cookie == 2) ||
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
797
798
799
800
  	    (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...
801
  	readdir->rd_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
802
803
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
804
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
805
  nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
806
  	       union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
807
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
808
809
  	u->readlink.rl_rqstp = rqstp;
  	u->readlink.rl_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
810
811
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
812
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
813
  nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
814
  	     union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
815
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
816
  	struct nfsd4_remove *remove = &u->remove;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
817
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
818

c87fb4a37   J. Bruce Fields   lockd: NLM grace ...
819
  	if (opens_in_grace(SVC_NET(rqstp)))
c815afc73   NeilBrown   [PATCH] nfsd4: bl...
820
  		return nfserr_grace;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
821
822
  	status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
  			     remove->rm_name, remove->rm_namelen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
823
  	if (!status) {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
824
825
  		fh_unlock(&cstate->current_fh);
  		set_change_info(&remove->rm_cinfo, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
826
827
828
  	}
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
829
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
830
  nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
831
  	     union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
832
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
833
  	struct nfsd4_rename *rename = &u->rename;
954244604   J. Bruce Fields   nfsd: remove unne...
834
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835

f8f71d006   J. Bruce Fields   nfsd4: forbid all...
836
  	if (opens_in_grace(SVC_NET(rqstp)))
c815afc73   NeilBrown   [PATCH] nfsd4: bl...
837
  		return nfserr_grace;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
838
839
  	status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
  			     rename->rn_snamelen, &cstate->current_fh,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
840
  			     rename->rn_tname, rename->rn_tnamelen);
2a6cf944c   J. Bruce Fields   nfsd4: don't rema...
841
842
843
844
845
  	if (status)
  		return status;
  	set_change_info(&rename->rn_sinfo, &cstate->current_fh);
  	set_change_info(&rename->rn_tinfo, &cstate->save_fh);
  	return nfs_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
846
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
847
  static __be32
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
848
  nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
849
  	      union nfsd4_op_u *u)
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
850
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
851
  	struct nfsd4_secinfo *secinfo = &u->secinfo;
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
852
853
854
  	struct svc_export *exp;
  	struct dentry *dentry;
  	__be32 err;
29a78a3ed   J. Bruce Fields   nfsd4: make fh_ve...
855
856
857
  	err = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_EXEC);
  	if (err)
  		return err;
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
858
859
860
861
862
  	err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
  				    secinfo->si_name, secinfo->si_namelen,
  				    &exp, &dentry);
  	if (err)
  		return err;
2f6fc056e   J. Bruce Fields   nfsd: fix deadloc...
863
  	fh_unlock(&cstate->current_fh);
2b0143b5c   David Howells   VFS: normal files...
864
  	if (d_really_is_negative(dentry)) {
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
865
866
867
868
869
  		exp_put(exp);
  		err = nfserr_noent;
  	} else
  		secinfo->si_exp = exp;
  	dput(dentry);
56560b9ae   J. Bruce Fields   nfsd4: 4.1 SECINF...
870
871
872
  	if (cstate->minorversion)
  		/* See rfc 5661 section 2.6.3.1.1.8 */
  		fh_put(&cstate->current_fh);
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
873
874
875
876
  	return err;
  }
  
  static __be32
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
877
  nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
878
  		union nfsd4_op_u *u)
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
879
880
  {
  	__be32 err;
eb69853da   Christoph Hellwig   nfsd4: properly t...
881
  	switch (u->secinfo_no_name.sin_style) {
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
882
883
884
885
886
887
888
889
890
891
  	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;
  	}
bf18f163e   Kinglong Mee   NFSD: Using exp_g...
892

eb69853da   Christoph Hellwig   nfsd4: properly t...
893
  	u->secinfo_no_name.sin_exp = exp_get(cstate->current_fh.fh_export);
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
894
895
896
  	fh_put(&cstate->current_fh);
  	return nfs_ok;
  }
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
897
898
899
900
901
902
  static void
  nfsd4_secinfo_release(union nfsd4_op_u *u)
  {
  	if (u->secinfo.si_exp)
  		exp_put(u->secinfo.si_exp);
  }
ec572b9e8   Eryu Guan   nfsd4: define nfs...
903
904
905
906
907
908
  static void
  nfsd4_secinfo_no_name_release(union nfsd4_op_u *u)
  {
  	if (u->secinfo_no_name.sin_exp)
  		exp_put(u->secinfo_no_name.sin_exp);
  }
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
909
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
910
  nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
911
  	      union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
912
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
913
  	struct nfsd4_setattr *setattr = &u->setattr;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
914
  	__be32 status = nfs_ok;
96f6f9850   Al Viro   nfsd: fix b0rken ...
915
  	int err;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
916

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
917
  	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
af90f707f   Christoph Hellwig   nfsd: take struct...
918
  		status = nfs4_preprocess_stateid_op(rqstp, cstate,
aa0d6aed4   Anna Schumaker   nfsd: Pass fileha...
919
  				&cstate->current_fh, &setattr->sa_stateid,
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
920
  				WR_STATE, NULL, NULL);
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
921
  		if (status) {
3e3b48009   Greg Banks   [PATCH] knfsd: ad...
922
923
  			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!
  ");
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
924
925
  			return status;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
926
  	}
96f6f9850   Al Viro   nfsd: fix b0rken ...
927
928
929
  	err = fh_want_write(&cstate->current_fh);
  	if (err)
  		return nfserrno(err);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
930
  	status = nfs_ok;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
931
932
933
934
935
  
  	status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
  				    nfsd_attrmask);
  	if (status)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
936
  	if (setattr->sa_acl != NULL)
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
937
938
  		status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
  					    setattr->sa_acl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
939
  	if (status)
18f335aff   Dave Hansen   [PATCH] r/o bind ...
940
  		goto out;
18032ca06   David Quigley   NFSD: Server impl...
941
942
943
944
945
  	if (setattr->sa_label.len)
  		status = nfsd4_set_nfs4_label(rqstp, &cstate->current_fh,
  				&setattr->sa_label);
  	if (status)
  		goto out;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
946
  	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
2a1aa4892   Arnd Bergmann   nfsd: pass a 64-b...
947
  				0, (time64_t)0);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
948
  out:
bad0dcffc   Al Viro   new helpers: fh_{...
949
  	fh_drop_write(&cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
950
951
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
952
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
953
  nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
954
  	    union nfsd4_op_u *u)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
956
  	struct nfsd4_write *write = &u->write;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
957
  	stateid_t *stateid = &write->wr_stateid;
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
958
  	struct nfsd_file *nf = NULL;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
959
  	__be32 status = nfs_ok;
31dec2538   David Shaw   Short write in nf...
960
  	unsigned long cnt;
ffe1137ba   J. Bruce Fields   nfsd4: delay fill...
961
  	int nvecs;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
963
964
  	if (write->wr_offset >= OFFSET_MAX)
  		return nfserr_inval;
d890be159   Chuck Lever   nfsd: Add I/O tra...
965
966
967
  	cnt = write->wr_buflen;
  	trace_nfsd_write_start(rqstp, &cstate->current_fh,
  			       write->wr_offset, cnt);
aa0d6aed4   Anna Schumaker   nfsd: Pass fileha...
968
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
969
  						stateid, WR_STATE, &nf, NULL);
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
970
971
972
973
974
  	if (status) {
  		dprintk("NFSD: nfsd4_write: couldn't process stateid!
  ");
  		return status;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
975
  	write->wr_how_written = write->wr_stable_how;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
976

3fd9557ae   Chuck Lever   NFSD: Refactor th...
977
978
  	nvecs = svc_fill_write_vector(rqstp, write->wr_pagelist,
  				      &write->wr_head, write->wr_buflen);
ffe1137ba   J. Bruce Fields   nfsd4: delay fill...
979
  	WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
16f8f8941   Trond Myklebust   nfsd: Allow nfsd_...
980
  	status = nfsd_vfs_write(rqstp, &cstate->current_fh, nf,
af90f707f   Christoph Hellwig   nfsd: take struct...
981
  				write->wr_offset, rqstp->rq_vec, nvecs, &cnt,
19e0663ff   Trond Myklebust   nfsd: Ensure samp...
982
983
  				write->wr_how_written,
  				(__be32 *)write->wr_verifier.data);
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
984
  	nfsd_file_put(nf);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985

31dec2538   David Shaw   Short write in nf...
986
  	write->wr_bytes_written = cnt;
d890be159   Chuck Lever   nfsd: Add I/O tra...
987
988
  	trace_nfsd_write_done(rqstp, &cstate->current_fh,
  			      write->wr_offset, cnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
989
  	return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
990
  }
24bab4912   Anna Schumaker   NFSD: Implement SEEK
991
  static __be32
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
992
  nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
993
994
  		  stateid_t *src_stateid, struct nfsd_file **src,
  		  stateid_t *dst_stateid, struct nfsd_file **dst)
ffa0160a1   Christoph Hellwig   nfsd: implement t...
995
  {
ffa0160a1   Christoph Hellwig   nfsd: implement t...
996
  	__be32 status;
01310bb7c   Scott Mayhew   nfsd: COPY and CL...
997
998
  	if (!cstate->save_fh.fh_dentry)
  		return nfserr_nofilehandle;
ffa0160a1   Christoph Hellwig   nfsd: implement t...
999
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
1000
  					    src_stateid, RD_STATE, src, NULL);
ffa0160a1   Christoph Hellwig   nfsd: implement t...
1001
1002
1003
1004
1005
1006
1007
  	if (status) {
  		dprintk("NFSD: %s: couldn't process src stateid!
  ", __func__);
  		goto out;
  	}
  
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
1008
  					    dst_stateid, WR_STATE, dst, NULL);
ffa0160a1   Christoph Hellwig   nfsd: implement t...
1009
1010
1011
1012
1013
1014
1015
  	if (status) {
  		dprintk("NFSD: %s: couldn't process dst stateid!
  ", __func__);
  		goto out_put_src;
  	}
  
  	/* fix up for NFS-specific error code */
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1016
1017
  	if (!S_ISREG(file_inode((*src)->nf_file)->i_mode) ||
  	    !S_ISREG(file_inode((*dst)->nf_file)->i_mode)) {
ffa0160a1   Christoph Hellwig   nfsd: implement t...
1018
1019
1020
  		status = nfserr_wrong_type;
  		goto out_put_dst;
  	}
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1021
1022
1023
  out:
  	return status;
  out_put_dst:
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1024
  	nfsd_file_put(*dst);
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1025
  out_put_src:
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1026
  	nfsd_file_put(*src);
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1027
1028
1029
1030
1031
  	goto out;
  }
  
  static __be32
  nfsd4_clone(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1032
  		union nfsd4_op_u *u)
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1033
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1034
  	struct nfsd4_clone *clone = &u->clone;
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1035
  	struct nfsd_file *src, *dst;
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1036
1037
1038
1039
1040
1041
  	__be32 status;
  
  	status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
  				   &clone->cl_dst_stateid, &dst);
  	if (status)
  		goto out;
b66ae6dd0   Trond Myklebust   nfsd: Pass the nf...
1042
1043
  	status = nfsd4_clone_file_range(src, clone->cl_src_pos,
  			dst, clone->cl_dst_pos, clone->cl_count,
a25e3726b   Trond Myklebust   nfsd: Ensure CLON...
1044
  			EX_ISSYNC(cstate->current_fh.fh_export));
ffa0160a1   Christoph Hellwig   nfsd: implement t...
1045

5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1046
1047
  	nfsd_file_put(dst);
  	nfsd_file_put(src);
ffa0160a1   Christoph Hellwig   nfsd: implement t...
1048
1049
1050
  out:
  	return status;
  }
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  void nfs4_put_copy(struct nfsd4_copy *copy)
  {
  	if (!refcount_dec_and_test(&copy->refcount))
  		return;
  	kfree(copy);
  }
  
  static bool
  check_and_set_stop_copy(struct nfsd4_copy *copy)
  {
  	bool value;
  
  	spin_lock(&copy->cp_clp->async_lock);
  	value = copy->stopped;
  	if (!copy->stopped)
  		copy->stopped = true;
  	spin_unlock(&copy->cp_clp->async_lock);
  	return value;
  }
  
  static void nfsd4_stop_copy(struct nfsd4_copy *copy)
  {
  	/* only 1 thread should stop the copy */
  	if (!check_and_set_stop_copy(copy))
  		kthread_stop(copy->copy_task);
  	nfs4_put_copy(copy);
  }
  
  static struct nfsd4_copy *nfsd4_get_copy(struct nfs4_client *clp)
  {
  	struct nfsd4_copy *copy = NULL;
  
  	spin_lock(&clp->async_lock);
  	if (!list_empty(&clp->async_copies)) {
  		copy = list_first_entry(&clp->async_copies, struct nfsd4_copy,
  					copies);
  		refcount_inc(&copy->refcount);
  	}
  	spin_unlock(&clp->async_lock);
  	return copy;
  }
  
  void nfsd4_shutdown_copy(struct nfs4_client *clp)
  {
  	struct nfsd4_copy *copy;
  
  	while ((copy = nfsd4_get_copy(clp)) != NULL)
  		nfsd4_stop_copy(copy);
  }
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
  #ifdef CONFIG_NFSD_V4_2_INTER_SSC
  
  extern struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
  				   struct nfs_fh *src_fh,
  				   nfs4_stateid *stateid);
  extern void nfs42_ssc_close(struct file *filep);
  
  extern void nfs_sb_deactive(struct super_block *sb);
  
  #define NFSD42_INTERSSC_MOUNTOPS "vers=4.2,addr=%s,sec=sys"
f2453978a   Chuck Lever   NFSD: Fix imprope...
1110
  /*
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
   * Support one copy source server for now.
   */
  static __be32
  nfsd4_interssc_connect(struct nl4_server *nss, struct svc_rqst *rqstp,
  		       struct vfsmount **mount)
  {
  	struct file_system_type *type;
  	struct vfsmount *ss_mnt;
  	struct nfs42_netaddr *naddr;
  	struct sockaddr_storage tmp_addr;
  	size_t tmp_addrlen, match_netid_len = 3;
  	char *startsep = "", *endsep = "", *match_netid = "tcp";
  	char *ipaddr, *dev_name, *raw_data;
b8290ca25   Olga Kornievskaia   NFSD fix nfserro ...
1124
1125
  	int len, raw_len;
  	__be32 status = nfserr_inval;
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
  
  	naddr = &nss->u.nl4_addr;
  	tmp_addrlen = rpc_uaddr2sockaddr(SVC_NET(rqstp), naddr->addr,
  					 naddr->addr_len,
  					 (struct sockaddr *)&tmp_addr,
  					 sizeof(tmp_addr));
  	if (tmp_addrlen == 0)
  		goto out_err;
  
  	if (tmp_addr.ss_family == AF_INET6) {
  		startsep = "[";
  		endsep = "]";
  		match_netid = "tcp6";
  		match_netid_len = 4;
  	}
  
  	if (naddr->netid_len != match_netid_len ||
  		strncmp(naddr->netid, match_netid, naddr->netid_len))
  		goto out_err;
  
  	/* Construct the raw data for the vfs_kern_mount call */
  	len = RPC_MAX_ADDRBUFLEN + 1;
  	ipaddr = kzalloc(len, GFP_KERNEL);
  	if (!ipaddr)
  		goto out_err;
  
  	rpc_ntop((struct sockaddr *)&tmp_addr, ipaddr, len);
  
  	/* 2 for ipv6 endsep and startsep. 3 for ":/" and trailing '/0'*/
  
  	raw_len = strlen(NFSD42_INTERSSC_MOUNTOPS) + strlen(ipaddr);
  	raw_data = kzalloc(raw_len, GFP_KERNEL);
  	if (!raw_data)
  		goto out_free_ipaddr;
  
  	snprintf(raw_data, raw_len, NFSD42_INTERSSC_MOUNTOPS, ipaddr);
b8290ca25   Olga Kornievskaia   NFSD fix nfserro ...
1162
  	status = nfserr_nodev;
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
  	type = get_fs_type("nfs");
  	if (!type)
  		goto out_free_rawdata;
  
  	/* Set the server:<export> for the vfs_kern_mount call */
  	dev_name = kzalloc(len + 5, GFP_KERNEL);
  	if (!dev_name)
  		goto out_free_rawdata;
  	snprintf(dev_name, len + 5, "%s%s%s:/", startsep, ipaddr, endsep);
  
  	/* Use an 'internal' mount: SB_KERNMOUNT -> MNT_INTERNAL */
  	ss_mnt = vfs_kern_mount(type, SB_KERNMOUNT, dev_name, raw_data);
  	module_put(type->owner);
  	if (IS_ERR(ss_mnt))
  		goto out_free_devname;
  
  	status = 0;
  	*mount = ss_mnt;
  
  out_free_devname:
  	kfree(dev_name);
  out_free_rawdata:
  	kfree(raw_data);
  out_free_ipaddr:
  	kfree(ipaddr);
  out_err:
  	return status;
  }
  
  static void
  nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
  {
0cfcd405e   Dai Ngo   NFSv4.2: Fix NFS4...
1195
  	nfs_do_sb_deactive(ss_mnt->mnt_sb);
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1196
1197
  	mntput(ss_mnt);
  }
f2453978a   Chuck Lever   NFSD: Fix imprope...
1198
  /*
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1199
   * Verify COPY destination stateid.
f2453978a   Chuck Lever   NFSD: Fix imprope...
1200
   *
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1201
1202
1203
1204
1205
   * Connect to the source server with NFSv4.1.
   * Create the source struct file for nfsd_copy_range.
   * Called with COPY cstate:
   *    SAVED_FH: source filehandle
   *    CURRENT_FH: destination filehandle
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1206
1207
1208
1209
1210
1211
1212
1213
   */
  static __be32
  nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
  		      struct nfsd4_compound_state *cstate,
  		      struct nfsd4_copy *copy, struct vfsmount **mount)
  {
  	struct svc_fh *s_fh = NULL;
  	stateid_t *s_stid = &copy->cp_src_stateid;
b8290ca25   Olga Kornievskaia   NFSD fix nfserro ...
1214
  	__be32 status = nfserr_inval;
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
  
  	/* Verify the destination stateid and set dst struct file*/
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
  					    &copy->cp_dst_stateid,
  					    WR_STATE, &copy->nf_dst, NULL);
  	if (status)
  		goto out;
  
  	status = nfsd4_interssc_connect(&copy->cp_src, rqstp, mount);
  	if (status)
  		goto out;
  
  	s_fh = &cstate->save_fh;
  
  	copy->c_fh.size = s_fh->fh_handle.fh_size;
  	memcpy(copy->c_fh.data, &s_fh->fh_handle.fh_base, copy->c_fh.size);
3f9544ca6   Olga Kornievskaia   NFSD: fix seqid i...
1231
  	copy->stateid.seqid = cpu_to_be32(s_stid->si_generation);
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
  	memcpy(copy->stateid.other, (void *)&s_stid->si_opaque,
  	       sizeof(stateid_opaque_t));
  
  	status = 0;
  out:
  	return status;
  }
  
  static void
  nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
  			struct nfsd_file *dst)
  {
  	nfs42_ssc_close(src->nf_file);
36e1e5ba9   Dai Ngo   NFSD: Fix use-aft...
1245
  	/* 'src' is freed by nfsd4_do_async_copy */
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
  	nfsd_file_put(dst);
  	mntput(ss_mnt);
  }
  
  #else /* CONFIG_NFSD_V4_2_INTER_SSC */
  
  static __be32
  nfsd4_setup_inter_ssc(struct svc_rqst *rqstp,
  		      struct nfsd4_compound_state *cstate,
  		      struct nfsd4_copy *copy,
  		      struct vfsmount **mount)
  {
  	*mount = NULL;
b8290ca25   Olga Kornievskaia   NFSD fix nfserro ...
1259
  	return nfserr_inval;
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
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
  }
  
  static void
  nfsd4_cleanup_inter_ssc(struct vfsmount *ss_mnt, struct nfsd_file *src,
  			struct nfsd_file *dst)
  {
  }
  
  static void
  nfsd4_interssc_disconnect(struct vfsmount *ss_mnt)
  {
  }
  
  static struct file *nfs42_ssc_open(struct vfsmount *ss_mnt,
  				   struct nfs_fh *src_fh,
  				   nfs4_stateid *stateid)
  {
  	return NULL;
  }
  #endif /* CONFIG_NFSD_V4_2_INTER_SSC */
  
  static __be32
  nfsd4_setup_intra_ssc(struct svc_rqst *rqstp,
  		      struct nfsd4_compound_state *cstate,
  		      struct nfsd4_copy *copy)
  {
  	return nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
  				 &copy->nf_src, &copy->cp_dst_stateid,
  				 &copy->nf_dst);
  }
  
  static void
  nfsd4_cleanup_intra_ssc(struct nfsd_file *src, struct nfsd_file *dst)
  {
  	nfsd_file_put(src);
  	nfsd_file_put(dst);
  }
e0639dc58   Olga Kornievskaia   NFSD introduce as...
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
  
  static void nfsd4_cb_offload_release(struct nfsd4_callback *cb)
  {
  	struct nfsd4_copy *copy = container_of(cb, struct nfsd4_copy, cp_cb);
  
  	nfs4_put_copy(copy);
  }
  
  static int nfsd4_cb_offload_done(struct nfsd4_callback *cb,
  				 struct rpc_task *task)
  {
  	return 1;
  }
  
  static const struct nfsd4_callback_ops nfsd4_cb_offload_ops = {
  	.release = nfsd4_cb_offload_release,
  	.done = nfsd4_cb_offload_done
  };
  
  static void nfsd4_init_copy_res(struct nfsd4_copy *copy, bool sync)
  {
  	copy->cp_res.wr_stable_how = NFS_UNSTABLE;
  	copy->cp_synchronous = sync;
  	gen_boot_verifier(&copy->cp_res.wr_verifier, copy->cp_clp->net);
  }
  
  static ssize_t _nfsd_copy_file_range(struct nfsd4_copy *copy)
  {
  	ssize_t bytes_copied = 0;
  	size_t bytes_total = copy->cp_count;
  	u64 src_pos = copy->cp_src_pos;
  	u64 dst_pos = copy->cp_dst_pos;
  
  	do {
  		if (kthread_should_stop())
  			break;
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1333
1334
1335
  		bytes_copied = nfsd_copy_file_range(copy->nf_src->nf_file,
  				src_pos, copy->nf_dst->nf_file, dst_pos,
  				bytes_total);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
  		if (bytes_copied <= 0)
  			break;
  		bytes_total -= bytes_copied;
  		copy->cp_res.wr_bytes_written += bytes_copied;
  		src_pos += bytes_copied;
  		dst_pos += bytes_copied;
  	} while (bytes_total > 0 && !copy->cp_synchronous);
  	return bytes_copied;
  }
  
  static __be32 nfsd4_do_copy(struct nfsd4_copy *copy, bool sync)
  {
  	__be32 status;
  	ssize_t bytes;
  
  	bytes = _nfsd_copy_file_range(copy);
  	/* for async copy, we ignore the error, client can always retry
  	 * to get the error
  	 */
  	if (bytes < 0 && !copy->cp_res.wr_bytes_written)
  		status = nfserrno(bytes);
  	else {
  		nfsd4_init_copy_res(copy, sync);
  		status = nfs_ok;
  	}
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1361
1362
1363
1364
1365
  	if (!copy->cp_intra) /* Inter server SSC */
  		nfsd4_cleanup_inter_ssc(copy->ss_mnt, copy->nf_src,
  					copy->nf_dst);
  	else
  		nfsd4_cleanup_intra_ssc(copy->nf_src, copy->nf_dst);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1366
1367
  	return status;
  }
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1368
  static int dup_copy_fields(struct nfsd4_copy *src, struct nfsd4_copy *dst)
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1369
1370
1371
1372
1373
1374
1375
1376
  {
  	dst->cp_src_pos = src->cp_src_pos;
  	dst->cp_dst_pos = src->cp_dst_pos;
  	dst->cp_count = src->cp_count;
  	dst->cp_synchronous = src->cp_synchronous;
  	memcpy(&dst->cp_res, &src->cp_res, sizeof(src->cp_res));
  	memcpy(&dst->fh, &src->fh, sizeof(src->fh));
  	dst->cp_clp = src->cp_clp;
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1377
  	dst->nf_dst = nfsd_file_get(src->nf_dst);
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1378
1379
1380
  	dst->cp_intra = src->cp_intra;
  	if (src->cp_intra) /* for inter, file_src doesn't exist yet */
  		dst->nf_src = nfsd_file_get(src->nf_src);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1381
  	memcpy(&dst->cp_stateid, &src->cp_stateid, sizeof(src->cp_stateid));
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1382
1383
1384
1385
1386
1387
  	memcpy(&dst->cp_src, &src->cp_src, sizeof(struct nl4_server));
  	memcpy(&dst->stateid, &src->stateid, sizeof(src->stateid));
  	memcpy(&dst->c_fh, &src->c_fh, sizeof(src->c_fh));
  	dst->ss_mnt = src->ss_mnt;
  
  	return 0;
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1388
1389
1390
1391
  }
  
  static void cleanup_async_copy(struct nfsd4_copy *copy)
  {
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
1392
  	nfs4_free_copy_state(copy);
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1393
  	nfsd_file_put(copy->nf_dst);
2e577f0fa   Olga Kornievskaia   NFSD fixing possi...
1394
1395
  	if (copy->cp_intra)
  		nfsd_file_put(copy->nf_src);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
  	spin_lock(&copy->cp_clp->async_lock);
  	list_del(&copy->copies);
  	spin_unlock(&copy->cp_clp->async_lock);
  	nfs4_put_copy(copy);
  }
  
  static int nfsd4_do_async_copy(void *data)
  {
  	struct nfsd4_copy *copy = (struct nfsd4_copy *)data;
  	struct nfsd4_copy *cb_copy;
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
  	if (!copy->cp_intra) { /* Inter server SSC */
  		copy->nf_src = kzalloc(sizeof(struct nfsd_file), GFP_KERNEL);
  		if (!copy->nf_src) {
  			copy->nfserr = nfserr_serverfault;
  			nfsd4_interssc_disconnect(copy->ss_mnt);
  			goto do_callback;
  		}
  		copy->nf_src->nf_file = nfs42_ssc_open(copy->ss_mnt, &copy->c_fh,
  					      &copy->stateid);
  		if (IS_ERR(copy->nf_src->nf_file)) {
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1416
1417
1418
1419
1420
  			copy->nfserr = nfserr_offload_denied;
  			nfsd4_interssc_disconnect(copy->ss_mnt);
  			goto do_callback;
  		}
  	}
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1421
  	copy->nfserr = nfsd4_do_copy(copy, 0);
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1422
  do_callback:
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1423
1424
1425
  	cb_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
  	if (!cb_copy)
  		goto out;
49a361327   Dai Ngo   NFSD: fix missing...
1426
  	refcount_set(&cb_copy->refcount, 1);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1427
1428
1429
1430
1431
1432
1433
1434
  	memcpy(&cb_copy->cp_res, &copy->cp_res, sizeof(copy->cp_res));
  	cb_copy->cp_clp = copy->cp_clp;
  	cb_copy->nfserr = copy->nfserr;
  	memcpy(&cb_copy->fh, &copy->fh, sizeof(copy->fh));
  	nfsd4_init_cb(&cb_copy->cp_cb, cb_copy->cp_clp,
  			&nfsd4_cb_offload_ops, NFSPROC4_CLNT_CB_OFFLOAD);
  	nfsd4_run_cb(&cb_copy->cp_cb);
  out:
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1435
1436
  	if (!copy->cp_intra)
  		kfree(copy->nf_src);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1437
1438
1439
  	cleanup_async_copy(copy);
  	return 0;
  }
ffa0160a1   Christoph Hellwig   nfsd: implement t...
1440
  static __be32
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1441
  nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1442
  		union nfsd4_op_u *u)
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1443
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1444
  	struct nfsd4_copy *copy = &u->copy;
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1445
  	__be32 status;
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1446
  	struct nfsd4_copy *async_copy = NULL;
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1447

ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
  	if (!copy->cp_intra) { /* Inter server SSC */
  		if (!inter_copy_offload_enable || copy->cp_synchronous) {
  			status = nfserr_notsupp;
  			goto out;
  		}
  		status = nfsd4_setup_inter_ssc(rqstp, cstate, copy,
  				&copy->ss_mnt);
  		if (status)
  			return nfserr_offload_denied;
  	} else {
  		status = nfsd4_setup_intra_ssc(rqstp, cstate, copy);
  		if (status)
  			return status;
  	}
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1462

e0639dc58   Olga Kornievskaia   NFSD introduce as...
1463
1464
1465
1466
1467
  	copy->cp_clp = cstate->clp;
  	memcpy(&copy->fh, &cstate->current_fh.fh_handle,
  		sizeof(struct knfsd_fh));
  	if (!copy->cp_synchronous) {
  		struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1468

e0639dc58   Olga Kornievskaia   NFSD introduce as...
1469
1470
1471
  		status = nfserrno(-ENOMEM);
  		async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
  		if (!async_copy)
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1472
1473
1474
  			goto out_err;
  		if (!nfs4_init_copy_state(nn, copy))
  			goto out_err;
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1475
1476
1477
  		refcount_set(&async_copy->refcount, 1);
  		memcpy(&copy->cp_res.cb_stateid, &copy->cp_stateid,
  			sizeof(copy->cp_stateid));
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1478
1479
1480
  		status = dup_copy_fields(copy, async_copy);
  		if (status)
  			goto out_err;
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1481
1482
1483
1484
1485
1486
1487
1488
1489
  		async_copy->copy_task = kthread_create(nfsd4_do_async_copy,
  				async_copy, "%s", "copy thread");
  		if (IS_ERR(async_copy->copy_task))
  			goto out_err;
  		spin_lock(&async_copy->cp_clp->async_lock);
  		list_add(&async_copy->copies,
  				&async_copy->cp_clp->async_copies);
  		spin_unlock(&async_copy->cp_clp->async_lock);
  		wake_up_process(async_copy->copy_task);
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1490
  		status = nfs_ok;
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1491
  	} else {
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1492
  		status = nfsd4_do_copy(copy, 1);
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1493
  	}
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1494
1495
  out:
  	return status;
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1496
  out_err:
18f428d4e   Olga Kornievskaia   NFSD fixing possi...
1497
1498
  	if (async_copy)
  		cleanup_async_copy(async_copy);
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1499
1500
1501
  	status = nfserrno(-ENOMEM);
  	if (!copy->cp_intra)
  		nfsd4_interssc_disconnect(copy->ss_mnt);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
  	goto out;
  }
  
  struct nfsd4_copy *
  find_async_copy(struct nfs4_client *clp, stateid_t *stateid)
  {
  	struct nfsd4_copy *copy;
  
  	spin_lock(&clp->async_lock);
  	list_for_each_entry(copy, &clp->async_copies, copies) {
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1512
  		if (memcmp(&copy->cp_stateid.stid, stateid, NFS4_STATEID_SIZE))
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1513
1514
1515
1516
1517
1518
1519
  			continue;
  		refcount_inc(&copy->refcount);
  		spin_unlock(&clp->async_lock);
  		return copy;
  	}
  	spin_unlock(&clp->async_lock);
  	return NULL;
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
1520
1521
1522
  }
  
  static __be32
885e2bf3e   Olga Kornievskaia   NFSD OFFLOAD_CANC...
1523
1524
1525
1526
  nfsd4_offload_cancel(struct svc_rqst *rqstp,
  		     struct nfsd4_compound_state *cstate,
  		     union nfsd4_op_u *u)
  {
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1527
  	struct nfsd4_offload_status *os = &u->offload_status;
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1528
1529
1530
1531
  	struct nfsd4_copy *copy;
  	struct nfs4_client *clp = cstate->clp;
  
  	copy = find_async_copy(clp, &os->stateid);
ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1532
1533
1534
1535
1536
  	if (!copy) {
  		struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
  
  		return manage_cpntf_state(nn, &os->stateid, clp, NULL);
  	} else
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1537
  		nfsd4_stop_copy(copy);
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1538

ce0887ac9   Olga Kornievskaia   NFSD add nfs4 int...
1539
  	return nfs_ok;
885e2bf3e   Olga Kornievskaia   NFSD OFFLOAD_CANC...
1540
1541
1542
  }
  
  static __be32
51911868f   Olga Kornievskaia   NFSD COPY_NOTIFY xdr
1543
1544
1545
  nfsd4_copy_notify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  		  union nfsd4_op_u *u)
  {
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
  	struct nfsd4_copy_notify *cn = &u->copy_notify;
  	__be32 status;
  	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
  	struct nfs4_stid *stid;
  	struct nfs4_cpntf_state *cps;
  	struct nfs4_client *clp = cstate->clp;
  
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
  					&cn->cpn_src_stateid, RD_STATE, NULL,
  					&stid);
  	if (status)
  		return status;
  
  	cn->cpn_sec = nn->nfsd4_lease;
  	cn->cpn_nsec = 0;
  
  	status = nfserrno(-ENOMEM);
  	cps = nfs4_alloc_init_cpntf_state(nn, stid);
  	if (!cps)
  		goto out;
  	memcpy(&cn->cpn_cnr_stateid, &cps->cp_stateid.stid, sizeof(stateid_t));
  	memcpy(&cps->cp_p_stateid, &stid->sc_stateid, sizeof(stateid_t));
  	memcpy(&cps->cp_p_clid, &clp->cl_clientid, sizeof(clientid_t));
  
  	/* For now, only return one server address in cpn_src, the
  	 * address used by the client to connect to this server.
  	 */
  	cn->cpn_src.nl4_type = NL4_NETADDR;
  	status = nfsd4_set_netaddr((struct sockaddr *)&rqstp->rq_daddr,
  				 &cn->cpn_src.u.nl4_addr);
  	WARN_ON_ONCE(status);
  	if (status) {
  		nfs4_put_cpntf_state(nn, cps);
  		goto out;
  	}
  out:
  	nfs4_put_stid(stid);
  	return status;
51911868f   Olga Kornievskaia   NFSD COPY_NOTIFY xdr
1584
1585
1586
  }
  
  static __be32
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1587
1588
1589
  nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  		struct nfsd4_fallocate *fallocate, int flags)
  {
0d4d6720c   J. Bruce Fields   nfsd4: skip unuse...
1590
  	__be32 status;
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1591
  	struct nfsd_file *nf;
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1592

aa0d6aed4   Anna Schumaker   nfsd: Pass fileha...
1593
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1594
  					    &fallocate->falloc_stateid,
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
1595
  					    WR_STATE, &nf, NULL);
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1596
1597
1598
1599
1600
  	if (status != nfs_ok) {
  		dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!
  ");
  		return status;
  	}
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1601
  	status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, nf->nf_file,
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1602
1603
1604
  				     fallocate->falloc_offset,
  				     fallocate->falloc_length,
  				     flags);
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1605
  	nfsd_file_put(nf);
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1606
1607
  	return status;
  }
6308bc98e   Olga Kornievskaia   NFSD OFFLOAD_STAT...
1608
1609
1610
1611
1612
  static __be32
  nfsd4_offload_status(struct svc_rqst *rqstp,
  		     struct nfsd4_compound_state *cstate,
  		     union nfsd4_op_u *u)
  {
e0639dc58   Olga Kornievskaia   NFSD introduce as...
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
  	struct nfsd4_offload_status *os = &u->offload_status;
  	__be32 status = 0;
  	struct nfsd4_copy *copy;
  	struct nfs4_client *clp = cstate->clp;
  
  	copy = find_async_copy(clp, &os->stateid);
  	if (copy) {
  		os->count = copy->cp_res.wr_bytes_written;
  		nfs4_put_copy(copy);
  	} else
  		status = nfserr_bad_stateid;
  
  	return status;
6308bc98e   Olga Kornievskaia   NFSD OFFLOAD_STAT...
1626
  }
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1627
1628
1629
  
  static __be32
  nfsd4_allocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1630
  	       union nfsd4_op_u *u)
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1631
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1632
  	return nfsd4_fallocate(rqstp, cstate, &u->allocate, 0);
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
1633
1634
1635
  }
  
  static __be32
b0cb90852   Anna Schumaker   nfsd: Add DEALLOC...
1636
  nfsd4_deallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1637
  		 union nfsd4_op_u *u)
b0cb90852   Anna Schumaker   nfsd: Add DEALLOC...
1638
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1639
  	return nfsd4_fallocate(rqstp, cstate, &u->deallocate,
b0cb90852   Anna Schumaker   nfsd: Add DEALLOC...
1640
1641
1642
1643
  			       FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE);
  }
  
  static __be32
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1644
  nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1645
  	   union nfsd4_op_u *u)
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1646
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1647
  	struct nfsd4_seek *seek = &u->seek;
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1648
1649
  	int whence;
  	__be32 status;
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1650
  	struct nfsd_file *nf;
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1651

aa0d6aed4   Anna Schumaker   nfsd: Pass fileha...
1652
  	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1653
  					    &seek->seek_stateid,
624322f1a   Olga Kornievskaia   NFSD add COPY_NOT...
1654
  					    RD_STATE, &nf, NULL);
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
  	if (status) {
  		dprintk("NFSD: nfsd4_seek: couldn't process stateid!
  ");
  		return status;
  	}
  
  	switch (seek->seek_whence) {
  	case NFS4_CONTENT_DATA:
  		whence = SEEK_DATA;
  		break;
  	case NFS4_CONTENT_HOLE:
  		whence = SEEK_HOLE;
  		break;
  	default:
  		status = nfserr_union_notsupp;
  		goto out;
  	}
  
  	/*
  	 * Note:  This call does change file->f_pos, but nothing in NFSD
  	 *        should ever file->f_pos.
  	 */
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1677
  	seek->seek_pos = vfs_llseek(nf->nf_file, seek->seek_offset, whence);
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1678
1679
  	if (seek->seek_pos < 0)
  		status = nfserrno(seek->seek_pos);
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1680
  	else if (seek->seek_pos >= i_size_read(file_inode(nf->nf_file)))
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1681
1682
1683
  		seek->seek_eof = true;
  
  out:
5c4583b2b   Jeff Layton   nfsd: hook up nfs...
1684
  	nfsd_file_put(nf);
24bab4912   Anna Schumaker   NFSD: Implement SEEK
1685
1686
  	return status;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1687
1688
1689
1690
1691
  /* 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...
1692
  static __be32
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
1693
  _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
1694
  	     struct nfsd4_verify *verify)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1695
  {
2ebbc012a   Al Viro   [PATCH] xdr annot...
1696
  	__be32 *buf, *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1697
  	int count;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
1698
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1699

8837abcab   Miklos Szeredi   nfsd: rename MAY_...
1700
  	status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1701
1702
  	if (status)
  		return status;
3c8e03166   Yu Zhiguo   NFSv4: do exact c...
1703
1704
1705
  	status = check_attr_support(rqstp, cstate, verify->ve_bmval, NULL);
  	if (status)
  		return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
  	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...
1718
  		return nfserr_jukebox;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1719

84822d0b3   J. Bruce Fields   nfsd4: simplify n...
1720
  	p = buf;
d51846586   J. Bruce Fields   nfsd4: tweak nfsd...
1721
  	status = nfsd4_encode_fattr_to_buf(&p, count, &cstate->current_fh,
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
1722
  				    cstate->current_fh.fh_export,
d51846586   J. Bruce Fields   nfsd4: tweak nfsd...
1723
1724
  				    cstate->current_fh.fh_dentry,
  				    verify->ve_bmval,
406a7ea97   Frank Filz   nfsd: Allow AIX c...
1725
  				    rqstp, 0);
41ae6e714   J. Bruce Fields   nfsd4: better VER...
1726
1727
1728
1729
  	/*
  	 * If nfsd4_encode_fattr() ran out of space, assume that's because
  	 * the attributes are longer (hence different) than those given:
  	 */
84822d0b3   J. Bruce Fields   nfsd4: simplify n...
1730
  	if (status == nfserr_resource)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1731
1732
1733
  		status = nfserr_not_same;
  	if (status)
  		goto out_kfree;
95ec28cda   Benny Halevy   nfsd: dynamically...
1734
1735
  	/* skip bitmap */
  	p = buf + 1 + ntohl(buf[0]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
  	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...
1746
1747
  static __be32
  nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1748
  	      union nfsd4_op_u *u)
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
1749
1750
  {
  	__be32 status;
eb69853da   Christoph Hellwig   nfsd4: properly t...
1751
  	status = _nfsd4_verify(rqstp, cstate, &u->verify);
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
1752
1753
1754
1755
1756
  	return status == nfserr_not_same ? nfs_ok : status;
  }
  
  static __be32
  nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1757
  	     union nfsd4_op_u *u)
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
1758
1759
  {
  	__be32 status;
eb69853da   Christoph Hellwig   nfsd4: properly t...
1760
  	status = _nfsd4_verify(rqstp, cstate, &u->nverify);
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
1761
1762
  	return status == nfserr_same ? nfs_ok : status;
  }
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1763
1764
1765
1766
  #ifdef CONFIG_NFSD_PNFS
  static const struct nfsd4_layout_ops *
  nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type)
  {
8a4c39268   Jeff Layton   nfsd: allow nfsd ...
1767
  	if (!exp->ex_layout_types) {
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1768
1769
1770
1771
  		dprintk("%s: export does not support pNFS
  ", __func__);
  		return NULL;
  	}
b550a32e6   Ari Kauppi   nfsd: fix undefin...
1772
1773
  	if (layout_type >= LAYOUT_TYPE_MAX ||
  	    !(exp->ex_layout_types & (1 << layout_type))) {
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
  		dprintk("%s: layout type %d not supported
  ",
  			__func__, layout_type);
  		return NULL;
  	}
  
  	return nfsd4_layout_ops[layout_type];
  }
  
  static __be32
  nfsd4_getdeviceinfo(struct svc_rqst *rqstp,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1785
  		struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1786
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1787
  	struct nfsd4_getdeviceinfo *gdp = &u->getdeviceinfo;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
  	const struct nfsd4_layout_ops *ops;
  	struct nfsd4_deviceid_map *map;
  	struct svc_export *exp;
  	__be32 nfserr;
  
  	dprintk("%s: layout_type %u dev_id [0x%llx:0x%x] maxcnt %u
  ",
  	       __func__,
  	       gdp->gd_layout_type,
  	       gdp->gd_devid.fsid_idx, gdp->gd_devid.generation,
  	       gdp->gd_maxcount);
  
  	map = nfsd4_find_devid_map(gdp->gd_devid.fsid_idx);
  	if (!map) {
  		dprintk("%s: couldn't find device ID to export mapping!
  ",
  			__func__);
  		return nfserr_noent;
  	}
  
  	exp = rqst_exp_find(rqstp, map->fsid_type, map->fsid);
  	if (IS_ERR(exp)) {
  		dprintk("%s: could not find device id
  ", __func__);
  		return nfserr_noent;
  	}
  
  	nfserr = nfserr_layoutunavailable;
  	ops = nfsd4_layout_verify(exp, gdp->gd_layout_type);
  	if (!ops)
  		goto out;
  
  	nfserr = nfs_ok;
f99d4fbda   Christoph Hellwig   nfsd: add SCSI la...
1821
1822
  	if (gdp->gd_maxcount != 0) {
  		nfserr = ops->proc_getdeviceinfo(exp->ex_path.mnt->mnt_sb,
d7c920d13   Tom Haynes   nfsd: flex file d...
1823
  				rqstp, cstate->session->se_client, gdp);
f99d4fbda   Christoph Hellwig   nfsd: add SCSI la...
1824
  	}
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1825
1826
  
  	gdp->gd_notify_types &= ops->notify_types;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1827
  out:
a1420384e   Kinglong Mee   NFSD: Put exports...
1828
  	exp_put(exp);
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1829
1830
  	return nfserr;
  }
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
1831
1832
1833
1834
1835
  static void
  nfsd4_getdeviceinfo_release(union nfsd4_op_u *u)
  {
  	kfree(u->getdeviceinfo.gd_device);
  }
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1836
1837
  static __be32
  nfsd4_layoutget(struct svc_rqst *rqstp,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1838
  		struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1839
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1840
  	struct nfsd4_layoutget *lgp = &u->layoutget;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1841
1842
1843
1844
  	struct svc_fh *current_fh = &cstate->current_fh;
  	const struct nfsd4_layout_ops *ops;
  	struct nfs4_layout_stateid *ls;
  	__be32 nfserr;
66282ec1c   Benjamin Coddington   nfsd4: permit lay...
1845
  	int accmode = NFSD_MAY_READ_IF_EXEC;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1846
1847
1848
  
  	switch (lgp->lg_seg.iomode) {
  	case IOMODE_READ:
66282ec1c   Benjamin Coddington   nfsd4: permit lay...
1849
  		accmode |= NFSD_MAY_READ;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1850
1851
  		break;
  	case IOMODE_RW:
66282ec1c   Benjamin Coddington   nfsd4: permit lay...
1852
  		accmode |= NFSD_MAY_READ | NFSD_MAY_WRITE;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
  		break;
  	default:
  		dprintk("%s: invalid iomode %d
  ",
  			__func__, lgp->lg_seg.iomode);
  		nfserr = nfserr_badiomode;
  		goto out;
  	}
  
  	nfserr = fh_verify(rqstp, current_fh, 0, accmode);
  	if (nfserr)
  		goto out;
  
  	nfserr = nfserr_layoutunavailable;
  	ops = nfsd4_layout_verify(current_fh->fh_export, lgp->lg_layout_type);
  	if (!ops)
  		goto out;
  
  	/*
  	 * Verify minlength and range as per RFC5661:
  	 *  o  If loga_length is less than loga_minlength,
  	 *     the metadata server MUST return NFS4ERR_INVAL.
  	 *  o  If the sum of loga_offset and loga_minlength exceeds
  	 *     NFS4_UINT64_MAX, and loga_minlength is not
  	 *     NFS4_UINT64_MAX, the error NFS4ERR_INVAL MUST result.
  	 *  o  If the sum of loga_offset and loga_length exceeds
  	 *     NFS4_UINT64_MAX, and loga_length is not NFS4_UINT64_MAX,
  	 *     the error NFS4ERR_INVAL MUST result.
  	 */
  	nfserr = nfserr_inval;
  	if (lgp->lg_seg.length < lgp->lg_minlength ||
  	    (lgp->lg_minlength != NFS4_MAX_UINT64 &&
  	     lgp->lg_minlength > NFS4_MAX_UINT64 - lgp->lg_seg.offset) ||
  	    (lgp->lg_seg.length != NFS4_MAX_UINT64 &&
  	     lgp->lg_seg.length > NFS4_MAX_UINT64 - lgp->lg_seg.offset))
  		goto out;
  	if (lgp->lg_seg.length == 0)
  		goto out;
  
  	nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lgp->lg_sid,
  						true, lgp->lg_layout_type, &ls);
31ef83dc0   Christoph Hellwig   nfsd: add trace e...
1894
  	if (nfserr) {
f394b62b7   Chuck Lever   nfsd: Add "nfsd_"...
1895
  		trace_nfsd_layout_get_lookup_fail(&lgp->lg_sid);
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1896
  		goto out;
31ef83dc0   Christoph Hellwig   nfsd: add trace e...
1897
  	}
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1898

c5c707f96   Christoph Hellwig   nfsd: implement p...
1899
1900
1901
  	nfserr = nfserr_recallconflict;
  	if (atomic_read(&ls->ls_stid.sc_file->fi_lo_recalls))
  		goto out_put_stid;
2b0143b5c   David Howells   VFS: normal files...
1902
  	nfserr = ops->proc_layoutget(d_inode(current_fh->fh_dentry),
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1903
1904
1905
1906
1907
1908
1909
  				     current_fh, lgp);
  	if (nfserr)
  		goto out_put_stid;
  
  	nfserr = nfsd4_insert_layout(lgp, ls);
  
  out_put_stid:
cc8a55320   Jeff Layton   nfsd: serialize l...
1910
  	mutex_unlock(&ls->ls_mutex);
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1911
1912
1913
1914
  	nfs4_put_stid(&ls->ls_stid);
  out:
  	return nfserr;
  }
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
1915
1916
1917
1918
1919
  static void
  nfsd4_layoutget_release(union nfsd4_op_u *u)
  {
  	kfree(u->layoutget.lg_content);
  }
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1920
1921
  static __be32
  nfsd4_layoutcommit(struct svc_rqst *rqstp,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1922
  		struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1923
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1924
  	struct nfsd4_layoutcommit *lcp = &u->layoutcommit;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
  	const struct nfsd4_layout_seg *seg = &lcp->lc_seg;
  	struct svc_fh *current_fh = &cstate->current_fh;
  	const struct nfsd4_layout_ops *ops;
  	loff_t new_size = lcp->lc_last_wr + 1;
  	struct inode *inode;
  	struct nfs4_layout_stateid *ls;
  	__be32 nfserr;
  
  	nfserr = fh_verify(rqstp, current_fh, 0, NFSD_MAY_WRITE);
  	if (nfserr)
  		goto out;
  
  	nfserr = nfserr_layoutunavailable;
  	ops = nfsd4_layout_verify(current_fh->fh_export, lcp->lc_layout_type);
  	if (!ops)
  		goto out;
2b0143b5c   David Howells   VFS: normal files...
1941
  	inode = d_inode(current_fh->fh_dentry);
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
  
  	nfserr = nfserr_inval;
  	if (new_size <= seg->offset) {
  		dprintk("pnfsd: last write before layout segment
  ");
  		goto out;
  	}
  	if (new_size > seg->offset + seg->length) {
  		dprintk("pnfsd: last write beyond layout segment
  ");
  		goto out;
  	}
  	if (!lcp->lc_newoffset && new_size > i_size_read(inode)) {
  		dprintk("pnfsd: layoutcommit beyond EOF
  ");
  		goto out;
  	}
  
  	nfserr = nfsd4_preprocess_layout_stateid(rqstp, cstate, &lcp->lc_sid,
  						false, lcp->lc_layout_type,
  						&ls);
  	if (nfserr) {
f394b62b7   Chuck Lever   nfsd: Add "nfsd_"...
1964
  		trace_nfsd_layout_commit_lookup_fail(&lcp->lc_sid);
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1965
1966
1967
1968
1969
  		/* fixup error code as per RFC5661 */
  		if (nfserr == nfserr_bad_stateid)
  			nfserr = nfserr_badlayout;
  		goto out;
  	}
cc8a55320   Jeff Layton   nfsd: serialize l...
1970
1971
  	/* LAYOUTCOMMIT does not require any serialization */
  	mutex_unlock(&ls->ls_mutex);
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1972
1973
1974
1975
1976
1977
  	if (new_size > i_size_read(inode)) {
  		lcp->lc_size_chg = 1;
  		lcp->lc_newsize = new_size;
  	} else {
  		lcp->lc_size_chg = 0;
  	}
d8398fc11   Kinglong Mee   nfsd: Set lc_size...
1978
  	nfserr = ops->proc_layoutcommit(inode, lcp);
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1979
1980
1981
1982
1983
1984
1985
  	nfs4_put_stid(&ls->ls_stid);
  out:
  	return nfserr;
  }
  
  static __be32
  nfsd4_layoutreturn(struct svc_rqst *rqstp,
eb69853da   Christoph Hellwig   nfsd4: properly t...
1986
  		struct nfsd4_compound_state *cstate, union nfsd4_op_u *u)
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1987
  {
eb69853da   Christoph Hellwig   nfsd4: properly t...
1988
  	struct nfsd4_layoutreturn *lrp = &u->layoutreturn;
9cf514ccf   Christoph Hellwig   nfsd: implement p...
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
  	struct svc_fh *current_fh = &cstate->current_fh;
  	__be32 nfserr;
  
  	nfserr = fh_verify(rqstp, current_fh, 0, NFSD_MAY_NOP);
  	if (nfserr)
  		goto out;
  
  	nfserr = nfserr_layoutunavailable;
  	if (!nfsd4_layout_verify(current_fh->fh_export, lrp->lr_layout_type))
  		goto out;
  
  	switch (lrp->lr_seg.iomode) {
  	case IOMODE_READ:
  	case IOMODE_RW:
  	case IOMODE_ANY:
  		break;
  	default:
  		dprintk("%s: invalid iomode %d
  ", __func__,
  			lrp->lr_seg.iomode);
  		nfserr = nfserr_inval;
  		goto out;
  	}
  
  	switch (lrp->lr_return_type) {
  	case RETURN_FILE:
  		nfserr = nfsd4_return_file_layouts(rqstp, cstate, lrp);
  		break;
  	case RETURN_FSID:
  	case RETURN_ALL:
  		nfserr = nfsd4_return_client_layouts(rqstp, cstate, lrp);
  		break;
  	default:
  		dprintk("%s: invalid return_type %d
  ", __func__,
  			lrp->lr_return_type);
  		nfserr = nfserr_inval;
  		break;
  	}
  out:
  	return nfserr;
  }
  #endif /* CONFIG_NFSD_PNFS */
23e50fe3a   Frank van der Linden   nfsd: implement t...
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
  static __be32
  nfsd4_getxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	       union nfsd4_op_u *u)
  {
  	struct nfsd4_getxattr *getxattr = &u->getxattr;
  
  	return nfsd_getxattr(rqstp, &cstate->current_fh,
  			     getxattr->getxa_name, &getxattr->getxa_buf,
  			     &getxattr->getxa_len);
  }
  
  static __be32
  nfsd4_setxattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	   union nfsd4_op_u *u)
  {
  	struct nfsd4_setxattr *setxattr = &u->setxattr;
  	__be32 ret;
  
  	if (opens_in_grace(SVC_NET(rqstp)))
  		return nfserr_grace;
  
  	ret = nfsd_setxattr(rqstp, &cstate->current_fh, setxattr->setxa_name,
  			    setxattr->setxa_buf, setxattr->setxa_len,
  			    setxattr->setxa_flags);
  
  	if (!ret)
  		set_change_info(&setxattr->setxa_cinfo, &cstate->current_fh);
  
  	return ret;
  }
  
  static __be32
  nfsd4_listxattrs(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	   union nfsd4_op_u *u)
  {
  	/*
  	 * Get the entire list, then copy out only the user attributes
  	 * in the encode function.
  	 */
  	return nfsd_listxattr(rqstp, &cstate->current_fh,
  			     &u->listxattrs.lsxa_buf, &u->listxattrs.lsxa_len);
  }
  
  static __be32
  nfsd4_removexattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	   union nfsd4_op_u *u)
  {
  	struct nfsd4_removexattr *removexattr = &u->removexattr;
  	__be32 ret;
  
  	if (opens_in_grace(SVC_NET(rqstp)))
  		return nfserr_grace;
  
  	ret = nfsd_removexattr(rqstp, &cstate->current_fh,
  	    removexattr->rmxa_name);
  
  	if (!ret)
  		set_change_info(&removexattr->rmxa_cinfo, &cstate->current_fh);
  
  	return ret;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2093
2094
2095
  /*
   * NULL call.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
2096
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
2097
  nfsd4_proc_null(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2098
  {
cc028a10a   Chuck Lever   NFSD: Hoist statu...
2099
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2100
  }
e2b209509   Shankar Anand   [PATCH] knfsd: nf...
2101
2102
2103
2104
2105
  static inline void nfsd4_increment_op_stats(u32 opnum)
  {
  	if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
  		nfsdstats.nfs4_opcount[opnum]++;
  }
bb2a8b0cd   Christoph Hellwig   nfsd4: const-ify ...
2106
  static const struct nfsd4_operation nfsd4_ops[];
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2107

f1c7f79b6   Adrian Bunk   [NFSD] uninline n...
2108
  static const char *nfsd4_op_name(unsigned opnum);
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2109

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2110
  /*
577163559   J. Bruce Fields   nfsd4: complete e...
2111
   * Enforce NFSv4.1 COMPOUND ordering rules:
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2112
   *
577163559   J. Bruce Fields   nfsd4: complete e...
2113
2114
2115
   * 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...
2116
2117
   *	- 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...
2118
2119
2120
   *	- 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...
2121
   */
577163559   J. Bruce Fields   nfsd4: complete e...
2122
  static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2123
  {
7a04cfda7   J. Bruce Fields   nfsd: clarify che...
2124
  	struct nfsd4_op *first_op = &args->ops[0];
577163559   J. Bruce Fields   nfsd4: complete e...
2125
2126
2127
2128
2129
2130
2131
  
  	/* 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;
7a04cfda7   J. Bruce Fields   nfsd: clarify che...
2132
  	if (first_op->status == nfserr_op_illegal)
577163559   J. Bruce Fields   nfsd4: complete e...
2133
  		return nfs_ok;
7a04cfda7   J. Bruce Fields   nfsd: clarify che...
2134
  	if (!(nfsd4_ops[first_op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
577163559   J. Bruce Fields   nfsd4: complete e...
2135
  		return nfserr_op_not_in_session;
7a04cfda7   J. Bruce Fields   nfsd: clarify che...
2136
  	if (first_op->opnum == OP_SEQUENCE)
577163559   J. Bruce Fields   nfsd4: complete e...
2137
  		return nfs_ok;
7a04cfda7   J. Bruce Fields   nfsd: clarify che...
2138
2139
2140
2141
2142
  	/*
  	 * So first_op is something allowed outside a session, like
  	 * EXCHANGE_ID; but then it has to be the only op in the
  	 * compound:
  	 */
577163559   J. Bruce Fields   nfsd4: complete e...
2143
2144
2145
  	if (args->opcnt != 1)
  		return nfserr_not_only_op;
  	return nfs_ok;
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2146
  }
f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2147
  const struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
22b032149   J. Bruce Fields   nfsd4: introduce ...
2148
2149
2150
  {
  	return &nfsd4_ops[op->opnum];
  }
1091006c5   J. Bruce Fields   nfsd: turn on rep...
2151
2152
  bool nfsd4_cache_this_op(struct nfsd4_op *op)
  {
e372ba60d   J. Bruce Fields   nfsd4: decoding e...
2153
2154
  	if (op->opnum == OP_ILLEGAL)
  		return false;
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
2155
  	return OPDESC(op)->op_flags & OP_CACHEME;
1091006c5   J. Bruce Fields   nfsd: turn on rep...
2156
  }
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2157
2158
2159
2160
2161
2162
  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];
bb2a8b0cd   Christoph Hellwig   nfsd4: const-ify ...
2163
2164
  	const struct nfsd4_operation *thisd = OPDESC(this);
  	const struct nfsd4_operation *nextd;
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2165

68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
  	/*
  	 * 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;
51904b080   J. Bruce Fields   nfsd4: fix crash ...
2179
2180
  	if (next->opnum == OP_ILLEGAL)
  		return false;
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2181
2182
2183
2184
2185
2186
2187
2188
  	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);
  }
2d124dfaa   J. Bruce Fields   nfsd4: move proc_...
2189
2190
2191
2192
2193
2194
2195
2196
  static void svcxdr_init_encode(struct svc_rqst *rqstp,
  			       struct nfsd4_compoundres *resp)
  {
  	struct xdr_stream *xdr = &resp->xdr;
  	struct xdr_buf *buf = &rqstp->rq_res;
  	struct kvec *head = buf->head;
  
  	xdr->buf = buf;
ddd1ea563   J. Bruce Fields   nfsd4: use xdr_re...
2197
  	xdr->iov = head;
2d124dfaa   J. Bruce Fields   nfsd4: move proc_...
2198
  	xdr->p   = head->iov_base + head->iov_len;
a5cddc885   J. Bruce Fields   nfsd4: better res...
2199
  	xdr->end = head->iov_base + PAGE_SIZE - rqstp->rq_auth_slack;
6ac90391c   J. Bruce Fields   nfsd4: keep xdr b...
2200
2201
  	/* Tail and page_len should be zero at this point: */
  	buf->len = buf->head[0].iov_len;
2825a7f90   J. Bruce Fields   nfsd4: allow enco...
2202
  	xdr->scratch.iov_len = 0;
05638dc73   J. Bruce Fields   nfsd4: simplify s...
2203
  	xdr->page_ptr = buf->pages - 1;
2825a7f90   J. Bruce Fields   nfsd4: allow enco...
2204
  	buf->buflen = PAGE_SIZE * (1 + rqstp->rq_page_end - buf->pages)
a5cddc885   J. Bruce Fields   nfsd4: better res...
2205
  		- rqstp->rq_auth_slack;
2d124dfaa   J. Bruce Fields   nfsd4: move proc_...
2206
  }
b9e8638e3   Olga Kornievskaia   NFSD: allow inter...
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
  #ifdef CONFIG_NFSD_V4_2_INTER_SSC
  static void
  check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
  {
  	struct nfsd4_op	*op, *current_op = NULL, *saved_op = NULL;
  	struct nfsd4_copy *copy;
  	struct nfsd4_putfh *putfh;
  	int i;
  
  	/* traverse all operation and if it's a COPY compound, mark the
  	 * source filehandle to skip verification
  	 */
  	for (i = 0; i < args->opcnt; i++) {
  		op = &args->ops[i];
  		if (op->opnum == OP_PUTFH)
  			current_op = op;
  		else if (op->opnum == OP_SAVEFH)
  			saved_op = current_op;
  		else if (op->opnum == OP_RESTOREFH)
  			current_op = saved_op;
  		else if (op->opnum == OP_COPY) {
  			copy = (struct nfsd4_copy *)&op->u;
  			if (!saved_op) {
  				op->status = nfserr_nofilehandle;
  				return;
  			}
  			putfh = (struct nfsd4_putfh *)&saved_op->u;
  			if (!copy->cp_intra)
  				putfh->no_verify = true;
  		}
  	}
  }
  #else
  static void
  check_if_stalefh_allowed(struct nfsd4_compoundargs *args)
  {
  }
  #endif
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2245
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2246
2247
   * COMPOUND call.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
2248
  static __be32
a6beb7327   Christoph Hellwig   sunrpc: properly ...
2249
  nfsd4_proc_compound(struct svc_rqst *rqstp)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2250
  {
a6beb7327   Christoph Hellwig   sunrpc: properly ...
2251
2252
  	struct nfsd4_compoundargs *args = rqstp->rq_argp;
  	struct nfsd4_compoundres *resp = rqstp->rq_resp;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2253
  	struct nfsd4_op	*op;
e354d571b   Andy Adamson   nfsd: embed nfsd4...
2254
  	struct nfsd4_compound_state *cstate = &resp->cstate;
4daeed25a   Kinglong Mee   NFSD: simplify sa...
2255
2256
  	struct svc_fh *current_fh = &cstate->current_fh;
  	struct svc_fh *save_fh = &cstate->save_fh;
e333f3bbe   Trond Myklebust   nfsd: Allow conta...
2257
  	struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
2258
  	__be32		status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2259

2d124dfaa   J. Bruce Fields   nfsd4: move proc_...
2260
  	svcxdr_init_encode(rqstp, resp);
4aea24b2f   J. Bruce Fields   nfsd4: embed xdr_...
2261
  	resp->tagp = resp->xdr.p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2262
  	/* reserve space for: taglen, tag, and opcnt */
d3f627c81   J. Bruce Fields   nfsd4: use xdr_st...
2263
  	xdr_reserve_space(&resp->xdr, 8 + args->taglen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2264
2265
  	resp->taglen = args->taglen;
  	resp->tag = args->tag;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2266
  	resp->rqstp = rqstp;
4daeed25a   Kinglong Mee   NFSD: simplify sa...
2267
  	cstate->minorversion = args->minorversion;
4daeed25a   Kinglong Mee   NFSD: simplify sa...
2268
2269
  	fh_init(current_fh, NFS4_FHSIZE);
  	fh_init(save_fh, NFS4_FHSIZE);
8ff30fa4e   NeilBrown   nfsd: disable def...
2270
2271
2272
2273
  	/*
  	 * Don't use the deferral mechanism for NFSv4; compounds make it
  	 * too hard to avoid non-idempotency problems.
  	 */
30660e04b   Jeff Layton   sunrpc: move rq_u...
2274
  	clear_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2275
2276
2277
2278
2279
  
  	/*
  	 * According to RFC3010, this takes precedence over all other errors.
  	 */
  	status = nfserr_minor_vers_mismatch;
e333f3bbe   Trond Myklebust   nfsd: Allow conta...
2280
  	if (nfsd_minorversion(nn, args->minorversion, NFSD_TEST) <= 0)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2281
  		goto out;
0078117c6   J. Bruce Fields   nfsd: return RESO...
2282
2283
2284
  	status = nfserr_resource;
  	if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2285

577163559   J. Bruce Fields   nfsd4: complete e...
2286
2287
  	status = nfs41_check_op_ordering(args);
  	if (status) {
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2288
  		op = &args->ops[0];
577163559   J. Bruce Fields   nfsd4: complete e...
2289
  		op->status = status;
5b7b15aee   J. Bruce Fields   nfsd: fix corrupt...
2290
  		resp->opcnt = 1;
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2291
2292
  		goto encode_op;
  	}
b9e8638e3   Olga Kornievskaia   NFSD: allow inter...
2293
  	check_if_stalefh_allowed(args);
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2294

28df3d153   J. Bruce Fields   nfsd: clients don...
2295
  	rqstp->rq_lease_breaker = (void **)&cstate->clp;
fff4080b2   Chuck Lever   nfsd: Trace NFSv4...
2296
  	trace_nfsd_compound(rqstp, args->opcnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2297
2298
2299
2300
2301
2302
2303
2304
  	while (!status && resp->opcnt < args->opcnt) {
  		op = &args->ops[resp->opcnt++];
  
  		/*
  		 * 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.
  		 */
9d313b17d   J. Bruce Fields   nfsd4: handle seq...
2305
2306
2307
  		if (op->status) {
  			if (op->opnum == OP_OPEN)
  				op->status = nfsd4_open_omfg(rqstp, cstate, op);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2308
  			goto encode_op;
9d313b17d   J. Bruce Fields   nfsd4: handle seq...
2309
  		}
b9e8638e3   Olga Kornievskaia   NFSD: allow inter...
2310
2311
  		if (!current_fh->fh_dentry &&
  				!HAS_FH_FLAG(current_fh, NFSD4_FH_FOREIGN)) {
f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2312
  			if (!(op->opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
42ca09938   J.Bruce Fields   [PATCH] knfsd: nf...
2313
2314
2315
  				op->status = nfserr_nofilehandle;
  				goto encode_op;
  			}
b9e8638e3   Olga Kornievskaia   NFSD: allow inter...
2316
2317
  		} else if (current_fh->fh_export &&
  			   current_fh->fh_export->ex_fslocs.migrated &&
f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2318
  			  !(op->opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
42ca09938   J.Bruce Fields   [PATCH] knfsd: nf...
2319
  			op->status = nfserr_moved;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2320
2321
  			goto encode_op;
  		}
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2322

2336745e8   Kinglong Mee   NFSD: Clear wcc d...
2323
  		fh_clear_wcc(current_fh);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2324
  		/* If op is non-idempotent */
f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2325
  		if (op->opdesc->op_flags & OP_MODIFIES_SOMETHING) {
4c69d5855   J. Bruce Fields   nfsd4: session ne...
2326
  			/*
a8095f7e8   J. Bruce Fields   nfsd4: size-check...
2327
2328
2329
  			 * Don't execute this op if we couldn't encode a
  			 * succesful reply:
  			 */
f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2330
  			u32 plen = op->opdesc->op_rsize_bop(rqstp, op);
a8095f7e8   J. Bruce Fields   nfsd4: size-check...
2331
2332
  			/*
  			 * Plus if there's another operation, make sure
4c69d5855   J. Bruce Fields   nfsd4: session ne...
2333
2334
2335
2336
  			 * we'll have space to at least encode an error:
  			 */
  			if (resp->opcnt < args->opcnt)
  				plen += COMPOUND_ERR_SLACK_SPACE;
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2337
2338
2339
2340
2341
  			op->status = nfsd4_check_resp_size(resp, plen);
  		}
  
  		if (op->status)
  			goto encode_op;
f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2342
2343
2344
  		if (op->opdesc->op_get_currentstateid)
  			op->opdesc->op_get_currentstateid(cstate, &op->u);
  		op->status = op->opdesc->op_func(rqstp, cstate, &op->u);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2345

9a307403d   J. Bruce Fields   nfsd4: fix null d...
2346
2347
2348
2349
2350
2351
2352
  		/* Only from SEQUENCE */
  		if (cstate->status == nfserr_replay_cache) {
  			dprintk("%s NFS4.1 replay from cache
  ", __func__);
  			status = op->status;
  			goto out;
  		}
8b70484c6   Tigran Mkrtchyan   nfsd41: handle cu...
2353
  		if (!op->status) {
f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2354
2355
  			if (op->opdesc->op_set_currentstateid)
  				op->opdesc->op_set_currentstateid(cstate, &op->u);
8b70484c6   Tigran Mkrtchyan   nfsd41: handle cu...
2356

f4f9ef4a1   J. Bruce Fields   nfsd4: opdesc wil...
2357
  			if (op->opdesc->op_flags & OP_CLEAR_STATEID)
37c593c57   Tigran Mkrtchyan   nfsd41: use curre...
2358
  				clear_current_stateid(cstate);
8b70484c6   Tigran Mkrtchyan   nfsd41: handle cu...
2359

d781e3df7   J. Bruce Fields   nfsd4: avoid NULL...
2360
2361
  			if (current_fh->fh_export &&
  					need_wrongsec_check(rqstp))
4daeed25a   Kinglong Mee   NFSD: simplify sa...
2362
  				op->status = check_nfsd_access(current_fh->fh_export, rqstp);
8b70484c6   Tigran Mkrtchyan   nfsd41: handle cu...
2363
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2364
  encode_op:
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
2365
  		if (op->status == nfserr_replay_me) {
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
2366
  			op->replay = &cstate->replay_owner->so_replay;
d0a381dd0   J. Bruce Fields   nfsd4: teach enco...
2367
  			nfsd4_encode_replay(&resp->xdr, op);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2368
2369
2370
2371
2372
  			status = op->status = op->replay->rp_status;
  		} else {
  			nfsd4_encode_operation(resp, op);
  			status = op->status;
  		}
0407717d8   Benny Halevy   nfsd: dprint each...
2373

fff4080b2   Chuck Lever   nfsd: Trace NFSv4...
2374
2375
  		trace_nfsd_compound_status(args->opcnt, resp->opcnt, status,
  					   nfsd4_op_name(op->opnum));
0407717d8   Benny Halevy   nfsd: dprint each...
2376

58fb12e6a   Jeff Layton   nfsd: Add a mutex...
2377
  		nfsd4_cstate_clear_replay(cstate);
e2b209509   Shankar Anand   [PATCH] knfsd: nf...
2378
  		nfsd4_increment_op_stats(op->opnum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2379
  	}
4daeed25a   Kinglong Mee   NFSD: simplify sa...
2380
2381
2382
  	fh_put(current_fh);
  	fh_put(save_fh);
  	BUG_ON(cstate->replay_owner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2383
  out:
cc028a10a   Chuck Lever   NFSD: Hoist statu...
2384
  	cstate->status = status;
2f425878b   Andy Adamson   nfsd: don't use t...
2385
  	/* Reset deferral mechanism for RPC deferrals */
30660e04b   Jeff Layton   sunrpc: move rq_u...
2386
  	set_bit(RQ_USEDEFERRAL, &rqstp->rq_flags);
cc028a10a   Chuck Lever   NFSD: Hoist statu...
2387
  	return rpc_success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2388
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2389
2390
2391
2392
2393
  #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)
8c7424cff   J. Bruce Fields   nfsd4: don't try ...
2394
2395
  /* We'll fall back on returning no lockowner if run out of space: */
  #define op_encode_lockowner_maxsz	(0)
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
  #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);
  }
2282cd2c0   Kinglong Mee   NFSD: Get respons...
2415
2416
2417
2418
2419
  static inline u32 nfsd4_access_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	/* ac_supported, ac_resp_access */
  	return (op_encode_hdr_size + 2)* sizeof(__be32);
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
  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);
  }
b86cef60d   J. Bruce Fields   nfsd4: better est...
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
  /*
   * Note since this is an idempotent operation we won't insist on failing
   * the op prematurely if the estimate is too large.  We may turn off splice
   * reads unnecessarily.
   */
  static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp,
  				      struct nfsd4_op *op)
  {
  	u32 *bmap = op->u.getattr.ga_bmval;
  	u32 bmap0 = bmap[0], bmap1 = bmap[1], bmap2 = bmap[2];
  	u32 ret = 0;
  
  	if (bmap0 & FATTR4_WORD0_ACL)
  		return svc_max_payload(rqstp);
  	if (bmap0 & FATTR4_WORD0_FS_LOCATIONS)
  		return svc_max_payload(rqstp);
  
  	if (bmap1 & FATTR4_WORD1_OWNER) {
  		ret += IDMAP_NAMESZ + 4;
  		bmap1 &= ~FATTR4_WORD1_OWNER;
  	}
  	if (bmap1 & FATTR4_WORD1_OWNER_GROUP) {
  		ret += IDMAP_NAMESZ + 4;
  		bmap1 &= ~FATTR4_WORD1_OWNER_GROUP;
  	}
  	if (bmap0 & FATTR4_WORD0_FILEHANDLE) {
  		ret += NFS4_FHSIZE + 4;
  		bmap0 &= ~FATTR4_WORD0_FILEHANDLE;
  	}
  	if (bmap2 & FATTR4_WORD2_SECURITY_LABEL) {
1ec8c0c47   Kinglong Mee   nfsd: Remove dupl...
2460
  		ret += NFS4_MAXLABELLEN + 12;
b86cef60d   J. Bruce Fields   nfsd4: better est...
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
  		bmap2 &= ~FATTR4_WORD2_SECURITY_LABEL;
  	}
  	/*
  	 * Largest of remaining attributes are 16 bytes (e.g.,
  	 * supported_attributes)
  	 */
  	ret += 16 * (hweight32(bmap0) + hweight32(bmap1) + hweight32(bmap2));
  	/* bitmask, length */
  	ret += 20;
  	return ret;
  }
2282cd2c0   Kinglong Mee   NFSD: Get respons...
2472
2473
2474
2475
  static inline u32 nfsd4_getfh_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + 1) * sizeof(__be32) + NFS4_FHSIZE;
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
  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);
3c7aa15d2   Kinglong Mee   NFSD: Using min/m...
2501
  	rlen = min(op->u.read.rd_length, maxcount);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2502

622f560e6   J. Bruce Fields   nfsd4: read size ...
2503
  	return (op_encode_hdr_size + 2 + XDR_QUADLEN(rlen)) * sizeof(__be32);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2504
  }
528b84934   Anna Schumaker   NFSD: Add READ_PL...
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
  static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	u32 maxcount = svc_max_payload(rqstp);
  	u32 rlen = min(op->u.read.rd_length, maxcount);
  	/*
  	 * If we detect that the file changed during hole encoding, then we
  	 * recover by encoding the remaining reply as data. This means we need
  	 * to set aside enough room to encode two data segments.
  	 */
  	u32 seg_len = 2 * (1 + 2 + 1);
  
  	return (op_encode_hdr_size + 2 + seg_len + XDR_QUADLEN(rlen)) * sizeof(__be32);
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2518
2519
  static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
3c7aa15d2   Kinglong Mee   NFSD: Using min/m...
2520
  	u32 maxcount = 0, rlen = 0;
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2521

3c7aa15d2   Kinglong Mee   NFSD: Using min/m...
2522
2523
  	maxcount = svc_max_payload(rqstp);
  	rlen = min(op->u.readdir.rd_maxcount, maxcount);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2524

561f0ed49   J. Bruce Fields   nfsd4: allow larg...
2525
2526
  	return (op_encode_hdr_size + op_encode_verifier_maxsz +
  		XDR_QUADLEN(rlen)) * sizeof(__be32);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2527
  }
2282cd2c0   Kinglong Mee   NFSD: Get respons...
2528
2529
2530
2531
  static inline u32 nfsd4_readlink_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + 1) * sizeof(__be32) + PAGE_SIZE;
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
  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);
  }
ccae70a9e   J. Bruce Fields   nfsd4: estimate s...
2543
2544
2545
  static inline u32 nfsd4_sequence_rsize(struct svc_rqst *rqstp,
  				       struct nfsd4_op *op)
  {
d1d84c962   J. Bruce Fields   nfsd4: fix respon...
2546
2547
  	return (op_encode_hdr_size
  		+ XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5) * sizeof(__be32);
ccae70a9e   J. Bruce Fields   nfsd4: estimate s...
2548
  }
2282cd2c0   Kinglong Mee   NFSD: Get respons...
2549
2550
2551
2552
2553
  static inline u32 nfsd4_test_stateid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + 1 + op->u.test_stateid.ts_num_ids)
  		* sizeof(__be32);
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2554
2555
2556
2557
  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);
  }
2282cd2c0   Kinglong Mee   NFSD: Get respons...
2558
2559
2560
2561
2562
  static inline u32 nfsd4_secinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + RPC_AUTH_MAXFLAVOR *
  		(4 + XDR_QUADLEN(GSS_OID_MAX_LEN))) * sizeof(__be32);
  }
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2563
2564
  static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
480efaee0   J. Bruce Fields   nfsd4: fix setcli...
2565
2566
  	return (op_encode_hdr_size + 2 + XDR_QUADLEN(NFS4_VERIFIER_SIZE)) *
  								sizeof(__be32);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2567
2568
2569
2570
  }
  
  static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
f34e432b6   J. Bruce Fields   nfsd4: fix write ...
2571
  	return (op_encode_hdr_size + 2 + op_encode_verifier_maxsz) * sizeof(__be32);
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2572
2573
2574
2575
2576
  }
  
  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 */\
a8bb84bc9   Kinglong Mee   nfsd: calculate t...
2577
2578
  		1 + 1 + /* eir_flags, spr_how */\
  		4 + /* spo_must_enforce & _allow with bitmap */\
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
  		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);
  }
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
  static inline u32 nfsd4_copy_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size +
  		1 /* wr_callback */ +
  		op_encode_stateid_maxsz /* wr_callback */ +
  		2 /* wr_count */ +
  		1 /* wr_committed */ +
  		op_encode_verifier_maxsz +
  		1 /* cr_consecutive */ +
  		1 /* cr_synchronous */) * sizeof(__be32);
  }
6308bc98e   Olga Kornievskaia   NFSD OFFLOAD_STAT...
2614
2615
2616
2617
2618
2619
2620
  static inline u32 nfsd4_offload_status_rsize(struct svc_rqst *rqstp,
  					     struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size +
  		2 /* osr_count */ +
  		1 /* osr_complete<1> optional 0 for now */) * sizeof(__be32);
  }
51911868f   Olga Kornievskaia   NFSD COPY_NOTIFY xdr
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
  static inline u32 nfsd4_copy_notify_rsize(struct svc_rqst *rqstp,
  					struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size +
  		3 /* cnr_lease_time */ +
  		1 /* We support one cnr_source_server */ +
  		1 /* cnr_stateid seq */ +
  		op_encode_stateid_maxsz /* cnr_stateid */ +
  		1 /* num cnr_source_server*/ +
  		1 /* nl4_type */ +
  		1 /* nl4 size */ +
  		XDR_QUADLEN(NFS4_OPAQUE_LIMIT) /*nl4_loc + nl4_loc_sz */)
  		* sizeof(__be32);
  }
9cf514ccf   Christoph Hellwig   nfsd: implement p...
2635
  #ifdef CONFIG_NFSD_PNFS
2282cd2c0   Kinglong Mee   NFSD: Get respons...
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
  static inline u32 nfsd4_getdeviceinfo_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	u32 maxcount = 0, rlen = 0;
  
  	maxcount = svc_max_payload(rqstp);
  	rlen = min(op->u.getdeviceinfo.gd_maxcount, maxcount);
  
  	return (op_encode_hdr_size +
  		1 /* gd_layout_type*/ +
  		XDR_QUADLEN(rlen) +
  		2 /* gd_notify_types */) * sizeof(__be32);
  }
9cf514ccf   Christoph Hellwig   nfsd: implement p...
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
  /*
   * At this stage we don't really know what layout driver will handle the request,
   * so we need to define an arbitrary upper bound here.
   */
  #define MAX_LAYOUT_SIZE		128
  static inline u32 nfsd4_layoutget_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size +
  		1 /* logr_return_on_close */ +
  		op_encode_stateid_maxsz +
  		1 /* nr of layouts */ +
  		MAX_LAYOUT_SIZE) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_layoutcommit_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size +
  		1 /* locr_newsize */ +
  		2 /* ns_size */) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_layoutreturn_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size +
  		1 /* lrs_stateid */ +
  		op_encode_stateid_maxsz) * sizeof(__be32);
  }
  #endif /* CONFIG_NFSD_PNFS */
2282cd2c0   Kinglong Mee   NFSD: Get respons...
2676
2677
2678
2679
2680
  
  static inline u32 nfsd4_seek_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + 3) * sizeof(__be32);
  }
23e50fe3a   Frank van der Linden   nfsd: implement t...
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
  static inline u32 nfsd4_getxattr_rsize(struct svc_rqst *rqstp,
  				       struct nfsd4_op *op)
  {
  	u32 maxcount, rlen;
  
  	maxcount = svc_max_payload(rqstp);
  	rlen = min_t(u32, XATTR_SIZE_MAX, maxcount);
  
  	return (op_encode_hdr_size + 1 + XDR_QUADLEN(rlen)) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_setxattr_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_listxattrs_rsize(struct svc_rqst *rqstp,
  					 struct nfsd4_op *op)
  {
  	u32 maxcount, rlen;
  
  	maxcount = svc_max_payload(rqstp);
  	rlen = min(op->u.listxattrs.lsxa_maxcount, maxcount);
  
  	return (op_encode_hdr_size + 4 + XDR_QUADLEN(rlen)) * sizeof(__be32);
  }
  
  static inline u32 nfsd4_removexattr_rsize(struct svc_rqst *rqstp,
  					  struct nfsd4_op *op)
  {
  	return (op_encode_hdr_size + op_encode_change_info_maxsz)
  		* sizeof(__be32);
  }
bb2a8b0cd   Christoph Hellwig   nfsd4: const-ify ...
2715
  static const struct nfsd4_operation nfsd4_ops[] = {
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2716
  	[OP_ACCESS] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2717
  		.op_func = nfsd4_access,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2718
  		.op_name = "OP_ACCESS",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2719
  		.op_rsize_bop = nfsd4_access_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2720
2721
  	},
  	[OP_CLOSE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2722
  		.op_func = nfsd4_close,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2723
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2724
  		.op_name = "OP_CLOSE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2725
  		.op_rsize_bop = nfsd4_status_stateid_rsize,
57832e7bd   Christoph Hellwig   nfsd4: properly t...
2726
  		.op_get_currentstateid = nfsd4_get_closestateid,
b60e98598   Christoph Hellwig   nfsd4: properly t...
2727
  		.op_set_currentstateid = nfsd4_set_closestateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2728
2729
  	},
  	[OP_COMMIT] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2730
  		.op_func = nfsd4_commit,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2731
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2732
  		.op_name = "OP_COMMIT",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2733
  		.op_rsize_bop = nfsd4_commit_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2734
2735
  	},
  	[OP_CREATE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2736
  		.op_func = nfsd4_create,
d14710532   Tigran Mkrtchyan   nfsd41: mark LOOK...
2737
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME | OP_CLEAR_STATEID,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2738
  		.op_name = "OP_CREATE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2739
  		.op_rsize_bop = nfsd4_create_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2740
2741
  	},
  	[OP_DELEGRETURN] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2742
  		.op_func = nfsd4_delegreturn,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2743
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2744
  		.op_name = "OP_DELEGRETURN",
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2745
  		.op_rsize_bop = nfsd4_only_status_rsize,
57832e7bd   Christoph Hellwig   nfsd4: properly t...
2746
  		.op_get_currentstateid = nfsd4_get_delegreturnstateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2747
2748
  	},
  	[OP_GETATTR] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2749
  		.op_func = nfsd4_getattr,
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
2750
  		.op_flags = ALLOWED_ON_ABSENT_FS,
b86cef60d   J. Bruce Fields   nfsd4: better est...
2751
  		.op_rsize_bop = nfsd4_getattr_rsize,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2752
  		.op_name = "OP_GETATTR",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2753
2754
  	},
  	[OP_GETFH] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2755
  		.op_func = nfsd4_getfh,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2756
  		.op_name = "OP_GETFH",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2757
  		.op_rsize_bop = nfsd4_getfh_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2758
2759
  	},
  	[OP_LINK] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2760
  		.op_func = nfsd4_link,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
2761
2762
  		.op_flags = ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING
  				| OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2763
  		.op_name = "OP_LINK",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2764
  		.op_rsize_bop = nfsd4_link_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2765
2766
  	},
  	[OP_LOCK] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2767
  		.op_func = nfsd4_lock,
b7571e4cd   J. Bruce Fields   nfsd4: skip encod...
2768
2769
  		.op_flags = OP_MODIFIES_SOMETHING |
  				OP_NONTRIVIAL_ERROR_ENCODE,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2770
  		.op_name = "OP_LOCK",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2771
  		.op_rsize_bop = nfsd4_lock_rsize,
b60e98598   Christoph Hellwig   nfsd4: properly t...
2772
  		.op_set_currentstateid = nfsd4_set_lockstateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2773
2774
  	},
  	[OP_LOCKT] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2775
  		.op_func = nfsd4_lockt,
b7571e4cd   J. Bruce Fields   nfsd4: skip encod...
2776
  		.op_flags = OP_NONTRIVIAL_ERROR_ENCODE,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2777
  		.op_name = "OP_LOCKT",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2778
  		.op_rsize_bop = nfsd4_lock_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2779
2780
  	},
  	[OP_LOCKU] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2781
  		.op_func = nfsd4_locku,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2782
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2783
  		.op_name = "OP_LOCKU",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2784
  		.op_rsize_bop = nfsd4_status_stateid_rsize,
57832e7bd   Christoph Hellwig   nfsd4: properly t...
2785
  		.op_get_currentstateid = nfsd4_get_lockustateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2786
2787
  	},
  	[OP_LOOKUP] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2788
  		.op_func = nfsd4_lookup,
d14710532   Tigran Mkrtchyan   nfsd41: mark LOOK...
2789
  		.op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2790
  		.op_name = "OP_LOOKUP",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2791
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2792
2793
  	},
  	[OP_LOOKUPP] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2794
  		.op_func = nfsd4_lookupp,
d14710532   Tigran Mkrtchyan   nfsd41: mark LOOK...
2795
  		.op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2796
  		.op_name = "OP_LOOKUPP",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2797
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2798
2799
  	},
  	[OP_NVERIFY] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2800
  		.op_func = nfsd4_nverify,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2801
  		.op_name = "OP_NVERIFY",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2802
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2803
2804
  	},
  	[OP_OPEN] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2805
  		.op_func = nfsd4_open,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2806
  		.op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2807
  		.op_name = "OP_OPEN",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2808
  		.op_rsize_bop = nfsd4_open_rsize,
b60e98598   Christoph Hellwig   nfsd4: properly t...
2809
  		.op_set_currentstateid = nfsd4_set_openstateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2810
2811
  	},
  	[OP_OPEN_CONFIRM] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2812
  		.op_func = nfsd4_open_confirm,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2813
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2814
  		.op_name = "OP_OPEN_CONFIRM",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2815
  		.op_rsize_bop = nfsd4_status_stateid_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2816
2817
  	},
  	[OP_OPEN_DOWNGRADE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2818
  		.op_func = nfsd4_open_downgrade,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2819
  		.op_flags = OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2820
  		.op_name = "OP_OPEN_DOWNGRADE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2821
  		.op_rsize_bop = nfsd4_status_stateid_rsize,
57832e7bd   Christoph Hellwig   nfsd4: properly t...
2822
  		.op_get_currentstateid = nfsd4_get_opendowngradestateid,
b60e98598   Christoph Hellwig   nfsd4: properly t...
2823
  		.op_set_currentstateid = nfsd4_set_opendowngradestateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2824
2825
  	},
  	[OP_PUTFH] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2826
  		.op_func = nfsd4_putfh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2827
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
5b648699a   J. Bruce Fields   nfsd4: READ, READ...
2828
  				| OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2829
  		.op_name = "OP_PUTFH",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2830
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2831
  	},
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
2832
  	[OP_PUTPUBFH] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2833
  		.op_func = nfsd4_putrootfh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2834
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
5b648699a   J. Bruce Fields   nfsd4: READ, READ...
2835
  				| OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2836
  		.op_name = "OP_PUTPUBFH",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2837
  		.op_rsize_bop = nfsd4_only_status_rsize,
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
2838
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2839
  	[OP_PUTROOTFH] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2840
  		.op_func = nfsd4_putrootfh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2841
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
5b648699a   J. Bruce Fields   nfsd4: READ, READ...
2842
  				| OP_IS_PUTFH_LIKE | OP_CLEAR_STATEID,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2843
  		.op_name = "OP_PUTROOTFH",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2844
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2845
2846
  	},
  	[OP_READ] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2847
  		.op_func = nfsd4_read,
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
2848
  		.op_release = nfsd4_read_release,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2849
  		.op_name = "OP_READ",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2850
  		.op_rsize_bop = nfsd4_read_rsize,
57832e7bd   Christoph Hellwig   nfsd4: properly t...
2851
  		.op_get_currentstateid = nfsd4_get_readstateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2852
2853
  	},
  	[OP_READDIR] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2854
  		.op_func = nfsd4_readdir,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2855
  		.op_name = "OP_READDIR",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2856
  		.op_rsize_bop = nfsd4_readdir_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2857
2858
  	},
  	[OP_READLINK] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2859
  		.op_func = nfsd4_readlink,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2860
  		.op_name = "OP_READLINK",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2861
  		.op_rsize_bop = nfsd4_readlink_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2862
2863
  	},
  	[OP_REMOVE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2864
  		.op_func = nfsd4_remove,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
2865
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2866
  		.op_name = "OP_REMOVE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2867
  		.op_rsize_bop = nfsd4_remove_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2868
2869
  	},
  	[OP_RENAME] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2870
  		.op_func = nfsd4_rename,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
2871
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2872
  		.op_name = "OP_RENAME",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2873
  		.op_rsize_bop = nfsd4_rename_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2874
2875
  	},
  	[OP_RENEW] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2876
  		.op_func = nfsd4_renew,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2877
2878
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
  				| OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2879
  		.op_name = "OP_RENEW",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2880
  		.op_rsize_bop = nfsd4_only_status_rsize,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2881

b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2882
2883
  	},
  	[OP_RESTOREFH] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2884
  		.op_func = nfsd4_restorefh,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2885
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2886
  				| OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2887
  		.op_name = "OP_RESTOREFH",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2888
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2889
2890
  	},
  	[OP_SAVEFH] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2891
  		.op_func = nfsd4_savefh,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2892
  		.op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2893
  		.op_name = "OP_SAVEFH",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2894
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2895
  	},
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
2896
  	[OP_SECINFO] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2897
  		.op_func = nfsd4_secinfo,
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
2898
  		.op_release = nfsd4_secinfo_release,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
2899
  		.op_flags = OP_HANDLES_WRONGSEC,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2900
  		.op_name = "OP_SECINFO",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2901
  		.op_rsize_bop = nfsd4_secinfo_rsize,
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
2902
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2903
  	[OP_SETATTR] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2904
  		.op_func = nfsd4_setattr,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2905
  		.op_name = "OP_SETATTR",
b7571e4cd   J. Bruce Fields   nfsd4: skip encod...
2906
2907
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME
  				| OP_NONTRIVIAL_ERROR_ENCODE,
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2908
  		.op_rsize_bop = nfsd4_setattr_rsize,
57832e7bd   Christoph Hellwig   nfsd4: properly t...
2909
  		.op_get_currentstateid = nfsd4_get_setattrstateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2910
2911
  	},
  	[OP_SETCLIENTID] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2912
  		.op_func = nfsd4_setclientid,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2913
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
b7571e4cd   J. Bruce Fields   nfsd4: skip encod...
2914
2915
  				| OP_MODIFIES_SOMETHING | OP_CACHEME
  				| OP_NONTRIVIAL_ERROR_ENCODE,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2916
  		.op_name = "OP_SETCLIENTID",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2917
  		.op_rsize_bop = nfsd4_setclientid_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2918
2919
  	},
  	[OP_SETCLIENTID_CONFIRM] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2920
  		.op_func = nfsd4_setclientid_confirm,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2921
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
2922
  				| OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2923
  		.op_name = "OP_SETCLIENTID_CONFIRM",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2924
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2925
2926
  	},
  	[OP_VERIFY] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2927
  		.op_func = nfsd4_verify,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2928
  		.op_name = "OP_VERIFY",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2929
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2930
2931
  	},
  	[OP_WRITE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2932
  		.op_func = nfsd4_write,
c856694e3   J. Bruce Fields   nfsd4: make op_ca...
2933
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2934
  		.op_name = "OP_WRITE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2935
  		.op_rsize_bop = nfsd4_write_rsize,
57832e7bd   Christoph Hellwig   nfsd4: properly t...
2936
  		.op_get_currentstateid = nfsd4_get_writestateid,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2937
2938
  	},
  	[OP_RELEASE_LOCKOWNER] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2939
  		.op_func = nfsd4_release_lockowner,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2940
2941
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
  				| OP_MODIFIES_SOMETHING,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
2942
  		.op_name = "OP_RELEASE_LOCKOWNER",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2943
  		.op_rsize_bop = nfsd4_only_status_rsize,
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
2944
  	},
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2945
2946
2947
  
  	/* NFSv4.1 operations */
  	[OP_EXCHANGE_ID] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2948
  		.op_func = nfsd4_exchange_id,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2949
2950
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2951
  		.op_name = "OP_EXCHANGE_ID",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2952
  		.op_rsize_bop = nfsd4_exchange_id_rsize,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2953
  	},
cb73a9f46   J. Bruce Fields   nfsd4: implement ...
2954
  	[OP_BACKCHANNEL_CTL] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2955
  		.op_func = nfsd4_backchannel_ctl,
cb73a9f46   J. Bruce Fields   nfsd4: implement ...
2956
2957
  		.op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
  		.op_name = "OP_BACKCHANNEL_CTL",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2958
  		.op_rsize_bop = nfsd4_only_status_rsize,
cb73a9f46   J. Bruce Fields   nfsd4: implement ...
2959
  	},
1d1bc8f20   J. Bruce Fields   nfsd4: support BI...
2960
  	[OP_BIND_CONN_TO_SESSION] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2961
  		.op_func = nfsd4_bind_conn_to_session,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2962
2963
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
1d1bc8f20   J. Bruce Fields   nfsd4: support BI...
2964
  		.op_name = "OP_BIND_CONN_TO_SESSION",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2965
  		.op_rsize_bop = nfsd4_bind_conn_to_session_rsize,
1d1bc8f20   J. Bruce Fields   nfsd4: support BI...
2966
  	},
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2967
  	[OP_CREATE_SESSION] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2968
  		.op_func = nfsd4_create_session,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2969
2970
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2971
  		.op_name = "OP_CREATE_SESSION",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2972
  		.op_rsize_bop = nfsd4_create_session_rsize,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2973
2974
  	},
  	[OP_DESTROY_SESSION] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2975
  		.op_func = nfsd4_destroy_session,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2976
2977
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2978
  		.op_name = "OP_DESTROY_SESSION",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2979
  		.op_rsize_bop = nfsd4_only_status_rsize,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2980
2981
  	},
  	[OP_SEQUENCE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2982
  		.op_func = nfsd4_sequence,
f9bb94c4c   Andy Adamson   nfsd41: enforce N...
2983
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2984
  		.op_name = "OP_SEQUENCE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2985
  		.op_rsize_bop = nfsd4_sequence_rsize,
069b6ad4b   Andy Adamson   nfsd41: proc stubs
2986
  	},
094b5d74f   Benny Halevy   NFSD: allow OP_DE...
2987
  	[OP_DESTROY_CLIENTID] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2988
  		.op_func = nfsd4_destroy_clientid,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2989
2990
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
  				| OP_MODIFIES_SOMETHING,
094b5d74f   Benny Halevy   NFSD: allow OP_DE...
2991
  		.op_name = "OP_DESTROY_CLIENTID",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2992
  		.op_rsize_bop = nfsd4_only_status_rsize,
094b5d74f   Benny Halevy   NFSD: allow OP_DE...
2993
  	},
4dc6ec00f   J. Bruce Fields   nfsd4: implement ...
2994
  	[OP_RECLAIM_COMPLETE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
2995
  		.op_func = nfsd4_reclaim_complete,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
2996
  		.op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
4dc6ec00f   J. Bruce Fields   nfsd4: implement ...
2997
  		.op_name = "OP_RECLAIM_COMPLETE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
2998
  		.op_rsize_bop = nfsd4_only_status_rsize,
4dc6ec00f   J. Bruce Fields   nfsd4: implement ...
2999
  	},
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
3000
  	[OP_SECINFO_NO_NAME] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3001
  		.op_func = nfsd4_secinfo_no_name,
ec572b9e8   Eryu Guan   nfsd4: define nfs...
3002
  		.op_release = nfsd4_secinfo_no_name_release,
68d931843   J. Bruce Fields   nfsd4: fix wrongs...
3003
  		.op_flags = OP_HANDLES_WRONGSEC,
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
3004
  		.op_name = "OP_SECINFO_NO_NAME",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3005
  		.op_rsize_bop = nfsd4_secinfo_rsize,
04f4ad16b   J. Bruce Fields   nfsd4: implement ...
3006
  	},
174568045   Bryan Schumaker   NFSD: Added TEST_...
3007
  	[OP_TEST_STATEID] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3008
  		.op_func = nfsd4_test_stateid,
174568045   Bryan Schumaker   NFSD: Added TEST_...
3009
3010
  		.op_flags = ALLOWED_WITHOUT_FH,
  		.op_name = "OP_TEST_STATEID",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3011
  		.op_rsize_bop = nfsd4_test_stateid_rsize,
174568045   Bryan Schumaker   NFSD: Added TEST_...
3012
  	},
e1ca12dfb   Bryan Schumaker   NFSD: added FREE_...
3013
  	[OP_FREE_STATEID] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3014
  		.op_func = nfsd4_free_stateid,
58e7b33a5   Mi Jinlong   nfsd41: try to ch...
3015
  		.op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
e1ca12dfb   Bryan Schumaker   NFSD: added FREE_...
3016
  		.op_name = "OP_FREE_STATEID",
57832e7bd   Christoph Hellwig   nfsd4: properly t...
3017
  		.op_get_currentstateid = nfsd4_get_freestateid,
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3018
  		.op_rsize_bop = nfsd4_only_status_rsize,
e1ca12dfb   Bryan Schumaker   NFSD: added FREE_...
3019
  	},
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3020
3021
  #ifdef CONFIG_NFSD_PNFS
  	[OP_GETDEVICEINFO] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3022
  		.op_func = nfsd4_getdeviceinfo,
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
3023
  		.op_release = nfsd4_getdeviceinfo_release,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3024
3025
  		.op_flags = ALLOWED_WITHOUT_FH,
  		.op_name = "OP_GETDEVICEINFO",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3026
  		.op_rsize_bop = nfsd4_getdeviceinfo_rsize,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3027
3028
  	},
  	[OP_LAYOUTGET] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3029
  		.op_func = nfsd4_layoutget,
34b1744c9   J. Bruce Fields   nfsd4: define ->o...
3030
  		.op_release = nfsd4_layoutget_release,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3031
3032
  		.op_flags = OP_MODIFIES_SOMETHING,
  		.op_name = "OP_LAYOUTGET",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3033
  		.op_rsize_bop = nfsd4_layoutget_rsize,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3034
3035
  	},
  	[OP_LAYOUTCOMMIT] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3036
  		.op_func = nfsd4_layoutcommit,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3037
3038
  		.op_flags = OP_MODIFIES_SOMETHING,
  		.op_name = "OP_LAYOUTCOMMIT",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3039
  		.op_rsize_bop = nfsd4_layoutcommit_rsize,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3040
3041
  	},
  	[OP_LAYOUTRETURN] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3042
  		.op_func = nfsd4_layoutreturn,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3043
3044
  		.op_flags = OP_MODIFIES_SOMETHING,
  		.op_name = "OP_LAYOUTRETURN",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3045
  		.op_rsize_bop = nfsd4_layoutreturn_rsize,
9cf514ccf   Christoph Hellwig   nfsd: implement p...
3046
3047
  	},
  #endif /* CONFIG_NFSD_PNFS */
24bab4912   Anna Schumaker   NFSD: Implement SEEK
3048
3049
  
  	/* NFSv4.2 operations */
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
3050
  	[OP_ALLOCATE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3051
  		.op_func = nfsd4_allocate,
03b31f489   Olga Kornievskaia   NFSD remove OP_CA...
3052
  		.op_flags = OP_MODIFIES_SOMETHING,
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
3053
  		.op_name = "OP_ALLOCATE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3054
  		.op_rsize_bop = nfsd4_only_status_rsize,
95d871f03   Anna Schumaker   nfsd: Add ALLOCAT...
3055
  	},
b0cb90852   Anna Schumaker   nfsd: Add DEALLOC...
3056
  	[OP_DEALLOCATE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3057
  		.op_func = nfsd4_deallocate,
03b31f489   Olga Kornievskaia   NFSD remove OP_CA...
3058
  		.op_flags = OP_MODIFIES_SOMETHING,
b0cb90852   Anna Schumaker   nfsd: Add DEALLOC...
3059
  		.op_name = "OP_DEALLOCATE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3060
  		.op_rsize_bop = nfsd4_only_status_rsize,
b0cb90852   Anna Schumaker   nfsd: Add DEALLOC...
3061
  	},
ffa0160a1   Christoph Hellwig   nfsd: implement t...
3062
  	[OP_CLONE] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3063
  		.op_func = nfsd4_clone,
03b31f489   Olga Kornievskaia   NFSD remove OP_CA...
3064
  		.op_flags = OP_MODIFIES_SOMETHING,
ffa0160a1   Christoph Hellwig   nfsd: implement t...
3065
  		.op_name = "OP_CLONE",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3066
  		.op_rsize_bop = nfsd4_only_status_rsize,
ffa0160a1   Christoph Hellwig   nfsd: implement t...
3067
  	},
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
3068
  	[OP_COPY] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3069
  		.op_func = nfsd4_copy,
03b31f489   Olga Kornievskaia   NFSD remove OP_CA...
3070
  		.op_flags = OP_MODIFIES_SOMETHING,
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
3071
  		.op_name = "OP_COPY",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3072
  		.op_rsize_bop = nfsd4_copy_rsize,
29ae7f9dc   Anna Schumaker   NFSD: Implement t...
3073
  	},
528b84934   Anna Schumaker   NFSD: Add READ_PL...
3074
3075
3076
3077
3078
3079
3080
  	[OP_READ_PLUS] = {
  		.op_func = nfsd4_read,
  		.op_release = nfsd4_read_release,
  		.op_name = "OP_READ_PLUS",
  		.op_rsize_bop = nfsd4_read_plus_rsize,
  		.op_get_currentstateid = nfsd4_get_readstateid,
  	},
24bab4912   Anna Schumaker   NFSD: Implement SEEK
3081
  	[OP_SEEK] = {
eb69853da   Christoph Hellwig   nfsd4: properly t...
3082
  		.op_func = nfsd4_seek,
24bab4912   Anna Schumaker   NFSD: Implement SEEK
3083
  		.op_name = "OP_SEEK",
1c1226385   Christoph Hellwig   nfsd4: remove nfs...
3084
  		.op_rsize_bop = nfsd4_seek_rsize,
24bab4912   Anna Schumaker   NFSD: Implement SEEK
3085
  	},
6308bc98e   Olga Kornievskaia   NFSD OFFLOAD_STAT...
3086
3087
3088
3089
3090
  	[OP_OFFLOAD_STATUS] = {
  		.op_func = nfsd4_offload_status,
  		.op_name = "OP_OFFLOAD_STATUS",
  		.op_rsize_bop = nfsd4_offload_status_rsize,
  	},
885e2bf3e   Olga Kornievskaia   NFSD OFFLOAD_CANC...
3091
3092
3093
3094
3095
3096
  	[OP_OFFLOAD_CANCEL] = {
  		.op_func = nfsd4_offload_cancel,
  		.op_flags = OP_MODIFIES_SOMETHING,
  		.op_name = "OP_OFFLOAD_CANCEL",
  		.op_rsize_bop = nfsd4_only_status_rsize,
  	},
51911868f   Olga Kornievskaia   NFSD COPY_NOTIFY xdr
3097
3098
3099
3100
3101
3102
  	[OP_COPY_NOTIFY] = {
  		.op_func = nfsd4_copy_notify,
  		.op_flags = OP_MODIFIES_SOMETHING,
  		.op_name = "OP_COPY_NOTIFY",
  		.op_rsize_bop = nfsd4_copy_notify_rsize,
  	},
23e50fe3a   Frank van der Linden   nfsd: implement t...
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
  	[OP_GETXATTR] = {
  		.op_func = nfsd4_getxattr,
  		.op_name = "OP_GETXATTR",
  		.op_rsize_bop = nfsd4_getxattr_rsize,
  	},
  	[OP_SETXATTR] = {
  		.op_func = nfsd4_setxattr,
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
  		.op_name = "OP_SETXATTR",
  		.op_rsize_bop = nfsd4_setxattr_rsize,
  	},
  	[OP_LISTXATTRS] = {
  		.op_func = nfsd4_listxattrs,
  		.op_name = "OP_LISTXATTRS",
  		.op_rsize_bop = nfsd4_listxattrs_rsize,
  	},
  	[OP_REMOVEXATTR] = {
  		.op_func = nfsd4_removexattr,
  		.op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
  		.op_name = "OP_REMOVEXATTR",
  		.op_rsize_bop = nfsd4_removexattr_rsize,
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
3125
  };
ed9416439   Andrew Elble   nfsd: implement m...
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
  /**
   * nfsd4_spo_must_allow - Determine if the compound op contains an
   * operation that is allowed to be sent with machine credentials
   *
   * @rqstp: a pointer to the struct svc_rqst
   *
   * Checks to see if the compound contains a spo_must_allow op
   * and confirms that it was sent with the proper machine creds.
   */
  
  bool nfsd4_spo_must_allow(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_compound_state *cstate = &resp->cstate;
  	struct nfs4_op_map *allow = &cstate->clp->cl_spo_must_allow;
  	u32 opiter;
  
  	if (!cstate->minorversion)
  		return false;
44b49aa65   Zheng Bin   nfsd: fix compari...
3147
  	if (cstate->spo_must_allowed)
ed9416439   Andrew Elble   nfsd: implement m...
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
  		return true;
  
  	opiter = resp->opcnt;
  	while (opiter < argp->opcnt) {
  		this = &argp->ops[opiter++];
  		if (test_bit(this->opnum, allow->u.longs) &&
  			cstate->clp->cl_mach_cred &&
  			nfsd4_mach_creds_match(cstate->clp, rqstp)) {
  			cstate->spo_must_allowed = true;
  			return true;
  		}
  	}
  	cstate->spo_must_allowed = false;
  	return false;
  }
4f0cefbf3   J. Bruce Fields   nfsd4: more preci...
3163
3164
  int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op)
  {
05b7278d5   Olga Kornievskaia   nfsd: fix oops on...
3165
  	if (op->opnum == OP_ILLEGAL || op->status == nfserr_notsupp)
4f0cefbf3   J. Bruce Fields   nfsd4: more preci...
3166
  		return op_encode_hdr_size * sizeof(__be32);
2282cd2c0   Kinglong Mee   NFSD: Get respons...
3167
3168
3169
  
  	BUG_ON(OPDESC(op)->op_rsize_bop == NULL);
  	return OPDESC(op)->op_rsize_bop(rqstp, op);
4f0cefbf3   J. Bruce Fields   nfsd4: more preci...
3170
  }
07d1f8020   J. Bruce Fields   nfsd4: fix encodi...
3171
3172
3173
3174
3175
3176
3177
3178
3179
  void warn_on_nonidempotent_op(struct nfsd4_op *op)
  {
  	if (OPDESC(op)->op_flags & OP_MODIFIES_SOMETHING) {
  		pr_err("unable to encode reply to nonidempotent op %d (%s)
  ",
  			op->opnum, nfsd4_op_name(op->opnum));
  		WARN_ON_ONCE(1);
  	}
  }
f1c7f79b6   Adrian Bunk   [NFSD] uninline n...
3180
  static const char *nfsd4_op_name(unsigned opnum)
b001a1b6a   Benny Halevy   nfsd: dprint oper...
3181
3182
3183
3184
3185
  {
  	if (opnum < ARRAY_SIZE(nfsd4_ops))
  		return nfsd4_ops[opnum].op_name;
  	return "unknown_operation";
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3186
  #define nfsd4_voidres			nfsd4_voidargs
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3187
  struct nfsd4_voidargs { int dummy; };
860bda29b   Christoph Hellwig   sunrpc: mark all ...
3188
  static const struct svc_procedure nfsd_procedures4[2] = {
0a93a47f0   Yu Zhiguo   NFSv4: kill off c...
3189
  	[NFSPROC4_NULL] = {
f7235b6bc   Christoph Hellwig   nfsd: use named i...
3190
  		.pc_func = nfsd4_proc_null,
dcc46991d   Chuck Lever   NFSD: Encoder and...
3191
  		.pc_decode = nfs4svc_decode_voidarg,
63f8de379   Christoph Hellwig   sunrpc: properly ...
3192
  		.pc_encode = nfs4svc_encode_voidres,
0a93a47f0   Yu Zhiguo   NFSv4: kill off c...
3193
3194
3195
3196
3197
3198
  		.pc_argsize = sizeof(struct nfsd4_voidargs),
  		.pc_ressize = sizeof(struct nfsd4_voidres),
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = 1,
  	},
  	[NFSPROC4_COMPOUND] = {
f7235b6bc   Christoph Hellwig   nfsd: use named i...
3199
  		.pc_func = nfsd4_proc_compound,
026fec7e7   Christoph Hellwig   sunrpc: properly ...
3200
  		.pc_decode = nfs4svc_decode_compoundargs,
63f8de379   Christoph Hellwig   sunrpc: properly ...
3201
  		.pc_encode = nfs4svc_encode_compoundres,
0a93a47f0   Yu Zhiguo   NFSv4: kill off c...
3202
3203
  		.pc_argsize = sizeof(struct nfsd4_compoundargs),
  		.pc_ressize = sizeof(struct nfsd4_compoundres),
3e98abffd   J. Bruce Fields   nfsd4: call nfsd4...
3204
  		.pc_release = nfsd4_release_compoundargs,
0a93a47f0   Yu Zhiguo   NFSv4: kill off c...
3205
3206
3207
  		.pc_cachetype = RC_NOCACHE,
  		.pc_xdrressize = NFSD_BUFSIZE/4,
  	},
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3208
  };
7fd38af9c   Christoph Hellwig   sunrpc: move pc_c...
3209
  static unsigned int nfsd_count3[ARRAY_SIZE(nfsd_procedures4)];
e9679189e   Christoph Hellwig   sunrpc: mark all ...
3210
  const struct svc_version nfsd_version4 = {
5283b03ee   Jeff Layton   nfs/nfsd/sunrpc: ...
3211
3212
3213
  	.vs_vers		= 4,
  	.vs_nproc		= 2,
  	.vs_proc		= nfsd_procedures4,
7fd38af9c   Christoph Hellwig   sunrpc: move pc_c...
3214
  	.vs_count		= nfsd_count3,
5283b03ee   Jeff Layton   nfs/nfsd/sunrpc: ...
3215
3216
3217
3218
  	.vs_dispatch		= nfsd_dispatch,
  	.vs_xdrsize		= NFS4_SVC_XDRSIZE,
  	.vs_rpcb_optnl		= true,
  	.vs_need_cong_ctrl	= true,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
3219
3220
3221
3222
3223
3224
3225
  };
  
  /*
   * Local variables:
   *  c-basic-offset: 8
   * End:
   */