Blame view

fs/nfsd/nfs4proc.c 31.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
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
34
35
  /*
   *  fs/nfsd/nfs4proc.c
   *
   *  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
36
37
38
39
40
   */
  
  #include <linux/param.h>
  #include <linux/major.h>
  #include <linux/slab.h>
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
41
  #include <linux/file.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
48
49
  
  #include <linux/sunrpc/svc.h>
  #include <linux/nfsd/nfsd.h>
  #include <linux/nfsd/cache.h>
  #include <linux/nfs4.h>
  #include <linux/nfsd/state.h>
  #include <linux/nfsd/xdr4.h>
  #include <linux/nfs4_acl.h>
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
50
  #include <linux/sunrpc/gss_api.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
56
57
58
59
60
61
62
  
  #define NFSDDBG_FACILITY		NFSDDBG_PROC
  
  static inline void
  fh_dup2(struct svc_fh *dst, struct svc_fh *src)
  {
  	fh_put(dst);
  	dget(src->fh_dentry);
  	if (src->fh_export)
  		cache_get(&src->fh_export->h);
  	*dst = *src;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
63
  static __be32
dc730e173   J. Bruce Fields   [PATCH] knfsd: nf...
64
  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
65
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
66
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
67
68
69
70
  
  	if (open->op_truncate &&
  		!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
  		return nfserr_inval;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  	if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
72
  		accmode |= NFSD_MAY_READ;
9801d8a39   J. Bruce Fields   [PATCH] knfsd: nf...
73
  	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
74
  		accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
9801d8a39   J. Bruce Fields   [PATCH] knfsd: nf...
75
  	if (open->op_share_deny & NFS4_SHARE_DENY_WRITE)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
76
  		accmode |= NFSD_MAY_WRITE;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
77
78
79
80
81
  
  	status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
  
  	return status;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
82
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
85
  do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  {
  	struct svc_fh resfh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
86
  	__be32 status;
81ac95c55   J. Bruce Fields   [PATCH] nfsd4: fi...
87
  	int created = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
88
89
90
91
92
93
94
95
96
97
98
99
  
  	fh_init(&resfh, NFS4_FHSIZE);
  	open->op_truncate = 0;
  
  	if (open->op_create) {
  		/*
  		 * Note: create modes (UNCHECKED,GUARDED...) are the same
  		 * in NFSv4 as in v3.
  		 */
  		status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data,
  					open->op_fname.len, &open->op_iattr,
  					&resfh, open->op_createmode,
749997e51   Jeff Layton   knfsd: set the re...
100
101
102
103
104
105
106
107
108
  					(u32 *)open->op_verf.data,
  					&open->op_truncate, &created);
  
  		/* If we ever decide to use different attrs to store the
  		 * verifier in nfsd_create_v3, then we'll need to change this
  		 */
  		if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
  			open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
  						FATTR4_WORD1_TIME_MODIFY);
af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
109
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
  		status = nfsd_lookup(rqstp, current_fh,
  				     open->op_fname.data, open->op_fname.len, &resfh);
  		fh_unlock(current_fh);
  	}
af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
114
115
  	if (status)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
116

af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
117
  	set_change_info(&open->op_cinfo, current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118

af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
119
120
121
122
123
  	/* set reply cache */
  	fh_dup2(current_fh, &resfh);
  	open->op_stateowner->so_replay.rp_openfh_len = resfh.fh_handle.fh_size;
  	memcpy(open->op_stateowner->so_replay.rp_openfh,
  			&resfh.fh_handle.fh_base, resfh.fh_handle.fh_size);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124

81ac95c55   J. Bruce Fields   [PATCH] nfsd4: fi...
125
  	if (!created)
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
126
127
  		status = do_open_permission(rqstp, current_fh, open,
  					    NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
128

af85852de   J. Bruce Fields   [PATCH] nfsd4: re...
129
  out:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
130
131
132
  	fh_put(&resfh);
  	return status;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
133
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
  do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
136
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  
  	/* Only reclaims from previously confirmed clients are valid */
  	if ((status = nfs4_check_open_reclaim(&open->op_clientid)))
  		return status;
  
  	/* We don't know the target directory, and therefore can not
  	* set the change info
  	*/
  
  	memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
  
  	/* set replay cache */
  	open->op_stateowner->so_replay.rp_openfh_len = current_fh->fh_handle.fh_size;
  	memcpy(open->op_stateowner->so_replay.rp_openfh,
  		&current_fh->fh_handle.fh_base,
  		current_fh->fh_handle.fh_size);
  
  	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
  		(open->op_iattr.ia_size == 0);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
156
157
  	status = do_open_permission(rqstp, current_fh, open,
  				    NFSD_MAY_OWNER_OVERRIDE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
  
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
161
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
162
  nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
163
  	   struct nfsd4_open *open)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
165
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
  	dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p
  ",
  		(int)open->op_fname.len, open->op_fname.data,
  		open->op_stateowner);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
170
171
172
173
174
175
176
177
  	/* This check required by spec. */
  	if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
  		return nfserr_inval;
  
  	nfs4_lock_state();
  
  	/* check seqid for replay. set nfs4_owner */
  	status = nfsd4_process_open1(open);
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
178
  	if (status == nfserr_replay_me) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
179
  		struct nfs4_replay *rp = &open->op_stateowner->so_replay;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
180
181
182
  		fh_put(&cstate->current_fh);
  		cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
  		memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  				rp->rp_openfh_len);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
184
  		status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
186
187
188
189
  		if (status)
  			dprintk("nfsd4_open: replay failed"
  				" restoring previous filehandle
  ");
  		else
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
190
  			status = nfserr_replay_me;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
191
192
193
  	}
  	if (status)
  		goto out;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
194
195
196
  
  	/* 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...
197
  	status = nfserr_grace;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
198
  	if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
cbd0d51a3   J. Bruce Fields   [PATCH] knfsd: fi...
199
200
  		goto out;
  	status = nfserr_no_grace;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
201
  	if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
cbd0d51a3   J. Bruce Fields   [PATCH] knfsd: fi...
202
  		goto out;
fb553c0f1   J. Bruce Fields   [PATCH] nfsd4: do...
203

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
  	switch (open->op_claim_type) {
0dd3c1921   NeilBrown   [PATCH] nfsd4: su...
205
206
207
208
209
  		case NFS4_OPEN_CLAIM_DELEGATE_CUR:
  			status = nfserr_inval;
  			if (open->op_create)
  				goto out;
  			/* fall through */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210
211
212
213
214
215
216
  		case NFS4_OPEN_CLAIM_NULL:
  			/*
  			 * (1) set CURRENT_FH to the file being opened,
  			 * creating it if necessary, (2) set open->op_cinfo,
  			 * (3) set open->op_truncate if the file is to be
  			 * truncated after opening, (4) do permission checking.
  			 */
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
217
218
  			status = do_open_lookup(rqstp, &cstate->current_fh,
  						open);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
219
220
221
222
  			if (status)
  				goto out;
  			break;
  		case NFS4_OPEN_CLAIM_PREVIOUS:
a525825df   J. Bruce Fields   [PATCH] nfsd4: ha...
223
  			open->op_stateowner->so_confirmed = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
224
225
226
227
228
229
  			/*
  			 * The CURRENT_FH is already set to the file being
  			 * opened.  (1) set open->op_cinfo, (2) set
  			 * open->op_truncate if the file is to be truncated
  			 * after opening, (3) do permission checking.
  			*/
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
230
231
  			status = do_open_fhandle(rqstp, &cstate->current_fh,
  						 open);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
  			if (status)
  				goto out;
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
235
               	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
a525825df   J. Bruce Fields   [PATCH] nfsd4: ha...
236
  			open->op_stateowner->so_confirmed = 1;
2fdada03b   J. Bruce Fields   knfsd: demote som...
237
238
  			dprintk("NFSD: unsupported OPEN claim type %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
239
240
241
242
  				open->op_claim_type);
  			status = nfserr_notsupp;
  			goto out;
  		default:
2fdada03b   J. Bruce Fields   knfsd: demote som...
243
244
  			dprintk("NFSD: Invalid OPEN claim type %d
  ",
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
245
246
247
248
249
250
251
252
253
  				open->op_claim_type);
  			status = nfserr_inval;
  			goto out;
  	}
  	/*
  	 * nfsd4_process_open2() does the actual opening of the file.  If
  	 * successful, it (1) truncates the file if open->op_truncate was
  	 * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
  	 */
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
254
  	status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
  out:
f2327d9ad   Neil Brown   [PATCH] nfsd4: mo...
256
  	if (open->op_stateowner) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
257
  		nfs4_get_stateowner(open->op_stateowner);
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
258
  		cstate->replay_owner = open->op_stateowner;
f2327d9ad   Neil Brown   [PATCH] nfsd4: mo...
259
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260
261
262
263
264
265
266
  	nfs4_unlock_state();
  	return status;
  }
  
  /*
   * filehandle-manipulating ops.
   */
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
267
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
268
269
  nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	    struct svc_fh **getfh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
270
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
271
  	if (!cstate->current_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272
  		return nfserr_nofilehandle;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
273
  	*getfh = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
274
275
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
276
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
277
278
  nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	    struct nfsd4_putfh *putfh)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
280
281
282
283
  	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);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
284
  	return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
285
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
286
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
287
288
  nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  		void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
290
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
291

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
292
  	fh_put(&cstate->current_fh);
df547efb0   J. Bruce Fields   knfsd: nfsd4: sim...
293
  	status = exp_pseudoroot(rqstp, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
294
295
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
296
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
297
298
  nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  		void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
299
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
300
  	if (!cstate->save_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
301
  		return nfserr_restorefh;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
302
  	fh_dup2(&cstate->current_fh, &cstate->save_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
303
304
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
305
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
306
307
  nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
308
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
309
  	if (!cstate->current_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310
  		return nfserr_nofilehandle;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
311
  	fh_dup2(&cstate->save_fh, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
312
313
314
315
316
317
  	return nfs_ok;
  }
  
  /*
   * misc nfsv4 ops
   */
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
318
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
319
320
  nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_access *access)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321
322
323
324
325
  {
  	if (access->ac_req_access & ~NFS3_ACCESS_FULL)
  		return nfserr_inval;
  
  	access->ac_resp_access = access->ac_req_access;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
326
327
  	return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
  			   &access->ac_supported);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
328
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
329
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
330
331
  nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_commit *commit)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
333
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
335
336
337
  
  	u32 *p = (u32 *)commit->co_verf.data;
  	*p++ = nfssvc_boot.tv_sec;
  	*p++ = nfssvc_boot.tv_usec;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
338
339
  	status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
  			     commit->co_count);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
340
341
342
343
  	if (status == nfserr_symlink)
  		status = nfserr_inval;
  	return status;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
344
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
345
346
  nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_create *create)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
347
348
  {
  	struct svc_fh resfh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
349
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
350
351
352
  	dev_t rdev;
  
  	fh_init(&resfh, NFS4_FHSIZE);
8837abcab   Miklos Szeredi   nfsd: rename MAY_...
353
354
  	status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
  			   NFSD_MAY_CREATE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
  	if (status == nfserr_symlink)
  		status = nfserr_notdir;
  	if (status)
  		return status;
  
  	switch (create->cr_type) {
  	case NF4LNK:
  		/* ugh! we have to null-terminate the linktext, or
  		 * vfs_symlink() will choke.  it is always safe to
  		 * null-terminate by brute force, since at worst we
  		 * will overwrite the first byte of the create namelen
  		 * in the XDR buffer, which has already been extracted
  		 * during XDR decode.
  		 */
  		create->cr_linkname[create->cr_linklen] = 0;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
370
371
372
373
  		status = nfsd_symlink(rqstp, &cstate->current_fh,
  				      create->cr_name, create->cr_namelen,
  				      create->cr_linkname, create->cr_linklen,
  				      &resfh, &create->cr_iattr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
375
376
377
378
379
380
  		break;
  
  	case NF4BLK:
  		rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  		if (MAJOR(rdev) != create->cr_specdata1 ||
  		    MINOR(rdev) != create->cr_specdata2)
  			return nfserr_inval;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
381
382
383
  		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
384
385
386
387
388
389
390
  		break;
  
  	case NF4CHR:
  		rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
  		if (MAJOR(rdev) != create->cr_specdata1 ||
  		    MINOR(rdev) != create->cr_specdata2)
  			return nfserr_inval;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
391
392
393
  		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
394
395
396
  		break;
  
  	case NF4SOCK:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
397
398
399
  		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
400
401
402
  		break;
  
  	case NF4FIFO:
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
403
404
405
  		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
406
407
408
409
  		break;
  
  	case NF4DIR:
  		create->cr_iattr.ia_valid &= ~ATTR_SIZE;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
410
411
412
  		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
413
414
415
416
417
418
419
  		break;
  
  	default:
  		status = nfserr_badtype;
  	}
  
  	if (!status) {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
420
421
422
  		fh_unlock(&cstate->current_fh);
  		set_change_info(&create->cr_cinfo, &cstate->current_fh);
  		fh_dup2(&cstate->current_fh, &resfh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
423
424
425
426
427
  	}
  
  	fh_put(&resfh);
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
428
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
429
430
  nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_getattr *getattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
431
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
432
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
433

8837abcab   Miklos Szeredi   nfsd: rename MAY_...
434
  	status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
435
436
437
438
439
440
441
442
  	if (status)
  		return status;
  
  	if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
  		return nfserr_inval;
  
  	getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
  	getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
443
  	getattr->ga_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444
445
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
446
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
447
448
  nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	   struct nfsd4_link *link)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
449
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
450
  	__be32 status = nfserr_nofilehandle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
451

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
452
  	if (!cstate->save_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
453
  		return status;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
454
455
  	status = nfsd_link(rqstp, &cstate->current_fh,
  			   link->li_name, link->li_namelen, &cstate->save_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
456
  	if (!status)
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
457
  		set_change_info(&link->li_cinfo, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
458
459
  	return status;
  }
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
460
  static __be32
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
461
462
  nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      void *arg)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
463
464
  {
  	struct svc_fh tmp_fh;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
465
  	__be32 ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466
467
  
  	fh_init(&tmp_fh, NFS4_FHSIZE);
df547efb0   J. Bruce Fields   knfsd: nfsd4: sim...
468
469
  	ret = exp_pseudoroot(rqstp, &tmp_fh);
  	if (ret)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
470
  		return ret;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
471
  	if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
472
473
474
475
  		fh_put(&tmp_fh);
  		return nfserr_noent;
  	}
  	fh_put(&tmp_fh);
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
476
477
  	return nfsd_lookup(rqstp, &cstate->current_fh,
  			   "..", 2, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
478
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
479
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
480
481
  nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_lookup *lookup)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482
  {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
483
484
485
  	return nfsd_lookup(rqstp, &cstate->current_fh,
  			   lookup->lo_name, lookup->lo_len,
  			   &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
486
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
487
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
488
489
  nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	   struct nfsd4_read *read)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
491
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492
493
  
  	/* no need to check permission - this will be done in nfsd_read() */
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
494
  	read->rd_filp = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
495
496
497
498
499
  	if (read->rd_offset >= OFFSET_MAX)
  		return nfserr_inval;
  
  	nfs4_lock_state();
  	/* check stateid */
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
500
501
  	if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
  				&read->rd_stateid,
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
502
  				CHECK_FH | RD_STATE, &read->rd_filp))) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
503
504
505
506
  		dprintk("NFSD: nfsd4_read: couldn't process stateid!
  ");
  		goto out;
  	}
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
507
508
  	if (read->rd_filp)
  		get_file(read->rd_filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
509
510
511
512
  	status = nfs_ok;
  out:
  	nfs4_unlock_state();
  	read->rd_rqstp = rqstp;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
513
  	read->rd_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
514
515
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
516
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
517
518
  nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_readdir *readdir)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
  {
  	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;
  
  	readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
  	readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
  
  	if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) ||
  	    (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...
536
  	readdir->rd_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
537
538
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
539
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
540
541
  nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	       struct nfsd4_readlink *readlink)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542
543
  {
  	readlink->rl_rqstp = rqstp;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
544
  	readlink->rl_fhp = &cstate->current_fh;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
545
546
  	return nfs_ok;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
547
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
548
549
  nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_remove *remove)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
550
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
551
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
552

c815afc73   NeilBrown   [PATCH] nfsd4: bl...
553
554
  	if (nfs4_in_grace())
  		return nfserr_grace;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
555
556
  	status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
  			     remove->rm_name, remove->rm_namelen);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
557
558
559
  	if (status == nfserr_symlink)
  		return nfserr_notdir;
  	if (!status) {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
560
561
  		fh_unlock(&cstate->current_fh);
  		set_change_info(&remove->rm_cinfo, &cstate->current_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
562
563
564
  	}
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
565
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
566
567
  nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_rename *rename)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
568
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
569
  	__be32 status = nfserr_nofilehandle;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
570

ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
571
  	if (!cstate->save_fh.fh_dentry)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
572
  		return status;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
573
  	if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
c815afc73   NeilBrown   [PATCH] nfsd4: bl...
574
575
  					& NFSEXP_NOSUBTREECHECK))
  		return nfserr_grace;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
576
577
  	status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
  			     rename->rn_snamelen, &cstate->current_fh,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
579
580
581
582
583
584
  			     rename->rn_tname, rename->rn_tnamelen);
  
  	/* the underlying filesystem returns different error's than required
  	 * by NFSv4. both save_fh and current_fh have been verified.. */
  	if (status == nfserr_isdir)
  		status = nfserr_exist;
  	else if ((status == nfserr_notdir) &&
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
585
586
                    (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
                     S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
587
588
589
590
591
  		status = nfserr_exist;
  	else if (status == nfserr_symlink)
  		status = nfserr_notdir;
  
  	if (!status) {
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
592
593
  		set_change_info(&rename->rn_sinfo, &cstate->current_fh);
  		set_change_info(&rename->rn_tinfo, &cstate->save_fh);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
594
595
596
  	}
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
597
  static __be32
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
  nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_secinfo *secinfo)
  {
  	struct svc_fh resfh;
  	struct svc_export *exp;
  	struct dentry *dentry;
  	__be32 err;
  
  	fh_init(&resfh, NFS4_FHSIZE);
  	err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
  				    secinfo->si_name, secinfo->si_namelen,
  				    &exp, &dentry);
  	if (err)
  		return err;
  	if (dentry->d_inode == NULL) {
  		exp_put(exp);
  		err = nfserr_noent;
  	} else
  		secinfo->si_exp = exp;
  	dput(dentry);
  	return err;
  }
  
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
622
623
  nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_setattr *setattr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
  {
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
625
  	__be32 status = nfs_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
626

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
627
628
  	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
  		nfs4_lock_state();
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
629
  		status = nfs4_preprocess_stateid_op(&cstate->current_fh,
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
630
  			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631
  		nfs4_unlock_state();
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
632
  		if (status) {
3e3b48009   Greg Banks   [PATCH] knfsd: ad...
633
634
  			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!
  ");
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
635
636
  			return status;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
637
  	}
18f335aff   Dave Hansen   [PATCH] r/o bind ...
638
639
640
  	status = mnt_want_write(cstate->current_fh.fh_export->ex_path.mnt);
  	if (status)
  		return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
641
642
  	status = nfs_ok;
  	if (setattr->sa_acl != NULL)
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
643
644
  		status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
  					    setattr->sa_acl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
645
  	if (status)
18f335aff   Dave Hansen   [PATCH] r/o bind ...
646
  		goto out;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
647
  	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  				0, (time_t)0);
18f335aff   Dave Hansen   [PATCH] r/o bind ...
649
650
  out:
  	mnt_drop_write(cstate->current_fh.fh_export->ex_path.mnt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
651
652
  	return status;
  }
7191155bd   J.Bruce Fields   [PATCH] knfsd: nf...
653
  static __be32
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
654
655
  nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	    struct nfsd4_write *write)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
656
657
658
659
  {
  	stateid_t *stateid = &write->wr_stateid;
  	struct file *filp = NULL;
  	u32 *p;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
660
  	__be32 status = nfs_ok;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
663
664
665
666
667
  
  	/* no need to check permission - this will be done in nfsd_write() */
  
  	if (write->wr_offset >= OFFSET_MAX)
  		return nfserr_inval;
  
  	nfs4_lock_state();
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
668
  	status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
669
  					CHECK_FH | WR_STATE, &filp);
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
670
671
  	if (filp)
  		get_file(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
672
  	nfs4_unlock_state();
375c5547c   J. Bruce Fields   [PATCH] nfsd4: nf...
673
674
675
676
677
  	if (status) {
  		dprintk("NFSD: nfsd4_write: couldn't process stateid!
  ");
  		return status;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
678
679
680
681
682
  	write->wr_bytes_written = write->wr_buflen;
  	write->wr_how_written = write->wr_stable_how;
  	p = (u32 *)write->wr_verifier.data;
  	*p++ = nfssvc_boot.tv_sec;
  	*p++ = nfssvc_boot.tv_usec;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
683
684
685
  	status =  nfsd_write(rqstp, &cstate->current_fh, filp,
  			     write->wr_offset, rqstp->rq_vec, write->wr_vlen,
  			     write->wr_buflen, &write->wr_how_written);
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
686
687
  	if (filp)
  		fput(filp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
688
689
690
691
  
  	if (status == nfserr_symlink)
  		status = nfserr_inval;
  	return status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
692
693
694
695
696
697
698
  }
  
  /* 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...
699
  static __be32
c954e2a5d   J.Bruce Fields   [PATCH] knfsd: nf...
700
  _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
701
  	     struct nfsd4_verify *verify)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
702
  {
2ebbc012a   Al Viro   [PATCH] xdr annot...
703
  	__be32 *buf, *p;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
704
  	int count;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
705
  	__be32 status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706

8837abcab   Miklos Szeredi   nfsd: rename MAY_...
707
  	status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
  	if (status)
  		return status;
  
  	if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0)
  	    || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
  		return nfserr_attrnotsupp;
  	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)
  		return nfserr_resource;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
727
728
729
  	status = nfsd4_encode_fattr(&cstate->current_fh,
  				    cstate->current_fh.fh_export,
  				    cstate->current_fh.fh_dentry, buf,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
730
  				    &count, verify->ve_bmval,
406a7ea97   Frank Filz   nfsd: Allow AIX c...
731
  				    rqstp, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
  
  	/* this means that nfsd4_encode_fattr() ran out of space */
  	if (status == nfserr_resource && count == 0)
  		status = nfserr_not_same;
  	if (status)
  		goto out_kfree;
  
  	p = buf + 3;
  	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...
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
  static __be32
  nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	      struct nfsd4_verify *verify)
  {
  	__be32 status;
  
  	status = _nfsd4_verify(rqstp, cstate, verify);
  	return status == nfserr_not_same ? nfs_ok : status;
  }
  
  static __be32
  nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
  	     struct nfsd4_verify *verify)
  {
  	__be32 status;
  
  	status = _nfsd4_verify(rqstp, cstate, verify);
  	return status == nfserr_same ? nfs_ok : status;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
769
770
771
  /*
   * NULL call.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
772
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
773
774
775
776
  nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
  {
  	return nfs_ok;
  }
e2b209509   Shankar Anand   [PATCH] knfsd: nf...
777
778
779
780
781
  static inline void nfsd4_increment_op_stats(u32 opnum)
  {
  	if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
  		nfsdstats.nfs4_opcount[opnum]++;
  }
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
782
783
784
785
786
787
  static void cstate_free(struct nfsd4_compound_state *cstate)
  {
  	if (cstate == NULL)
  		return;
  	fh_put(&cstate->current_fh);
  	fh_put(&cstate->save_fh);
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
788
  	BUG_ON(cstate->replay_owner);
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
789
790
791
792
793
794
795
796
797
798
799
800
  	kfree(cstate);
  }
  
  static struct nfsd4_compound_state *cstate_alloc(void)
  {
  	struct nfsd4_compound_state *cstate;
  
  	cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);
  	if (cstate == NULL)
  		return NULL;
  	fh_init(&cstate->current_fh, NFS4_FHSIZE);
  	fh_init(&cstate->save_fh, NFS4_FHSIZE);
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
801
  	cstate->replay_owner = NULL;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
802
803
  	return cstate;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
804

b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
805
806
807
808
809
810
  typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
  			      void *);
  
  struct nfsd4_operation {
  	nfsd4op_func op_func;
  	u32 op_flags;
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
811
812
  /* Most ops require a valid current filehandle; a few don't: */
  #define ALLOWED_WITHOUT_FH 1
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
813
  /* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
814
  #define ALLOWED_ON_ABSENT_FS 2
b001a1b6a   Benny Halevy   nfsd: dprint oper...
815
  	char *op_name;
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
816
817
818
  };
  
  static struct nfsd4_operation nfsd4_ops[];
f1c7f79b6   Adrian Bunk   [NFSD] uninline n...
819
  static const char *nfsd4_op_name(unsigned opnum);
b001a1b6a   Benny Halevy   nfsd: dprint oper...
820

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
821
822
823
  /*
   * COMPOUND call.
   */
7111c66e4   Al Viro   [PATCH] fix svc_p...
824
  static __be32
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
825
826
827
828
829
  nfsd4_proc_compound(struct svc_rqst *rqstp,
  		    struct nfsd4_compoundargs *args,
  		    struct nfsd4_compoundres *resp)
  {
  	struct nfsd4_op	*op;
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
830
  	struct nfsd4_operation *opdesc;
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
831
  	struct nfsd4_compound_state *cstate = NULL;
e57101991   J.Bruce Fields   [PATCH] knfsd: nf...
832
  	int		slack_bytes;
b37ad28bc   Al Viro   [PATCH] nfsd: nfs...
833
  	__be32		status;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
834

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
  	resp->xbuf = &rqstp->rq_res;
  	resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
  	resp->tagp = resp->p;
  	/* reserve space for: taglen, tag, and opcnt */
  	resp->p += 2 + XDR_QUADLEN(args->taglen);
  	resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
  	resp->taglen = args->taglen;
  	resp->tag = args->tag;
  	resp->opcnt = 0;
  	resp->rqstp = rqstp;
  
  	/*
  	 * According to RFC3010, this takes precedence over all other errors.
  	 */
  	status = nfserr_minor_vers_mismatch;
  	if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
  		goto out;
c228c24bf   Andy Adamson   nfsd: fix compoun...
852
853
854
855
  	status = nfserr_resource;
  	cstate = cstate_alloc();
  	if (cstate == NULL)
  		goto out;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
856
857
858
  	status = nfs_ok;
  	while (!status && resp->opcnt < args->opcnt) {
  		op = &args->ops[resp->opcnt++];
b001a1b6a   Benny Halevy   nfsd: dprint oper...
859
860
861
862
  		dprintk("nfsv4 compound op #%d/%d: %d (%s)
  ",
  			resp->opcnt, args->opcnt, op->opnum,
  			nfsd4_op_name(op->opnum));
fd4452770   J. Bruce Fields   [PATCH] nfsd4: op...
863

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
864
865
866
867
868
869
870
871
872
873
874
875
876
  		/*
  		 * The XDR decode routines may have pre-set op->status;
  		 * for example, if there is a miscellaneous XDR error
  		 * it will be set to nfserr_bad_xdr.
  		 */
  		if (op->status)
  			goto encode_op;
  
  		/* We must be able to encode a successful response to
  		 * this operation, with enough room left over to encode a
  		 * failed response to the next operation.  If we don't
  		 * have enough room, fail with ERR_RESOURCE.
  		 */
e57101991   J.Bruce Fields   [PATCH] knfsd: nf...
877
878
879
880
  		slack_bytes = (char *)resp->end - (char *)resp->p;
  		if (slack_bytes < COMPOUND_SLACK_SPACE
  				+ COMPOUND_ERR_SLACK_SPACE) {
  			BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
881
882
883
  			op->status = nfserr_resource;
  			goto encode_op;
  		}
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
884
  		opdesc = &nfsd4_ops[op->opnum];
ca3643171   J.Bruce Fields   [PATCH] knfsd: nf...
885
  		if (!cstate->current_fh.fh_dentry) {
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
886
  			if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
42ca09938   J.Bruce Fields   [PATCH] knfsd: nf...
887
888
889
  				op->status = nfserr_nofilehandle;
  				goto encode_op;
  			}
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
890
891
  		} else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
  			  !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
42ca09938   J.Bruce Fields   [PATCH] knfsd: nf...
892
  			op->status = nfserr_moved;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
893
894
  			goto encode_op;
  		}
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
895
896
897
898
  
  		if (opdesc->op_func)
  			op->status = opdesc->op_func(rqstp, cstate, &op->u);
  		else
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
899
  			BUG_ON(op->status == nfs_ok);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
900
901
  
  encode_op:
a90b061c0   Al Viro   [PATCH] nfsd: nfs...
902
  		if (op->status == nfserr_replay_me) {
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
903
  			op->replay = &cstate->replay_owner->so_replay;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
904
905
906
907
908
909
  			nfsd4_encode_replay(resp, op);
  			status = op->status = op->replay->rp_status;
  		} else {
  			nfsd4_encode_operation(resp, op);
  			status = op->status;
  		}
a4f1706a9   J.Bruce Fields   [PATCH] knfsd: nf...
910
911
912
  		if (cstate->replay_owner) {
  			nfs4_put_stateowner(cstate->replay_owner);
  			cstate->replay_owner = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
913
  		}
7e06b7f9e   NeilBrown   [PATCH] knfsd: nf...
914
915
916
  		/* XXX Ugh, we need to get rid of this kind of special case: */
  		if (op->opnum == OP_READ && op->u.read.rd_filp)
  			fput(op->u.read.rd_filp);
e2b209509   Shankar Anand   [PATCH] knfsd: nf...
917
918
  
  		nfsd4_increment_op_stats(op->opnum);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
919
  	}
c228c24bf   Andy Adamson   nfsd: fix compoun...
920
  	cstate_free(cstate);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
921
922
  out:
  	nfsd4_release_compoundargs(args);
3b12cd986   J. Bruce Fields   nfsd: add dprintk...
923
924
  	dprintk("nfsv4 compound returned %d
  ", ntohl(status));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
925
926
  	return status;
  }
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
927
928
929
  static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
  	[OP_ACCESS] = {
  		.op_func = (nfsd4op_func)nfsd4_access,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
930
  		.op_name = "OP_ACCESS",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
931
932
933
  	},
  	[OP_CLOSE] = {
  		.op_func = (nfsd4op_func)nfsd4_close,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
934
  		.op_name = "OP_CLOSE",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
935
936
937
  	},
  	[OP_COMMIT] = {
  		.op_func = (nfsd4op_func)nfsd4_commit,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
938
  		.op_name = "OP_COMMIT",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
939
940
941
  	},
  	[OP_CREATE] = {
  		.op_func = (nfsd4op_func)nfsd4_create,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
942
  		.op_name = "OP_CREATE",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
943
944
945
  	},
  	[OP_DELEGRETURN] = {
  		.op_func = (nfsd4op_func)nfsd4_delegreturn,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
946
  		.op_name = "OP_DELEGRETURN",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
947
948
949
  	},
  	[OP_GETATTR] = {
  		.op_func = (nfsd4op_func)nfsd4_getattr,
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
950
  		.op_flags = ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
951
  		.op_name = "OP_GETATTR",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
952
953
954
  	},
  	[OP_GETFH] = {
  		.op_func = (nfsd4op_func)nfsd4_getfh,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
955
  		.op_name = "OP_GETFH",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
956
957
958
  	},
  	[OP_LINK] = {
  		.op_func = (nfsd4op_func)nfsd4_link,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
959
  		.op_name = "OP_LINK",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
960
961
962
  	},
  	[OP_LOCK] = {
  		.op_func = (nfsd4op_func)nfsd4_lock,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
963
  		.op_name = "OP_LOCK",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
964
965
966
  	},
  	[OP_LOCKT] = {
  		.op_func = (nfsd4op_func)nfsd4_lockt,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
967
  		.op_name = "OP_LOCKT",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
968
969
970
  	},
  	[OP_LOCKU] = {
  		.op_func = (nfsd4op_func)nfsd4_locku,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
971
  		.op_name = "OP_LOCKU",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
972
973
974
  	},
  	[OP_LOOKUP] = {
  		.op_func = (nfsd4op_func)nfsd4_lookup,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
975
  		.op_name = "OP_LOOKUP",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
976
977
978
  	},
  	[OP_LOOKUPP] = {
  		.op_func = (nfsd4op_func)nfsd4_lookupp,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
979
  		.op_name = "OP_LOOKUPP",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
980
981
982
  	},
  	[OP_NVERIFY] = {
  		.op_func = (nfsd4op_func)nfsd4_nverify,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
983
  		.op_name = "OP_NVERIFY",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
984
985
986
  	},
  	[OP_OPEN] = {
  		.op_func = (nfsd4op_func)nfsd4_open,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
987
  		.op_name = "OP_OPEN",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
988
989
990
  	},
  	[OP_OPEN_CONFIRM] = {
  		.op_func = (nfsd4op_func)nfsd4_open_confirm,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
991
  		.op_name = "OP_OPEN_CONFIRM",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
992
993
994
  	},
  	[OP_OPEN_DOWNGRADE] = {
  		.op_func = (nfsd4op_func)nfsd4_open_downgrade,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
995
  		.op_name = "OP_OPEN_DOWNGRADE",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
996
997
998
  	},
  	[OP_PUTFH] = {
  		.op_func = (nfsd4op_func)nfsd4_putfh,
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
999
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1000
  		.op_name = "OP_PUTFH",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1001
  	},
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
1002
  	[OP_PUTPUBFH] = {
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1003
  		/* unsupported, just for future reference: */
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1004
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1005
  		.op_name = "OP_PUTPUBFH",
eeac294eb   J.Bruce Fields   [PATCH] knfsd: nf...
1006
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1007
1008
  	[OP_PUTROOTFH] = {
  		.op_func = (nfsd4op_func)nfsd4_putrootfh,
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1009
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1010
  		.op_name = "OP_PUTROOTFH",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1011
1012
1013
  	},
  	[OP_READ] = {
  		.op_func = (nfsd4op_func)nfsd4_read,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1014
  		.op_name = "OP_READ",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1015
1016
1017
  	},
  	[OP_READDIR] = {
  		.op_func = (nfsd4op_func)nfsd4_readdir,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1018
  		.op_name = "OP_READDIR",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1019
1020
1021
  	},
  	[OP_READLINK] = {
  		.op_func = (nfsd4op_func)nfsd4_readlink,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1022
  		.op_name = "OP_READLINK",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1023
1024
1025
  	},
  	[OP_REMOVE] = {
  		.op_func = (nfsd4op_func)nfsd4_remove,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1026
  		.op_name = "OP_REMOVE",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1027
1028
  	},
  	[OP_RENAME] = {
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1029
  		.op_name = "OP_RENAME",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1030
1031
1032
1033
  		.op_func = (nfsd4op_func)nfsd4_rename,
  	},
  	[OP_RENEW] = {
  		.op_func = (nfsd4op_func)nfsd4_renew,
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1034
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1035
  		.op_name = "OP_RENEW",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1036
1037
1038
  	},
  	[OP_RESTOREFH] = {
  		.op_func = (nfsd4op_func)nfsd4_restorefh,
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1039
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1040
  		.op_name = "OP_RESTOREFH",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1041
1042
1043
  	},
  	[OP_SAVEFH] = {
  		.op_func = (nfsd4op_func)nfsd4_savefh,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1044
  		.op_name = "OP_SAVEFH",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1045
  	},
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
1046
1047
  	[OP_SECINFO] = {
  		.op_func = (nfsd4op_func)nfsd4_secinfo,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1048
  		.op_name = "OP_SECINFO",
dcb488a3b   Andy Adamson   knfsd: nfsd4: imp...
1049
  	},
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1050
1051
  	[OP_SETATTR] = {
  		.op_func = (nfsd4op_func)nfsd4_setattr,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1052
  		.op_name = "OP_SETATTR",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1053
1054
1055
  	},
  	[OP_SETCLIENTID] = {
  		.op_func = (nfsd4op_func)nfsd4_setclientid,
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1056
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1057
  		.op_name = "OP_SETCLIENTID",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1058
1059
1060
  	},
  	[OP_SETCLIENTID_CONFIRM] = {
  		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1061
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1062
  		.op_name = "OP_SETCLIENTID_CONFIRM",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1063
1064
1065
  	},
  	[OP_VERIFY] = {
  		.op_func = (nfsd4op_func)nfsd4_verify,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1066
  		.op_name = "OP_VERIFY",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1067
1068
1069
  	},
  	[OP_WRITE] = {
  		.op_func = (nfsd4op_func)nfsd4_write,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1070
  		.op_name = "OP_WRITE",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1071
1072
1073
  	},
  	[OP_RELEASE_LOCKOWNER] = {
  		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
27d630ece   J.Bruce Fields   [PATCH] knfsd: nf...
1074
  		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1075
  		.op_name = "OP_RELEASE_LOCKOWNER",
b591480bb   J.Bruce Fields   [PATCH] knfsd: nf...
1076
1077
  	},
  };
f1c7f79b6   Adrian Bunk   [NFSD] uninline n...
1078
  static const char *nfsd4_op_name(unsigned opnum)
b001a1b6a   Benny Halevy   nfsd: dprint oper...
1079
1080
1081
1082
1083
  {
  	if (opnum < ARRAY_SIZE(nfsd4_ops))
  		return nfsd4_ops[opnum].op_name;
  	return "unknown_operation";
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
  #define nfs4svc_decode_voidargs		NULL
  #define nfs4svc_release_void		NULL
  #define nfsd4_voidres			nfsd4_voidargs
  #define nfs4svc_release_compound	NULL
  struct nfsd4_voidargs { int dummy; };
  
  #define PROC(name, argt, rest, relt, cache, respsize)	\
   { (svc_procfunc) nfsd4_proc_##name,		\
     (kxdrproc_t) nfs4svc_decode_##argt##args,	\
     (kxdrproc_t) nfs4svc_encode_##rest##res,	\
     (kxdrproc_t) nfs4svc_release_##relt,		\
     sizeof(struct nfsd4_##argt##args),		\
     sizeof(struct nfsd4_##rest##res),		\
     0,						\
     cache,					\
     respsize,					\
   }
  
  /*
   * TODO: At the present time, the NFSv4 server does not do XID caching
   * of requests.  Implementing XID caching would not be a serious problem,
   * although it would require a mild change in interfaces since one
   * doesn't know whether an NFSv4 request is idempotent until after the
   * XDR decode.  However, XID caching totally confuses pynfs (Peter
   * Astrand's regression testsuite for NFSv4 servers), which reuses
   * XID's liberally, so I've left it unimplemented until pynfs generates
   * better XID's.
   */
  static struct svc_procedure		nfsd_procedures4[2] = {
    PROC(null,	 void,		void,		void,	  RC_NOCACHE, 1),
7775f4c85   NeilBrown   [PATCH] knfsd: Co...
1114
    PROC(compound, compound,	compound,	compound, RC_NOCACHE, NFSD_BUFSIZE/4)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
  };
  
  struct svc_version	nfsd_version4 = {
  		.vs_vers	= 4,
  		.vs_nproc	= 2,
  		.vs_proc	= nfsd_procedures4,
  		.vs_dispatch	= nfsd_dispatch,
  		.vs_xdrsize	= NFS4_SVC_XDRSIZE,
  };
  
  /*
   * Local variables:
   *  c-basic-offset: 8
   * End:
   */