Commit 84822d0b3bc5a74a4290727dd1ab4fc7dcd6a348

Authored by J. Bruce Fields
1 parent d1c3ed669a

nfsd4: simplify nfsd4_encode_fattr interface slightly

It seems slightly simpler to make nfsd4_encode_fattr rather than its
callers responsible for advancing the write pointer on success.

(Also: the count == 0 check in the verify case looks superfluous.
Running out of buffer space is really the only reason fattr encoding
should fail with eresource.)

Signed-off-by: J. Bruce Fields <bfields@redhat.com>

Showing 3 changed files with 13 additions and 17 deletions Inline Diff

1 /* 1 /*
2 * Server-side procedures for NFSv4. 2 * Server-side procedures for NFSv4.
3 * 3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan. 4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Kendrick Smith <kmsmith@umich.edu> 7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <andros@umich.edu> 8 * Andy Adamson <andros@umich.edu>
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 13 *
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its 19 * 3. Neither the name of the University nor the names of its
20 * contributors may be used to endorse or promote products derived 20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission. 21 * from this software without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */ 34 */
35 #include <linux/file.h> 35 #include <linux/file.h>
36 #include <linux/slab.h> 36 #include <linux/slab.h>
37 37
38 #include "idmap.h" 38 #include "idmap.h"
39 #include "cache.h" 39 #include "cache.h"
40 #include "xdr4.h" 40 #include "xdr4.h"
41 #include "vfs.h" 41 #include "vfs.h"
42 #include "current_stateid.h" 42 #include "current_stateid.h"
43 #include "netns.h" 43 #include "netns.h"
44 44
45 #define NFSDDBG_FACILITY NFSDDBG_PROC 45 #define NFSDDBG_FACILITY NFSDDBG_PROC
46 46
47 static u32 nfsd_attrmask[] = { 47 static u32 nfsd_attrmask[] = {
48 NFSD_WRITEABLE_ATTRS_WORD0, 48 NFSD_WRITEABLE_ATTRS_WORD0,
49 NFSD_WRITEABLE_ATTRS_WORD1, 49 NFSD_WRITEABLE_ATTRS_WORD1,
50 NFSD_WRITEABLE_ATTRS_WORD2 50 NFSD_WRITEABLE_ATTRS_WORD2
51 }; 51 };
52 52
53 static u32 nfsd41_ex_attrmask[] = { 53 static u32 nfsd41_ex_attrmask[] = {
54 NFSD_SUPPATTR_EXCLCREAT_WORD0, 54 NFSD_SUPPATTR_EXCLCREAT_WORD0,
55 NFSD_SUPPATTR_EXCLCREAT_WORD1, 55 NFSD_SUPPATTR_EXCLCREAT_WORD1,
56 NFSD_SUPPATTR_EXCLCREAT_WORD2 56 NFSD_SUPPATTR_EXCLCREAT_WORD2
57 }; 57 };
58 58
59 static __be32 59 static __be32
60 check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 60 check_attr_support(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
61 u32 *bmval, u32 *writable) 61 u32 *bmval, u32 *writable)
62 { 62 {
63 struct dentry *dentry = cstate->current_fh.fh_dentry; 63 struct dentry *dentry = cstate->current_fh.fh_dentry;
64 64
65 /* 65 /*
66 * Check about attributes are supported by the NFSv4 server or not. 66 * Check about attributes are supported by the NFSv4 server or not.
67 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP. 67 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP.
68 */ 68 */
69 if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) || 69 if ((bmval[0] & ~nfsd_suppattrs0(cstate->minorversion)) ||
70 (bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) || 70 (bmval[1] & ~nfsd_suppattrs1(cstate->minorversion)) ||
71 (bmval[2] & ~nfsd_suppattrs2(cstate->minorversion))) 71 (bmval[2] & ~nfsd_suppattrs2(cstate->minorversion)))
72 return nfserr_attrnotsupp; 72 return nfserr_attrnotsupp;
73 73
74 /* 74 /*
75 * Check FATTR4_WORD0_ACL can be supported 75 * Check FATTR4_WORD0_ACL can be supported
76 * in current environment or not. 76 * in current environment or not.
77 */ 77 */
78 if (bmval[0] & FATTR4_WORD0_ACL) { 78 if (bmval[0] & FATTR4_WORD0_ACL) {
79 if (!IS_POSIXACL(dentry->d_inode)) 79 if (!IS_POSIXACL(dentry->d_inode))
80 return nfserr_attrnotsupp; 80 return nfserr_attrnotsupp;
81 } 81 }
82 82
83 /* 83 /*
84 * According to spec, read-only attributes return ERR_INVAL. 84 * According to spec, read-only attributes return ERR_INVAL.
85 */ 85 */
86 if (writable) { 86 if (writable) {
87 if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) || 87 if ((bmval[0] & ~writable[0]) || (bmval[1] & ~writable[1]) ||
88 (bmval[2] & ~writable[2])) 88 (bmval[2] & ~writable[2]))
89 return nfserr_inval; 89 return nfserr_inval;
90 } 90 }
91 91
92 return nfs_ok; 92 return nfs_ok;
93 } 93 }
94 94
95 static __be32 95 static __be32
96 nfsd4_check_open_attributes(struct svc_rqst *rqstp, 96 nfsd4_check_open_attributes(struct svc_rqst *rqstp,
97 struct nfsd4_compound_state *cstate, struct nfsd4_open *open) 97 struct nfsd4_compound_state *cstate, struct nfsd4_open *open)
98 { 98 {
99 __be32 status = nfs_ok; 99 __be32 status = nfs_ok;
100 100
101 if (open->op_create == NFS4_OPEN_CREATE) { 101 if (open->op_create == NFS4_OPEN_CREATE) {
102 if (open->op_createmode == NFS4_CREATE_UNCHECKED 102 if (open->op_createmode == NFS4_CREATE_UNCHECKED
103 || open->op_createmode == NFS4_CREATE_GUARDED) 103 || open->op_createmode == NFS4_CREATE_GUARDED)
104 status = check_attr_support(rqstp, cstate, 104 status = check_attr_support(rqstp, cstate,
105 open->op_bmval, nfsd_attrmask); 105 open->op_bmval, nfsd_attrmask);
106 else if (open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1) 106 else if (open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1)
107 status = check_attr_support(rqstp, cstate, 107 status = check_attr_support(rqstp, cstate,
108 open->op_bmval, nfsd41_ex_attrmask); 108 open->op_bmval, nfsd41_ex_attrmask);
109 } 109 }
110 110
111 return status; 111 return status;
112 } 112 }
113 113
114 static int 114 static int
115 is_create_with_attrs(struct nfsd4_open *open) 115 is_create_with_attrs(struct nfsd4_open *open)
116 { 116 {
117 return open->op_create == NFS4_OPEN_CREATE 117 return open->op_create == NFS4_OPEN_CREATE
118 && (open->op_createmode == NFS4_CREATE_UNCHECKED 118 && (open->op_createmode == NFS4_CREATE_UNCHECKED
119 || open->op_createmode == NFS4_CREATE_GUARDED 119 || open->op_createmode == NFS4_CREATE_GUARDED
120 || open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1); 120 || open->op_createmode == NFS4_CREATE_EXCLUSIVE4_1);
121 } 121 }
122 122
123 /* 123 /*
124 * if error occurs when setting the acl, just clear the acl bit 124 * if error occurs when setting the acl, just clear the acl bit
125 * in the returned attr bitmap. 125 * in the returned attr bitmap.
126 */ 126 */
127 static void 127 static void
128 do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp, 128 do_set_nfs4_acl(struct svc_rqst *rqstp, struct svc_fh *fhp,
129 struct nfs4_acl *acl, u32 *bmval) 129 struct nfs4_acl *acl, u32 *bmval)
130 { 130 {
131 __be32 status; 131 __be32 status;
132 132
133 status = nfsd4_set_nfs4_acl(rqstp, fhp, acl); 133 status = nfsd4_set_nfs4_acl(rqstp, fhp, acl);
134 if (status) 134 if (status)
135 /* 135 /*
136 * We should probably fail the whole open at this point, 136 * We should probably fail the whole open at this point,
137 * but we've already created the file, so it's too late; 137 * but we've already created the file, so it's too late;
138 * So this seems the least of evils: 138 * So this seems the least of evils:
139 */ 139 */
140 bmval[0] &= ~FATTR4_WORD0_ACL; 140 bmval[0] &= ~FATTR4_WORD0_ACL;
141 } 141 }
142 142
143 static inline void 143 static inline void
144 fh_dup2(struct svc_fh *dst, struct svc_fh *src) 144 fh_dup2(struct svc_fh *dst, struct svc_fh *src)
145 { 145 {
146 fh_put(dst); 146 fh_put(dst);
147 dget(src->fh_dentry); 147 dget(src->fh_dentry);
148 if (src->fh_export) 148 if (src->fh_export)
149 cache_get(&src->fh_export->h); 149 cache_get(&src->fh_export->h);
150 *dst = *src; 150 *dst = *src;
151 } 151 }
152 152
153 static __be32 153 static __be32
154 do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode) 154 do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, int accmode)
155 { 155 {
156 __be32 status; 156 __be32 status;
157 157
158 if (open->op_truncate && 158 if (open->op_truncate &&
159 !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) 159 !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
160 return nfserr_inval; 160 return nfserr_inval;
161 161
162 accmode |= NFSD_MAY_READ_IF_EXEC; 162 accmode |= NFSD_MAY_READ_IF_EXEC;
163 163
164 if (open->op_share_access & NFS4_SHARE_ACCESS_READ) 164 if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
165 accmode |= NFSD_MAY_READ; 165 accmode |= NFSD_MAY_READ;
166 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE) 166 if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
167 accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC); 167 accmode |= (NFSD_MAY_WRITE | NFSD_MAY_TRUNC);
168 if (open->op_share_deny & NFS4_SHARE_DENY_READ) 168 if (open->op_share_deny & NFS4_SHARE_DENY_READ)
169 accmode |= NFSD_MAY_WRITE; 169 accmode |= NFSD_MAY_WRITE;
170 170
171 status = fh_verify(rqstp, current_fh, S_IFREG, accmode); 171 status = fh_verify(rqstp, current_fh, S_IFREG, accmode);
172 172
173 return status; 173 return status;
174 } 174 }
175 175
176 static __be32 nfsd_check_obj_isreg(struct svc_fh *fh) 176 static __be32 nfsd_check_obj_isreg(struct svc_fh *fh)
177 { 177 {
178 umode_t mode = fh->fh_dentry->d_inode->i_mode; 178 umode_t mode = fh->fh_dentry->d_inode->i_mode;
179 179
180 if (S_ISREG(mode)) 180 if (S_ISREG(mode))
181 return nfs_ok; 181 return nfs_ok;
182 if (S_ISDIR(mode)) 182 if (S_ISDIR(mode))
183 return nfserr_isdir; 183 return nfserr_isdir;
184 /* 184 /*
185 * Using err_symlink as our catch-all case may look odd; but 185 * Using err_symlink as our catch-all case may look odd; but
186 * there's no other obvious error for this case in 4.0, and we 186 * there's no other obvious error for this case in 4.0, and we
187 * happen to know that it will cause the linux v4 client to do 187 * happen to know that it will cause the linux v4 client to do
188 * the right thing on attempts to open something other than a 188 * the right thing on attempts to open something other than a
189 * regular file. 189 * regular file.
190 */ 190 */
191 return nfserr_symlink; 191 return nfserr_symlink;
192 } 192 }
193 193
194 static __be32 194 static __be32
195 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 195 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
196 { 196 {
197 struct svc_fh *resfh; 197 struct svc_fh *resfh;
198 int accmode; 198 int accmode;
199 __be32 status; 199 __be32 status;
200 200
201 resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); 201 resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
202 if (!resfh) 202 if (!resfh)
203 return nfserr_jukebox; 203 return nfserr_jukebox;
204 fh_init(resfh, NFS4_FHSIZE); 204 fh_init(resfh, NFS4_FHSIZE);
205 open->op_truncate = 0; 205 open->op_truncate = 0;
206 206
207 if (open->op_create) { 207 if (open->op_create) {
208 /* FIXME: check session persistence and pnfs flags. 208 /* FIXME: check session persistence and pnfs flags.
209 * The nfsv4.1 spec requires the following semantics: 209 * The nfsv4.1 spec requires the following semantics:
210 * 210 *
211 * Persistent | pNFS | Server REQUIRED | Client Allowed 211 * Persistent | pNFS | Server REQUIRED | Client Allowed
212 * Reply Cache | server | | 212 * Reply Cache | server | |
213 * -------------+--------+-----------------+-------------------- 213 * -------------+--------+-----------------+--------------------
214 * no | no | EXCLUSIVE4_1 | EXCLUSIVE4_1 214 * no | no | EXCLUSIVE4_1 | EXCLUSIVE4_1
215 * | | | (SHOULD) 215 * | | | (SHOULD)
216 * | | and EXCLUSIVE4 | or EXCLUSIVE4 216 * | | and EXCLUSIVE4 | or EXCLUSIVE4
217 * | | | (SHOULD NOT) 217 * | | | (SHOULD NOT)
218 * no | yes | EXCLUSIVE4_1 | EXCLUSIVE4_1 218 * no | yes | EXCLUSIVE4_1 | EXCLUSIVE4_1
219 * yes | no | GUARDED4 | GUARDED4 219 * yes | no | GUARDED4 | GUARDED4
220 * yes | yes | GUARDED4 | GUARDED4 220 * yes | yes | GUARDED4 | GUARDED4
221 */ 221 */
222 222
223 /* 223 /*
224 * Note: create modes (UNCHECKED,GUARDED...) are the same 224 * Note: create modes (UNCHECKED,GUARDED...) are the same
225 * in NFSv4 as in v3 except EXCLUSIVE4_1. 225 * in NFSv4 as in v3 except EXCLUSIVE4_1.
226 */ 226 */
227 status = do_nfsd_create(rqstp, current_fh, open->op_fname.data, 227 status = do_nfsd_create(rqstp, current_fh, open->op_fname.data,
228 open->op_fname.len, &open->op_iattr, 228 open->op_fname.len, &open->op_iattr,
229 resfh, open->op_createmode, 229 resfh, open->op_createmode,
230 (u32 *)open->op_verf.data, 230 (u32 *)open->op_verf.data,
231 &open->op_truncate, &open->op_created); 231 &open->op_truncate, &open->op_created);
232 232
233 /* 233 /*
234 * Following rfc 3530 14.2.16, use the returned bitmask 234 * Following rfc 3530 14.2.16, use the returned bitmask
235 * to indicate which attributes we used to store the 235 * to indicate which attributes we used to store the
236 * verifier: 236 * verifier:
237 */ 237 */
238 if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0) 238 if (open->op_createmode == NFS4_CREATE_EXCLUSIVE && status == 0)
239 open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS | 239 open->op_bmval[1] = (FATTR4_WORD1_TIME_ACCESS |
240 FATTR4_WORD1_TIME_MODIFY); 240 FATTR4_WORD1_TIME_MODIFY);
241 } else { 241 } else {
242 status = nfsd_lookup(rqstp, current_fh, 242 status = nfsd_lookup(rqstp, current_fh,
243 open->op_fname.data, open->op_fname.len, resfh); 243 open->op_fname.data, open->op_fname.len, resfh);
244 fh_unlock(current_fh); 244 fh_unlock(current_fh);
245 } 245 }
246 if (status) 246 if (status)
247 goto out; 247 goto out;
248 status = nfsd_check_obj_isreg(resfh); 248 status = nfsd_check_obj_isreg(resfh);
249 if (status) 249 if (status)
250 goto out; 250 goto out;
251 251
252 if (is_create_with_attrs(open) && open->op_acl != NULL) 252 if (is_create_with_attrs(open) && open->op_acl != NULL)
253 do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval); 253 do_set_nfs4_acl(rqstp, resfh, open->op_acl, open->op_bmval);
254 254
255 /* set reply cache */ 255 /* set reply cache */
256 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh, 256 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
257 &resfh->fh_handle); 257 &resfh->fh_handle);
258 accmode = NFSD_MAY_NOP; 258 accmode = NFSD_MAY_NOP;
259 if (open->op_created) 259 if (open->op_created)
260 accmode |= NFSD_MAY_OWNER_OVERRIDE; 260 accmode |= NFSD_MAY_OWNER_OVERRIDE;
261 status = do_open_permission(rqstp, resfh, open, accmode); 261 status = do_open_permission(rqstp, resfh, open, accmode);
262 set_change_info(&open->op_cinfo, current_fh); 262 set_change_info(&open->op_cinfo, current_fh);
263 fh_dup2(current_fh, resfh); 263 fh_dup2(current_fh, resfh);
264 out: 264 out:
265 fh_put(resfh); 265 fh_put(resfh);
266 kfree(resfh); 266 kfree(resfh);
267 return status; 267 return status;
268 } 268 }
269 269
270 static __be32 270 static __be32
271 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 271 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
272 { 272 {
273 __be32 status; 273 __be32 status;
274 274
275 /* We don't know the target directory, and therefore can not 275 /* We don't know the target directory, and therefore can not
276 * set the change info 276 * set the change info
277 */ 277 */
278 278
279 memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info)); 279 memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info));
280 280
281 /* set replay cache */ 281 /* set replay cache */
282 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh, 282 fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh,
283 &current_fh->fh_handle); 283 &current_fh->fh_handle);
284 284
285 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && 285 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
286 (open->op_iattr.ia_size == 0); 286 (open->op_iattr.ia_size == 0);
287 287
288 status = do_open_permission(rqstp, current_fh, open, 288 status = do_open_permission(rqstp, current_fh, open,
289 NFSD_MAY_OWNER_OVERRIDE); 289 NFSD_MAY_OWNER_OVERRIDE);
290 290
291 return status; 291 return status;
292 } 292 }
293 293
294 static void 294 static void
295 copy_clientid(clientid_t *clid, struct nfsd4_session *session) 295 copy_clientid(clientid_t *clid, struct nfsd4_session *session)
296 { 296 {
297 struct nfsd4_sessionid *sid = 297 struct nfsd4_sessionid *sid =
298 (struct nfsd4_sessionid *)session->se_sessionid.data; 298 (struct nfsd4_sessionid *)session->se_sessionid.data;
299 299
300 clid->cl_boot = sid->clientid.cl_boot; 300 clid->cl_boot = sid->clientid.cl_boot;
301 clid->cl_id = sid->clientid.cl_id; 301 clid->cl_id = sid->clientid.cl_id;
302 } 302 }
303 303
304 static __be32 304 static __be32
305 nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 305 nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
306 struct nfsd4_open *open) 306 struct nfsd4_open *open)
307 { 307 {
308 __be32 status; 308 __be32 status;
309 struct nfsd4_compoundres *resp; 309 struct nfsd4_compoundres *resp;
310 struct net *net = SVC_NET(rqstp); 310 struct net *net = SVC_NET(rqstp);
311 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 311 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
312 312
313 dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n", 313 dprintk("NFSD: nfsd4_open filename %.*s op_openowner %p\n",
314 (int)open->op_fname.len, open->op_fname.data, 314 (int)open->op_fname.len, open->op_fname.data,
315 open->op_openowner); 315 open->op_openowner);
316 316
317 /* This check required by spec. */ 317 /* This check required by spec. */
318 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) 318 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL)
319 return nfserr_inval; 319 return nfserr_inval;
320 320
321 open->op_created = 0; 321 open->op_created = 0;
322 /* 322 /*
323 * RFC5661 18.51.3 323 * RFC5661 18.51.3
324 * Before RECLAIM_COMPLETE done, server should deny new lock 324 * Before RECLAIM_COMPLETE done, server should deny new lock
325 */ 325 */
326 if (nfsd4_has_session(cstate) && 326 if (nfsd4_has_session(cstate) &&
327 !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, 327 !test_bit(NFSD4_CLIENT_RECLAIM_COMPLETE,
328 &cstate->session->se_client->cl_flags) && 328 &cstate->session->se_client->cl_flags) &&
329 open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 329 open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
330 return nfserr_grace; 330 return nfserr_grace;
331 331
332 if (nfsd4_has_session(cstate)) 332 if (nfsd4_has_session(cstate))
333 copy_clientid(&open->op_clientid, cstate->session); 333 copy_clientid(&open->op_clientid, cstate->session);
334 334
335 nfs4_lock_state(); 335 nfs4_lock_state();
336 336
337 /* check seqid for replay. set nfs4_owner */ 337 /* check seqid for replay. set nfs4_owner */
338 resp = rqstp->rq_resp; 338 resp = rqstp->rq_resp;
339 status = nfsd4_process_open1(&resp->cstate, open, nn); 339 status = nfsd4_process_open1(&resp->cstate, open, nn);
340 if (status == nfserr_replay_me) { 340 if (status == nfserr_replay_me) {
341 struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay; 341 struct nfs4_replay *rp = &open->op_openowner->oo_owner.so_replay;
342 fh_put(&cstate->current_fh); 342 fh_put(&cstate->current_fh);
343 fh_copy_shallow(&cstate->current_fh.fh_handle, 343 fh_copy_shallow(&cstate->current_fh.fh_handle,
344 &rp->rp_openfh); 344 &rp->rp_openfh);
345 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP); 345 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
346 if (status) 346 if (status)
347 dprintk("nfsd4_open: replay failed" 347 dprintk("nfsd4_open: replay failed"
348 " restoring previous filehandle\n"); 348 " restoring previous filehandle\n");
349 else 349 else
350 status = nfserr_replay_me; 350 status = nfserr_replay_me;
351 } 351 }
352 if (status) 352 if (status)
353 goto out; 353 goto out;
354 354
355 status = nfsd4_check_open_attributes(rqstp, cstate, open); 355 status = nfsd4_check_open_attributes(rqstp, cstate, open);
356 if (status) 356 if (status)
357 goto out; 357 goto out;
358 358
359 /* Openowner is now set, so sequence id will get bumped. Now we need 359 /* Openowner is now set, so sequence id will get bumped. Now we need
360 * these checks before we do any creates: */ 360 * these checks before we do any creates: */
361 status = nfserr_grace; 361 status = nfserr_grace;
362 if (locks_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 362 if (locks_in_grace(net) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
363 goto out; 363 goto out;
364 status = nfserr_no_grace; 364 status = nfserr_no_grace;
365 if (!locks_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) 365 if (!locks_in_grace(net) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
366 goto out; 366 goto out;
367 367
368 switch (open->op_claim_type) { 368 switch (open->op_claim_type) {
369 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 369 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
370 case NFS4_OPEN_CLAIM_NULL: 370 case NFS4_OPEN_CLAIM_NULL:
371 status = do_open_lookup(rqstp, &cstate->current_fh, 371 status = do_open_lookup(rqstp, &cstate->current_fh,
372 open); 372 open);
373 if (status) 373 if (status)
374 goto out; 374 goto out;
375 break; 375 break;
376 case NFS4_OPEN_CLAIM_PREVIOUS: 376 case NFS4_OPEN_CLAIM_PREVIOUS:
377 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 377 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
378 status = nfs4_check_open_reclaim(&open->op_clientid, 378 status = nfs4_check_open_reclaim(&open->op_clientid,
379 cstate->minorversion, 379 cstate->minorversion,
380 nn); 380 nn);
381 if (status) 381 if (status)
382 goto out; 382 goto out;
383 case NFS4_OPEN_CLAIM_FH: 383 case NFS4_OPEN_CLAIM_FH:
384 case NFS4_OPEN_CLAIM_DELEG_CUR_FH: 384 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
385 status = do_open_fhandle(rqstp, &cstate->current_fh, 385 status = do_open_fhandle(rqstp, &cstate->current_fh,
386 open); 386 open);
387 if (status) 387 if (status)
388 goto out; 388 goto out;
389 break; 389 break;
390 case NFS4_OPEN_CLAIM_DELEG_PREV_FH: 390 case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
391 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 391 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
392 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; 392 open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED;
393 dprintk("NFSD: unsupported OPEN claim type %d\n", 393 dprintk("NFSD: unsupported OPEN claim type %d\n",
394 open->op_claim_type); 394 open->op_claim_type);
395 status = nfserr_notsupp; 395 status = nfserr_notsupp;
396 goto out; 396 goto out;
397 default: 397 default:
398 dprintk("NFSD: Invalid OPEN claim type %d\n", 398 dprintk("NFSD: Invalid OPEN claim type %d\n",
399 open->op_claim_type); 399 open->op_claim_type);
400 status = nfserr_inval; 400 status = nfserr_inval;
401 goto out; 401 goto out;
402 } 402 }
403 /* 403 /*
404 * nfsd4_process_open2() does the actual opening of the file. If 404 * nfsd4_process_open2() does the actual opening of the file. If
405 * successful, it (1) truncates the file if open->op_truncate was 405 * successful, it (1) truncates the file if open->op_truncate was
406 * set, (2) sets open->op_stateid, (3) sets open->op_delegation. 406 * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
407 */ 407 */
408 status = nfsd4_process_open2(rqstp, &cstate->current_fh, open); 408 status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
409 WARN_ON(status && open->op_created); 409 WARN_ON(status && open->op_created);
410 out: 410 out:
411 nfsd4_cleanup_open_state(open, status); 411 nfsd4_cleanup_open_state(open, status);
412 if (open->op_openowner) 412 if (open->op_openowner)
413 cstate->replay_owner = &open->op_openowner->oo_owner; 413 cstate->replay_owner = &open->op_openowner->oo_owner;
414 else 414 else
415 nfs4_unlock_state(); 415 nfs4_unlock_state();
416 return status; 416 return status;
417 } 417 }
418 418
419 /* 419 /*
420 * filehandle-manipulating ops. 420 * filehandle-manipulating ops.
421 */ 421 */
422 static __be32 422 static __be32
423 nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 423 nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
424 struct svc_fh **getfh) 424 struct svc_fh **getfh)
425 { 425 {
426 if (!cstate->current_fh.fh_dentry) 426 if (!cstate->current_fh.fh_dentry)
427 return nfserr_nofilehandle; 427 return nfserr_nofilehandle;
428 428
429 *getfh = &cstate->current_fh; 429 *getfh = &cstate->current_fh;
430 return nfs_ok; 430 return nfs_ok;
431 } 431 }
432 432
433 static __be32 433 static __be32
434 nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 434 nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
435 struct nfsd4_putfh *putfh) 435 struct nfsd4_putfh *putfh)
436 { 436 {
437 fh_put(&cstate->current_fh); 437 fh_put(&cstate->current_fh);
438 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; 438 cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
439 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, 439 memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
440 putfh->pf_fhlen); 440 putfh->pf_fhlen);
441 return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS); 441 return fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_BYPASS_GSS);
442 } 442 }
443 443
444 static __be32 444 static __be32
445 nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 445 nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
446 void *arg) 446 void *arg)
447 { 447 {
448 __be32 status; 448 __be32 status;
449 449
450 fh_put(&cstate->current_fh); 450 fh_put(&cstate->current_fh);
451 status = exp_pseudoroot(rqstp, &cstate->current_fh); 451 status = exp_pseudoroot(rqstp, &cstate->current_fh);
452 return status; 452 return status;
453 } 453 }
454 454
455 static __be32 455 static __be32
456 nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 456 nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
457 void *arg) 457 void *arg)
458 { 458 {
459 if (!cstate->save_fh.fh_dentry) 459 if (!cstate->save_fh.fh_dentry)
460 return nfserr_restorefh; 460 return nfserr_restorefh;
461 461
462 fh_dup2(&cstate->current_fh, &cstate->save_fh); 462 fh_dup2(&cstate->current_fh, &cstate->save_fh);
463 if (HAS_STATE_ID(cstate, SAVED_STATE_ID_FLAG)) { 463 if (HAS_STATE_ID(cstate, SAVED_STATE_ID_FLAG)) {
464 memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t)); 464 memcpy(&cstate->current_stateid, &cstate->save_stateid, sizeof(stateid_t));
465 SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG); 465 SET_STATE_ID(cstate, CURRENT_STATE_ID_FLAG);
466 } 466 }
467 return nfs_ok; 467 return nfs_ok;
468 } 468 }
469 469
470 static __be32 470 static __be32
471 nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 471 nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
472 void *arg) 472 void *arg)
473 { 473 {
474 if (!cstate->current_fh.fh_dentry) 474 if (!cstate->current_fh.fh_dentry)
475 return nfserr_nofilehandle; 475 return nfserr_nofilehandle;
476 476
477 fh_dup2(&cstate->save_fh, &cstate->current_fh); 477 fh_dup2(&cstate->save_fh, &cstate->current_fh);
478 if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) { 478 if (HAS_STATE_ID(cstate, CURRENT_STATE_ID_FLAG)) {
479 memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t)); 479 memcpy(&cstate->save_stateid, &cstate->current_stateid, sizeof(stateid_t));
480 SET_STATE_ID(cstate, SAVED_STATE_ID_FLAG); 480 SET_STATE_ID(cstate, SAVED_STATE_ID_FLAG);
481 } 481 }
482 return nfs_ok; 482 return nfs_ok;
483 } 483 }
484 484
485 /* 485 /*
486 * misc nfsv4 ops 486 * misc nfsv4 ops
487 */ 487 */
488 static __be32 488 static __be32
489 nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 489 nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
490 struct nfsd4_access *access) 490 struct nfsd4_access *access)
491 { 491 {
492 if (access->ac_req_access & ~NFS3_ACCESS_FULL) 492 if (access->ac_req_access & ~NFS3_ACCESS_FULL)
493 return nfserr_inval; 493 return nfserr_inval;
494 494
495 access->ac_resp_access = access->ac_req_access; 495 access->ac_resp_access = access->ac_req_access;
496 return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access, 496 return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
497 &access->ac_supported); 497 &access->ac_supported);
498 } 498 }
499 499
500 static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net) 500 static void gen_boot_verifier(nfs4_verifier *verifier, struct net *net)
501 { 501 {
502 __be32 verf[2]; 502 __be32 verf[2];
503 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 503 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
504 504
505 verf[0] = (__be32)nn->nfssvc_boot.tv_sec; 505 verf[0] = (__be32)nn->nfssvc_boot.tv_sec;
506 verf[1] = (__be32)nn->nfssvc_boot.tv_usec; 506 verf[1] = (__be32)nn->nfssvc_boot.tv_usec;
507 memcpy(verifier->data, verf, sizeof(verifier->data)); 507 memcpy(verifier->data, verf, sizeof(verifier->data));
508 } 508 }
509 509
510 static __be32 510 static __be32
511 nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 511 nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
512 struct nfsd4_commit *commit) 512 struct nfsd4_commit *commit)
513 { 513 {
514 gen_boot_verifier(&commit->co_verf, SVC_NET(rqstp)); 514 gen_boot_verifier(&commit->co_verf, SVC_NET(rqstp));
515 return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, 515 return nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
516 commit->co_count); 516 commit->co_count);
517 } 517 }
518 518
519 static __be32 519 static __be32
520 nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 520 nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
521 struct nfsd4_create *create) 521 struct nfsd4_create *create)
522 { 522 {
523 struct svc_fh resfh; 523 struct svc_fh resfh;
524 __be32 status; 524 __be32 status;
525 dev_t rdev; 525 dev_t rdev;
526 526
527 fh_init(&resfh, NFS4_FHSIZE); 527 fh_init(&resfh, NFS4_FHSIZE);
528 528
529 status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, 529 status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR,
530 NFSD_MAY_CREATE); 530 NFSD_MAY_CREATE);
531 if (status) 531 if (status)
532 return status; 532 return status;
533 533
534 status = check_attr_support(rqstp, cstate, create->cr_bmval, 534 status = check_attr_support(rqstp, cstate, create->cr_bmval,
535 nfsd_attrmask); 535 nfsd_attrmask);
536 if (status) 536 if (status)
537 return status; 537 return status;
538 538
539 switch (create->cr_type) { 539 switch (create->cr_type) {
540 case NF4LNK: 540 case NF4LNK:
541 /* ugh! we have to null-terminate the linktext, or 541 /* ugh! we have to null-terminate the linktext, or
542 * vfs_symlink() will choke. it is always safe to 542 * vfs_symlink() will choke. it is always safe to
543 * null-terminate by brute force, since at worst we 543 * null-terminate by brute force, since at worst we
544 * will overwrite the first byte of the create namelen 544 * will overwrite the first byte of the create namelen
545 * in the XDR buffer, which has already been extracted 545 * in the XDR buffer, which has already been extracted
546 * during XDR decode. 546 * during XDR decode.
547 */ 547 */
548 create->cr_linkname[create->cr_linklen] = 0; 548 create->cr_linkname[create->cr_linklen] = 0;
549 549
550 status = nfsd_symlink(rqstp, &cstate->current_fh, 550 status = nfsd_symlink(rqstp, &cstate->current_fh,
551 create->cr_name, create->cr_namelen, 551 create->cr_name, create->cr_namelen,
552 create->cr_linkname, create->cr_linklen, 552 create->cr_linkname, create->cr_linklen,
553 &resfh, &create->cr_iattr); 553 &resfh, &create->cr_iattr);
554 break; 554 break;
555 555
556 case NF4BLK: 556 case NF4BLK:
557 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2); 557 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
558 if (MAJOR(rdev) != create->cr_specdata1 || 558 if (MAJOR(rdev) != create->cr_specdata1 ||
559 MINOR(rdev) != create->cr_specdata2) 559 MINOR(rdev) != create->cr_specdata2)
560 return nfserr_inval; 560 return nfserr_inval;
561 status = nfsd_create(rqstp, &cstate->current_fh, 561 status = nfsd_create(rqstp, &cstate->current_fh,
562 create->cr_name, create->cr_namelen, 562 create->cr_name, create->cr_namelen,
563 &create->cr_iattr, S_IFBLK, rdev, &resfh); 563 &create->cr_iattr, S_IFBLK, rdev, &resfh);
564 break; 564 break;
565 565
566 case NF4CHR: 566 case NF4CHR:
567 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2); 567 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2);
568 if (MAJOR(rdev) != create->cr_specdata1 || 568 if (MAJOR(rdev) != create->cr_specdata1 ||
569 MINOR(rdev) != create->cr_specdata2) 569 MINOR(rdev) != create->cr_specdata2)
570 return nfserr_inval; 570 return nfserr_inval;
571 status = nfsd_create(rqstp, &cstate->current_fh, 571 status = nfsd_create(rqstp, &cstate->current_fh,
572 create->cr_name, create->cr_namelen, 572 create->cr_name, create->cr_namelen,
573 &create->cr_iattr,S_IFCHR, rdev, &resfh); 573 &create->cr_iattr,S_IFCHR, rdev, &resfh);
574 break; 574 break;
575 575
576 case NF4SOCK: 576 case NF4SOCK:
577 status = nfsd_create(rqstp, &cstate->current_fh, 577 status = nfsd_create(rqstp, &cstate->current_fh,
578 create->cr_name, create->cr_namelen, 578 create->cr_name, create->cr_namelen,
579 &create->cr_iattr, S_IFSOCK, 0, &resfh); 579 &create->cr_iattr, S_IFSOCK, 0, &resfh);
580 break; 580 break;
581 581
582 case NF4FIFO: 582 case NF4FIFO:
583 status = nfsd_create(rqstp, &cstate->current_fh, 583 status = nfsd_create(rqstp, &cstate->current_fh,
584 create->cr_name, create->cr_namelen, 584 create->cr_name, create->cr_namelen,
585 &create->cr_iattr, S_IFIFO, 0, &resfh); 585 &create->cr_iattr, S_IFIFO, 0, &resfh);
586 break; 586 break;
587 587
588 case NF4DIR: 588 case NF4DIR:
589 create->cr_iattr.ia_valid &= ~ATTR_SIZE; 589 create->cr_iattr.ia_valid &= ~ATTR_SIZE;
590 status = nfsd_create(rqstp, &cstate->current_fh, 590 status = nfsd_create(rqstp, &cstate->current_fh,
591 create->cr_name, create->cr_namelen, 591 create->cr_name, create->cr_namelen,
592 &create->cr_iattr, S_IFDIR, 0, &resfh); 592 &create->cr_iattr, S_IFDIR, 0, &resfh);
593 break; 593 break;
594 594
595 default: 595 default:
596 status = nfserr_badtype; 596 status = nfserr_badtype;
597 } 597 }
598 598
599 if (status) 599 if (status)
600 goto out; 600 goto out;
601 601
602 if (create->cr_acl != NULL) 602 if (create->cr_acl != NULL)
603 do_set_nfs4_acl(rqstp, &resfh, create->cr_acl, 603 do_set_nfs4_acl(rqstp, &resfh, create->cr_acl,
604 create->cr_bmval); 604 create->cr_bmval);
605 605
606 fh_unlock(&cstate->current_fh); 606 fh_unlock(&cstate->current_fh);
607 set_change_info(&create->cr_cinfo, &cstate->current_fh); 607 set_change_info(&create->cr_cinfo, &cstate->current_fh);
608 fh_dup2(&cstate->current_fh, &resfh); 608 fh_dup2(&cstate->current_fh, &resfh);
609 out: 609 out:
610 fh_put(&resfh); 610 fh_put(&resfh);
611 return status; 611 return status;
612 } 612 }
613 613
614 static __be32 614 static __be32
615 nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 615 nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
616 struct nfsd4_getattr *getattr) 616 struct nfsd4_getattr *getattr)
617 { 617 {
618 __be32 status; 618 __be32 status;
619 619
620 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP); 620 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
621 if (status) 621 if (status)
622 return status; 622 return status;
623 623
624 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 624 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
625 return nfserr_inval; 625 return nfserr_inval;
626 626
627 getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion); 627 getattr->ga_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
628 getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); 628 getattr->ga_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
629 getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); 629 getattr->ga_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
630 630
631 getattr->ga_fhp = &cstate->current_fh; 631 getattr->ga_fhp = &cstate->current_fh;
632 return nfs_ok; 632 return nfs_ok;
633 } 633 }
634 634
635 static __be32 635 static __be32
636 nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 636 nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
637 struct nfsd4_link *link) 637 struct nfsd4_link *link)
638 { 638 {
639 __be32 status = nfserr_nofilehandle; 639 __be32 status = nfserr_nofilehandle;
640 640
641 if (!cstate->save_fh.fh_dentry) 641 if (!cstate->save_fh.fh_dentry)
642 return status; 642 return status;
643 status = nfsd_link(rqstp, &cstate->current_fh, 643 status = nfsd_link(rqstp, &cstate->current_fh,
644 link->li_name, link->li_namelen, &cstate->save_fh); 644 link->li_name, link->li_namelen, &cstate->save_fh);
645 if (!status) 645 if (!status)
646 set_change_info(&link->li_cinfo, &cstate->current_fh); 646 set_change_info(&link->li_cinfo, &cstate->current_fh);
647 return status; 647 return status;
648 } 648 }
649 649
650 static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh) 650 static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
651 { 651 {
652 struct svc_fh tmp_fh; 652 struct svc_fh tmp_fh;
653 __be32 ret; 653 __be32 ret;
654 654
655 fh_init(&tmp_fh, NFS4_FHSIZE); 655 fh_init(&tmp_fh, NFS4_FHSIZE);
656 ret = exp_pseudoroot(rqstp, &tmp_fh); 656 ret = exp_pseudoroot(rqstp, &tmp_fh);
657 if (ret) 657 if (ret)
658 return ret; 658 return ret;
659 if (tmp_fh.fh_dentry == fh->fh_dentry) { 659 if (tmp_fh.fh_dentry == fh->fh_dentry) {
660 fh_put(&tmp_fh); 660 fh_put(&tmp_fh);
661 return nfserr_noent; 661 return nfserr_noent;
662 } 662 }
663 fh_put(&tmp_fh); 663 fh_put(&tmp_fh);
664 return nfsd_lookup(rqstp, fh, "..", 2, fh); 664 return nfsd_lookup(rqstp, fh, "..", 2, fh);
665 } 665 }
666 666
667 static __be32 667 static __be32
668 nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 668 nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
669 void *arg) 669 void *arg)
670 { 670 {
671 return nfsd4_do_lookupp(rqstp, &cstate->current_fh); 671 return nfsd4_do_lookupp(rqstp, &cstate->current_fh);
672 } 672 }
673 673
674 static __be32 674 static __be32
675 nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 675 nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
676 struct nfsd4_lookup *lookup) 676 struct nfsd4_lookup *lookup)
677 { 677 {
678 return nfsd_lookup(rqstp, &cstate->current_fh, 678 return nfsd_lookup(rqstp, &cstate->current_fh,
679 lookup->lo_name, lookup->lo_len, 679 lookup->lo_name, lookup->lo_len,
680 &cstate->current_fh); 680 &cstate->current_fh);
681 } 681 }
682 682
683 static __be32 683 static __be32
684 nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 684 nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
685 struct nfsd4_read *read) 685 struct nfsd4_read *read)
686 { 686 {
687 __be32 status; 687 __be32 status;
688 688
689 /* no need to check permission - this will be done in nfsd_read() */ 689 /* no need to check permission - this will be done in nfsd_read() */
690 690
691 read->rd_filp = NULL; 691 read->rd_filp = NULL;
692 if (read->rd_offset >= OFFSET_MAX) 692 if (read->rd_offset >= OFFSET_MAX)
693 return nfserr_inval; 693 return nfserr_inval;
694 694
695 /* 695 /*
696 * If we do a zero copy read, then a client will see read data 696 * If we do a zero copy read, then a client will see read data
697 * that reflects the state of the file *after* performing the 697 * that reflects the state of the file *after* performing the
698 * following compound. 698 * following compound.
699 * 699 *
700 * To ensure proper ordering, we therefore turn off zero copy if 700 * To ensure proper ordering, we therefore turn off zero copy if
701 * the client wants us to do more in this compound: 701 * the client wants us to do more in this compound:
702 */ 702 */
703 if (!nfsd4_last_compound_op(rqstp)) 703 if (!nfsd4_last_compound_op(rqstp))
704 rqstp->rq_splice_ok = false; 704 rqstp->rq_splice_ok = false;
705 705
706 nfs4_lock_state(); 706 nfs4_lock_state();
707 /* check stateid */ 707 /* check stateid */
708 if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), 708 if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
709 cstate, &read->rd_stateid, 709 cstate, &read->rd_stateid,
710 RD_STATE, &read->rd_filp))) { 710 RD_STATE, &read->rd_filp))) {
711 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 711 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
712 goto out; 712 goto out;
713 } 713 }
714 if (read->rd_filp) 714 if (read->rd_filp)
715 get_file(read->rd_filp); 715 get_file(read->rd_filp);
716 status = nfs_ok; 716 status = nfs_ok;
717 out: 717 out:
718 nfs4_unlock_state(); 718 nfs4_unlock_state();
719 read->rd_rqstp = rqstp; 719 read->rd_rqstp = rqstp;
720 read->rd_fhp = &cstate->current_fh; 720 read->rd_fhp = &cstate->current_fh;
721 return status; 721 return status;
722 } 722 }
723 723
724 static __be32 724 static __be32
725 nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 725 nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
726 struct nfsd4_readdir *readdir) 726 struct nfsd4_readdir *readdir)
727 { 727 {
728 u64 cookie = readdir->rd_cookie; 728 u64 cookie = readdir->rd_cookie;
729 static const nfs4_verifier zeroverf; 729 static const nfs4_verifier zeroverf;
730 730
731 /* no need to check permission - this will be done in nfsd_readdir() */ 731 /* no need to check permission - this will be done in nfsd_readdir() */
732 732
733 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 733 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)
734 return nfserr_inval; 734 return nfserr_inval;
735 735
736 readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion); 736 readdir->rd_bmval[0] &= nfsd_suppattrs0(cstate->minorversion);
737 readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion); 737 readdir->rd_bmval[1] &= nfsd_suppattrs1(cstate->minorversion);
738 readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion); 738 readdir->rd_bmval[2] &= nfsd_suppattrs2(cstate->minorversion);
739 739
740 if ((cookie == 1) || (cookie == 2) || 740 if ((cookie == 1) || (cookie == 2) ||
741 (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE))) 741 (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE)))
742 return nfserr_bad_cookie; 742 return nfserr_bad_cookie;
743 743
744 readdir->rd_rqstp = rqstp; 744 readdir->rd_rqstp = rqstp;
745 readdir->rd_fhp = &cstate->current_fh; 745 readdir->rd_fhp = &cstate->current_fh;
746 return nfs_ok; 746 return nfs_ok;
747 } 747 }
748 748
749 static __be32 749 static __be32
750 nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 750 nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
751 struct nfsd4_readlink *readlink) 751 struct nfsd4_readlink *readlink)
752 { 752 {
753 readlink->rl_rqstp = rqstp; 753 readlink->rl_rqstp = rqstp;
754 readlink->rl_fhp = &cstate->current_fh; 754 readlink->rl_fhp = &cstate->current_fh;
755 return nfs_ok; 755 return nfs_ok;
756 } 756 }
757 757
758 static __be32 758 static __be32
759 nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 759 nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
760 struct nfsd4_remove *remove) 760 struct nfsd4_remove *remove)
761 { 761 {
762 __be32 status; 762 __be32 status;
763 763
764 if (locks_in_grace(SVC_NET(rqstp))) 764 if (locks_in_grace(SVC_NET(rqstp)))
765 return nfserr_grace; 765 return nfserr_grace;
766 status = nfsd_unlink(rqstp, &cstate->current_fh, 0, 766 status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
767 remove->rm_name, remove->rm_namelen); 767 remove->rm_name, remove->rm_namelen);
768 if (!status) { 768 if (!status) {
769 fh_unlock(&cstate->current_fh); 769 fh_unlock(&cstate->current_fh);
770 set_change_info(&remove->rm_cinfo, &cstate->current_fh); 770 set_change_info(&remove->rm_cinfo, &cstate->current_fh);
771 } 771 }
772 return status; 772 return status;
773 } 773 }
774 774
775 static __be32 775 static __be32
776 nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 776 nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
777 struct nfsd4_rename *rename) 777 struct nfsd4_rename *rename)
778 { 778 {
779 __be32 status = nfserr_nofilehandle; 779 __be32 status = nfserr_nofilehandle;
780 780
781 if (!cstate->save_fh.fh_dentry) 781 if (!cstate->save_fh.fh_dentry)
782 return status; 782 return status;
783 if (locks_in_grace(SVC_NET(rqstp)) && 783 if (locks_in_grace(SVC_NET(rqstp)) &&
784 !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK)) 784 !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
785 return nfserr_grace; 785 return nfserr_grace;
786 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, 786 status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
787 rename->rn_snamelen, &cstate->current_fh, 787 rename->rn_snamelen, &cstate->current_fh,
788 rename->rn_tname, rename->rn_tnamelen); 788 rename->rn_tname, rename->rn_tnamelen);
789 789
790 /* the underlying filesystem returns different error's than required 790 /* the underlying filesystem returns different error's than required
791 * by NFSv4. both save_fh and current_fh have been verified.. */ 791 * by NFSv4. both save_fh and current_fh have been verified.. */
792 if (status == nfserr_isdir) 792 if (status == nfserr_isdir)
793 status = nfserr_exist; 793 status = nfserr_exist;
794 else if ((status == nfserr_notdir) && 794 else if ((status == nfserr_notdir) &&
795 (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) && 795 (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
796 S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode))) 796 S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
797 status = nfserr_exist; 797 status = nfserr_exist;
798 798
799 if (!status) { 799 if (!status) {
800 set_change_info(&rename->rn_sinfo, &cstate->current_fh); 800 set_change_info(&rename->rn_sinfo, &cstate->current_fh);
801 set_change_info(&rename->rn_tinfo, &cstate->save_fh); 801 set_change_info(&rename->rn_tinfo, &cstate->save_fh);
802 } 802 }
803 return status; 803 return status;
804 } 804 }
805 805
806 static __be32 806 static __be32
807 nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 807 nfsd4_secinfo(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
808 struct nfsd4_secinfo *secinfo) 808 struct nfsd4_secinfo *secinfo)
809 { 809 {
810 struct svc_fh resfh; 810 struct svc_fh resfh;
811 struct svc_export *exp; 811 struct svc_export *exp;
812 struct dentry *dentry; 812 struct dentry *dentry;
813 __be32 err; 813 __be32 err;
814 814
815 fh_init(&resfh, NFS4_FHSIZE); 815 fh_init(&resfh, NFS4_FHSIZE);
816 err = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_EXEC); 816 err = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, NFSD_MAY_EXEC);
817 if (err) 817 if (err)
818 return err; 818 return err;
819 err = nfsd_lookup_dentry(rqstp, &cstate->current_fh, 819 err = nfsd_lookup_dentry(rqstp, &cstate->current_fh,
820 secinfo->si_name, secinfo->si_namelen, 820 secinfo->si_name, secinfo->si_namelen,
821 &exp, &dentry); 821 &exp, &dentry);
822 if (err) 822 if (err)
823 return err; 823 return err;
824 if (dentry->d_inode == NULL) { 824 if (dentry->d_inode == NULL) {
825 exp_put(exp); 825 exp_put(exp);
826 err = nfserr_noent; 826 err = nfserr_noent;
827 } else 827 } else
828 secinfo->si_exp = exp; 828 secinfo->si_exp = exp;
829 dput(dentry); 829 dput(dentry);
830 if (cstate->minorversion) 830 if (cstate->minorversion)
831 /* See rfc 5661 section 2.6.3.1.1.8 */ 831 /* See rfc 5661 section 2.6.3.1.1.8 */
832 fh_put(&cstate->current_fh); 832 fh_put(&cstate->current_fh);
833 return err; 833 return err;
834 } 834 }
835 835
836 static __be32 836 static __be32
837 nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 837 nfsd4_secinfo_no_name(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
838 struct nfsd4_secinfo_no_name *sin) 838 struct nfsd4_secinfo_no_name *sin)
839 { 839 {
840 __be32 err; 840 __be32 err;
841 841
842 switch (sin->sin_style) { 842 switch (sin->sin_style) {
843 case NFS4_SECINFO_STYLE4_CURRENT_FH: 843 case NFS4_SECINFO_STYLE4_CURRENT_FH:
844 break; 844 break;
845 case NFS4_SECINFO_STYLE4_PARENT: 845 case NFS4_SECINFO_STYLE4_PARENT:
846 err = nfsd4_do_lookupp(rqstp, &cstate->current_fh); 846 err = nfsd4_do_lookupp(rqstp, &cstate->current_fh);
847 if (err) 847 if (err)
848 return err; 848 return err;
849 break; 849 break;
850 default: 850 default:
851 return nfserr_inval; 851 return nfserr_inval;
852 } 852 }
853 exp_get(cstate->current_fh.fh_export); 853 exp_get(cstate->current_fh.fh_export);
854 sin->sin_exp = cstate->current_fh.fh_export; 854 sin->sin_exp = cstate->current_fh.fh_export;
855 fh_put(&cstate->current_fh); 855 fh_put(&cstate->current_fh);
856 return nfs_ok; 856 return nfs_ok;
857 } 857 }
858 858
859 static __be32 859 static __be32
860 nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 860 nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
861 struct nfsd4_setattr *setattr) 861 struct nfsd4_setattr *setattr)
862 { 862 {
863 __be32 status = nfs_ok; 863 __be32 status = nfs_ok;
864 int err; 864 int err;
865 865
866 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 866 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
867 nfs4_lock_state(); 867 nfs4_lock_state();
868 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate, 868 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate,
869 &setattr->sa_stateid, WR_STATE, NULL); 869 &setattr->sa_stateid, WR_STATE, NULL);
870 nfs4_unlock_state(); 870 nfs4_unlock_state();
871 if (status) { 871 if (status) {
872 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n"); 872 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
873 return status; 873 return status;
874 } 874 }
875 } 875 }
876 err = fh_want_write(&cstate->current_fh); 876 err = fh_want_write(&cstate->current_fh);
877 if (err) 877 if (err)
878 return nfserrno(err); 878 return nfserrno(err);
879 status = nfs_ok; 879 status = nfs_ok;
880 880
881 status = check_attr_support(rqstp, cstate, setattr->sa_bmval, 881 status = check_attr_support(rqstp, cstate, setattr->sa_bmval,
882 nfsd_attrmask); 882 nfsd_attrmask);
883 if (status) 883 if (status)
884 goto out; 884 goto out;
885 885
886 if (setattr->sa_acl != NULL) 886 if (setattr->sa_acl != NULL)
887 status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh, 887 status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
888 setattr->sa_acl); 888 setattr->sa_acl);
889 if (status) 889 if (status)
890 goto out; 890 goto out;
891 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr, 891 status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
892 0, (time_t)0); 892 0, (time_t)0);
893 out: 893 out:
894 fh_drop_write(&cstate->current_fh); 894 fh_drop_write(&cstate->current_fh);
895 return status; 895 return status;
896 } 896 }
897 897
898 static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write) 898 static int fill_in_write_vector(struct kvec *vec, struct nfsd4_write *write)
899 { 899 {
900 int i = 1; 900 int i = 1;
901 int buflen = write->wr_buflen; 901 int buflen = write->wr_buflen;
902 902
903 vec[0].iov_base = write->wr_head.iov_base; 903 vec[0].iov_base = write->wr_head.iov_base;
904 vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len); 904 vec[0].iov_len = min_t(int, buflen, write->wr_head.iov_len);
905 buflen -= vec[0].iov_len; 905 buflen -= vec[0].iov_len;
906 906
907 while (buflen) { 907 while (buflen) {
908 vec[i].iov_base = page_address(write->wr_pagelist[i - 1]); 908 vec[i].iov_base = page_address(write->wr_pagelist[i - 1]);
909 vec[i].iov_len = min_t(int, PAGE_SIZE, buflen); 909 vec[i].iov_len = min_t(int, PAGE_SIZE, buflen);
910 buflen -= vec[i].iov_len; 910 buflen -= vec[i].iov_len;
911 i++; 911 i++;
912 } 912 }
913 return i; 913 return i;
914 } 914 }
915 915
916 static __be32 916 static __be32
917 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 917 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
918 struct nfsd4_write *write) 918 struct nfsd4_write *write)
919 { 919 {
920 stateid_t *stateid = &write->wr_stateid; 920 stateid_t *stateid = &write->wr_stateid;
921 struct file *filp = NULL; 921 struct file *filp = NULL;
922 __be32 status = nfs_ok; 922 __be32 status = nfs_ok;
923 unsigned long cnt; 923 unsigned long cnt;
924 int nvecs; 924 int nvecs;
925 925
926 /* no need to check permission - this will be done in nfsd_write() */ 926 /* no need to check permission - this will be done in nfsd_write() */
927 927
928 if (write->wr_offset >= OFFSET_MAX) 928 if (write->wr_offset >= OFFSET_MAX)
929 return nfserr_inval; 929 return nfserr_inval;
930 930
931 nfs4_lock_state(); 931 nfs4_lock_state();
932 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), 932 status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
933 cstate, stateid, WR_STATE, &filp); 933 cstate, stateid, WR_STATE, &filp);
934 if (filp) 934 if (filp)
935 get_file(filp); 935 get_file(filp);
936 nfs4_unlock_state(); 936 nfs4_unlock_state();
937 937
938 if (status) { 938 if (status) {
939 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 939 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
940 return status; 940 return status;
941 } 941 }
942 942
943 cnt = write->wr_buflen; 943 cnt = write->wr_buflen;
944 write->wr_how_written = write->wr_stable_how; 944 write->wr_how_written = write->wr_stable_how;
945 gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp)); 945 gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp));
946 946
947 nvecs = fill_in_write_vector(rqstp->rq_vec, write); 947 nvecs = fill_in_write_vector(rqstp->rq_vec, write);
948 WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec)); 948 WARN_ON_ONCE(nvecs > ARRAY_SIZE(rqstp->rq_vec));
949 949
950 status = nfsd_write(rqstp, &cstate->current_fh, filp, 950 status = nfsd_write(rqstp, &cstate->current_fh, filp,
951 write->wr_offset, rqstp->rq_vec, nvecs, 951 write->wr_offset, rqstp->rq_vec, nvecs,
952 &cnt, &write->wr_how_written); 952 &cnt, &write->wr_how_written);
953 if (filp) 953 if (filp)
954 fput(filp); 954 fput(filp);
955 955
956 write->wr_bytes_written = cnt; 956 write->wr_bytes_written = cnt;
957 957
958 return status; 958 return status;
959 } 959 }
960 960
961 /* This routine never returns NFS_OK! If there are no other errors, it 961 /* This routine never returns NFS_OK! If there are no other errors, it
962 * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the 962 * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the
963 * attributes matched. VERIFY is implemented by mapping NFSERR_SAME 963 * attributes matched. VERIFY is implemented by mapping NFSERR_SAME
964 * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK. 964 * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
965 */ 965 */
966 static __be32 966 static __be32
967 _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 967 _nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
968 struct nfsd4_verify *verify) 968 struct nfsd4_verify *verify)
969 { 969 {
970 __be32 *buf, *p; 970 __be32 *buf, *p;
971 int count; 971 int count;
972 __be32 status; 972 __be32 status;
973 973
974 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP); 974 status = fh_verify(rqstp, &cstate->current_fh, 0, NFSD_MAY_NOP);
975 if (status) 975 if (status)
976 return status; 976 return status;
977 977
978 status = check_attr_support(rqstp, cstate, verify->ve_bmval, NULL); 978 status = check_attr_support(rqstp, cstate, verify->ve_bmval, NULL);
979 if (status) 979 if (status)
980 return status; 980 return status;
981 981
982 if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR) 982 if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)
983 || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)) 983 || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1))
984 return nfserr_inval; 984 return nfserr_inval;
985 if (verify->ve_attrlen & 3) 985 if (verify->ve_attrlen & 3)
986 return nfserr_inval; 986 return nfserr_inval;
987 987
988 /* count in words: 988 /* count in words:
989 * bitmap_len(1) + bitmap(2) + attr_len(1) = 4 989 * bitmap_len(1) + bitmap(2) + attr_len(1) = 4
990 */ 990 */
991 count = 4 + (verify->ve_attrlen >> 2); 991 count = 4 + (verify->ve_attrlen >> 2);
992 buf = kmalloc(count << 2, GFP_KERNEL); 992 buf = kmalloc(count << 2, GFP_KERNEL);
993 if (!buf) 993 if (!buf)
994 return nfserr_jukebox; 994 return nfserr_jukebox;
995 995
996 p = buf;
996 status = nfsd4_encode_fattr(&cstate->current_fh, 997 status = nfsd4_encode_fattr(&cstate->current_fh,
997 cstate->current_fh.fh_export, 998 cstate->current_fh.fh_export,
998 cstate->current_fh.fh_dentry, buf, 999 cstate->current_fh.fh_dentry, &p,
999 &count, verify->ve_bmval, 1000 count, verify->ve_bmval,
1000 rqstp, 0); 1001 rqstp, 0);
1001 1002
1002 /* this means that nfsd4_encode_fattr() ran out of space */ 1003 /* this means that nfsd4_encode_fattr() ran out of space */
1003 if (status == nfserr_resource && count == 0) 1004 if (status == nfserr_resource)
1004 status = nfserr_not_same; 1005 status = nfserr_not_same;
1005 if (status) 1006 if (status)
1006 goto out_kfree; 1007 goto out_kfree;
1007 1008
1008 /* skip bitmap */ 1009 /* skip bitmap */
1009 p = buf + 1 + ntohl(buf[0]); 1010 p = buf + 1 + ntohl(buf[0]);
1010 status = nfserr_not_same; 1011 status = nfserr_not_same;
1011 if (ntohl(*p++) != verify->ve_attrlen) 1012 if (ntohl(*p++) != verify->ve_attrlen)
1012 goto out_kfree; 1013 goto out_kfree;
1013 if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen)) 1014 if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen))
1014 status = nfserr_same; 1015 status = nfserr_same;
1015 1016
1016 out_kfree: 1017 out_kfree:
1017 kfree(buf); 1018 kfree(buf);
1018 return status; 1019 return status;
1019 } 1020 }
1020 1021
1021 static __be32 1022 static __be32
1022 nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1023 nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1023 struct nfsd4_verify *verify) 1024 struct nfsd4_verify *verify)
1024 { 1025 {
1025 __be32 status; 1026 __be32 status;
1026 1027
1027 status = _nfsd4_verify(rqstp, cstate, verify); 1028 status = _nfsd4_verify(rqstp, cstate, verify);
1028 return status == nfserr_not_same ? nfs_ok : status; 1029 return status == nfserr_not_same ? nfs_ok : status;
1029 } 1030 }
1030 1031
1031 static __be32 1032 static __be32
1032 nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1033 nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1033 struct nfsd4_verify *verify) 1034 struct nfsd4_verify *verify)
1034 { 1035 {
1035 __be32 status; 1036 __be32 status;
1036 1037
1037 status = _nfsd4_verify(rqstp, cstate, verify); 1038 status = _nfsd4_verify(rqstp, cstate, verify);
1038 return status == nfserr_same ? nfs_ok : status; 1039 return status == nfserr_same ? nfs_ok : status;
1039 } 1040 }
1040 1041
1041 /* 1042 /*
1042 * NULL call. 1043 * NULL call.
1043 */ 1044 */
1044 static __be32 1045 static __be32
1045 nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) 1046 nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp)
1046 { 1047 {
1047 return nfs_ok; 1048 return nfs_ok;
1048 } 1049 }
1049 1050
1050 static inline void nfsd4_increment_op_stats(u32 opnum) 1051 static inline void nfsd4_increment_op_stats(u32 opnum)
1051 { 1052 {
1052 if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP) 1053 if (opnum >= FIRST_NFS4_OP && opnum <= LAST_NFS4_OP)
1053 nfsdstats.nfs4_opcount[opnum]++; 1054 nfsdstats.nfs4_opcount[opnum]++;
1054 } 1055 }
1055 1056
1056 typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *, 1057 typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
1057 void *); 1058 void *);
1058 typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op); 1059 typedef u32(*nfsd4op_rsize)(struct svc_rqst *, struct nfsd4_op *op);
1059 typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *); 1060 typedef void(*stateid_setter)(struct nfsd4_compound_state *, void *);
1060 typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *); 1061 typedef void(*stateid_getter)(struct nfsd4_compound_state *, void *);
1061 1062
1062 enum nfsd4_op_flags { 1063 enum nfsd4_op_flags {
1063 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */ 1064 ALLOWED_WITHOUT_FH = 1 << 0, /* No current filehandle required */
1064 ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */ 1065 ALLOWED_ON_ABSENT_FS = 1 << 1, /* ops processed on absent fs */
1065 ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */ 1066 ALLOWED_AS_FIRST_OP = 1 << 2, /* ops reqired first in compound */
1066 /* For rfc 5661 section 2.6.3.1.1: */ 1067 /* For rfc 5661 section 2.6.3.1.1: */
1067 OP_HANDLES_WRONGSEC = 1 << 3, 1068 OP_HANDLES_WRONGSEC = 1 << 3,
1068 OP_IS_PUTFH_LIKE = 1 << 4, 1069 OP_IS_PUTFH_LIKE = 1 << 4,
1069 /* 1070 /*
1070 * These are the ops whose result size we estimate before 1071 * These are the ops whose result size we estimate before
1071 * encoding, to avoid performing an op then not being able to 1072 * encoding, to avoid performing an op then not being able to
1072 * respond or cache a response. This includes writes and setattrs 1073 * respond or cache a response. This includes writes and setattrs
1073 * as well as the operations usually called "nonidempotent": 1074 * as well as the operations usually called "nonidempotent":
1074 */ 1075 */
1075 OP_MODIFIES_SOMETHING = 1 << 5, 1076 OP_MODIFIES_SOMETHING = 1 << 5,
1076 /* 1077 /*
1077 * Cache compounds containing these ops in the xid-based drc: 1078 * Cache compounds containing these ops in the xid-based drc:
1078 * We use the DRC for compounds containing non-idempotent 1079 * We use the DRC for compounds containing non-idempotent
1079 * operations, *except* those that are 4.1-specific (since 1080 * operations, *except* those that are 4.1-specific (since
1080 * sessions provide their own EOS), and except for stateful 1081 * sessions provide their own EOS), and except for stateful
1081 * operations other than setclientid and setclientid_confirm 1082 * operations other than setclientid and setclientid_confirm
1082 * (since sequence numbers provide EOS for open, lock, etc in 1083 * (since sequence numbers provide EOS for open, lock, etc in
1083 * the v4.0 case). 1084 * the v4.0 case).
1084 */ 1085 */
1085 OP_CACHEME = 1 << 6, 1086 OP_CACHEME = 1 << 6,
1086 /* 1087 /*
1087 * These are ops which clear current state id. 1088 * These are ops which clear current state id.
1088 */ 1089 */
1089 OP_CLEAR_STATEID = 1 << 7, 1090 OP_CLEAR_STATEID = 1 << 7,
1090 }; 1091 };
1091 1092
1092 struct nfsd4_operation { 1093 struct nfsd4_operation {
1093 nfsd4op_func op_func; 1094 nfsd4op_func op_func;
1094 u32 op_flags; 1095 u32 op_flags;
1095 char *op_name; 1096 char *op_name;
1096 /* Try to get response size before operation */ 1097 /* Try to get response size before operation */
1097 nfsd4op_rsize op_rsize_bop; 1098 nfsd4op_rsize op_rsize_bop;
1098 stateid_getter op_get_currentstateid; 1099 stateid_getter op_get_currentstateid;
1099 stateid_setter op_set_currentstateid; 1100 stateid_setter op_set_currentstateid;
1100 }; 1101 };
1101 1102
1102 static struct nfsd4_operation nfsd4_ops[]; 1103 static struct nfsd4_operation nfsd4_ops[];
1103 1104
1104 #ifdef NFSD_DEBUG 1105 #ifdef NFSD_DEBUG
1105 static const char *nfsd4_op_name(unsigned opnum); 1106 static const char *nfsd4_op_name(unsigned opnum);
1106 #endif 1107 #endif
1107 1108
1108 /* 1109 /*
1109 * Enforce NFSv4.1 COMPOUND ordering rules: 1110 * Enforce NFSv4.1 COMPOUND ordering rules:
1110 * 1111 *
1111 * Also note, enforced elsewhere: 1112 * Also note, enforced elsewhere:
1112 * - SEQUENCE other than as first op results in 1113 * - SEQUENCE other than as first op results in
1113 * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().) 1114 * NFS4ERR_SEQUENCE_POS. (Enforced in nfsd4_sequence().)
1114 * - BIND_CONN_TO_SESSION must be the only op in its compound. 1115 * - BIND_CONN_TO_SESSION must be the only op in its compound.
1115 * (Enforced in nfsd4_bind_conn_to_session().) 1116 * (Enforced in nfsd4_bind_conn_to_session().)
1116 * - DESTROY_SESSION must be the final operation in a compound, if 1117 * - DESTROY_SESSION must be the final operation in a compound, if
1117 * sessionid's in SEQUENCE and DESTROY_SESSION are the same. 1118 * sessionid's in SEQUENCE and DESTROY_SESSION are the same.
1118 * (Enforced in nfsd4_destroy_session().) 1119 * (Enforced in nfsd4_destroy_session().)
1119 */ 1120 */
1120 static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args) 1121 static __be32 nfs41_check_op_ordering(struct nfsd4_compoundargs *args)
1121 { 1122 {
1122 struct nfsd4_op *op = &args->ops[0]; 1123 struct nfsd4_op *op = &args->ops[0];
1123 1124
1124 /* These ordering requirements don't apply to NFSv4.0: */ 1125 /* These ordering requirements don't apply to NFSv4.0: */
1125 if (args->minorversion == 0) 1126 if (args->minorversion == 0)
1126 return nfs_ok; 1127 return nfs_ok;
1127 /* This is weird, but OK, not our problem: */ 1128 /* This is weird, but OK, not our problem: */
1128 if (args->opcnt == 0) 1129 if (args->opcnt == 0)
1129 return nfs_ok; 1130 return nfs_ok;
1130 if (op->status == nfserr_op_illegal) 1131 if (op->status == nfserr_op_illegal)
1131 return nfs_ok; 1132 return nfs_ok;
1132 if (!(nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP)) 1133 if (!(nfsd4_ops[op->opnum].op_flags & ALLOWED_AS_FIRST_OP))
1133 return nfserr_op_not_in_session; 1134 return nfserr_op_not_in_session;
1134 if (op->opnum == OP_SEQUENCE) 1135 if (op->opnum == OP_SEQUENCE)
1135 return nfs_ok; 1136 return nfs_ok;
1136 if (args->opcnt != 1) 1137 if (args->opcnt != 1)
1137 return nfserr_not_only_op; 1138 return nfserr_not_only_op;
1138 return nfs_ok; 1139 return nfs_ok;
1139 } 1140 }
1140 1141
1141 static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op) 1142 static inline struct nfsd4_operation *OPDESC(struct nfsd4_op *op)
1142 { 1143 {
1143 return &nfsd4_ops[op->opnum]; 1144 return &nfsd4_ops[op->opnum];
1144 } 1145 }
1145 1146
1146 bool nfsd4_cache_this_op(struct nfsd4_op *op) 1147 bool nfsd4_cache_this_op(struct nfsd4_op *op)
1147 { 1148 {
1148 return OPDESC(op)->op_flags & OP_CACHEME; 1149 return OPDESC(op)->op_flags & OP_CACHEME;
1149 } 1150 }
1150 1151
1151 static bool need_wrongsec_check(struct svc_rqst *rqstp) 1152 static bool need_wrongsec_check(struct svc_rqst *rqstp)
1152 { 1153 {
1153 struct nfsd4_compoundres *resp = rqstp->rq_resp; 1154 struct nfsd4_compoundres *resp = rqstp->rq_resp;
1154 struct nfsd4_compoundargs *argp = rqstp->rq_argp; 1155 struct nfsd4_compoundargs *argp = rqstp->rq_argp;
1155 struct nfsd4_op *this = &argp->ops[resp->opcnt - 1]; 1156 struct nfsd4_op *this = &argp->ops[resp->opcnt - 1];
1156 struct nfsd4_op *next = &argp->ops[resp->opcnt]; 1157 struct nfsd4_op *next = &argp->ops[resp->opcnt];
1157 struct nfsd4_operation *thisd; 1158 struct nfsd4_operation *thisd;
1158 struct nfsd4_operation *nextd; 1159 struct nfsd4_operation *nextd;
1159 1160
1160 thisd = OPDESC(this); 1161 thisd = OPDESC(this);
1161 /* 1162 /*
1162 * Most ops check wronsec on our own; only the putfh-like ops 1163 * Most ops check wronsec on our own; only the putfh-like ops
1163 * have special rules. 1164 * have special rules.
1164 */ 1165 */
1165 if (!(thisd->op_flags & OP_IS_PUTFH_LIKE)) 1166 if (!(thisd->op_flags & OP_IS_PUTFH_LIKE))
1166 return false; 1167 return false;
1167 /* 1168 /*
1168 * rfc 5661 2.6.3.1.1.6: don't bother erroring out a 1169 * rfc 5661 2.6.3.1.1.6: don't bother erroring out a
1169 * put-filehandle operation if we're not going to use the 1170 * put-filehandle operation if we're not going to use the
1170 * result: 1171 * result:
1171 */ 1172 */
1172 if (argp->opcnt == resp->opcnt) 1173 if (argp->opcnt == resp->opcnt)
1173 return false; 1174 return false;
1174 1175
1175 nextd = OPDESC(next); 1176 nextd = OPDESC(next);
1176 /* 1177 /*
1177 * Rest of 2.6.3.1.1: certain operations will return WRONGSEC 1178 * Rest of 2.6.3.1.1: certain operations will return WRONGSEC
1178 * errors themselves as necessary; others should check for them 1179 * errors themselves as necessary; others should check for them
1179 * now: 1180 * now:
1180 */ 1181 */
1181 return !(nextd->op_flags & OP_HANDLES_WRONGSEC); 1182 return !(nextd->op_flags & OP_HANDLES_WRONGSEC);
1182 } 1183 }
1183 1184
1184 /* 1185 /*
1185 * COMPOUND call. 1186 * COMPOUND call.
1186 */ 1187 */
1187 static __be32 1188 static __be32
1188 nfsd4_proc_compound(struct svc_rqst *rqstp, 1189 nfsd4_proc_compound(struct svc_rqst *rqstp,
1189 struct nfsd4_compoundargs *args, 1190 struct nfsd4_compoundargs *args,
1190 struct nfsd4_compoundres *resp) 1191 struct nfsd4_compoundres *resp)
1191 { 1192 {
1192 struct nfsd4_op *op; 1193 struct nfsd4_op *op;
1193 struct nfsd4_operation *opdesc; 1194 struct nfsd4_operation *opdesc;
1194 struct nfsd4_compound_state *cstate = &resp->cstate; 1195 struct nfsd4_compound_state *cstate = &resp->cstate;
1195 int slack_bytes; 1196 int slack_bytes;
1196 u32 plen = 0; 1197 u32 plen = 0;
1197 __be32 status; 1198 __be32 status;
1198 1199
1199 resp->xbuf = &rqstp->rq_res; 1200 resp->xbuf = &rqstp->rq_res;
1200 resp->p = rqstp->rq_res.head[0].iov_base + 1201 resp->p = rqstp->rq_res.head[0].iov_base +
1201 rqstp->rq_res.head[0].iov_len; 1202 rqstp->rq_res.head[0].iov_len;
1202 resp->tagp = resp->p; 1203 resp->tagp = resp->p;
1203 /* reserve space for: taglen, tag, and opcnt */ 1204 /* reserve space for: taglen, tag, and opcnt */
1204 resp->p += 2 + XDR_QUADLEN(args->taglen); 1205 resp->p += 2 + XDR_QUADLEN(args->taglen);
1205 resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE; 1206 resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE;
1206 resp->taglen = args->taglen; 1207 resp->taglen = args->taglen;
1207 resp->tag = args->tag; 1208 resp->tag = args->tag;
1208 resp->opcnt = 0; 1209 resp->opcnt = 0;
1209 resp->rqstp = rqstp; 1210 resp->rqstp = rqstp;
1210 resp->cstate.minorversion = args->minorversion; 1211 resp->cstate.minorversion = args->minorversion;
1211 resp->cstate.replay_owner = NULL; 1212 resp->cstate.replay_owner = NULL;
1212 resp->cstate.session = NULL; 1213 resp->cstate.session = NULL;
1213 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE); 1214 fh_init(&resp->cstate.current_fh, NFS4_FHSIZE);
1214 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE); 1215 fh_init(&resp->cstate.save_fh, NFS4_FHSIZE);
1215 /* 1216 /*
1216 * Don't use the deferral mechanism for NFSv4; compounds make it 1217 * Don't use the deferral mechanism for NFSv4; compounds make it
1217 * too hard to avoid non-idempotency problems. 1218 * too hard to avoid non-idempotency problems.
1218 */ 1219 */
1219 rqstp->rq_usedeferral = 0; 1220 rqstp->rq_usedeferral = 0;
1220 1221
1221 /* 1222 /*
1222 * According to RFC3010, this takes precedence over all other errors. 1223 * According to RFC3010, this takes precedence over all other errors.
1223 */ 1224 */
1224 status = nfserr_minor_vers_mismatch; 1225 status = nfserr_minor_vers_mismatch;
1225 if (args->minorversion > nfsd_supported_minorversion) 1226 if (args->minorversion > nfsd_supported_minorversion)
1226 goto out; 1227 goto out;
1227 1228
1228 status = nfs41_check_op_ordering(args); 1229 status = nfs41_check_op_ordering(args);
1229 if (status) { 1230 if (status) {
1230 op = &args->ops[0]; 1231 op = &args->ops[0];
1231 op->status = status; 1232 op->status = status;
1232 goto encode_op; 1233 goto encode_op;
1233 } 1234 }
1234 1235
1235 while (!status && resp->opcnt < args->opcnt) { 1236 while (!status && resp->opcnt < args->opcnt) {
1236 op = &args->ops[resp->opcnt++]; 1237 op = &args->ops[resp->opcnt++];
1237 1238
1238 dprintk("nfsv4 compound op #%d/%d: %d (%s)\n", 1239 dprintk("nfsv4 compound op #%d/%d: %d (%s)\n",
1239 resp->opcnt, args->opcnt, op->opnum, 1240 resp->opcnt, args->opcnt, op->opnum,
1240 nfsd4_op_name(op->opnum)); 1241 nfsd4_op_name(op->opnum));
1241 /* 1242 /*
1242 * The XDR decode routines may have pre-set op->status; 1243 * The XDR decode routines may have pre-set op->status;
1243 * for example, if there is a miscellaneous XDR error 1244 * for example, if there is a miscellaneous XDR error
1244 * it will be set to nfserr_bad_xdr. 1245 * it will be set to nfserr_bad_xdr.
1245 */ 1246 */
1246 if (op->status) 1247 if (op->status)
1247 goto encode_op; 1248 goto encode_op;
1248 1249
1249 /* We must be able to encode a successful response to 1250 /* We must be able to encode a successful response to
1250 * this operation, with enough room left over to encode a 1251 * this operation, with enough room left over to encode a
1251 * failed response to the next operation. If we don't 1252 * failed response to the next operation. If we don't
1252 * have enough room, fail with ERR_RESOURCE. 1253 * have enough room, fail with ERR_RESOURCE.
1253 */ 1254 */
1254 slack_bytes = (char *)resp->end - (char *)resp->p; 1255 slack_bytes = (char *)resp->end - (char *)resp->p;
1255 if (slack_bytes < COMPOUND_SLACK_SPACE 1256 if (slack_bytes < COMPOUND_SLACK_SPACE
1256 + COMPOUND_ERR_SLACK_SPACE) { 1257 + COMPOUND_ERR_SLACK_SPACE) {
1257 BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE); 1258 BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
1258 op->status = nfserr_resource; 1259 op->status = nfserr_resource;
1259 goto encode_op; 1260 goto encode_op;
1260 } 1261 }
1261 1262
1262 opdesc = OPDESC(op); 1263 opdesc = OPDESC(op);
1263 1264
1264 if (!cstate->current_fh.fh_dentry) { 1265 if (!cstate->current_fh.fh_dentry) {
1265 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) { 1266 if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
1266 op->status = nfserr_nofilehandle; 1267 op->status = nfserr_nofilehandle;
1267 goto encode_op; 1268 goto encode_op;
1268 } 1269 }
1269 } else if (cstate->current_fh.fh_export->ex_fslocs.migrated && 1270 } else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
1270 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) { 1271 !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
1271 op->status = nfserr_moved; 1272 op->status = nfserr_moved;
1272 goto encode_op; 1273 goto encode_op;
1273 } 1274 }
1274 1275
1275 /* If op is non-idempotent */ 1276 /* If op is non-idempotent */
1276 if (opdesc->op_flags & OP_MODIFIES_SOMETHING) { 1277 if (opdesc->op_flags & OP_MODIFIES_SOMETHING) {
1277 plen = opdesc->op_rsize_bop(rqstp, op); 1278 plen = opdesc->op_rsize_bop(rqstp, op);
1278 op->status = nfsd4_check_resp_size(resp, plen); 1279 op->status = nfsd4_check_resp_size(resp, plen);
1279 } 1280 }
1280 1281
1281 if (op->status) 1282 if (op->status)
1282 goto encode_op; 1283 goto encode_op;
1283 1284
1284 if (opdesc->op_func) { 1285 if (opdesc->op_func) {
1285 if (opdesc->op_get_currentstateid) 1286 if (opdesc->op_get_currentstateid)
1286 opdesc->op_get_currentstateid(cstate, &op->u); 1287 opdesc->op_get_currentstateid(cstate, &op->u);
1287 op->status = opdesc->op_func(rqstp, cstate, &op->u); 1288 op->status = opdesc->op_func(rqstp, cstate, &op->u);
1288 } else 1289 } else
1289 BUG_ON(op->status == nfs_ok); 1290 BUG_ON(op->status == nfs_ok);
1290 1291
1291 if (!op->status) { 1292 if (!op->status) {
1292 if (opdesc->op_set_currentstateid) 1293 if (opdesc->op_set_currentstateid)
1293 opdesc->op_set_currentstateid(cstate, &op->u); 1294 opdesc->op_set_currentstateid(cstate, &op->u);
1294 1295
1295 if (opdesc->op_flags & OP_CLEAR_STATEID) 1296 if (opdesc->op_flags & OP_CLEAR_STATEID)
1296 clear_current_stateid(cstate); 1297 clear_current_stateid(cstate);
1297 1298
1298 if (need_wrongsec_check(rqstp)) 1299 if (need_wrongsec_check(rqstp))
1299 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp); 1300 op->status = check_nfsd_access(cstate->current_fh.fh_export, rqstp);
1300 } 1301 }
1301 1302
1302 encode_op: 1303 encode_op:
1303 /* Only from SEQUENCE */ 1304 /* Only from SEQUENCE */
1304 if (resp->cstate.status == nfserr_replay_cache) { 1305 if (resp->cstate.status == nfserr_replay_cache) {
1305 dprintk("%s NFS4.1 replay from cache\n", __func__); 1306 dprintk("%s NFS4.1 replay from cache\n", __func__);
1306 status = op->status; 1307 status = op->status;
1307 goto out; 1308 goto out;
1308 } 1309 }
1309 if (op->status == nfserr_replay_me) { 1310 if (op->status == nfserr_replay_me) {
1310 op->replay = &cstate->replay_owner->so_replay; 1311 op->replay = &cstate->replay_owner->so_replay;
1311 nfsd4_encode_replay(resp, op); 1312 nfsd4_encode_replay(resp, op);
1312 status = op->status = op->replay->rp_status; 1313 status = op->status = op->replay->rp_status;
1313 } else { 1314 } else {
1314 nfsd4_encode_operation(resp, op); 1315 nfsd4_encode_operation(resp, op);
1315 status = op->status; 1316 status = op->status;
1316 } 1317 }
1317 1318
1318 dprintk("nfsv4 compound op %p opcnt %d #%d: %d: status %d\n", 1319 dprintk("nfsv4 compound op %p opcnt %d #%d: %d: status %d\n",
1319 args->ops, args->opcnt, resp->opcnt, op->opnum, 1320 args->ops, args->opcnt, resp->opcnt, op->opnum,
1320 be32_to_cpu(status)); 1321 be32_to_cpu(status));
1321 1322
1322 if (cstate->replay_owner) { 1323 if (cstate->replay_owner) {
1323 nfs4_unlock_state(); 1324 nfs4_unlock_state();
1324 cstate->replay_owner = NULL; 1325 cstate->replay_owner = NULL;
1325 } 1326 }
1326 /* XXX Ugh, we need to get rid of this kind of special case: */ 1327 /* XXX Ugh, we need to get rid of this kind of special case: */
1327 if (op->opnum == OP_READ && op->u.read.rd_filp) 1328 if (op->opnum == OP_READ && op->u.read.rd_filp)
1328 fput(op->u.read.rd_filp); 1329 fput(op->u.read.rd_filp);
1329 1330
1330 nfsd4_increment_op_stats(op->opnum); 1331 nfsd4_increment_op_stats(op->opnum);
1331 } 1332 }
1332 1333
1333 resp->cstate.status = status; 1334 resp->cstate.status = status;
1334 fh_put(&resp->cstate.current_fh); 1335 fh_put(&resp->cstate.current_fh);
1335 fh_put(&resp->cstate.save_fh); 1336 fh_put(&resp->cstate.save_fh);
1336 BUG_ON(resp->cstate.replay_owner); 1337 BUG_ON(resp->cstate.replay_owner);
1337 out: 1338 out:
1338 /* Reset deferral mechanism for RPC deferrals */ 1339 /* Reset deferral mechanism for RPC deferrals */
1339 rqstp->rq_usedeferral = 1; 1340 rqstp->rq_usedeferral = 1;
1340 dprintk("nfsv4 compound returned %d\n", ntohl(status)); 1341 dprintk("nfsv4 compound returned %d\n", ntohl(status));
1341 return status; 1342 return status;
1342 } 1343 }
1343 1344
1344 #define op_encode_hdr_size (2) 1345 #define op_encode_hdr_size (2)
1345 #define op_encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE)) 1346 #define op_encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
1346 #define op_encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE)) 1347 #define op_encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
1347 #define op_encode_change_info_maxsz (5) 1348 #define op_encode_change_info_maxsz (5)
1348 #define nfs4_fattr_bitmap_maxsz (4) 1349 #define nfs4_fattr_bitmap_maxsz (4)
1349 1350
1350 #define op_encode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 1351 #define op_encode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
1351 #define op_encode_lock_denied_maxsz (8 + op_encode_lockowner_maxsz) 1352 #define op_encode_lock_denied_maxsz (8 + op_encode_lockowner_maxsz)
1352 1353
1353 #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) 1354 #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
1354 1355
1355 #define op_encode_ace_maxsz (3 + nfs4_owner_maxsz) 1356 #define op_encode_ace_maxsz (3 + nfs4_owner_maxsz)
1356 #define op_encode_delegation_maxsz (1 + op_encode_stateid_maxsz + 1 + \ 1357 #define op_encode_delegation_maxsz (1 + op_encode_stateid_maxsz + 1 + \
1357 op_encode_ace_maxsz) 1358 op_encode_ace_maxsz)
1358 1359
1359 #define op_encode_channel_attrs_maxsz (6 + 1 + 1) 1360 #define op_encode_channel_attrs_maxsz (6 + 1 + 1)
1360 1361
1361 static inline u32 nfsd4_only_status_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1362 static inline u32 nfsd4_only_status_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1362 { 1363 {
1363 return (op_encode_hdr_size) * sizeof(__be32); 1364 return (op_encode_hdr_size) * sizeof(__be32);
1364 } 1365 }
1365 1366
1366 static inline u32 nfsd4_status_stateid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1367 static inline u32 nfsd4_status_stateid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1367 { 1368 {
1368 return (op_encode_hdr_size + op_encode_stateid_maxsz)* sizeof(__be32); 1369 return (op_encode_hdr_size + op_encode_stateid_maxsz)* sizeof(__be32);
1369 } 1370 }
1370 1371
1371 static inline u32 nfsd4_commit_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1372 static inline u32 nfsd4_commit_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1372 { 1373 {
1373 return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32); 1374 return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32);
1374 } 1375 }
1375 1376
1376 static inline u32 nfsd4_create_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1377 static inline u32 nfsd4_create_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1377 { 1378 {
1378 return (op_encode_hdr_size + op_encode_change_info_maxsz 1379 return (op_encode_hdr_size + op_encode_change_info_maxsz
1379 + nfs4_fattr_bitmap_maxsz) * sizeof(__be32); 1380 + nfs4_fattr_bitmap_maxsz) * sizeof(__be32);
1380 } 1381 }
1381 1382
1382 static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1383 static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1383 { 1384 {
1384 return (op_encode_hdr_size + op_encode_change_info_maxsz) 1385 return (op_encode_hdr_size + op_encode_change_info_maxsz)
1385 * sizeof(__be32); 1386 * sizeof(__be32);
1386 } 1387 }
1387 1388
1388 static inline u32 nfsd4_lock_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1389 static inline u32 nfsd4_lock_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1389 { 1390 {
1390 return (op_encode_hdr_size + op_encode_lock_denied_maxsz) 1391 return (op_encode_hdr_size + op_encode_lock_denied_maxsz)
1391 * sizeof(__be32); 1392 * sizeof(__be32);
1392 } 1393 }
1393 1394
1394 static inline u32 nfsd4_open_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1395 static inline u32 nfsd4_open_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1395 { 1396 {
1396 return (op_encode_hdr_size + op_encode_stateid_maxsz 1397 return (op_encode_hdr_size + op_encode_stateid_maxsz
1397 + op_encode_change_info_maxsz + 1 1398 + op_encode_change_info_maxsz + 1
1398 + nfs4_fattr_bitmap_maxsz 1399 + nfs4_fattr_bitmap_maxsz
1399 + op_encode_delegation_maxsz) * sizeof(__be32); 1400 + op_encode_delegation_maxsz) * sizeof(__be32);
1400 } 1401 }
1401 1402
1402 static inline u32 nfsd4_read_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1403 static inline u32 nfsd4_read_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1403 { 1404 {
1404 u32 maxcount = 0, rlen = 0; 1405 u32 maxcount = 0, rlen = 0;
1405 1406
1406 maxcount = svc_max_payload(rqstp); 1407 maxcount = svc_max_payload(rqstp);
1407 rlen = op->u.read.rd_length; 1408 rlen = op->u.read.rd_length;
1408 1409
1409 if (rlen > maxcount) 1410 if (rlen > maxcount)
1410 rlen = maxcount; 1411 rlen = maxcount;
1411 1412
1412 return (op_encode_hdr_size + 2) * sizeof(__be32) + rlen; 1413 return (op_encode_hdr_size + 2) * sizeof(__be32) + rlen;
1413 } 1414 }
1414 1415
1415 static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1416 static inline u32 nfsd4_readdir_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1416 { 1417 {
1417 u32 rlen = op->u.readdir.rd_maxcount; 1418 u32 rlen = op->u.readdir.rd_maxcount;
1418 1419
1419 if (rlen > PAGE_SIZE) 1420 if (rlen > PAGE_SIZE)
1420 rlen = PAGE_SIZE; 1421 rlen = PAGE_SIZE;
1421 1422
1422 return (op_encode_hdr_size + op_encode_verifier_maxsz) 1423 return (op_encode_hdr_size + op_encode_verifier_maxsz)
1423 * sizeof(__be32) + rlen; 1424 * sizeof(__be32) + rlen;
1424 } 1425 }
1425 1426
1426 static inline u32 nfsd4_remove_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1427 static inline u32 nfsd4_remove_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1427 { 1428 {
1428 return (op_encode_hdr_size + op_encode_change_info_maxsz) 1429 return (op_encode_hdr_size + op_encode_change_info_maxsz)
1429 * sizeof(__be32); 1430 * sizeof(__be32);
1430 } 1431 }
1431 1432
1432 static inline u32 nfsd4_rename_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1433 static inline u32 nfsd4_rename_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1433 { 1434 {
1434 return (op_encode_hdr_size + op_encode_change_info_maxsz 1435 return (op_encode_hdr_size + op_encode_change_info_maxsz
1435 + op_encode_change_info_maxsz) * sizeof(__be32); 1436 + op_encode_change_info_maxsz) * sizeof(__be32);
1436 } 1437 }
1437 1438
1438 static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1439 static inline u32 nfsd4_setattr_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1439 { 1440 {
1440 return (op_encode_hdr_size + nfs4_fattr_bitmap_maxsz) * sizeof(__be32); 1441 return (op_encode_hdr_size + nfs4_fattr_bitmap_maxsz) * sizeof(__be32);
1441 } 1442 }
1442 1443
1443 static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1444 static inline u32 nfsd4_setclientid_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1444 { 1445 {
1445 return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32); 1446 return (op_encode_hdr_size + 2 + 1024) * sizeof(__be32);
1446 } 1447 }
1447 1448
1448 static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1449 static inline u32 nfsd4_write_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1449 { 1450 {
1450 return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32); 1451 return (op_encode_hdr_size + op_encode_verifier_maxsz) * sizeof(__be32);
1451 } 1452 }
1452 1453
1453 static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1454 static inline u32 nfsd4_exchange_id_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1454 { 1455 {
1455 return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\ 1456 return (op_encode_hdr_size + 2 + 1 + /* eir_clientid, eir_sequenceid */\
1456 1 + 1 + 0 + /* eir_flags, spr_how, SP4_NONE (for now) */\ 1457 1 + 1 + 0 + /* eir_flags, spr_how, SP4_NONE (for now) */\
1457 2 + /*eir_server_owner.so_minor_id */\ 1458 2 + /*eir_server_owner.so_minor_id */\
1458 /* eir_server_owner.so_major_id<> */\ 1459 /* eir_server_owner.so_major_id<> */\
1459 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ 1460 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\
1460 /* eir_server_scope<> */\ 1461 /* eir_server_scope<> */\
1461 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\ 1462 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 +\
1462 1 + /* eir_server_impl_id array length */\ 1463 1 + /* eir_server_impl_id array length */\
1463 0 /* ignored eir_server_impl_id contents */) * sizeof(__be32); 1464 0 /* ignored eir_server_impl_id contents */) * sizeof(__be32);
1464 } 1465 }
1465 1466
1466 static inline u32 nfsd4_bind_conn_to_session_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1467 static inline u32 nfsd4_bind_conn_to_session_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1467 { 1468 {
1468 return (op_encode_hdr_size + \ 1469 return (op_encode_hdr_size + \
1469 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + /* bctsr_sessid */\ 1470 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + /* bctsr_sessid */\
1470 2 /* bctsr_dir, use_conn_in_rdma_mode */) * sizeof(__be32); 1471 2 /* bctsr_dir, use_conn_in_rdma_mode */) * sizeof(__be32);
1471 } 1472 }
1472 1473
1473 static inline u32 nfsd4_create_session_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1474 static inline u32 nfsd4_create_session_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1474 { 1475 {
1475 return (op_encode_hdr_size + \ 1476 return (op_encode_hdr_size + \
1476 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + /* sessionid */\ 1477 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + /* sessionid */\
1477 2 + /* csr_sequence, csr_flags */\ 1478 2 + /* csr_sequence, csr_flags */\
1478 op_encode_channel_attrs_maxsz + \ 1479 op_encode_channel_attrs_maxsz + \
1479 op_encode_channel_attrs_maxsz) * sizeof(__be32); 1480 op_encode_channel_attrs_maxsz) * sizeof(__be32);
1480 } 1481 }
1481 1482
1482 static struct nfsd4_operation nfsd4_ops[] = { 1483 static struct nfsd4_operation nfsd4_ops[] = {
1483 [OP_ACCESS] = { 1484 [OP_ACCESS] = {
1484 .op_func = (nfsd4op_func)nfsd4_access, 1485 .op_func = (nfsd4op_func)nfsd4_access,
1485 .op_name = "OP_ACCESS", 1486 .op_name = "OP_ACCESS",
1486 }, 1487 },
1487 [OP_CLOSE] = { 1488 [OP_CLOSE] = {
1488 .op_func = (nfsd4op_func)nfsd4_close, 1489 .op_func = (nfsd4op_func)nfsd4_close,
1489 .op_flags = OP_MODIFIES_SOMETHING, 1490 .op_flags = OP_MODIFIES_SOMETHING,
1490 .op_name = "OP_CLOSE", 1491 .op_name = "OP_CLOSE",
1491 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1492 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1492 .op_get_currentstateid = (stateid_getter)nfsd4_get_closestateid, 1493 .op_get_currentstateid = (stateid_getter)nfsd4_get_closestateid,
1493 .op_set_currentstateid = (stateid_setter)nfsd4_set_closestateid, 1494 .op_set_currentstateid = (stateid_setter)nfsd4_set_closestateid,
1494 }, 1495 },
1495 [OP_COMMIT] = { 1496 [OP_COMMIT] = {
1496 .op_func = (nfsd4op_func)nfsd4_commit, 1497 .op_func = (nfsd4op_func)nfsd4_commit,
1497 .op_flags = OP_MODIFIES_SOMETHING, 1498 .op_flags = OP_MODIFIES_SOMETHING,
1498 .op_name = "OP_COMMIT", 1499 .op_name = "OP_COMMIT",
1499 .op_rsize_bop = (nfsd4op_rsize)nfsd4_commit_rsize, 1500 .op_rsize_bop = (nfsd4op_rsize)nfsd4_commit_rsize,
1500 }, 1501 },
1501 [OP_CREATE] = { 1502 [OP_CREATE] = {
1502 .op_func = (nfsd4op_func)nfsd4_create, 1503 .op_func = (nfsd4op_func)nfsd4_create,
1503 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME | OP_CLEAR_STATEID, 1504 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME | OP_CLEAR_STATEID,
1504 .op_name = "OP_CREATE", 1505 .op_name = "OP_CREATE",
1505 .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize, 1506 .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_rsize,
1506 }, 1507 },
1507 [OP_DELEGRETURN] = { 1508 [OP_DELEGRETURN] = {
1508 .op_func = (nfsd4op_func)nfsd4_delegreturn, 1509 .op_func = (nfsd4op_func)nfsd4_delegreturn,
1509 .op_flags = OP_MODIFIES_SOMETHING, 1510 .op_flags = OP_MODIFIES_SOMETHING,
1510 .op_name = "OP_DELEGRETURN", 1511 .op_name = "OP_DELEGRETURN",
1511 .op_rsize_bop = nfsd4_only_status_rsize, 1512 .op_rsize_bop = nfsd4_only_status_rsize,
1512 .op_get_currentstateid = (stateid_getter)nfsd4_get_delegreturnstateid, 1513 .op_get_currentstateid = (stateid_getter)nfsd4_get_delegreturnstateid,
1513 }, 1514 },
1514 [OP_GETATTR] = { 1515 [OP_GETATTR] = {
1515 .op_func = (nfsd4op_func)nfsd4_getattr, 1516 .op_func = (nfsd4op_func)nfsd4_getattr,
1516 .op_flags = ALLOWED_ON_ABSENT_FS, 1517 .op_flags = ALLOWED_ON_ABSENT_FS,
1517 .op_name = "OP_GETATTR", 1518 .op_name = "OP_GETATTR",
1518 }, 1519 },
1519 [OP_GETFH] = { 1520 [OP_GETFH] = {
1520 .op_func = (nfsd4op_func)nfsd4_getfh, 1521 .op_func = (nfsd4op_func)nfsd4_getfh,
1521 .op_name = "OP_GETFH", 1522 .op_name = "OP_GETFH",
1522 }, 1523 },
1523 [OP_LINK] = { 1524 [OP_LINK] = {
1524 .op_func = (nfsd4op_func)nfsd4_link, 1525 .op_func = (nfsd4op_func)nfsd4_link,
1525 .op_flags = ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING 1526 .op_flags = ALLOWED_ON_ABSENT_FS | OP_MODIFIES_SOMETHING
1526 | OP_CACHEME, 1527 | OP_CACHEME,
1527 .op_name = "OP_LINK", 1528 .op_name = "OP_LINK",
1528 .op_rsize_bop = (nfsd4op_rsize)nfsd4_link_rsize, 1529 .op_rsize_bop = (nfsd4op_rsize)nfsd4_link_rsize,
1529 }, 1530 },
1530 [OP_LOCK] = { 1531 [OP_LOCK] = {
1531 .op_func = (nfsd4op_func)nfsd4_lock, 1532 .op_func = (nfsd4op_func)nfsd4_lock,
1532 .op_flags = OP_MODIFIES_SOMETHING, 1533 .op_flags = OP_MODIFIES_SOMETHING,
1533 .op_name = "OP_LOCK", 1534 .op_name = "OP_LOCK",
1534 .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize, 1535 .op_rsize_bop = (nfsd4op_rsize)nfsd4_lock_rsize,
1535 .op_set_currentstateid = (stateid_setter)nfsd4_set_lockstateid, 1536 .op_set_currentstateid = (stateid_setter)nfsd4_set_lockstateid,
1536 }, 1537 },
1537 [OP_LOCKT] = { 1538 [OP_LOCKT] = {
1538 .op_func = (nfsd4op_func)nfsd4_lockt, 1539 .op_func = (nfsd4op_func)nfsd4_lockt,
1539 .op_name = "OP_LOCKT", 1540 .op_name = "OP_LOCKT",
1540 }, 1541 },
1541 [OP_LOCKU] = { 1542 [OP_LOCKU] = {
1542 .op_func = (nfsd4op_func)nfsd4_locku, 1543 .op_func = (nfsd4op_func)nfsd4_locku,
1543 .op_flags = OP_MODIFIES_SOMETHING, 1544 .op_flags = OP_MODIFIES_SOMETHING,
1544 .op_name = "OP_LOCKU", 1545 .op_name = "OP_LOCKU",
1545 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1546 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1546 .op_get_currentstateid = (stateid_getter)nfsd4_get_lockustateid, 1547 .op_get_currentstateid = (stateid_getter)nfsd4_get_lockustateid,
1547 }, 1548 },
1548 [OP_LOOKUP] = { 1549 [OP_LOOKUP] = {
1549 .op_func = (nfsd4op_func)nfsd4_lookup, 1550 .op_func = (nfsd4op_func)nfsd4_lookup,
1550 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, 1551 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
1551 .op_name = "OP_LOOKUP", 1552 .op_name = "OP_LOOKUP",
1552 }, 1553 },
1553 [OP_LOOKUPP] = { 1554 [OP_LOOKUPP] = {
1554 .op_func = (nfsd4op_func)nfsd4_lookupp, 1555 .op_func = (nfsd4op_func)nfsd4_lookupp,
1555 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID, 1556 .op_flags = OP_HANDLES_WRONGSEC | OP_CLEAR_STATEID,
1556 .op_name = "OP_LOOKUPP", 1557 .op_name = "OP_LOOKUPP",
1557 }, 1558 },
1558 [OP_NVERIFY] = { 1559 [OP_NVERIFY] = {
1559 .op_func = (nfsd4op_func)nfsd4_nverify, 1560 .op_func = (nfsd4op_func)nfsd4_nverify,
1560 .op_name = "OP_NVERIFY", 1561 .op_name = "OP_NVERIFY",
1561 }, 1562 },
1562 [OP_OPEN] = { 1563 [OP_OPEN] = {
1563 .op_func = (nfsd4op_func)nfsd4_open, 1564 .op_func = (nfsd4op_func)nfsd4_open,
1564 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING, 1565 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
1565 .op_name = "OP_OPEN", 1566 .op_name = "OP_OPEN",
1566 .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize, 1567 .op_rsize_bop = (nfsd4op_rsize)nfsd4_open_rsize,
1567 .op_set_currentstateid = (stateid_setter)nfsd4_set_openstateid, 1568 .op_set_currentstateid = (stateid_setter)nfsd4_set_openstateid,
1568 }, 1569 },
1569 [OP_OPEN_CONFIRM] = { 1570 [OP_OPEN_CONFIRM] = {
1570 .op_func = (nfsd4op_func)nfsd4_open_confirm, 1571 .op_func = (nfsd4op_func)nfsd4_open_confirm,
1571 .op_flags = OP_MODIFIES_SOMETHING, 1572 .op_flags = OP_MODIFIES_SOMETHING,
1572 .op_name = "OP_OPEN_CONFIRM", 1573 .op_name = "OP_OPEN_CONFIRM",
1573 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1574 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1574 }, 1575 },
1575 [OP_OPEN_DOWNGRADE] = { 1576 [OP_OPEN_DOWNGRADE] = {
1576 .op_func = (nfsd4op_func)nfsd4_open_downgrade, 1577 .op_func = (nfsd4op_func)nfsd4_open_downgrade,
1577 .op_flags = OP_MODIFIES_SOMETHING, 1578 .op_flags = OP_MODIFIES_SOMETHING,
1578 .op_name = "OP_OPEN_DOWNGRADE", 1579 .op_name = "OP_OPEN_DOWNGRADE",
1579 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize, 1580 .op_rsize_bop = (nfsd4op_rsize)nfsd4_status_stateid_rsize,
1580 .op_get_currentstateid = (stateid_getter)nfsd4_get_opendowngradestateid, 1581 .op_get_currentstateid = (stateid_getter)nfsd4_get_opendowngradestateid,
1581 .op_set_currentstateid = (stateid_setter)nfsd4_set_opendowngradestateid, 1582 .op_set_currentstateid = (stateid_setter)nfsd4_set_opendowngradestateid,
1582 }, 1583 },
1583 [OP_PUTFH] = { 1584 [OP_PUTFH] = {
1584 .op_func = (nfsd4op_func)nfsd4_putfh, 1585 .op_func = (nfsd4op_func)nfsd4_putfh,
1585 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1586 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1586 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING 1587 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
1587 | OP_CLEAR_STATEID, 1588 | OP_CLEAR_STATEID,
1588 .op_name = "OP_PUTFH", 1589 .op_name = "OP_PUTFH",
1589 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1590 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1590 }, 1591 },
1591 [OP_PUTPUBFH] = { 1592 [OP_PUTPUBFH] = {
1592 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1593 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1593 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1594 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1594 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING 1595 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
1595 | OP_CLEAR_STATEID, 1596 | OP_CLEAR_STATEID,
1596 .op_name = "OP_PUTPUBFH", 1597 .op_name = "OP_PUTPUBFH",
1597 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1598 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1598 }, 1599 },
1599 [OP_PUTROOTFH] = { 1600 [OP_PUTROOTFH] = {
1600 .op_func = (nfsd4op_func)nfsd4_putrootfh, 1601 .op_func = (nfsd4op_func)nfsd4_putrootfh,
1601 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1602 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1602 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING 1603 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING
1603 | OP_CLEAR_STATEID, 1604 | OP_CLEAR_STATEID,
1604 .op_name = "OP_PUTROOTFH", 1605 .op_name = "OP_PUTROOTFH",
1605 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1606 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1606 }, 1607 },
1607 [OP_READ] = { 1608 [OP_READ] = {
1608 .op_func = (nfsd4op_func)nfsd4_read, 1609 .op_func = (nfsd4op_func)nfsd4_read,
1609 .op_flags = OP_MODIFIES_SOMETHING, 1610 .op_flags = OP_MODIFIES_SOMETHING,
1610 .op_name = "OP_READ", 1611 .op_name = "OP_READ",
1611 .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize, 1612 .op_rsize_bop = (nfsd4op_rsize)nfsd4_read_rsize,
1612 .op_get_currentstateid = (stateid_getter)nfsd4_get_readstateid, 1613 .op_get_currentstateid = (stateid_getter)nfsd4_get_readstateid,
1613 }, 1614 },
1614 [OP_READDIR] = { 1615 [OP_READDIR] = {
1615 .op_func = (nfsd4op_func)nfsd4_readdir, 1616 .op_func = (nfsd4op_func)nfsd4_readdir,
1616 .op_flags = OP_MODIFIES_SOMETHING, 1617 .op_flags = OP_MODIFIES_SOMETHING,
1617 .op_name = "OP_READDIR", 1618 .op_name = "OP_READDIR",
1618 .op_rsize_bop = (nfsd4op_rsize)nfsd4_readdir_rsize, 1619 .op_rsize_bop = (nfsd4op_rsize)nfsd4_readdir_rsize,
1619 }, 1620 },
1620 [OP_READLINK] = { 1621 [OP_READLINK] = {
1621 .op_func = (nfsd4op_func)nfsd4_readlink, 1622 .op_func = (nfsd4op_func)nfsd4_readlink,
1622 .op_name = "OP_READLINK", 1623 .op_name = "OP_READLINK",
1623 }, 1624 },
1624 [OP_REMOVE] = { 1625 [OP_REMOVE] = {
1625 .op_func = (nfsd4op_func)nfsd4_remove, 1626 .op_func = (nfsd4op_func)nfsd4_remove,
1626 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, 1627 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
1627 .op_name = "OP_REMOVE", 1628 .op_name = "OP_REMOVE",
1628 .op_rsize_bop = (nfsd4op_rsize)nfsd4_remove_rsize, 1629 .op_rsize_bop = (nfsd4op_rsize)nfsd4_remove_rsize,
1629 }, 1630 },
1630 [OP_RENAME] = { 1631 [OP_RENAME] = {
1631 .op_func = (nfsd4op_func)nfsd4_rename, 1632 .op_func = (nfsd4op_func)nfsd4_rename,
1632 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, 1633 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
1633 .op_name = "OP_RENAME", 1634 .op_name = "OP_RENAME",
1634 .op_rsize_bop = (nfsd4op_rsize)nfsd4_rename_rsize, 1635 .op_rsize_bop = (nfsd4op_rsize)nfsd4_rename_rsize,
1635 }, 1636 },
1636 [OP_RENEW] = { 1637 [OP_RENEW] = {
1637 .op_func = (nfsd4op_func)nfsd4_renew, 1638 .op_func = (nfsd4op_func)nfsd4_renew,
1638 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1639 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1639 | OP_MODIFIES_SOMETHING, 1640 | OP_MODIFIES_SOMETHING,
1640 .op_name = "OP_RENEW", 1641 .op_name = "OP_RENEW",
1641 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1642 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1642 1643
1643 }, 1644 },
1644 [OP_RESTOREFH] = { 1645 [OP_RESTOREFH] = {
1645 .op_func = (nfsd4op_func)nfsd4_restorefh, 1646 .op_func = (nfsd4op_func)nfsd4_restorefh,
1646 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1647 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1647 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING, 1648 | OP_IS_PUTFH_LIKE | OP_MODIFIES_SOMETHING,
1648 .op_name = "OP_RESTOREFH", 1649 .op_name = "OP_RESTOREFH",
1649 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1650 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1650 }, 1651 },
1651 [OP_SAVEFH] = { 1652 [OP_SAVEFH] = {
1652 .op_func = (nfsd4op_func)nfsd4_savefh, 1653 .op_func = (nfsd4op_func)nfsd4_savefh,
1653 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING, 1654 .op_flags = OP_HANDLES_WRONGSEC | OP_MODIFIES_SOMETHING,
1654 .op_name = "OP_SAVEFH", 1655 .op_name = "OP_SAVEFH",
1655 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1656 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1656 }, 1657 },
1657 [OP_SECINFO] = { 1658 [OP_SECINFO] = {
1658 .op_func = (nfsd4op_func)nfsd4_secinfo, 1659 .op_func = (nfsd4op_func)nfsd4_secinfo,
1659 .op_flags = OP_HANDLES_WRONGSEC, 1660 .op_flags = OP_HANDLES_WRONGSEC,
1660 .op_name = "OP_SECINFO", 1661 .op_name = "OP_SECINFO",
1661 }, 1662 },
1662 [OP_SETATTR] = { 1663 [OP_SETATTR] = {
1663 .op_func = (nfsd4op_func)nfsd4_setattr, 1664 .op_func = (nfsd4op_func)nfsd4_setattr,
1664 .op_name = "OP_SETATTR", 1665 .op_name = "OP_SETATTR",
1665 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, 1666 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
1666 .op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize, 1667 .op_rsize_bop = (nfsd4op_rsize)nfsd4_setattr_rsize,
1667 .op_get_currentstateid = (stateid_getter)nfsd4_get_setattrstateid, 1668 .op_get_currentstateid = (stateid_getter)nfsd4_get_setattrstateid,
1668 }, 1669 },
1669 [OP_SETCLIENTID] = { 1670 [OP_SETCLIENTID] = {
1670 .op_func = (nfsd4op_func)nfsd4_setclientid, 1671 .op_func = (nfsd4op_func)nfsd4_setclientid,
1671 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1672 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1672 | OP_MODIFIES_SOMETHING | OP_CACHEME, 1673 | OP_MODIFIES_SOMETHING | OP_CACHEME,
1673 .op_name = "OP_SETCLIENTID", 1674 .op_name = "OP_SETCLIENTID",
1674 .op_rsize_bop = (nfsd4op_rsize)nfsd4_setclientid_rsize, 1675 .op_rsize_bop = (nfsd4op_rsize)nfsd4_setclientid_rsize,
1675 }, 1676 },
1676 [OP_SETCLIENTID_CONFIRM] = { 1677 [OP_SETCLIENTID_CONFIRM] = {
1677 .op_func = (nfsd4op_func)nfsd4_setclientid_confirm, 1678 .op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
1678 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1679 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1679 | OP_MODIFIES_SOMETHING | OP_CACHEME, 1680 | OP_MODIFIES_SOMETHING | OP_CACHEME,
1680 .op_name = "OP_SETCLIENTID_CONFIRM", 1681 .op_name = "OP_SETCLIENTID_CONFIRM",
1681 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1682 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1682 }, 1683 },
1683 [OP_VERIFY] = { 1684 [OP_VERIFY] = {
1684 .op_func = (nfsd4op_func)nfsd4_verify, 1685 .op_func = (nfsd4op_func)nfsd4_verify,
1685 .op_name = "OP_VERIFY", 1686 .op_name = "OP_VERIFY",
1686 }, 1687 },
1687 [OP_WRITE] = { 1688 [OP_WRITE] = {
1688 .op_func = (nfsd4op_func)nfsd4_write, 1689 .op_func = (nfsd4op_func)nfsd4_write,
1689 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, 1690 .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME,
1690 .op_name = "OP_WRITE", 1691 .op_name = "OP_WRITE",
1691 .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, 1692 .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize,
1692 .op_get_currentstateid = (stateid_getter)nfsd4_get_writestateid, 1693 .op_get_currentstateid = (stateid_getter)nfsd4_get_writestateid,
1693 }, 1694 },
1694 [OP_RELEASE_LOCKOWNER] = { 1695 [OP_RELEASE_LOCKOWNER] = {
1695 .op_func = (nfsd4op_func)nfsd4_release_lockowner, 1696 .op_func = (nfsd4op_func)nfsd4_release_lockowner,
1696 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS 1697 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS
1697 | OP_MODIFIES_SOMETHING, 1698 | OP_MODIFIES_SOMETHING,
1698 .op_name = "OP_RELEASE_LOCKOWNER", 1699 .op_name = "OP_RELEASE_LOCKOWNER",
1699 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1700 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1700 }, 1701 },
1701 1702
1702 /* NFSv4.1 operations */ 1703 /* NFSv4.1 operations */
1703 [OP_EXCHANGE_ID] = { 1704 [OP_EXCHANGE_ID] = {
1704 .op_func = (nfsd4op_func)nfsd4_exchange_id, 1705 .op_func = (nfsd4op_func)nfsd4_exchange_id,
1705 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP 1706 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
1706 | OP_MODIFIES_SOMETHING, 1707 | OP_MODIFIES_SOMETHING,
1707 .op_name = "OP_EXCHANGE_ID", 1708 .op_name = "OP_EXCHANGE_ID",
1708 .op_rsize_bop = (nfsd4op_rsize)nfsd4_exchange_id_rsize, 1709 .op_rsize_bop = (nfsd4op_rsize)nfsd4_exchange_id_rsize,
1709 }, 1710 },
1710 [OP_BACKCHANNEL_CTL] = { 1711 [OP_BACKCHANNEL_CTL] = {
1711 .op_func = (nfsd4op_func)nfsd4_backchannel_ctl, 1712 .op_func = (nfsd4op_func)nfsd4_backchannel_ctl,
1712 .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING, 1713 .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
1713 .op_name = "OP_BACKCHANNEL_CTL", 1714 .op_name = "OP_BACKCHANNEL_CTL",
1714 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1715 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1715 }, 1716 },
1716 [OP_BIND_CONN_TO_SESSION] = { 1717 [OP_BIND_CONN_TO_SESSION] = {
1717 .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session, 1718 .op_func = (nfsd4op_func)nfsd4_bind_conn_to_session,
1718 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP 1719 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
1719 | OP_MODIFIES_SOMETHING, 1720 | OP_MODIFIES_SOMETHING,
1720 .op_name = "OP_BIND_CONN_TO_SESSION", 1721 .op_name = "OP_BIND_CONN_TO_SESSION",
1721 .op_rsize_bop = (nfsd4op_rsize)nfsd4_bind_conn_to_session_rsize, 1722 .op_rsize_bop = (nfsd4op_rsize)nfsd4_bind_conn_to_session_rsize,
1722 }, 1723 },
1723 [OP_CREATE_SESSION] = { 1724 [OP_CREATE_SESSION] = {
1724 .op_func = (nfsd4op_func)nfsd4_create_session, 1725 .op_func = (nfsd4op_func)nfsd4_create_session,
1725 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP 1726 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
1726 | OP_MODIFIES_SOMETHING, 1727 | OP_MODIFIES_SOMETHING,
1727 .op_name = "OP_CREATE_SESSION", 1728 .op_name = "OP_CREATE_SESSION",
1728 .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_session_rsize, 1729 .op_rsize_bop = (nfsd4op_rsize)nfsd4_create_session_rsize,
1729 }, 1730 },
1730 [OP_DESTROY_SESSION] = { 1731 [OP_DESTROY_SESSION] = {
1731 .op_func = (nfsd4op_func)nfsd4_destroy_session, 1732 .op_func = (nfsd4op_func)nfsd4_destroy_session,
1732 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP 1733 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
1733 | OP_MODIFIES_SOMETHING, 1734 | OP_MODIFIES_SOMETHING,
1734 .op_name = "OP_DESTROY_SESSION", 1735 .op_name = "OP_DESTROY_SESSION",
1735 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1736 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1736 }, 1737 },
1737 [OP_SEQUENCE] = { 1738 [OP_SEQUENCE] = {
1738 .op_func = (nfsd4op_func)nfsd4_sequence, 1739 .op_func = (nfsd4op_func)nfsd4_sequence,
1739 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP, 1740 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP,
1740 .op_name = "OP_SEQUENCE", 1741 .op_name = "OP_SEQUENCE",
1741 }, 1742 },
1742 [OP_DESTROY_CLIENTID] = { 1743 [OP_DESTROY_CLIENTID] = {
1743 .op_func = (nfsd4op_func)nfsd4_destroy_clientid, 1744 .op_func = (nfsd4op_func)nfsd4_destroy_clientid,
1744 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP 1745 .op_flags = ALLOWED_WITHOUT_FH | ALLOWED_AS_FIRST_OP
1745 | OP_MODIFIES_SOMETHING, 1746 | OP_MODIFIES_SOMETHING,
1746 .op_name = "OP_DESTROY_CLIENTID", 1747 .op_name = "OP_DESTROY_CLIENTID",
1747 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1748 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1748 }, 1749 },
1749 [OP_RECLAIM_COMPLETE] = { 1750 [OP_RECLAIM_COMPLETE] = {
1750 .op_func = (nfsd4op_func)nfsd4_reclaim_complete, 1751 .op_func = (nfsd4op_func)nfsd4_reclaim_complete,
1751 .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING, 1752 .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
1752 .op_name = "OP_RECLAIM_COMPLETE", 1753 .op_name = "OP_RECLAIM_COMPLETE",
1753 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1754 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1754 }, 1755 },
1755 [OP_SECINFO_NO_NAME] = { 1756 [OP_SECINFO_NO_NAME] = {
1756 .op_func = (nfsd4op_func)nfsd4_secinfo_no_name, 1757 .op_func = (nfsd4op_func)nfsd4_secinfo_no_name,
1757 .op_flags = OP_HANDLES_WRONGSEC, 1758 .op_flags = OP_HANDLES_WRONGSEC,
1758 .op_name = "OP_SECINFO_NO_NAME", 1759 .op_name = "OP_SECINFO_NO_NAME",
1759 }, 1760 },
1760 [OP_TEST_STATEID] = { 1761 [OP_TEST_STATEID] = {
1761 .op_func = (nfsd4op_func)nfsd4_test_stateid, 1762 .op_func = (nfsd4op_func)nfsd4_test_stateid,
1762 .op_flags = ALLOWED_WITHOUT_FH, 1763 .op_flags = ALLOWED_WITHOUT_FH,
1763 .op_name = "OP_TEST_STATEID", 1764 .op_name = "OP_TEST_STATEID",
1764 }, 1765 },
1765 [OP_FREE_STATEID] = { 1766 [OP_FREE_STATEID] = {
1766 .op_func = (nfsd4op_func)nfsd4_free_stateid, 1767 .op_func = (nfsd4op_func)nfsd4_free_stateid,
1767 .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING, 1768 .op_flags = ALLOWED_WITHOUT_FH | OP_MODIFIES_SOMETHING,
1768 .op_name = "OP_FREE_STATEID", 1769 .op_name = "OP_FREE_STATEID",
1769 .op_get_currentstateid = (stateid_getter)nfsd4_get_freestateid, 1770 .op_get_currentstateid = (stateid_getter)nfsd4_get_freestateid,
1770 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, 1771 .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize,
1771 }, 1772 },
1772 }; 1773 };
1773 1774
1774 #ifdef NFSD_DEBUG 1775 #ifdef NFSD_DEBUG
1775 static const char *nfsd4_op_name(unsigned opnum) 1776 static const char *nfsd4_op_name(unsigned opnum)
1776 { 1777 {
1777 if (opnum < ARRAY_SIZE(nfsd4_ops)) 1778 if (opnum < ARRAY_SIZE(nfsd4_ops))
1778 return nfsd4_ops[opnum].op_name; 1779 return nfsd4_ops[opnum].op_name;
1779 return "unknown_operation"; 1780 return "unknown_operation";
1780 } 1781 }
1781 #endif 1782 #endif
1782 1783
1783 #define nfsd4_voidres nfsd4_voidargs 1784 #define nfsd4_voidres nfsd4_voidargs
1784 struct nfsd4_voidargs { int dummy; }; 1785 struct nfsd4_voidargs { int dummy; };
1785 1786
1786 static struct svc_procedure nfsd_procedures4[2] = { 1787 static struct svc_procedure nfsd_procedures4[2] = {
1787 [NFSPROC4_NULL] = { 1788 [NFSPROC4_NULL] = {
1788 .pc_func = (svc_procfunc) nfsd4_proc_null, 1789 .pc_func = (svc_procfunc) nfsd4_proc_null,
1789 .pc_encode = (kxdrproc_t) nfs4svc_encode_voidres, 1790 .pc_encode = (kxdrproc_t) nfs4svc_encode_voidres,
1790 .pc_argsize = sizeof(struct nfsd4_voidargs), 1791 .pc_argsize = sizeof(struct nfsd4_voidargs),
1791 .pc_ressize = sizeof(struct nfsd4_voidres), 1792 .pc_ressize = sizeof(struct nfsd4_voidres),
1792 .pc_cachetype = RC_NOCACHE, 1793 .pc_cachetype = RC_NOCACHE,
1793 .pc_xdrressize = 1, 1794 .pc_xdrressize = 1,
1794 }, 1795 },
1795 [NFSPROC4_COMPOUND] = { 1796 [NFSPROC4_COMPOUND] = {
1796 .pc_func = (svc_procfunc) nfsd4_proc_compound, 1797 .pc_func = (svc_procfunc) nfsd4_proc_compound,
1797 .pc_decode = (kxdrproc_t) nfs4svc_decode_compoundargs, 1798 .pc_decode = (kxdrproc_t) nfs4svc_decode_compoundargs,
1798 .pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres, 1799 .pc_encode = (kxdrproc_t) nfs4svc_encode_compoundres,
1799 .pc_argsize = sizeof(struct nfsd4_compoundargs), 1800 .pc_argsize = sizeof(struct nfsd4_compoundargs),
1800 .pc_ressize = sizeof(struct nfsd4_compoundres), 1801 .pc_ressize = sizeof(struct nfsd4_compoundres),
1801 .pc_release = nfsd4_release_compoundargs, 1802 .pc_release = nfsd4_release_compoundargs,
1802 .pc_cachetype = RC_NOCACHE, 1803 .pc_cachetype = RC_NOCACHE,
1803 .pc_xdrressize = NFSD_BUFSIZE/4, 1804 .pc_xdrressize = NFSD_BUFSIZE/4,
1804 }, 1805 },
1805 }; 1806 };
1806 1807
1807 struct svc_version nfsd_version4 = { 1808 struct svc_version nfsd_version4 = {
1808 .vs_vers = 4, 1809 .vs_vers = 4,
1809 .vs_nproc = 2, 1810 .vs_nproc = 2,
1810 .vs_proc = nfsd_procedures4, 1811 .vs_proc = nfsd_procedures4,
1811 .vs_dispatch = nfsd_dispatch, 1812 .vs_dispatch = nfsd_dispatch,
1812 .vs_xdrsize = NFS4_SVC_XDRSIZE, 1813 .vs_xdrsize = NFS4_SVC_XDRSIZE,
1813 }; 1814 };
1814 1815
1815 /* 1816 /*
1816 * Local variables: 1817 * Local variables:
1817 * c-basic-offset: 8 1818 * c-basic-offset: 8
1818 * End: 1819 * End:
1819 */ 1820 */
1820 1821
1 /* 1 /*
2 * Server-side XDR for NFSv4 2 * Server-side XDR for NFSv4
3 * 3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan. 4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Kendrick Smith <kmsmith@umich.edu> 7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <andros@umich.edu> 8 * Andy Adamson <andros@umich.edu>
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 13 *
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its 19 * 3. Neither the name of the University nor the names of its
20 * contributors may be used to endorse or promote products derived 20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission. 21 * from this software without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * 34 *
35 * TODO: Neil Brown made the following observation: We currently 35 * TODO: Neil Brown made the following observation: We currently
36 * initially reserve NFSD_BUFSIZE space on the transmit queue and 36 * initially reserve NFSD_BUFSIZE space on the transmit queue and
37 * never release any of that until the request is complete. 37 * never release any of that until the request is complete.
38 * It would be good to calculate a new maximum response size while 38 * It would be good to calculate a new maximum response size while
39 * decoding the COMPOUND, and call svc_reserve with this number 39 * decoding the COMPOUND, and call svc_reserve with this number
40 * at the end of nfs4svc_decode_compoundargs. 40 * at the end of nfs4svc_decode_compoundargs.
41 */ 41 */
42 42
43 #include <linux/slab.h> 43 #include <linux/slab.h>
44 #include <linux/namei.h> 44 #include <linux/namei.h>
45 #include <linux/statfs.h> 45 #include <linux/statfs.h>
46 #include <linux/utsname.h> 46 #include <linux/utsname.h>
47 #include <linux/pagemap.h> 47 #include <linux/pagemap.h>
48 #include <linux/sunrpc/svcauth_gss.h> 48 #include <linux/sunrpc/svcauth_gss.h>
49 49
50 #include "idmap.h" 50 #include "idmap.h"
51 #include "acl.h" 51 #include "acl.h"
52 #include "xdr4.h" 52 #include "xdr4.h"
53 #include "vfs.h" 53 #include "vfs.h"
54 #include "state.h" 54 #include "state.h"
55 #include "cache.h" 55 #include "cache.h"
56 #include "netns.h" 56 #include "netns.h"
57 57
58 #define NFSDDBG_FACILITY NFSDDBG_XDR 58 #define NFSDDBG_FACILITY NFSDDBG_XDR
59 59
60 /* 60 /*
61 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing 61 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
62 * directory in order to indicate to the client that a filesystem boundary is present 62 * directory in order to indicate to the client that a filesystem boundary is present
63 * We use a fixed fsid for a referral 63 * We use a fixed fsid for a referral
64 */ 64 */
65 #define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL 65 #define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL
66 #define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL 66 #define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL
67 67
68 static __be32 68 static __be32
69 check_filename(char *str, int len) 69 check_filename(char *str, int len)
70 { 70 {
71 int i; 71 int i;
72 72
73 if (len == 0) 73 if (len == 0)
74 return nfserr_inval; 74 return nfserr_inval;
75 if (isdotent(str, len)) 75 if (isdotent(str, len))
76 return nfserr_badname; 76 return nfserr_badname;
77 for (i = 0; i < len; i++) 77 for (i = 0; i < len; i++)
78 if (str[i] == '/') 78 if (str[i] == '/')
79 return nfserr_badname; 79 return nfserr_badname;
80 return 0; 80 return 0;
81 } 81 }
82 82
83 #define DECODE_HEAD \ 83 #define DECODE_HEAD \
84 __be32 *p; \ 84 __be32 *p; \
85 __be32 status 85 __be32 status
86 #define DECODE_TAIL \ 86 #define DECODE_TAIL \
87 status = 0; \ 87 status = 0; \
88 out: \ 88 out: \
89 return status; \ 89 return status; \
90 xdr_error: \ 90 xdr_error: \
91 dprintk("NFSD: xdr error (%s:%d)\n", \ 91 dprintk("NFSD: xdr error (%s:%d)\n", \
92 __FILE__, __LINE__); \ 92 __FILE__, __LINE__); \
93 status = nfserr_bad_xdr; \ 93 status = nfserr_bad_xdr; \
94 goto out 94 goto out
95 95
96 #define READ32(x) (x) = ntohl(*p++) 96 #define READ32(x) (x) = ntohl(*p++)
97 #define READ64(x) do { \ 97 #define READ64(x) do { \
98 (x) = (u64)ntohl(*p++) << 32; \ 98 (x) = (u64)ntohl(*p++) << 32; \
99 (x) |= ntohl(*p++); \ 99 (x) |= ntohl(*p++); \
100 } while (0) 100 } while (0)
101 #define READTIME(x) do { \ 101 #define READTIME(x) do { \
102 p++; \ 102 p++; \
103 (x) = ntohl(*p++); \ 103 (x) = ntohl(*p++); \
104 p++; \ 104 p++; \
105 } while (0) 105 } while (0)
106 #define READMEM(x,nbytes) do { \ 106 #define READMEM(x,nbytes) do { \
107 x = (char *)p; \ 107 x = (char *)p; \
108 p += XDR_QUADLEN(nbytes); \ 108 p += XDR_QUADLEN(nbytes); \
109 } while (0) 109 } while (0)
110 #define SAVEMEM(x,nbytes) do { \ 110 #define SAVEMEM(x,nbytes) do { \
111 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \ 111 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
112 savemem(argp, p, nbytes) : \ 112 savemem(argp, p, nbytes) : \
113 (char *)p)) { \ 113 (char *)p)) { \
114 dprintk("NFSD: xdr error (%s:%d)\n", \ 114 dprintk("NFSD: xdr error (%s:%d)\n", \
115 __FILE__, __LINE__); \ 115 __FILE__, __LINE__); \
116 goto xdr_error; \ 116 goto xdr_error; \
117 } \ 117 } \
118 p += XDR_QUADLEN(nbytes); \ 118 p += XDR_QUADLEN(nbytes); \
119 } while (0) 119 } while (0)
120 #define COPYMEM(x,nbytes) do { \ 120 #define COPYMEM(x,nbytes) do { \
121 memcpy((x), p, nbytes); \ 121 memcpy((x), p, nbytes); \
122 p += XDR_QUADLEN(nbytes); \ 122 p += XDR_QUADLEN(nbytes); \
123 } while (0) 123 } while (0)
124 124
125 /* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */ 125 /* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */
126 #define READ_BUF(nbytes) do { \ 126 #define READ_BUF(nbytes) do { \
127 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \ 127 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \
128 p = argp->p; \ 128 p = argp->p; \
129 argp->p += XDR_QUADLEN(nbytes); \ 129 argp->p += XDR_QUADLEN(nbytes); \
130 } else if (!(p = read_buf(argp, nbytes))) { \ 130 } else if (!(p = read_buf(argp, nbytes))) { \
131 dprintk("NFSD: xdr error (%s:%d)\n", \ 131 dprintk("NFSD: xdr error (%s:%d)\n", \
132 __FILE__, __LINE__); \ 132 __FILE__, __LINE__); \
133 goto xdr_error; \ 133 goto xdr_error; \
134 } \ 134 } \
135 } while (0) 135 } while (0)
136 136
137 static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) 137 static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
138 { 138 {
139 /* We want more bytes than seem to be available. 139 /* We want more bytes than seem to be available.
140 * Maybe we need a new page, maybe we have just run out 140 * Maybe we need a new page, maybe we have just run out
141 */ 141 */
142 unsigned int avail = (char *)argp->end - (char *)argp->p; 142 unsigned int avail = (char *)argp->end - (char *)argp->p;
143 __be32 *p; 143 __be32 *p;
144 if (avail + argp->pagelen < nbytes) 144 if (avail + argp->pagelen < nbytes)
145 return NULL; 145 return NULL;
146 if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */ 146 if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
147 return NULL; 147 return NULL;
148 /* ok, we can do it with the current plus the next page */ 148 /* ok, we can do it with the current plus the next page */
149 if (nbytes <= sizeof(argp->tmp)) 149 if (nbytes <= sizeof(argp->tmp))
150 p = argp->tmp; 150 p = argp->tmp;
151 else { 151 else {
152 kfree(argp->tmpp); 152 kfree(argp->tmpp);
153 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); 153 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
154 if (!p) 154 if (!p)
155 return NULL; 155 return NULL;
156 156
157 } 157 }
158 /* 158 /*
159 * The following memcpy is safe because read_buf is always 159 * The following memcpy is safe because read_buf is always
160 * called with nbytes > avail, and the two cases above both 160 * called with nbytes > avail, and the two cases above both
161 * guarantee p points to at least nbytes bytes. 161 * guarantee p points to at least nbytes bytes.
162 */ 162 */
163 memcpy(p, argp->p, avail); 163 memcpy(p, argp->p, avail);
164 /* step to next page */ 164 /* step to next page */
165 argp->p = page_address(argp->pagelist[0]); 165 argp->p = page_address(argp->pagelist[0]);
166 argp->pagelist++; 166 argp->pagelist++;
167 if (argp->pagelen < PAGE_SIZE) { 167 if (argp->pagelen < PAGE_SIZE) {
168 argp->end = argp->p + (argp->pagelen>>2); 168 argp->end = argp->p + (argp->pagelen>>2);
169 argp->pagelen = 0; 169 argp->pagelen = 0;
170 } else { 170 } else {
171 argp->end = argp->p + (PAGE_SIZE>>2); 171 argp->end = argp->p + (PAGE_SIZE>>2);
172 argp->pagelen -= PAGE_SIZE; 172 argp->pagelen -= PAGE_SIZE;
173 } 173 }
174 memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); 174 memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
175 argp->p += XDR_QUADLEN(nbytes - avail); 175 argp->p += XDR_QUADLEN(nbytes - avail);
176 return p; 176 return p;
177 } 177 }
178 178
179 static int zero_clientid(clientid_t *clid) 179 static int zero_clientid(clientid_t *clid)
180 { 180 {
181 return (clid->cl_boot == 0) && (clid->cl_id == 0); 181 return (clid->cl_boot == 0) && (clid->cl_id == 0);
182 } 182 }
183 183
184 static int 184 static int
185 defer_free(struct nfsd4_compoundargs *argp, 185 defer_free(struct nfsd4_compoundargs *argp,
186 void (*release)(const void *), void *p) 186 void (*release)(const void *), void *p)
187 { 187 {
188 struct tmpbuf *tb; 188 struct tmpbuf *tb;
189 189
190 tb = kmalloc(sizeof(*tb), GFP_KERNEL); 190 tb = kmalloc(sizeof(*tb), GFP_KERNEL);
191 if (!tb) 191 if (!tb)
192 return -ENOMEM; 192 return -ENOMEM;
193 tb->buf = p; 193 tb->buf = p;
194 tb->release = release; 194 tb->release = release;
195 tb->next = argp->to_free; 195 tb->next = argp->to_free;
196 argp->to_free = tb; 196 argp->to_free = tb;
197 return 0; 197 return 0;
198 } 198 }
199 199
200 static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) 200 static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
201 { 201 {
202 if (p == argp->tmp) { 202 if (p == argp->tmp) {
203 p = kmemdup(argp->tmp, nbytes, GFP_KERNEL); 203 p = kmemdup(argp->tmp, nbytes, GFP_KERNEL);
204 if (!p) 204 if (!p)
205 return NULL; 205 return NULL;
206 } else { 206 } else {
207 BUG_ON(p != argp->tmpp); 207 BUG_ON(p != argp->tmpp);
208 argp->tmpp = NULL; 208 argp->tmpp = NULL;
209 } 209 }
210 if (defer_free(argp, kfree, p)) { 210 if (defer_free(argp, kfree, p)) {
211 kfree(p); 211 kfree(p);
212 return NULL; 212 return NULL;
213 } else 213 } else
214 return (char *)p; 214 return (char *)p;
215 } 215 }
216 216
217 static __be32 217 static __be32
218 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) 218 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
219 { 219 {
220 u32 bmlen; 220 u32 bmlen;
221 DECODE_HEAD; 221 DECODE_HEAD;
222 222
223 bmval[0] = 0; 223 bmval[0] = 0;
224 bmval[1] = 0; 224 bmval[1] = 0;
225 bmval[2] = 0; 225 bmval[2] = 0;
226 226
227 READ_BUF(4); 227 READ_BUF(4);
228 READ32(bmlen); 228 READ32(bmlen);
229 if (bmlen > 1000) 229 if (bmlen > 1000)
230 goto xdr_error; 230 goto xdr_error;
231 231
232 READ_BUF(bmlen << 2); 232 READ_BUF(bmlen << 2);
233 if (bmlen > 0) 233 if (bmlen > 0)
234 READ32(bmval[0]); 234 READ32(bmval[0]);
235 if (bmlen > 1) 235 if (bmlen > 1)
236 READ32(bmval[1]); 236 READ32(bmval[1]);
237 if (bmlen > 2) 237 if (bmlen > 2)
238 READ32(bmval[2]); 238 READ32(bmval[2]);
239 239
240 DECODE_TAIL; 240 DECODE_TAIL;
241 } 241 }
242 242
243 static __be32 243 static __be32
244 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, 244 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
245 struct iattr *iattr, struct nfs4_acl **acl) 245 struct iattr *iattr, struct nfs4_acl **acl)
246 { 246 {
247 int expected_len, len = 0; 247 int expected_len, len = 0;
248 u32 dummy32; 248 u32 dummy32;
249 char *buf; 249 char *buf;
250 int host_err; 250 int host_err;
251 251
252 DECODE_HEAD; 252 DECODE_HEAD;
253 iattr->ia_valid = 0; 253 iattr->ia_valid = 0;
254 if ((status = nfsd4_decode_bitmap(argp, bmval))) 254 if ((status = nfsd4_decode_bitmap(argp, bmval)))
255 return status; 255 return status;
256 256
257 READ_BUF(4); 257 READ_BUF(4);
258 READ32(expected_len); 258 READ32(expected_len);
259 259
260 if (bmval[0] & FATTR4_WORD0_SIZE) { 260 if (bmval[0] & FATTR4_WORD0_SIZE) {
261 READ_BUF(8); 261 READ_BUF(8);
262 len += 8; 262 len += 8;
263 READ64(iattr->ia_size); 263 READ64(iattr->ia_size);
264 iattr->ia_valid |= ATTR_SIZE; 264 iattr->ia_valid |= ATTR_SIZE;
265 } 265 }
266 if (bmval[0] & FATTR4_WORD0_ACL) { 266 if (bmval[0] & FATTR4_WORD0_ACL) {
267 int nace; 267 int nace;
268 struct nfs4_ace *ace; 268 struct nfs4_ace *ace;
269 269
270 READ_BUF(4); len += 4; 270 READ_BUF(4); len += 4;
271 READ32(nace); 271 READ32(nace);
272 272
273 if (nace > NFS4_ACL_MAX) 273 if (nace > NFS4_ACL_MAX)
274 return nfserr_resource; 274 return nfserr_resource;
275 275
276 *acl = nfs4_acl_new(nace); 276 *acl = nfs4_acl_new(nace);
277 if (*acl == NULL) { 277 if (*acl == NULL) {
278 host_err = -ENOMEM; 278 host_err = -ENOMEM;
279 goto out_nfserr; 279 goto out_nfserr;
280 } 280 }
281 defer_free(argp, kfree, *acl); 281 defer_free(argp, kfree, *acl);
282 282
283 (*acl)->naces = nace; 283 (*acl)->naces = nace;
284 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) { 284 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
285 READ_BUF(16); len += 16; 285 READ_BUF(16); len += 16;
286 READ32(ace->type); 286 READ32(ace->type);
287 READ32(ace->flag); 287 READ32(ace->flag);
288 READ32(ace->access_mask); 288 READ32(ace->access_mask);
289 READ32(dummy32); 289 READ32(dummy32);
290 READ_BUF(dummy32); 290 READ_BUF(dummy32);
291 len += XDR_QUADLEN(dummy32) << 2; 291 len += XDR_QUADLEN(dummy32) << 2;
292 READMEM(buf, dummy32); 292 READMEM(buf, dummy32);
293 ace->whotype = nfs4_acl_get_whotype(buf, dummy32); 293 ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
294 status = nfs_ok; 294 status = nfs_ok;
295 if (ace->whotype != NFS4_ACL_WHO_NAMED) 295 if (ace->whotype != NFS4_ACL_WHO_NAMED)
296 ace->who = 0; 296 ace->who = 0;
297 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) 297 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
298 status = nfsd_map_name_to_gid(argp->rqstp, 298 status = nfsd_map_name_to_gid(argp->rqstp,
299 buf, dummy32, &ace->who); 299 buf, dummy32, &ace->who);
300 else 300 else
301 status = nfsd_map_name_to_uid(argp->rqstp, 301 status = nfsd_map_name_to_uid(argp->rqstp,
302 buf, dummy32, &ace->who); 302 buf, dummy32, &ace->who);
303 if (status) 303 if (status)
304 return status; 304 return status;
305 } 305 }
306 } else 306 } else
307 *acl = NULL; 307 *acl = NULL;
308 if (bmval[1] & FATTR4_WORD1_MODE) { 308 if (bmval[1] & FATTR4_WORD1_MODE) {
309 READ_BUF(4); 309 READ_BUF(4);
310 len += 4; 310 len += 4;
311 READ32(iattr->ia_mode); 311 READ32(iattr->ia_mode);
312 iattr->ia_mode &= (S_IFMT | S_IALLUGO); 312 iattr->ia_mode &= (S_IFMT | S_IALLUGO);
313 iattr->ia_valid |= ATTR_MODE; 313 iattr->ia_valid |= ATTR_MODE;
314 } 314 }
315 if (bmval[1] & FATTR4_WORD1_OWNER) { 315 if (bmval[1] & FATTR4_WORD1_OWNER) {
316 READ_BUF(4); 316 READ_BUF(4);
317 len += 4; 317 len += 4;
318 READ32(dummy32); 318 READ32(dummy32);
319 READ_BUF(dummy32); 319 READ_BUF(dummy32);
320 len += (XDR_QUADLEN(dummy32) << 2); 320 len += (XDR_QUADLEN(dummy32) << 2);
321 READMEM(buf, dummy32); 321 READMEM(buf, dummy32);
322 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) 322 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
323 return status; 323 return status;
324 iattr->ia_valid |= ATTR_UID; 324 iattr->ia_valid |= ATTR_UID;
325 } 325 }
326 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { 326 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
327 READ_BUF(4); 327 READ_BUF(4);
328 len += 4; 328 len += 4;
329 READ32(dummy32); 329 READ32(dummy32);
330 READ_BUF(dummy32); 330 READ_BUF(dummy32);
331 len += (XDR_QUADLEN(dummy32) << 2); 331 len += (XDR_QUADLEN(dummy32) << 2);
332 READMEM(buf, dummy32); 332 READMEM(buf, dummy32);
333 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) 333 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
334 return status; 334 return status;
335 iattr->ia_valid |= ATTR_GID; 335 iattr->ia_valid |= ATTR_GID;
336 } 336 }
337 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 337 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
338 READ_BUF(4); 338 READ_BUF(4);
339 len += 4; 339 len += 4;
340 READ32(dummy32); 340 READ32(dummy32);
341 switch (dummy32) { 341 switch (dummy32) {
342 case NFS4_SET_TO_CLIENT_TIME: 342 case NFS4_SET_TO_CLIENT_TIME:
343 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 343 /* We require the high 32 bits of 'seconds' to be 0, and we ignore
344 all 32 bits of 'nseconds'. */ 344 all 32 bits of 'nseconds'. */
345 READ_BUF(12); 345 READ_BUF(12);
346 len += 12; 346 len += 12;
347 READ32(dummy32); 347 READ32(dummy32);
348 if (dummy32) 348 if (dummy32)
349 return nfserr_inval; 349 return nfserr_inval;
350 READ32(iattr->ia_atime.tv_sec); 350 READ32(iattr->ia_atime.tv_sec);
351 READ32(iattr->ia_atime.tv_nsec); 351 READ32(iattr->ia_atime.tv_nsec);
352 if (iattr->ia_atime.tv_nsec >= (u32)1000000000) 352 if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
353 return nfserr_inval; 353 return nfserr_inval;
354 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET); 354 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
355 break; 355 break;
356 case NFS4_SET_TO_SERVER_TIME: 356 case NFS4_SET_TO_SERVER_TIME:
357 iattr->ia_valid |= ATTR_ATIME; 357 iattr->ia_valid |= ATTR_ATIME;
358 break; 358 break;
359 default: 359 default:
360 goto xdr_error; 360 goto xdr_error;
361 } 361 }
362 } 362 }
363 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 363 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
364 READ_BUF(4); 364 READ_BUF(4);
365 len += 4; 365 len += 4;
366 READ32(dummy32); 366 READ32(dummy32);
367 switch (dummy32) { 367 switch (dummy32) {
368 case NFS4_SET_TO_CLIENT_TIME: 368 case NFS4_SET_TO_CLIENT_TIME:
369 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 369 /* We require the high 32 bits of 'seconds' to be 0, and we ignore
370 all 32 bits of 'nseconds'. */ 370 all 32 bits of 'nseconds'. */
371 READ_BUF(12); 371 READ_BUF(12);
372 len += 12; 372 len += 12;
373 READ32(dummy32); 373 READ32(dummy32);
374 if (dummy32) 374 if (dummy32)
375 return nfserr_inval; 375 return nfserr_inval;
376 READ32(iattr->ia_mtime.tv_sec); 376 READ32(iattr->ia_mtime.tv_sec);
377 READ32(iattr->ia_mtime.tv_nsec); 377 READ32(iattr->ia_mtime.tv_nsec);
378 if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) 378 if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
379 return nfserr_inval; 379 return nfserr_inval;
380 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET); 380 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
381 break; 381 break;
382 case NFS4_SET_TO_SERVER_TIME: 382 case NFS4_SET_TO_SERVER_TIME:
383 iattr->ia_valid |= ATTR_MTIME; 383 iattr->ia_valid |= ATTR_MTIME;
384 break; 384 break;
385 default: 385 default:
386 goto xdr_error; 386 goto xdr_error;
387 } 387 }
388 } 388 }
389 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0 389 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
390 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1 390 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
391 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) 391 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
392 READ_BUF(expected_len - len); 392 READ_BUF(expected_len - len);
393 else if (len != expected_len) 393 else if (len != expected_len)
394 goto xdr_error; 394 goto xdr_error;
395 395
396 DECODE_TAIL; 396 DECODE_TAIL;
397 397
398 out_nfserr: 398 out_nfserr:
399 status = nfserrno(host_err); 399 status = nfserrno(host_err);
400 goto out; 400 goto out;
401 } 401 }
402 402
403 static __be32 403 static __be32
404 nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid) 404 nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
405 { 405 {
406 DECODE_HEAD; 406 DECODE_HEAD;
407 407
408 READ_BUF(sizeof(stateid_t)); 408 READ_BUF(sizeof(stateid_t));
409 READ32(sid->si_generation); 409 READ32(sid->si_generation);
410 COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); 410 COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
411 411
412 DECODE_TAIL; 412 DECODE_TAIL;
413 } 413 }
414 414
415 static __be32 415 static __be32
416 nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access) 416 nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
417 { 417 {
418 DECODE_HEAD; 418 DECODE_HEAD;
419 419
420 READ_BUF(4); 420 READ_BUF(4);
421 READ32(access->ac_req_access); 421 READ32(access->ac_req_access);
422 422
423 DECODE_TAIL; 423 DECODE_TAIL;
424 } 424 }
425 425
426 static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs) 426 static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
427 { 427 {
428 DECODE_HEAD; 428 DECODE_HEAD;
429 u32 dummy, uid, gid; 429 u32 dummy, uid, gid;
430 char *machine_name; 430 char *machine_name;
431 int i; 431 int i;
432 int nr_secflavs; 432 int nr_secflavs;
433 433
434 /* callback_sec_params4 */ 434 /* callback_sec_params4 */
435 READ_BUF(4); 435 READ_BUF(4);
436 READ32(nr_secflavs); 436 READ32(nr_secflavs);
437 cbs->flavor = (u32)(-1); 437 cbs->flavor = (u32)(-1);
438 for (i = 0; i < nr_secflavs; ++i) { 438 for (i = 0; i < nr_secflavs; ++i) {
439 READ_BUF(4); 439 READ_BUF(4);
440 READ32(dummy); 440 READ32(dummy);
441 switch (dummy) { 441 switch (dummy) {
442 case RPC_AUTH_NULL: 442 case RPC_AUTH_NULL:
443 /* Nothing to read */ 443 /* Nothing to read */
444 if (cbs->flavor == (u32)(-1)) 444 if (cbs->flavor == (u32)(-1))
445 cbs->flavor = RPC_AUTH_NULL; 445 cbs->flavor = RPC_AUTH_NULL;
446 break; 446 break;
447 case RPC_AUTH_UNIX: 447 case RPC_AUTH_UNIX:
448 READ_BUF(8); 448 READ_BUF(8);
449 /* stamp */ 449 /* stamp */
450 READ32(dummy); 450 READ32(dummy);
451 451
452 /* machine name */ 452 /* machine name */
453 READ32(dummy); 453 READ32(dummy);
454 READ_BUF(dummy); 454 READ_BUF(dummy);
455 SAVEMEM(machine_name, dummy); 455 SAVEMEM(machine_name, dummy);
456 456
457 /* uid, gid */ 457 /* uid, gid */
458 READ_BUF(8); 458 READ_BUF(8);
459 READ32(uid); 459 READ32(uid);
460 READ32(gid); 460 READ32(gid);
461 461
462 /* more gids */ 462 /* more gids */
463 READ_BUF(4); 463 READ_BUF(4);
464 READ32(dummy); 464 READ32(dummy);
465 READ_BUF(dummy * 4); 465 READ_BUF(dummy * 4);
466 if (cbs->flavor == (u32)(-1)) { 466 if (cbs->flavor == (u32)(-1)) {
467 cbs->uid = uid; 467 cbs->uid = uid;
468 cbs->gid = gid; 468 cbs->gid = gid;
469 cbs->flavor = RPC_AUTH_UNIX; 469 cbs->flavor = RPC_AUTH_UNIX;
470 } 470 }
471 break; 471 break;
472 case RPC_AUTH_GSS: 472 case RPC_AUTH_GSS:
473 dprintk("RPC_AUTH_GSS callback secflavor " 473 dprintk("RPC_AUTH_GSS callback secflavor "
474 "not supported!\n"); 474 "not supported!\n");
475 READ_BUF(8); 475 READ_BUF(8);
476 /* gcbp_service */ 476 /* gcbp_service */
477 READ32(dummy); 477 READ32(dummy);
478 /* gcbp_handle_from_server */ 478 /* gcbp_handle_from_server */
479 READ32(dummy); 479 READ32(dummy);
480 READ_BUF(dummy); 480 READ_BUF(dummy);
481 p += XDR_QUADLEN(dummy); 481 p += XDR_QUADLEN(dummy);
482 /* gcbp_handle_from_client */ 482 /* gcbp_handle_from_client */
483 READ_BUF(4); 483 READ_BUF(4);
484 READ32(dummy); 484 READ32(dummy);
485 READ_BUF(dummy); 485 READ_BUF(dummy);
486 break; 486 break;
487 default: 487 default:
488 dprintk("Illegal callback secflavor\n"); 488 dprintk("Illegal callback secflavor\n");
489 return nfserr_inval; 489 return nfserr_inval;
490 } 490 }
491 } 491 }
492 DECODE_TAIL; 492 DECODE_TAIL;
493 } 493 }
494 494
495 static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc) 495 static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
496 { 496 {
497 DECODE_HEAD; 497 DECODE_HEAD;
498 498
499 READ_BUF(4); 499 READ_BUF(4);
500 READ32(bc->bc_cb_program); 500 READ32(bc->bc_cb_program);
501 nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec); 501 nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
502 502
503 DECODE_TAIL; 503 DECODE_TAIL;
504 } 504 }
505 505
506 static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts) 506 static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
507 { 507 {
508 DECODE_HEAD; 508 DECODE_HEAD;
509 509
510 READ_BUF(NFS4_MAX_SESSIONID_LEN + 8); 510 READ_BUF(NFS4_MAX_SESSIONID_LEN + 8);
511 COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); 511 COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
512 READ32(bcts->dir); 512 READ32(bcts->dir);
513 /* XXX: skipping ctsa_use_conn_in_rdma_mode. Perhaps Tom Tucker 513 /* XXX: skipping ctsa_use_conn_in_rdma_mode. Perhaps Tom Tucker
514 * could help us figure out we should be using it. */ 514 * could help us figure out we should be using it. */
515 DECODE_TAIL; 515 DECODE_TAIL;
516 } 516 }
517 517
518 static __be32 518 static __be32
519 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) 519 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
520 { 520 {
521 DECODE_HEAD; 521 DECODE_HEAD;
522 522
523 READ_BUF(4); 523 READ_BUF(4);
524 READ32(close->cl_seqid); 524 READ32(close->cl_seqid);
525 return nfsd4_decode_stateid(argp, &close->cl_stateid); 525 return nfsd4_decode_stateid(argp, &close->cl_stateid);
526 526
527 DECODE_TAIL; 527 DECODE_TAIL;
528 } 528 }
529 529
530 530
531 static __be32 531 static __be32
532 nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit) 532 nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
533 { 533 {
534 DECODE_HEAD; 534 DECODE_HEAD;
535 535
536 READ_BUF(12); 536 READ_BUF(12);
537 READ64(commit->co_offset); 537 READ64(commit->co_offset);
538 READ32(commit->co_count); 538 READ32(commit->co_count);
539 539
540 DECODE_TAIL; 540 DECODE_TAIL;
541 } 541 }
542 542
543 static __be32 543 static __be32
544 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create) 544 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
545 { 545 {
546 DECODE_HEAD; 546 DECODE_HEAD;
547 547
548 READ_BUF(4); 548 READ_BUF(4);
549 READ32(create->cr_type); 549 READ32(create->cr_type);
550 switch (create->cr_type) { 550 switch (create->cr_type) {
551 case NF4LNK: 551 case NF4LNK:
552 READ_BUF(4); 552 READ_BUF(4);
553 READ32(create->cr_linklen); 553 READ32(create->cr_linklen);
554 READ_BUF(create->cr_linklen); 554 READ_BUF(create->cr_linklen);
555 SAVEMEM(create->cr_linkname, create->cr_linklen); 555 SAVEMEM(create->cr_linkname, create->cr_linklen);
556 break; 556 break;
557 case NF4BLK: 557 case NF4BLK:
558 case NF4CHR: 558 case NF4CHR:
559 READ_BUF(8); 559 READ_BUF(8);
560 READ32(create->cr_specdata1); 560 READ32(create->cr_specdata1);
561 READ32(create->cr_specdata2); 561 READ32(create->cr_specdata2);
562 break; 562 break;
563 case NF4SOCK: 563 case NF4SOCK:
564 case NF4FIFO: 564 case NF4FIFO:
565 case NF4DIR: 565 case NF4DIR:
566 default: 566 default:
567 break; 567 break;
568 } 568 }
569 569
570 READ_BUF(4); 570 READ_BUF(4);
571 READ32(create->cr_namelen); 571 READ32(create->cr_namelen);
572 READ_BUF(create->cr_namelen); 572 READ_BUF(create->cr_namelen);
573 SAVEMEM(create->cr_name, create->cr_namelen); 573 SAVEMEM(create->cr_name, create->cr_namelen);
574 if ((status = check_filename(create->cr_name, create->cr_namelen))) 574 if ((status = check_filename(create->cr_name, create->cr_namelen)))
575 return status; 575 return status;
576 576
577 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, 577 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
578 &create->cr_acl); 578 &create->cr_acl);
579 if (status) 579 if (status)
580 goto out; 580 goto out;
581 581
582 DECODE_TAIL; 582 DECODE_TAIL;
583 } 583 }
584 584
585 static inline __be32 585 static inline __be32
586 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr) 586 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
587 { 587 {
588 return nfsd4_decode_stateid(argp, &dr->dr_stateid); 588 return nfsd4_decode_stateid(argp, &dr->dr_stateid);
589 } 589 }
590 590
591 static inline __be32 591 static inline __be32
592 nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr) 592 nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
593 { 593 {
594 return nfsd4_decode_bitmap(argp, getattr->ga_bmval); 594 return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
595 } 595 }
596 596
597 static __be32 597 static __be32
598 nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link) 598 nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
599 { 599 {
600 DECODE_HEAD; 600 DECODE_HEAD;
601 601
602 READ_BUF(4); 602 READ_BUF(4);
603 READ32(link->li_namelen); 603 READ32(link->li_namelen);
604 READ_BUF(link->li_namelen); 604 READ_BUF(link->li_namelen);
605 SAVEMEM(link->li_name, link->li_namelen); 605 SAVEMEM(link->li_name, link->li_namelen);
606 if ((status = check_filename(link->li_name, link->li_namelen))) 606 if ((status = check_filename(link->li_name, link->li_namelen)))
607 return status; 607 return status;
608 608
609 DECODE_TAIL; 609 DECODE_TAIL;
610 } 610 }
611 611
612 static __be32 612 static __be32
613 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock) 613 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
614 { 614 {
615 DECODE_HEAD; 615 DECODE_HEAD;
616 616
617 /* 617 /*
618 * type, reclaim(boolean), offset, length, new_lock_owner(boolean) 618 * type, reclaim(boolean), offset, length, new_lock_owner(boolean)
619 */ 619 */
620 READ_BUF(28); 620 READ_BUF(28);
621 READ32(lock->lk_type); 621 READ32(lock->lk_type);
622 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT)) 622 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
623 goto xdr_error; 623 goto xdr_error;
624 READ32(lock->lk_reclaim); 624 READ32(lock->lk_reclaim);
625 READ64(lock->lk_offset); 625 READ64(lock->lk_offset);
626 READ64(lock->lk_length); 626 READ64(lock->lk_length);
627 READ32(lock->lk_is_new); 627 READ32(lock->lk_is_new);
628 628
629 if (lock->lk_is_new) { 629 if (lock->lk_is_new) {
630 READ_BUF(4); 630 READ_BUF(4);
631 READ32(lock->lk_new_open_seqid); 631 READ32(lock->lk_new_open_seqid);
632 status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid); 632 status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
633 if (status) 633 if (status)
634 return status; 634 return status;
635 READ_BUF(8 + sizeof(clientid_t)); 635 READ_BUF(8 + sizeof(clientid_t));
636 READ32(lock->lk_new_lock_seqid); 636 READ32(lock->lk_new_lock_seqid);
637 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t)); 637 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
638 READ32(lock->lk_new_owner.len); 638 READ32(lock->lk_new_owner.len);
639 READ_BUF(lock->lk_new_owner.len); 639 READ_BUF(lock->lk_new_owner.len);
640 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len); 640 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
641 } else { 641 } else {
642 status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid); 642 status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
643 if (status) 643 if (status)
644 return status; 644 return status;
645 READ_BUF(4); 645 READ_BUF(4);
646 READ32(lock->lk_old_lock_seqid); 646 READ32(lock->lk_old_lock_seqid);
647 } 647 }
648 648
649 DECODE_TAIL; 649 DECODE_TAIL;
650 } 650 }
651 651
652 static __be32 652 static __be32
653 nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt) 653 nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
654 { 654 {
655 DECODE_HEAD; 655 DECODE_HEAD;
656 656
657 READ_BUF(32); 657 READ_BUF(32);
658 READ32(lockt->lt_type); 658 READ32(lockt->lt_type);
659 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT)) 659 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
660 goto xdr_error; 660 goto xdr_error;
661 READ64(lockt->lt_offset); 661 READ64(lockt->lt_offset);
662 READ64(lockt->lt_length); 662 READ64(lockt->lt_length);
663 COPYMEM(&lockt->lt_clientid, 8); 663 COPYMEM(&lockt->lt_clientid, 8);
664 READ32(lockt->lt_owner.len); 664 READ32(lockt->lt_owner.len);
665 READ_BUF(lockt->lt_owner.len); 665 READ_BUF(lockt->lt_owner.len);
666 READMEM(lockt->lt_owner.data, lockt->lt_owner.len); 666 READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
667 667
668 DECODE_TAIL; 668 DECODE_TAIL;
669 } 669 }
670 670
671 static __be32 671 static __be32
672 nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku) 672 nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
673 { 673 {
674 DECODE_HEAD; 674 DECODE_HEAD;
675 675
676 READ_BUF(8); 676 READ_BUF(8);
677 READ32(locku->lu_type); 677 READ32(locku->lu_type);
678 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT)) 678 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
679 goto xdr_error; 679 goto xdr_error;
680 READ32(locku->lu_seqid); 680 READ32(locku->lu_seqid);
681 status = nfsd4_decode_stateid(argp, &locku->lu_stateid); 681 status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
682 if (status) 682 if (status)
683 return status; 683 return status;
684 READ_BUF(16); 684 READ_BUF(16);
685 READ64(locku->lu_offset); 685 READ64(locku->lu_offset);
686 READ64(locku->lu_length); 686 READ64(locku->lu_length);
687 687
688 DECODE_TAIL; 688 DECODE_TAIL;
689 } 689 }
690 690
691 static __be32 691 static __be32
692 nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup) 692 nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
693 { 693 {
694 DECODE_HEAD; 694 DECODE_HEAD;
695 695
696 READ_BUF(4); 696 READ_BUF(4);
697 READ32(lookup->lo_len); 697 READ32(lookup->lo_len);
698 READ_BUF(lookup->lo_len); 698 READ_BUF(lookup->lo_len);
699 SAVEMEM(lookup->lo_name, lookup->lo_len); 699 SAVEMEM(lookup->lo_name, lookup->lo_len);
700 if ((status = check_filename(lookup->lo_name, lookup->lo_len))) 700 if ((status = check_filename(lookup->lo_name, lookup->lo_len)))
701 return status; 701 return status;
702 702
703 DECODE_TAIL; 703 DECODE_TAIL;
704 } 704 }
705 705
706 static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when) 706 static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
707 { 707 {
708 __be32 *p; 708 __be32 *p;
709 u32 w; 709 u32 w;
710 710
711 READ_BUF(4); 711 READ_BUF(4);
712 READ32(w); 712 READ32(w);
713 *share_access = w & NFS4_SHARE_ACCESS_MASK; 713 *share_access = w & NFS4_SHARE_ACCESS_MASK;
714 *deleg_want = w & NFS4_SHARE_WANT_MASK; 714 *deleg_want = w & NFS4_SHARE_WANT_MASK;
715 if (deleg_when) 715 if (deleg_when)
716 *deleg_when = w & NFS4_SHARE_WHEN_MASK; 716 *deleg_when = w & NFS4_SHARE_WHEN_MASK;
717 717
718 switch (w & NFS4_SHARE_ACCESS_MASK) { 718 switch (w & NFS4_SHARE_ACCESS_MASK) {
719 case NFS4_SHARE_ACCESS_READ: 719 case NFS4_SHARE_ACCESS_READ:
720 case NFS4_SHARE_ACCESS_WRITE: 720 case NFS4_SHARE_ACCESS_WRITE:
721 case NFS4_SHARE_ACCESS_BOTH: 721 case NFS4_SHARE_ACCESS_BOTH:
722 break; 722 break;
723 default: 723 default:
724 return nfserr_bad_xdr; 724 return nfserr_bad_xdr;
725 } 725 }
726 w &= ~NFS4_SHARE_ACCESS_MASK; 726 w &= ~NFS4_SHARE_ACCESS_MASK;
727 if (!w) 727 if (!w)
728 return nfs_ok; 728 return nfs_ok;
729 if (!argp->minorversion) 729 if (!argp->minorversion)
730 return nfserr_bad_xdr; 730 return nfserr_bad_xdr;
731 switch (w & NFS4_SHARE_WANT_MASK) { 731 switch (w & NFS4_SHARE_WANT_MASK) {
732 case NFS4_SHARE_WANT_NO_PREFERENCE: 732 case NFS4_SHARE_WANT_NO_PREFERENCE:
733 case NFS4_SHARE_WANT_READ_DELEG: 733 case NFS4_SHARE_WANT_READ_DELEG:
734 case NFS4_SHARE_WANT_WRITE_DELEG: 734 case NFS4_SHARE_WANT_WRITE_DELEG:
735 case NFS4_SHARE_WANT_ANY_DELEG: 735 case NFS4_SHARE_WANT_ANY_DELEG:
736 case NFS4_SHARE_WANT_NO_DELEG: 736 case NFS4_SHARE_WANT_NO_DELEG:
737 case NFS4_SHARE_WANT_CANCEL: 737 case NFS4_SHARE_WANT_CANCEL:
738 break; 738 break;
739 default: 739 default:
740 return nfserr_bad_xdr; 740 return nfserr_bad_xdr;
741 } 741 }
742 w &= ~NFS4_SHARE_WANT_MASK; 742 w &= ~NFS4_SHARE_WANT_MASK;
743 if (!w) 743 if (!w)
744 return nfs_ok; 744 return nfs_ok;
745 745
746 if (!deleg_when) /* open_downgrade */ 746 if (!deleg_when) /* open_downgrade */
747 return nfserr_inval; 747 return nfserr_inval;
748 switch (w) { 748 switch (w) {
749 case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL: 749 case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL:
750 case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED: 750 case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED:
751 case (NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL | 751 case (NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL |
752 NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED): 752 NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED):
753 return nfs_ok; 753 return nfs_ok;
754 } 754 }
755 xdr_error: 755 xdr_error:
756 return nfserr_bad_xdr; 756 return nfserr_bad_xdr;
757 } 757 }
758 758
759 static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x) 759 static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
760 { 760 {
761 __be32 *p; 761 __be32 *p;
762 762
763 READ_BUF(4); 763 READ_BUF(4);
764 READ32(*x); 764 READ32(*x);
765 /* Note: unlinke access bits, deny bits may be zero. */ 765 /* Note: unlinke access bits, deny bits may be zero. */
766 if (*x & ~NFS4_SHARE_DENY_BOTH) 766 if (*x & ~NFS4_SHARE_DENY_BOTH)
767 return nfserr_bad_xdr; 767 return nfserr_bad_xdr;
768 return nfs_ok; 768 return nfs_ok;
769 xdr_error: 769 xdr_error:
770 return nfserr_bad_xdr; 770 return nfserr_bad_xdr;
771 } 771 }
772 772
773 static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o) 773 static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
774 { 774 {
775 __be32 *p; 775 __be32 *p;
776 776
777 READ_BUF(4); 777 READ_BUF(4);
778 READ32(o->len); 778 READ32(o->len);
779 779
780 if (o->len == 0 || o->len > NFS4_OPAQUE_LIMIT) 780 if (o->len == 0 || o->len > NFS4_OPAQUE_LIMIT)
781 return nfserr_bad_xdr; 781 return nfserr_bad_xdr;
782 782
783 READ_BUF(o->len); 783 READ_BUF(o->len);
784 SAVEMEM(o->data, o->len); 784 SAVEMEM(o->data, o->len);
785 return nfs_ok; 785 return nfs_ok;
786 xdr_error: 786 xdr_error:
787 return nfserr_bad_xdr; 787 return nfserr_bad_xdr;
788 } 788 }
789 789
790 static __be32 790 static __be32
791 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) 791 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
792 { 792 {
793 DECODE_HEAD; 793 DECODE_HEAD;
794 u32 dummy; 794 u32 dummy;
795 795
796 memset(open->op_bmval, 0, sizeof(open->op_bmval)); 796 memset(open->op_bmval, 0, sizeof(open->op_bmval));
797 open->op_iattr.ia_valid = 0; 797 open->op_iattr.ia_valid = 0;
798 open->op_openowner = NULL; 798 open->op_openowner = NULL;
799 799
800 /* seqid, share_access, share_deny, clientid, ownerlen */ 800 /* seqid, share_access, share_deny, clientid, ownerlen */
801 READ_BUF(4); 801 READ_BUF(4);
802 READ32(open->op_seqid); 802 READ32(open->op_seqid);
803 /* decode, yet ignore deleg_when until supported */ 803 /* decode, yet ignore deleg_when until supported */
804 status = nfsd4_decode_share_access(argp, &open->op_share_access, 804 status = nfsd4_decode_share_access(argp, &open->op_share_access,
805 &open->op_deleg_want, &dummy); 805 &open->op_deleg_want, &dummy);
806 if (status) 806 if (status)
807 goto xdr_error; 807 goto xdr_error;
808 status = nfsd4_decode_share_deny(argp, &open->op_share_deny); 808 status = nfsd4_decode_share_deny(argp, &open->op_share_deny);
809 if (status) 809 if (status)
810 goto xdr_error; 810 goto xdr_error;
811 READ_BUF(sizeof(clientid_t)); 811 READ_BUF(sizeof(clientid_t));
812 COPYMEM(&open->op_clientid, sizeof(clientid_t)); 812 COPYMEM(&open->op_clientid, sizeof(clientid_t));
813 status = nfsd4_decode_opaque(argp, &open->op_owner); 813 status = nfsd4_decode_opaque(argp, &open->op_owner);
814 if (status) 814 if (status)
815 goto xdr_error; 815 goto xdr_error;
816 READ_BUF(4); 816 READ_BUF(4);
817 READ32(open->op_create); 817 READ32(open->op_create);
818 switch (open->op_create) { 818 switch (open->op_create) {
819 case NFS4_OPEN_NOCREATE: 819 case NFS4_OPEN_NOCREATE:
820 break; 820 break;
821 case NFS4_OPEN_CREATE: 821 case NFS4_OPEN_CREATE:
822 READ_BUF(4); 822 READ_BUF(4);
823 READ32(open->op_createmode); 823 READ32(open->op_createmode);
824 switch (open->op_createmode) { 824 switch (open->op_createmode) {
825 case NFS4_CREATE_UNCHECKED: 825 case NFS4_CREATE_UNCHECKED:
826 case NFS4_CREATE_GUARDED: 826 case NFS4_CREATE_GUARDED:
827 status = nfsd4_decode_fattr(argp, open->op_bmval, 827 status = nfsd4_decode_fattr(argp, open->op_bmval,
828 &open->op_iattr, &open->op_acl); 828 &open->op_iattr, &open->op_acl);
829 if (status) 829 if (status)
830 goto out; 830 goto out;
831 break; 831 break;
832 case NFS4_CREATE_EXCLUSIVE: 832 case NFS4_CREATE_EXCLUSIVE:
833 READ_BUF(NFS4_VERIFIER_SIZE); 833 READ_BUF(NFS4_VERIFIER_SIZE);
834 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); 834 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
835 break; 835 break;
836 case NFS4_CREATE_EXCLUSIVE4_1: 836 case NFS4_CREATE_EXCLUSIVE4_1:
837 if (argp->minorversion < 1) 837 if (argp->minorversion < 1)
838 goto xdr_error; 838 goto xdr_error;
839 READ_BUF(NFS4_VERIFIER_SIZE); 839 READ_BUF(NFS4_VERIFIER_SIZE);
840 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE); 840 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
841 status = nfsd4_decode_fattr(argp, open->op_bmval, 841 status = nfsd4_decode_fattr(argp, open->op_bmval,
842 &open->op_iattr, &open->op_acl); 842 &open->op_iattr, &open->op_acl);
843 if (status) 843 if (status)
844 goto out; 844 goto out;
845 break; 845 break;
846 default: 846 default:
847 goto xdr_error; 847 goto xdr_error;
848 } 848 }
849 break; 849 break;
850 default: 850 default:
851 goto xdr_error; 851 goto xdr_error;
852 } 852 }
853 853
854 /* open_claim */ 854 /* open_claim */
855 READ_BUF(4); 855 READ_BUF(4);
856 READ32(open->op_claim_type); 856 READ32(open->op_claim_type);
857 switch (open->op_claim_type) { 857 switch (open->op_claim_type) {
858 case NFS4_OPEN_CLAIM_NULL: 858 case NFS4_OPEN_CLAIM_NULL:
859 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 859 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
860 READ_BUF(4); 860 READ_BUF(4);
861 READ32(open->op_fname.len); 861 READ32(open->op_fname.len);
862 READ_BUF(open->op_fname.len); 862 READ_BUF(open->op_fname.len);
863 SAVEMEM(open->op_fname.data, open->op_fname.len); 863 SAVEMEM(open->op_fname.data, open->op_fname.len);
864 if ((status = check_filename(open->op_fname.data, open->op_fname.len))) 864 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
865 return status; 865 return status;
866 break; 866 break;
867 case NFS4_OPEN_CLAIM_PREVIOUS: 867 case NFS4_OPEN_CLAIM_PREVIOUS:
868 READ_BUF(4); 868 READ_BUF(4);
869 READ32(open->op_delegate_type); 869 READ32(open->op_delegate_type);
870 break; 870 break;
871 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 871 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
872 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid); 872 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
873 if (status) 873 if (status)
874 return status; 874 return status;
875 READ_BUF(4); 875 READ_BUF(4);
876 READ32(open->op_fname.len); 876 READ32(open->op_fname.len);
877 READ_BUF(open->op_fname.len); 877 READ_BUF(open->op_fname.len);
878 SAVEMEM(open->op_fname.data, open->op_fname.len); 878 SAVEMEM(open->op_fname.data, open->op_fname.len);
879 if ((status = check_filename(open->op_fname.data, open->op_fname.len))) 879 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
880 return status; 880 return status;
881 break; 881 break;
882 case NFS4_OPEN_CLAIM_FH: 882 case NFS4_OPEN_CLAIM_FH:
883 case NFS4_OPEN_CLAIM_DELEG_PREV_FH: 883 case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
884 if (argp->minorversion < 1) 884 if (argp->minorversion < 1)
885 goto xdr_error; 885 goto xdr_error;
886 /* void */ 886 /* void */
887 break; 887 break;
888 case NFS4_OPEN_CLAIM_DELEG_CUR_FH: 888 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
889 if (argp->minorversion < 1) 889 if (argp->minorversion < 1)
890 goto xdr_error; 890 goto xdr_error;
891 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid); 891 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
892 if (status) 892 if (status)
893 return status; 893 return status;
894 break; 894 break;
895 default: 895 default:
896 goto xdr_error; 896 goto xdr_error;
897 } 897 }
898 898
899 DECODE_TAIL; 899 DECODE_TAIL;
900 } 900 }
901 901
902 static __be32 902 static __be32
903 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf) 903 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
904 { 904 {
905 DECODE_HEAD; 905 DECODE_HEAD;
906 906
907 status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid); 907 status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
908 if (status) 908 if (status)
909 return status; 909 return status;
910 READ_BUF(4); 910 READ_BUF(4);
911 READ32(open_conf->oc_seqid); 911 READ32(open_conf->oc_seqid);
912 912
913 DECODE_TAIL; 913 DECODE_TAIL;
914 } 914 }
915 915
916 static __be32 916 static __be32
917 nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down) 917 nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
918 { 918 {
919 DECODE_HEAD; 919 DECODE_HEAD;
920 920
921 status = nfsd4_decode_stateid(argp, &open_down->od_stateid); 921 status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
922 if (status) 922 if (status)
923 return status; 923 return status;
924 READ_BUF(4); 924 READ_BUF(4);
925 READ32(open_down->od_seqid); 925 READ32(open_down->od_seqid);
926 status = nfsd4_decode_share_access(argp, &open_down->od_share_access, 926 status = nfsd4_decode_share_access(argp, &open_down->od_share_access,
927 &open_down->od_deleg_want, NULL); 927 &open_down->od_deleg_want, NULL);
928 if (status) 928 if (status)
929 return status; 929 return status;
930 status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny); 930 status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
931 if (status) 931 if (status)
932 return status; 932 return status;
933 DECODE_TAIL; 933 DECODE_TAIL;
934 } 934 }
935 935
936 static __be32 936 static __be32
937 nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh) 937 nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
938 { 938 {
939 DECODE_HEAD; 939 DECODE_HEAD;
940 940
941 READ_BUF(4); 941 READ_BUF(4);
942 READ32(putfh->pf_fhlen); 942 READ32(putfh->pf_fhlen);
943 if (putfh->pf_fhlen > NFS4_FHSIZE) 943 if (putfh->pf_fhlen > NFS4_FHSIZE)
944 goto xdr_error; 944 goto xdr_error;
945 READ_BUF(putfh->pf_fhlen); 945 READ_BUF(putfh->pf_fhlen);
946 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen); 946 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
947 947
948 DECODE_TAIL; 948 DECODE_TAIL;
949 } 949 }
950 950
951 static __be32 951 static __be32
952 nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read) 952 nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
953 { 953 {
954 DECODE_HEAD; 954 DECODE_HEAD;
955 955
956 status = nfsd4_decode_stateid(argp, &read->rd_stateid); 956 status = nfsd4_decode_stateid(argp, &read->rd_stateid);
957 if (status) 957 if (status)
958 return status; 958 return status;
959 READ_BUF(12); 959 READ_BUF(12);
960 READ64(read->rd_offset); 960 READ64(read->rd_offset);
961 READ32(read->rd_length); 961 READ32(read->rd_length);
962 962
963 DECODE_TAIL; 963 DECODE_TAIL;
964 } 964 }
965 965
966 static __be32 966 static __be32
967 nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir) 967 nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
968 { 968 {
969 DECODE_HEAD; 969 DECODE_HEAD;
970 970
971 READ_BUF(24); 971 READ_BUF(24);
972 READ64(readdir->rd_cookie); 972 READ64(readdir->rd_cookie);
973 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data)); 973 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
974 READ32(readdir->rd_dircount); /* just in case you needed a useless field... */ 974 READ32(readdir->rd_dircount); /* just in case you needed a useless field... */
975 READ32(readdir->rd_maxcount); 975 READ32(readdir->rd_maxcount);
976 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval))) 976 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
977 goto out; 977 goto out;
978 978
979 DECODE_TAIL; 979 DECODE_TAIL;
980 } 980 }
981 981
982 static __be32 982 static __be32
983 nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove) 983 nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
984 { 984 {
985 DECODE_HEAD; 985 DECODE_HEAD;
986 986
987 READ_BUF(4); 987 READ_BUF(4);
988 READ32(remove->rm_namelen); 988 READ32(remove->rm_namelen);
989 READ_BUF(remove->rm_namelen); 989 READ_BUF(remove->rm_namelen);
990 SAVEMEM(remove->rm_name, remove->rm_namelen); 990 SAVEMEM(remove->rm_name, remove->rm_namelen);
991 if ((status = check_filename(remove->rm_name, remove->rm_namelen))) 991 if ((status = check_filename(remove->rm_name, remove->rm_namelen)))
992 return status; 992 return status;
993 993
994 DECODE_TAIL; 994 DECODE_TAIL;
995 } 995 }
996 996
997 static __be32 997 static __be32
998 nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename) 998 nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
999 { 999 {
1000 DECODE_HEAD; 1000 DECODE_HEAD;
1001 1001
1002 READ_BUF(4); 1002 READ_BUF(4);
1003 READ32(rename->rn_snamelen); 1003 READ32(rename->rn_snamelen);
1004 READ_BUF(rename->rn_snamelen + 4); 1004 READ_BUF(rename->rn_snamelen + 4);
1005 SAVEMEM(rename->rn_sname, rename->rn_snamelen); 1005 SAVEMEM(rename->rn_sname, rename->rn_snamelen);
1006 READ32(rename->rn_tnamelen); 1006 READ32(rename->rn_tnamelen);
1007 READ_BUF(rename->rn_tnamelen); 1007 READ_BUF(rename->rn_tnamelen);
1008 SAVEMEM(rename->rn_tname, rename->rn_tnamelen); 1008 SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
1009 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen))) 1009 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen)))
1010 return status; 1010 return status;
1011 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen))) 1011 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen)))
1012 return status; 1012 return status;
1013 1013
1014 DECODE_TAIL; 1014 DECODE_TAIL;
1015 } 1015 }
1016 1016
1017 static __be32 1017 static __be32
1018 nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) 1018 nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
1019 { 1019 {
1020 DECODE_HEAD; 1020 DECODE_HEAD;
1021 1021
1022 READ_BUF(sizeof(clientid_t)); 1022 READ_BUF(sizeof(clientid_t));
1023 COPYMEM(clientid, sizeof(clientid_t)); 1023 COPYMEM(clientid, sizeof(clientid_t));
1024 1024
1025 DECODE_TAIL; 1025 DECODE_TAIL;
1026 } 1026 }
1027 1027
1028 static __be32 1028 static __be32
1029 nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp, 1029 nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
1030 struct nfsd4_secinfo *secinfo) 1030 struct nfsd4_secinfo *secinfo)
1031 { 1031 {
1032 DECODE_HEAD; 1032 DECODE_HEAD;
1033 1033
1034 READ_BUF(4); 1034 READ_BUF(4);
1035 READ32(secinfo->si_namelen); 1035 READ32(secinfo->si_namelen);
1036 READ_BUF(secinfo->si_namelen); 1036 READ_BUF(secinfo->si_namelen);
1037 SAVEMEM(secinfo->si_name, secinfo->si_namelen); 1037 SAVEMEM(secinfo->si_name, secinfo->si_namelen);
1038 status = check_filename(secinfo->si_name, secinfo->si_namelen); 1038 status = check_filename(secinfo->si_name, secinfo->si_namelen);
1039 if (status) 1039 if (status)
1040 return status; 1040 return status;
1041 DECODE_TAIL; 1041 DECODE_TAIL;
1042 } 1042 }
1043 1043
1044 static __be32 1044 static __be32
1045 nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp, 1045 nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
1046 struct nfsd4_secinfo_no_name *sin) 1046 struct nfsd4_secinfo_no_name *sin)
1047 { 1047 {
1048 DECODE_HEAD; 1048 DECODE_HEAD;
1049 1049
1050 READ_BUF(4); 1050 READ_BUF(4);
1051 READ32(sin->sin_style); 1051 READ32(sin->sin_style);
1052 DECODE_TAIL; 1052 DECODE_TAIL;
1053 } 1053 }
1054 1054
1055 static __be32 1055 static __be32
1056 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) 1056 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
1057 { 1057 {
1058 __be32 status; 1058 __be32 status;
1059 1059
1060 status = nfsd4_decode_stateid(argp, &setattr->sa_stateid); 1060 status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
1061 if (status) 1061 if (status)
1062 return status; 1062 return status;
1063 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, 1063 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
1064 &setattr->sa_acl); 1064 &setattr->sa_acl);
1065 } 1065 }
1066 1066
1067 static __be32 1067 static __be32
1068 nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid) 1068 nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
1069 { 1069 {
1070 DECODE_HEAD; 1070 DECODE_HEAD;
1071 1071
1072 READ_BUF(NFS4_VERIFIER_SIZE); 1072 READ_BUF(NFS4_VERIFIER_SIZE);
1073 COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE); 1073 COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
1074 1074
1075 status = nfsd4_decode_opaque(argp, &setclientid->se_name); 1075 status = nfsd4_decode_opaque(argp, &setclientid->se_name);
1076 if (status) 1076 if (status)
1077 return nfserr_bad_xdr; 1077 return nfserr_bad_xdr;
1078 READ_BUF(8); 1078 READ_BUF(8);
1079 READ32(setclientid->se_callback_prog); 1079 READ32(setclientid->se_callback_prog);
1080 READ32(setclientid->se_callback_netid_len); 1080 READ32(setclientid->se_callback_netid_len);
1081 1081
1082 READ_BUF(setclientid->se_callback_netid_len + 4); 1082 READ_BUF(setclientid->se_callback_netid_len + 4);
1083 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); 1083 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
1084 READ32(setclientid->se_callback_addr_len); 1084 READ32(setclientid->se_callback_addr_len);
1085 1085
1086 READ_BUF(setclientid->se_callback_addr_len + 4); 1086 READ_BUF(setclientid->se_callback_addr_len + 4);
1087 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len); 1087 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
1088 READ32(setclientid->se_callback_ident); 1088 READ32(setclientid->se_callback_ident);
1089 1089
1090 DECODE_TAIL; 1090 DECODE_TAIL;
1091 } 1091 }
1092 1092
1093 static __be32 1093 static __be32
1094 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c) 1094 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
1095 { 1095 {
1096 DECODE_HEAD; 1096 DECODE_HEAD;
1097 1097
1098 READ_BUF(8 + NFS4_VERIFIER_SIZE); 1098 READ_BUF(8 + NFS4_VERIFIER_SIZE);
1099 COPYMEM(&scd_c->sc_clientid, 8); 1099 COPYMEM(&scd_c->sc_clientid, 8);
1100 COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE); 1100 COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
1101 1101
1102 DECODE_TAIL; 1102 DECODE_TAIL;
1103 } 1103 }
1104 1104
1105 /* Also used for NVERIFY */ 1105 /* Also used for NVERIFY */
1106 static __be32 1106 static __be32
1107 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify) 1107 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
1108 { 1108 {
1109 DECODE_HEAD; 1109 DECODE_HEAD;
1110 1110
1111 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval))) 1111 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
1112 goto out; 1112 goto out;
1113 1113
1114 /* For convenience's sake, we compare raw xdr'd attributes in 1114 /* For convenience's sake, we compare raw xdr'd attributes in
1115 * nfsd4_proc_verify */ 1115 * nfsd4_proc_verify */
1116 1116
1117 READ_BUF(4); 1117 READ_BUF(4);
1118 READ32(verify->ve_attrlen); 1118 READ32(verify->ve_attrlen);
1119 READ_BUF(verify->ve_attrlen); 1119 READ_BUF(verify->ve_attrlen);
1120 SAVEMEM(verify->ve_attrval, verify->ve_attrlen); 1120 SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
1121 1121
1122 DECODE_TAIL; 1122 DECODE_TAIL;
1123 } 1123 }
1124 1124
1125 static __be32 1125 static __be32
1126 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) 1126 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1127 { 1127 {
1128 int avail; 1128 int avail;
1129 int len; 1129 int len;
1130 DECODE_HEAD; 1130 DECODE_HEAD;
1131 1131
1132 status = nfsd4_decode_stateid(argp, &write->wr_stateid); 1132 status = nfsd4_decode_stateid(argp, &write->wr_stateid);
1133 if (status) 1133 if (status)
1134 return status; 1134 return status;
1135 READ_BUF(16); 1135 READ_BUF(16);
1136 READ64(write->wr_offset); 1136 READ64(write->wr_offset);
1137 READ32(write->wr_stable_how); 1137 READ32(write->wr_stable_how);
1138 if (write->wr_stable_how > 2) 1138 if (write->wr_stable_how > 2)
1139 goto xdr_error; 1139 goto xdr_error;
1140 READ32(write->wr_buflen); 1140 READ32(write->wr_buflen);
1141 1141
1142 /* Sorry .. no magic macros for this.. * 1142 /* Sorry .. no magic macros for this.. *
1143 * READ_BUF(write->wr_buflen); 1143 * READ_BUF(write->wr_buflen);
1144 * SAVEMEM(write->wr_buf, write->wr_buflen); 1144 * SAVEMEM(write->wr_buf, write->wr_buflen);
1145 */ 1145 */
1146 avail = (char*)argp->end - (char*)argp->p; 1146 avail = (char*)argp->end - (char*)argp->p;
1147 if (avail + argp->pagelen < write->wr_buflen) { 1147 if (avail + argp->pagelen < write->wr_buflen) {
1148 dprintk("NFSD: xdr error (%s:%d)\n", 1148 dprintk("NFSD: xdr error (%s:%d)\n",
1149 __FILE__, __LINE__); 1149 __FILE__, __LINE__);
1150 goto xdr_error; 1150 goto xdr_error;
1151 } 1151 }
1152 write->wr_head.iov_base = p; 1152 write->wr_head.iov_base = p;
1153 write->wr_head.iov_len = avail; 1153 write->wr_head.iov_len = avail;
1154 WARN_ON(avail != (XDR_QUADLEN(avail) << 2)); 1154 WARN_ON(avail != (XDR_QUADLEN(avail) << 2));
1155 write->wr_pagelist = argp->pagelist; 1155 write->wr_pagelist = argp->pagelist;
1156 1156
1157 len = XDR_QUADLEN(write->wr_buflen) << 2; 1157 len = XDR_QUADLEN(write->wr_buflen) << 2;
1158 if (len >= avail) { 1158 if (len >= avail) {
1159 int pages; 1159 int pages;
1160 1160
1161 len -= avail; 1161 len -= avail;
1162 1162
1163 pages = len >> PAGE_SHIFT; 1163 pages = len >> PAGE_SHIFT;
1164 argp->pagelist += pages; 1164 argp->pagelist += pages;
1165 argp->pagelen -= pages * PAGE_SIZE; 1165 argp->pagelen -= pages * PAGE_SIZE;
1166 len -= pages * PAGE_SIZE; 1166 len -= pages * PAGE_SIZE;
1167 1167
1168 argp->p = (__be32 *)page_address(argp->pagelist[0]); 1168 argp->p = (__be32 *)page_address(argp->pagelist[0]);
1169 argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE); 1169 argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE);
1170 } 1170 }
1171 argp->p += XDR_QUADLEN(len); 1171 argp->p += XDR_QUADLEN(len);
1172 1172
1173 DECODE_TAIL; 1173 DECODE_TAIL;
1174 } 1174 }
1175 1175
1176 static __be32 1176 static __be32
1177 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner) 1177 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
1178 { 1178 {
1179 DECODE_HEAD; 1179 DECODE_HEAD;
1180 1180
1181 READ_BUF(12); 1181 READ_BUF(12);
1182 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t)); 1182 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
1183 READ32(rlockowner->rl_owner.len); 1183 READ32(rlockowner->rl_owner.len);
1184 READ_BUF(rlockowner->rl_owner.len); 1184 READ_BUF(rlockowner->rl_owner.len);
1185 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len); 1185 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
1186 1186
1187 if (argp->minorversion && !zero_clientid(&rlockowner->rl_clientid)) 1187 if (argp->minorversion && !zero_clientid(&rlockowner->rl_clientid))
1188 return nfserr_inval; 1188 return nfserr_inval;
1189 DECODE_TAIL; 1189 DECODE_TAIL;
1190 } 1190 }
1191 1191
1192 static __be32 1192 static __be32
1193 nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp, 1193 nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
1194 struct nfsd4_exchange_id *exid) 1194 struct nfsd4_exchange_id *exid)
1195 { 1195 {
1196 int dummy, tmp; 1196 int dummy, tmp;
1197 DECODE_HEAD; 1197 DECODE_HEAD;
1198 1198
1199 READ_BUF(NFS4_VERIFIER_SIZE); 1199 READ_BUF(NFS4_VERIFIER_SIZE);
1200 COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE); 1200 COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
1201 1201
1202 status = nfsd4_decode_opaque(argp, &exid->clname); 1202 status = nfsd4_decode_opaque(argp, &exid->clname);
1203 if (status) 1203 if (status)
1204 return nfserr_bad_xdr; 1204 return nfserr_bad_xdr;
1205 1205
1206 READ_BUF(4); 1206 READ_BUF(4);
1207 READ32(exid->flags); 1207 READ32(exid->flags);
1208 1208
1209 /* Ignore state_protect4_a */ 1209 /* Ignore state_protect4_a */
1210 READ_BUF(4); 1210 READ_BUF(4);
1211 READ32(exid->spa_how); 1211 READ32(exid->spa_how);
1212 switch (exid->spa_how) { 1212 switch (exid->spa_how) {
1213 case SP4_NONE: 1213 case SP4_NONE:
1214 break; 1214 break;
1215 case SP4_MACH_CRED: 1215 case SP4_MACH_CRED:
1216 /* spo_must_enforce */ 1216 /* spo_must_enforce */
1217 READ_BUF(4); 1217 READ_BUF(4);
1218 READ32(dummy); 1218 READ32(dummy);
1219 READ_BUF(dummy * 4); 1219 READ_BUF(dummy * 4);
1220 p += dummy; 1220 p += dummy;
1221 1221
1222 /* spo_must_allow */ 1222 /* spo_must_allow */
1223 READ_BUF(4); 1223 READ_BUF(4);
1224 READ32(dummy); 1224 READ32(dummy);
1225 READ_BUF(dummy * 4); 1225 READ_BUF(dummy * 4);
1226 p += dummy; 1226 p += dummy;
1227 break; 1227 break;
1228 case SP4_SSV: 1228 case SP4_SSV:
1229 /* ssp_ops */ 1229 /* ssp_ops */
1230 READ_BUF(4); 1230 READ_BUF(4);
1231 READ32(dummy); 1231 READ32(dummy);
1232 READ_BUF(dummy * 4); 1232 READ_BUF(dummy * 4);
1233 p += dummy; 1233 p += dummy;
1234 1234
1235 READ_BUF(4); 1235 READ_BUF(4);
1236 READ32(dummy); 1236 READ32(dummy);
1237 READ_BUF(dummy * 4); 1237 READ_BUF(dummy * 4);
1238 p += dummy; 1238 p += dummy;
1239 1239
1240 /* ssp_hash_algs<> */ 1240 /* ssp_hash_algs<> */
1241 READ_BUF(4); 1241 READ_BUF(4);
1242 READ32(tmp); 1242 READ32(tmp);
1243 while (tmp--) { 1243 while (tmp--) {
1244 READ_BUF(4); 1244 READ_BUF(4);
1245 READ32(dummy); 1245 READ32(dummy);
1246 READ_BUF(dummy); 1246 READ_BUF(dummy);
1247 p += XDR_QUADLEN(dummy); 1247 p += XDR_QUADLEN(dummy);
1248 } 1248 }
1249 1249
1250 /* ssp_encr_algs<> */ 1250 /* ssp_encr_algs<> */
1251 READ_BUF(4); 1251 READ_BUF(4);
1252 READ32(tmp); 1252 READ32(tmp);
1253 while (tmp--) { 1253 while (tmp--) {
1254 READ_BUF(4); 1254 READ_BUF(4);
1255 READ32(dummy); 1255 READ32(dummy);
1256 READ_BUF(dummy); 1256 READ_BUF(dummy);
1257 p += XDR_QUADLEN(dummy); 1257 p += XDR_QUADLEN(dummy);
1258 } 1258 }
1259 1259
1260 /* ssp_window and ssp_num_gss_handles */ 1260 /* ssp_window and ssp_num_gss_handles */
1261 READ_BUF(8); 1261 READ_BUF(8);
1262 READ32(dummy); 1262 READ32(dummy);
1263 READ32(dummy); 1263 READ32(dummy);
1264 break; 1264 break;
1265 default: 1265 default:
1266 goto xdr_error; 1266 goto xdr_error;
1267 } 1267 }
1268 1268
1269 /* Ignore Implementation ID */ 1269 /* Ignore Implementation ID */
1270 READ_BUF(4); /* nfs_impl_id4 array length */ 1270 READ_BUF(4); /* nfs_impl_id4 array length */
1271 READ32(dummy); 1271 READ32(dummy);
1272 1272
1273 if (dummy > 1) 1273 if (dummy > 1)
1274 goto xdr_error; 1274 goto xdr_error;
1275 1275
1276 if (dummy == 1) { 1276 if (dummy == 1) {
1277 /* nii_domain */ 1277 /* nii_domain */
1278 READ_BUF(4); 1278 READ_BUF(4);
1279 READ32(dummy); 1279 READ32(dummy);
1280 READ_BUF(dummy); 1280 READ_BUF(dummy);
1281 p += XDR_QUADLEN(dummy); 1281 p += XDR_QUADLEN(dummy);
1282 1282
1283 /* nii_name */ 1283 /* nii_name */
1284 READ_BUF(4); 1284 READ_BUF(4);
1285 READ32(dummy); 1285 READ32(dummy);
1286 READ_BUF(dummy); 1286 READ_BUF(dummy);
1287 p += XDR_QUADLEN(dummy); 1287 p += XDR_QUADLEN(dummy);
1288 1288
1289 /* nii_date */ 1289 /* nii_date */
1290 READ_BUF(12); 1290 READ_BUF(12);
1291 p += 3; 1291 p += 3;
1292 } 1292 }
1293 DECODE_TAIL; 1293 DECODE_TAIL;
1294 } 1294 }
1295 1295
1296 static __be32 1296 static __be32
1297 nfsd4_decode_create_session(struct nfsd4_compoundargs *argp, 1297 nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1298 struct nfsd4_create_session *sess) 1298 struct nfsd4_create_session *sess)
1299 { 1299 {
1300 DECODE_HEAD; 1300 DECODE_HEAD;
1301 u32 dummy; 1301 u32 dummy;
1302 1302
1303 READ_BUF(16); 1303 READ_BUF(16);
1304 COPYMEM(&sess->clientid, 8); 1304 COPYMEM(&sess->clientid, 8);
1305 READ32(sess->seqid); 1305 READ32(sess->seqid);
1306 READ32(sess->flags); 1306 READ32(sess->flags);
1307 1307
1308 /* Fore channel attrs */ 1308 /* Fore channel attrs */
1309 READ_BUF(28); 1309 READ_BUF(28);
1310 READ32(dummy); /* headerpadsz is always 0 */ 1310 READ32(dummy); /* headerpadsz is always 0 */
1311 READ32(sess->fore_channel.maxreq_sz); 1311 READ32(sess->fore_channel.maxreq_sz);
1312 READ32(sess->fore_channel.maxresp_sz); 1312 READ32(sess->fore_channel.maxresp_sz);
1313 READ32(sess->fore_channel.maxresp_cached); 1313 READ32(sess->fore_channel.maxresp_cached);
1314 READ32(sess->fore_channel.maxops); 1314 READ32(sess->fore_channel.maxops);
1315 READ32(sess->fore_channel.maxreqs); 1315 READ32(sess->fore_channel.maxreqs);
1316 READ32(sess->fore_channel.nr_rdma_attrs); 1316 READ32(sess->fore_channel.nr_rdma_attrs);
1317 if (sess->fore_channel.nr_rdma_attrs == 1) { 1317 if (sess->fore_channel.nr_rdma_attrs == 1) {
1318 READ_BUF(4); 1318 READ_BUF(4);
1319 READ32(sess->fore_channel.rdma_attrs); 1319 READ32(sess->fore_channel.rdma_attrs);
1320 } else if (sess->fore_channel.nr_rdma_attrs > 1) { 1320 } else if (sess->fore_channel.nr_rdma_attrs > 1) {
1321 dprintk("Too many fore channel attr bitmaps!\n"); 1321 dprintk("Too many fore channel attr bitmaps!\n");
1322 goto xdr_error; 1322 goto xdr_error;
1323 } 1323 }
1324 1324
1325 /* Back channel attrs */ 1325 /* Back channel attrs */
1326 READ_BUF(28); 1326 READ_BUF(28);
1327 READ32(dummy); /* headerpadsz is always 0 */ 1327 READ32(dummy); /* headerpadsz is always 0 */
1328 READ32(sess->back_channel.maxreq_sz); 1328 READ32(sess->back_channel.maxreq_sz);
1329 READ32(sess->back_channel.maxresp_sz); 1329 READ32(sess->back_channel.maxresp_sz);
1330 READ32(sess->back_channel.maxresp_cached); 1330 READ32(sess->back_channel.maxresp_cached);
1331 READ32(sess->back_channel.maxops); 1331 READ32(sess->back_channel.maxops);
1332 READ32(sess->back_channel.maxreqs); 1332 READ32(sess->back_channel.maxreqs);
1333 READ32(sess->back_channel.nr_rdma_attrs); 1333 READ32(sess->back_channel.nr_rdma_attrs);
1334 if (sess->back_channel.nr_rdma_attrs == 1) { 1334 if (sess->back_channel.nr_rdma_attrs == 1) {
1335 READ_BUF(4); 1335 READ_BUF(4);
1336 READ32(sess->back_channel.rdma_attrs); 1336 READ32(sess->back_channel.rdma_attrs);
1337 } else if (sess->back_channel.nr_rdma_attrs > 1) { 1337 } else if (sess->back_channel.nr_rdma_attrs > 1) {
1338 dprintk("Too many back channel attr bitmaps!\n"); 1338 dprintk("Too many back channel attr bitmaps!\n");
1339 goto xdr_error; 1339 goto xdr_error;
1340 } 1340 }
1341 1341
1342 READ_BUF(4); 1342 READ_BUF(4);
1343 READ32(sess->callback_prog); 1343 READ32(sess->callback_prog);
1344 nfsd4_decode_cb_sec(argp, &sess->cb_sec); 1344 nfsd4_decode_cb_sec(argp, &sess->cb_sec);
1345 DECODE_TAIL; 1345 DECODE_TAIL;
1346 } 1346 }
1347 1347
1348 static __be32 1348 static __be32
1349 nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp, 1349 nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
1350 struct nfsd4_destroy_session *destroy_session) 1350 struct nfsd4_destroy_session *destroy_session)
1351 { 1351 {
1352 DECODE_HEAD; 1352 DECODE_HEAD;
1353 READ_BUF(NFS4_MAX_SESSIONID_LEN); 1353 READ_BUF(NFS4_MAX_SESSIONID_LEN);
1354 COPYMEM(destroy_session->sessionid.data, NFS4_MAX_SESSIONID_LEN); 1354 COPYMEM(destroy_session->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1355 1355
1356 DECODE_TAIL; 1356 DECODE_TAIL;
1357 } 1357 }
1358 1358
1359 static __be32 1359 static __be32
1360 nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp, 1360 nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
1361 struct nfsd4_free_stateid *free_stateid) 1361 struct nfsd4_free_stateid *free_stateid)
1362 { 1362 {
1363 DECODE_HEAD; 1363 DECODE_HEAD;
1364 1364
1365 READ_BUF(sizeof(stateid_t)); 1365 READ_BUF(sizeof(stateid_t));
1366 READ32(free_stateid->fr_stateid.si_generation); 1366 READ32(free_stateid->fr_stateid.si_generation);
1367 COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t)); 1367 COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t));
1368 1368
1369 DECODE_TAIL; 1369 DECODE_TAIL;
1370 } 1370 }
1371 1371
1372 static __be32 1372 static __be32
1373 nfsd4_decode_sequence(struct nfsd4_compoundargs *argp, 1373 nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1374 struct nfsd4_sequence *seq) 1374 struct nfsd4_sequence *seq)
1375 { 1375 {
1376 DECODE_HEAD; 1376 DECODE_HEAD;
1377 1377
1378 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16); 1378 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
1379 COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN); 1379 COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1380 READ32(seq->seqid); 1380 READ32(seq->seqid);
1381 READ32(seq->slotid); 1381 READ32(seq->slotid);
1382 READ32(seq->maxslots); 1382 READ32(seq->maxslots);
1383 READ32(seq->cachethis); 1383 READ32(seq->cachethis);
1384 1384
1385 DECODE_TAIL; 1385 DECODE_TAIL;
1386 } 1386 }
1387 1387
1388 static __be32 1388 static __be32
1389 nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid) 1389 nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
1390 { 1390 {
1391 int i; 1391 int i;
1392 __be32 *p, status; 1392 __be32 *p, status;
1393 struct nfsd4_test_stateid_id *stateid; 1393 struct nfsd4_test_stateid_id *stateid;
1394 1394
1395 READ_BUF(4); 1395 READ_BUF(4);
1396 test_stateid->ts_num_ids = ntohl(*p++); 1396 test_stateid->ts_num_ids = ntohl(*p++);
1397 1397
1398 INIT_LIST_HEAD(&test_stateid->ts_stateid_list); 1398 INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
1399 1399
1400 for (i = 0; i < test_stateid->ts_num_ids; i++) { 1400 for (i = 0; i < test_stateid->ts_num_ids; i++) {
1401 stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL); 1401 stateid = kmalloc(sizeof(struct nfsd4_test_stateid_id), GFP_KERNEL);
1402 if (!stateid) { 1402 if (!stateid) {
1403 status = nfserrno(-ENOMEM); 1403 status = nfserrno(-ENOMEM);
1404 goto out; 1404 goto out;
1405 } 1405 }
1406 1406
1407 defer_free(argp, kfree, stateid); 1407 defer_free(argp, kfree, stateid);
1408 INIT_LIST_HEAD(&stateid->ts_id_list); 1408 INIT_LIST_HEAD(&stateid->ts_id_list);
1409 list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list); 1409 list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
1410 1410
1411 status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid); 1411 status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid);
1412 if (status) 1412 if (status)
1413 goto out; 1413 goto out;
1414 } 1414 }
1415 1415
1416 status = 0; 1416 status = 0;
1417 out: 1417 out:
1418 return status; 1418 return status;
1419 xdr_error: 1419 xdr_error:
1420 dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__); 1420 dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
1421 status = nfserr_bad_xdr; 1421 status = nfserr_bad_xdr;
1422 goto out; 1422 goto out;
1423 } 1423 }
1424 1424
1425 static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp, struct nfsd4_destroy_clientid *dc) 1425 static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp, struct nfsd4_destroy_clientid *dc)
1426 { 1426 {
1427 DECODE_HEAD; 1427 DECODE_HEAD;
1428 1428
1429 READ_BUF(8); 1429 READ_BUF(8);
1430 COPYMEM(&dc->clientid, 8); 1430 COPYMEM(&dc->clientid, 8);
1431 1431
1432 DECODE_TAIL; 1432 DECODE_TAIL;
1433 } 1433 }
1434 1434
1435 static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc) 1435 static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
1436 { 1436 {
1437 DECODE_HEAD; 1437 DECODE_HEAD;
1438 1438
1439 READ_BUF(4); 1439 READ_BUF(4);
1440 READ32(rc->rca_one_fs); 1440 READ32(rc->rca_one_fs);
1441 1441
1442 DECODE_TAIL; 1442 DECODE_TAIL;
1443 } 1443 }
1444 1444
1445 static __be32 1445 static __be32
1446 nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p) 1446 nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
1447 { 1447 {
1448 return nfs_ok; 1448 return nfs_ok;
1449 } 1449 }
1450 1450
1451 static __be32 1451 static __be32
1452 nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p) 1452 nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
1453 { 1453 {
1454 return nfserr_notsupp; 1454 return nfserr_notsupp;
1455 } 1455 }
1456 1456
1457 typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *); 1457 typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
1458 1458
1459 static nfsd4_dec nfsd4_dec_ops[] = { 1459 static nfsd4_dec nfsd4_dec_ops[] = {
1460 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access, 1460 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
1461 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close, 1461 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
1462 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit, 1462 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
1463 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create, 1463 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
1464 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp, 1464 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
1465 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn, 1465 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
1466 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr, 1466 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
1467 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop, 1467 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
1468 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link, 1468 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
1469 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock, 1469 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
1470 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt, 1470 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
1471 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku, 1471 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
1472 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup, 1472 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
1473 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop, 1473 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
1474 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1474 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1475 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open, 1475 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
1476 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp, 1476 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
1477 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm, 1477 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm,
1478 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade, 1478 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
1479 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh, 1479 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
1480 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_noop, 1480 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_noop,
1481 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop, 1481 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
1482 [OP_READ] = (nfsd4_dec)nfsd4_decode_read, 1482 [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
1483 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir, 1483 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
1484 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop, 1484 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
1485 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove, 1485 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
1486 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename, 1486 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
1487 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_renew, 1487 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_renew,
1488 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop, 1488 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
1489 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop, 1489 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
1490 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo, 1490 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
1491 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr, 1491 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
1492 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_setclientid, 1492 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_setclientid,
1493 [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm, 1493 [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
1494 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1494 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1495 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write, 1495 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
1496 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner, 1496 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner,
1497 }; 1497 };
1498 1498
1499 static nfsd4_dec nfsd41_dec_ops[] = { 1499 static nfsd4_dec nfsd41_dec_ops[] = {
1500 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access, 1500 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
1501 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close, 1501 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
1502 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit, 1502 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
1503 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create, 1503 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
1504 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp, 1504 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
1505 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn, 1505 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
1506 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr, 1506 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
1507 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop, 1507 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
1508 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link, 1508 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
1509 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock, 1509 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
1510 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt, 1510 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
1511 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku, 1511 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
1512 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup, 1512 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
1513 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop, 1513 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
1514 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1514 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1515 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open, 1515 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
1516 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp, 1516 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
1517 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_notsupp, 1517 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_notsupp,
1518 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade, 1518 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
1519 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh, 1519 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
1520 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_notsupp, 1520 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_notsupp,
1521 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop, 1521 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
1522 [OP_READ] = (nfsd4_dec)nfsd4_decode_read, 1522 [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
1523 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir, 1523 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
1524 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop, 1524 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
1525 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove, 1525 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
1526 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename, 1526 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
1527 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_notsupp, 1527 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_notsupp,
1528 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop, 1528 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
1529 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop, 1529 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
1530 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo, 1530 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
1531 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr, 1531 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
1532 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp, 1532 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_notsupp,
1533 [OP_SETCLIENTID_CONFIRM]= (nfsd4_dec)nfsd4_decode_notsupp, 1533 [OP_SETCLIENTID_CONFIRM]= (nfsd4_dec)nfsd4_decode_notsupp,
1534 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify, 1534 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1535 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write, 1535 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
1536 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_notsupp, 1536 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_notsupp,
1537 1537
1538 /* new operations for NFSv4.1 */ 1538 /* new operations for NFSv4.1 */
1539 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_backchannel_ctl, 1539 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_backchannel_ctl,
1540 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session, 1540 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
1541 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id, 1541 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
1542 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session, 1542 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
1543 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session, 1543 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
1544 [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_free_stateid, 1544 [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_free_stateid,
1545 [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp, 1545 [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1546 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp, 1546 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp,
1547 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp, 1547 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
1548 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp, 1548 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp,
1549 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp, 1549 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp,
1550 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp, 1550 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp,
1551 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name, 1551 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name,
1552 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence, 1552 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
1553 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp, 1553 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
1554 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_test_stateid, 1554 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_test_stateid,
1555 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp, 1555 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1556 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_destroy_clientid, 1556 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_destroy_clientid,
1557 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete, 1557 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete,
1558 }; 1558 };
1559 1559
1560 struct nfsd4_minorversion_ops { 1560 struct nfsd4_minorversion_ops {
1561 nfsd4_dec *decoders; 1561 nfsd4_dec *decoders;
1562 int nops; 1562 int nops;
1563 }; 1563 };
1564 1564
1565 static struct nfsd4_minorversion_ops nfsd4_minorversion[] = { 1565 static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
1566 [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) }, 1566 [0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
1567 [1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) }, 1567 [1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) },
1568 }; 1568 };
1569 1569
1570 static __be32 1570 static __be32
1571 nfsd4_decode_compound(struct nfsd4_compoundargs *argp) 1571 nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1572 { 1572 {
1573 DECODE_HEAD; 1573 DECODE_HEAD;
1574 struct nfsd4_op *op; 1574 struct nfsd4_op *op;
1575 struct nfsd4_minorversion_ops *ops; 1575 struct nfsd4_minorversion_ops *ops;
1576 bool cachethis = false; 1576 bool cachethis = false;
1577 int i; 1577 int i;
1578 1578
1579 READ_BUF(4); 1579 READ_BUF(4);
1580 READ32(argp->taglen); 1580 READ32(argp->taglen);
1581 READ_BUF(argp->taglen + 8); 1581 READ_BUF(argp->taglen + 8);
1582 SAVEMEM(argp->tag, argp->taglen); 1582 SAVEMEM(argp->tag, argp->taglen);
1583 READ32(argp->minorversion); 1583 READ32(argp->minorversion);
1584 READ32(argp->opcnt); 1584 READ32(argp->opcnt);
1585 1585
1586 if (argp->taglen > NFSD4_MAX_TAGLEN) 1586 if (argp->taglen > NFSD4_MAX_TAGLEN)
1587 goto xdr_error; 1587 goto xdr_error;
1588 if (argp->opcnt > 100) 1588 if (argp->opcnt > 100)
1589 goto xdr_error; 1589 goto xdr_error;
1590 1590
1591 if (argp->opcnt > ARRAY_SIZE(argp->iops)) { 1591 if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
1592 argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); 1592 argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
1593 if (!argp->ops) { 1593 if (!argp->ops) {
1594 argp->ops = argp->iops; 1594 argp->ops = argp->iops;
1595 dprintk("nfsd: couldn't allocate room for COMPOUND\n"); 1595 dprintk("nfsd: couldn't allocate room for COMPOUND\n");
1596 goto xdr_error; 1596 goto xdr_error;
1597 } 1597 }
1598 } 1598 }
1599 1599
1600 if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion)) 1600 if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion))
1601 argp->opcnt = 0; 1601 argp->opcnt = 0;
1602 1602
1603 ops = &nfsd4_minorversion[argp->minorversion]; 1603 ops = &nfsd4_minorversion[argp->minorversion];
1604 for (i = 0; i < argp->opcnt; i++) { 1604 for (i = 0; i < argp->opcnt; i++) {
1605 op = &argp->ops[i]; 1605 op = &argp->ops[i];
1606 op->replay = NULL; 1606 op->replay = NULL;
1607 1607
1608 READ_BUF(4); 1608 READ_BUF(4);
1609 READ32(op->opnum); 1609 READ32(op->opnum);
1610 1610
1611 if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP) 1611 if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
1612 op->status = ops->decoders[op->opnum](argp, &op->u); 1612 op->status = ops->decoders[op->opnum](argp, &op->u);
1613 else { 1613 else {
1614 op->opnum = OP_ILLEGAL; 1614 op->opnum = OP_ILLEGAL;
1615 op->status = nfserr_op_illegal; 1615 op->status = nfserr_op_illegal;
1616 } 1616 }
1617 1617
1618 if (op->status) { 1618 if (op->status) {
1619 argp->opcnt = i+1; 1619 argp->opcnt = i+1;
1620 break; 1620 break;
1621 } 1621 }
1622 /* 1622 /*
1623 * We'll try to cache the result in the DRC if any one 1623 * We'll try to cache the result in the DRC if any one
1624 * op in the compound wants to be cached: 1624 * op in the compound wants to be cached:
1625 */ 1625 */
1626 cachethis |= nfsd4_cache_this_op(op); 1626 cachethis |= nfsd4_cache_this_op(op);
1627 } 1627 }
1628 /* Sessions make the DRC unnecessary: */ 1628 /* Sessions make the DRC unnecessary: */
1629 if (argp->minorversion) 1629 if (argp->minorversion)
1630 cachethis = false; 1630 cachethis = false;
1631 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; 1631 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
1632 1632
1633 DECODE_TAIL; 1633 DECODE_TAIL;
1634 } 1634 }
1635 1635
1636 #define WRITE32(n) *p++ = htonl(n) 1636 #define WRITE32(n) *p++ = htonl(n)
1637 #define WRITE64(n) do { \ 1637 #define WRITE64(n) do { \
1638 *p++ = htonl((u32)((n) >> 32)); \ 1638 *p++ = htonl((u32)((n) >> 32)); \
1639 *p++ = htonl((u32)(n)); \ 1639 *p++ = htonl((u32)(n)); \
1640 } while (0) 1640 } while (0)
1641 #define WRITEMEM(ptr,nbytes) do { if (nbytes > 0) { \ 1641 #define WRITEMEM(ptr,nbytes) do { if (nbytes > 0) { \
1642 *(p + XDR_QUADLEN(nbytes) -1) = 0; \ 1642 *(p + XDR_QUADLEN(nbytes) -1) = 0; \
1643 memcpy(p, ptr, nbytes); \ 1643 memcpy(p, ptr, nbytes); \
1644 p += XDR_QUADLEN(nbytes); \ 1644 p += XDR_QUADLEN(nbytes); \
1645 }} while (0) 1645 }} while (0)
1646 1646
1647 static void write32(__be32 **p, u32 n) 1647 static void write32(__be32 **p, u32 n)
1648 { 1648 {
1649 *(*p)++ = htonl(n); 1649 *(*p)++ = htonl(n);
1650 } 1650 }
1651 1651
1652 static void write64(__be32 **p, u64 n) 1652 static void write64(__be32 **p, u64 n)
1653 { 1653 {
1654 write32(p, (n >> 32)); 1654 write32(p, (n >> 32));
1655 write32(p, (u32)n); 1655 write32(p, (u32)n);
1656 } 1656 }
1657 1657
1658 static void write_change(__be32 **p, struct kstat *stat, struct inode *inode) 1658 static void write_change(__be32 **p, struct kstat *stat, struct inode *inode)
1659 { 1659 {
1660 if (IS_I_VERSION(inode)) { 1660 if (IS_I_VERSION(inode)) {
1661 write64(p, inode->i_version); 1661 write64(p, inode->i_version);
1662 } else { 1662 } else {
1663 write32(p, stat->ctime.tv_sec); 1663 write32(p, stat->ctime.tv_sec);
1664 write32(p, stat->ctime.tv_nsec); 1664 write32(p, stat->ctime.tv_nsec);
1665 } 1665 }
1666 } 1666 }
1667 1667
1668 static void write_cinfo(__be32 **p, struct nfsd4_change_info *c) 1668 static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
1669 { 1669 {
1670 write32(p, c->atomic); 1670 write32(p, c->atomic);
1671 if (c->change_supported) { 1671 if (c->change_supported) {
1672 write64(p, c->before_change); 1672 write64(p, c->before_change);
1673 write64(p, c->after_change); 1673 write64(p, c->after_change);
1674 } else { 1674 } else {
1675 write32(p, c->before_ctime_sec); 1675 write32(p, c->before_ctime_sec);
1676 write32(p, c->before_ctime_nsec); 1676 write32(p, c->before_ctime_nsec);
1677 write32(p, c->after_ctime_sec); 1677 write32(p, c->after_ctime_sec);
1678 write32(p, c->after_ctime_nsec); 1678 write32(p, c->after_ctime_nsec);
1679 } 1679 }
1680 } 1680 }
1681 1681
1682 #define RESERVE_SPACE(nbytes) do { \ 1682 #define RESERVE_SPACE(nbytes) do { \
1683 p = resp->p; \ 1683 p = resp->p; \
1684 BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end); \ 1684 BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end); \
1685 } while (0) 1685 } while (0)
1686 #define ADJUST_ARGS() resp->p = p 1686 #define ADJUST_ARGS() resp->p = p
1687 1687
1688 /* 1688 /*
1689 * Header routine to setup seqid operation replay cache 1689 * Header routine to setup seqid operation replay cache
1690 */ 1690 */
1691 #define ENCODE_SEQID_OP_HEAD \ 1691 #define ENCODE_SEQID_OP_HEAD \
1692 __be32 *save; \ 1692 __be32 *save; \
1693 \ 1693 \
1694 save = resp->p; 1694 save = resp->p;
1695 1695
1696 /* 1696 /*
1697 * Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This 1697 * Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This
1698 * is where sequence id's are incremented, and the replay cache is filled. 1698 * is where sequence id's are incremented, and the replay cache is filled.
1699 * Note that we increment sequence id's here, at the last moment, so we're sure 1699 * Note that we increment sequence id's here, at the last moment, so we're sure
1700 * we know whether the error to be returned is a sequence id mutating error. 1700 * we know whether the error to be returned is a sequence id mutating error.
1701 */ 1701 */
1702 1702
1703 static void encode_seqid_op_tail(struct nfsd4_compoundres *resp, __be32 *save, __be32 nfserr) 1703 static void encode_seqid_op_tail(struct nfsd4_compoundres *resp, __be32 *save, __be32 nfserr)
1704 { 1704 {
1705 struct nfs4_stateowner *stateowner = resp->cstate.replay_owner; 1705 struct nfs4_stateowner *stateowner = resp->cstate.replay_owner;
1706 1706
1707 if (seqid_mutating_err(ntohl(nfserr)) && stateowner) { 1707 if (seqid_mutating_err(ntohl(nfserr)) && stateowner) {
1708 stateowner->so_seqid++; 1708 stateowner->so_seqid++;
1709 stateowner->so_replay.rp_status = nfserr; 1709 stateowner->so_replay.rp_status = nfserr;
1710 stateowner->so_replay.rp_buflen = 1710 stateowner->so_replay.rp_buflen =
1711 (char *)resp->p - (char *)save; 1711 (char *)resp->p - (char *)save;
1712 memcpy(stateowner->so_replay.rp_buf, save, 1712 memcpy(stateowner->so_replay.rp_buf, save,
1713 stateowner->so_replay.rp_buflen); 1713 stateowner->so_replay.rp_buflen);
1714 nfsd4_purge_closed_stateid(stateowner); 1714 nfsd4_purge_closed_stateid(stateowner);
1715 } 1715 }
1716 } 1716 }
1717 1717
1718 /* Encode as an array of strings the string given with components 1718 /* Encode as an array of strings the string given with components
1719 * separated @sep, escaped with esc_enter and esc_exit. 1719 * separated @sep, escaped with esc_enter and esc_exit.
1720 */ 1720 */
1721 static __be32 nfsd4_encode_components_esc(char sep, char *components, 1721 static __be32 nfsd4_encode_components_esc(char sep, char *components,
1722 __be32 **pp, int *buflen, 1722 __be32 **pp, int *buflen,
1723 char esc_enter, char esc_exit) 1723 char esc_enter, char esc_exit)
1724 { 1724 {
1725 __be32 *p = *pp; 1725 __be32 *p = *pp;
1726 __be32 *countp = p; 1726 __be32 *countp = p;
1727 int strlen, count=0; 1727 int strlen, count=0;
1728 char *str, *end, *next; 1728 char *str, *end, *next;
1729 1729
1730 dprintk("nfsd4_encode_components(%s)\n", components); 1730 dprintk("nfsd4_encode_components(%s)\n", components);
1731 if ((*buflen -= 4) < 0) 1731 if ((*buflen -= 4) < 0)
1732 return nfserr_resource; 1732 return nfserr_resource;
1733 WRITE32(0); /* We will fill this in with @count later */ 1733 WRITE32(0); /* We will fill this in with @count later */
1734 end = str = components; 1734 end = str = components;
1735 while (*end) { 1735 while (*end) {
1736 bool found_esc = false; 1736 bool found_esc = false;
1737 1737
1738 /* try to parse as esc_start, ..., esc_end, sep */ 1738 /* try to parse as esc_start, ..., esc_end, sep */
1739 if (*str == esc_enter) { 1739 if (*str == esc_enter) {
1740 for (; *end && (*end != esc_exit); end++) 1740 for (; *end && (*end != esc_exit); end++)
1741 /* find esc_exit or end of string */; 1741 /* find esc_exit or end of string */;
1742 next = end + 1; 1742 next = end + 1;
1743 if (*end && (!*next || *next == sep)) { 1743 if (*end && (!*next || *next == sep)) {
1744 str++; 1744 str++;
1745 found_esc = true; 1745 found_esc = true;
1746 } 1746 }
1747 } 1747 }
1748 1748
1749 if (!found_esc) 1749 if (!found_esc)
1750 for (; *end && (*end != sep); end++) 1750 for (; *end && (*end != sep); end++)
1751 /* find sep or end of string */; 1751 /* find sep or end of string */;
1752 1752
1753 strlen = end - str; 1753 strlen = end - str;
1754 if (strlen) { 1754 if (strlen) {
1755 if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0) 1755 if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0)
1756 return nfserr_resource; 1756 return nfserr_resource;
1757 WRITE32(strlen); 1757 WRITE32(strlen);
1758 WRITEMEM(str, strlen); 1758 WRITEMEM(str, strlen);
1759 count++; 1759 count++;
1760 } 1760 }
1761 else 1761 else
1762 end++; 1762 end++;
1763 str = end; 1763 str = end;
1764 } 1764 }
1765 *pp = p; 1765 *pp = p;
1766 p = countp; 1766 p = countp;
1767 WRITE32(count); 1767 WRITE32(count);
1768 return 0; 1768 return 0;
1769 } 1769 }
1770 1770
1771 /* Encode as an array of strings the string given with components 1771 /* Encode as an array of strings the string given with components
1772 * separated @sep. 1772 * separated @sep.
1773 */ 1773 */
1774 static __be32 nfsd4_encode_components(char sep, char *components, 1774 static __be32 nfsd4_encode_components(char sep, char *components,
1775 __be32 **pp, int *buflen) 1775 __be32 **pp, int *buflen)
1776 { 1776 {
1777 return nfsd4_encode_components_esc(sep, components, pp, buflen, 0, 0); 1777 return nfsd4_encode_components_esc(sep, components, pp, buflen, 0, 0);
1778 } 1778 }
1779 1779
1780 /* 1780 /*
1781 * encode a location element of a fs_locations structure 1781 * encode a location element of a fs_locations structure
1782 */ 1782 */
1783 static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, 1783 static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
1784 __be32 **pp, int *buflen) 1784 __be32 **pp, int *buflen)
1785 { 1785 {
1786 __be32 status; 1786 __be32 status;
1787 __be32 *p = *pp; 1787 __be32 *p = *pp;
1788 1788
1789 status = nfsd4_encode_components_esc(':', location->hosts, &p, buflen, 1789 status = nfsd4_encode_components_esc(':', location->hosts, &p, buflen,
1790 '[', ']'); 1790 '[', ']');
1791 if (status) 1791 if (status)
1792 return status; 1792 return status;
1793 status = nfsd4_encode_components('/', location->path, &p, buflen); 1793 status = nfsd4_encode_components('/', location->path, &p, buflen);
1794 if (status) 1794 if (status)
1795 return status; 1795 return status;
1796 *pp = p; 1796 *pp = p;
1797 return 0; 1797 return 0;
1798 } 1798 }
1799 1799
1800 /* 1800 /*
1801 * Encode a path in RFC3530 'pathname4' format 1801 * Encode a path in RFC3530 'pathname4' format
1802 */ 1802 */
1803 static __be32 nfsd4_encode_path(const struct path *root, 1803 static __be32 nfsd4_encode_path(const struct path *root,
1804 const struct path *path, __be32 **pp, int *buflen) 1804 const struct path *path, __be32 **pp, int *buflen)
1805 { 1805 {
1806 struct path cur = { 1806 struct path cur = {
1807 .mnt = path->mnt, 1807 .mnt = path->mnt,
1808 .dentry = path->dentry, 1808 .dentry = path->dentry,
1809 }; 1809 };
1810 __be32 *p = *pp; 1810 __be32 *p = *pp;
1811 struct dentry **components = NULL; 1811 struct dentry **components = NULL;
1812 unsigned int ncomponents = 0; 1812 unsigned int ncomponents = 0;
1813 __be32 err = nfserr_jukebox; 1813 __be32 err = nfserr_jukebox;
1814 1814
1815 dprintk("nfsd4_encode_components("); 1815 dprintk("nfsd4_encode_components(");
1816 1816
1817 path_get(&cur); 1817 path_get(&cur);
1818 /* First walk the path up to the nfsd root, and store the 1818 /* First walk the path up to the nfsd root, and store the
1819 * dentries/path components in an array. 1819 * dentries/path components in an array.
1820 */ 1820 */
1821 for (;;) { 1821 for (;;) {
1822 if (cur.dentry == root->dentry && cur.mnt == root->mnt) 1822 if (cur.dentry == root->dentry && cur.mnt == root->mnt)
1823 break; 1823 break;
1824 if (cur.dentry == cur.mnt->mnt_root) { 1824 if (cur.dentry == cur.mnt->mnt_root) {
1825 if (follow_up(&cur)) 1825 if (follow_up(&cur))
1826 continue; 1826 continue;
1827 goto out_free; 1827 goto out_free;
1828 } 1828 }
1829 if ((ncomponents & 15) == 0) { 1829 if ((ncomponents & 15) == 0) {
1830 struct dentry **new; 1830 struct dentry **new;
1831 new = krealloc(components, 1831 new = krealloc(components,
1832 sizeof(*new) * (ncomponents + 16), 1832 sizeof(*new) * (ncomponents + 16),
1833 GFP_KERNEL); 1833 GFP_KERNEL);
1834 if (!new) 1834 if (!new)
1835 goto out_free; 1835 goto out_free;
1836 components = new; 1836 components = new;
1837 } 1837 }
1838 components[ncomponents++] = cur.dentry; 1838 components[ncomponents++] = cur.dentry;
1839 cur.dentry = dget_parent(cur.dentry); 1839 cur.dentry = dget_parent(cur.dentry);
1840 } 1840 }
1841 1841
1842 *buflen -= 4; 1842 *buflen -= 4;
1843 if (*buflen < 0) 1843 if (*buflen < 0)
1844 goto out_free; 1844 goto out_free;
1845 WRITE32(ncomponents); 1845 WRITE32(ncomponents);
1846 1846
1847 while (ncomponents) { 1847 while (ncomponents) {
1848 struct dentry *dentry = components[ncomponents - 1]; 1848 struct dentry *dentry = components[ncomponents - 1];
1849 unsigned int len = dentry->d_name.len; 1849 unsigned int len = dentry->d_name.len;
1850 1850
1851 *buflen -= 4 + (XDR_QUADLEN(len) << 2); 1851 *buflen -= 4 + (XDR_QUADLEN(len) << 2);
1852 if (*buflen < 0) 1852 if (*buflen < 0)
1853 goto out_free; 1853 goto out_free;
1854 WRITE32(len); 1854 WRITE32(len);
1855 WRITEMEM(dentry->d_name.name, len); 1855 WRITEMEM(dentry->d_name.name, len);
1856 dprintk("/%s", dentry->d_name.name); 1856 dprintk("/%s", dentry->d_name.name);
1857 dput(dentry); 1857 dput(dentry);
1858 ncomponents--; 1858 ncomponents--;
1859 } 1859 }
1860 1860
1861 *pp = p; 1861 *pp = p;
1862 err = 0; 1862 err = 0;
1863 out_free: 1863 out_free:
1864 dprintk(")\n"); 1864 dprintk(")\n");
1865 while (ncomponents) 1865 while (ncomponents)
1866 dput(components[--ncomponents]); 1866 dput(components[--ncomponents]);
1867 kfree(components); 1867 kfree(components);
1868 path_put(&cur); 1868 path_put(&cur);
1869 return err; 1869 return err;
1870 } 1870 }
1871 1871
1872 static __be32 nfsd4_encode_fsloc_fsroot(struct svc_rqst *rqstp, 1872 static __be32 nfsd4_encode_fsloc_fsroot(struct svc_rqst *rqstp,
1873 const struct path *path, __be32 **pp, int *buflen) 1873 const struct path *path, __be32 **pp, int *buflen)
1874 { 1874 {
1875 struct svc_export *exp_ps; 1875 struct svc_export *exp_ps;
1876 __be32 res; 1876 __be32 res;
1877 1877
1878 exp_ps = rqst_find_fsidzero_export(rqstp); 1878 exp_ps = rqst_find_fsidzero_export(rqstp);
1879 if (IS_ERR(exp_ps)) 1879 if (IS_ERR(exp_ps))
1880 return nfserrno(PTR_ERR(exp_ps)); 1880 return nfserrno(PTR_ERR(exp_ps));
1881 res = nfsd4_encode_path(&exp_ps->ex_path, path, pp, buflen); 1881 res = nfsd4_encode_path(&exp_ps->ex_path, path, pp, buflen);
1882 exp_put(exp_ps); 1882 exp_put(exp_ps);
1883 return res; 1883 return res;
1884 } 1884 }
1885 1885
1886 /* 1886 /*
1887 * encode a fs_locations structure 1887 * encode a fs_locations structure
1888 */ 1888 */
1889 static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp, 1889 static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
1890 struct svc_export *exp, 1890 struct svc_export *exp,
1891 __be32 **pp, int *buflen) 1891 __be32 **pp, int *buflen)
1892 { 1892 {
1893 __be32 status; 1893 __be32 status;
1894 int i; 1894 int i;
1895 __be32 *p = *pp; 1895 __be32 *p = *pp;
1896 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; 1896 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
1897 1897
1898 status = nfsd4_encode_fsloc_fsroot(rqstp, &exp->ex_path, &p, buflen); 1898 status = nfsd4_encode_fsloc_fsroot(rqstp, &exp->ex_path, &p, buflen);
1899 if (status) 1899 if (status)
1900 return status; 1900 return status;
1901 if ((*buflen -= 4) < 0) 1901 if ((*buflen -= 4) < 0)
1902 return nfserr_resource; 1902 return nfserr_resource;
1903 WRITE32(fslocs->locations_count); 1903 WRITE32(fslocs->locations_count);
1904 for (i=0; i<fslocs->locations_count; i++) { 1904 for (i=0; i<fslocs->locations_count; i++) {
1905 status = nfsd4_encode_fs_location4(&fslocs->locations[i], 1905 status = nfsd4_encode_fs_location4(&fslocs->locations[i],
1906 &p, buflen); 1906 &p, buflen);
1907 if (status) 1907 if (status)
1908 return status; 1908 return status;
1909 } 1909 }
1910 *pp = p; 1910 *pp = p;
1911 return 0; 1911 return 0;
1912 } 1912 }
1913 1913
1914 static u32 nfs4_file_type(umode_t mode) 1914 static u32 nfs4_file_type(umode_t mode)
1915 { 1915 {
1916 switch (mode & S_IFMT) { 1916 switch (mode & S_IFMT) {
1917 case S_IFIFO: return NF4FIFO; 1917 case S_IFIFO: return NF4FIFO;
1918 case S_IFCHR: return NF4CHR; 1918 case S_IFCHR: return NF4CHR;
1919 case S_IFDIR: return NF4DIR; 1919 case S_IFDIR: return NF4DIR;
1920 case S_IFBLK: return NF4BLK; 1920 case S_IFBLK: return NF4BLK;
1921 case S_IFLNK: return NF4LNK; 1921 case S_IFLNK: return NF4LNK;
1922 case S_IFREG: return NF4REG; 1922 case S_IFREG: return NF4REG;
1923 case S_IFSOCK: return NF4SOCK; 1923 case S_IFSOCK: return NF4SOCK;
1924 default: return NF4BAD; 1924 default: return NF4BAD;
1925 }; 1925 };
1926 } 1926 }
1927 1927
1928 static __be32 1928 static __be32
1929 nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group, 1929 nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1930 __be32 **p, int *buflen) 1930 __be32 **p, int *buflen)
1931 { 1931 {
1932 int status; 1932 int status;
1933 1933
1934 if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4) 1934 if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1935 return nfserr_resource; 1935 return nfserr_resource;
1936 if (whotype != NFS4_ACL_WHO_NAMED) 1936 if (whotype != NFS4_ACL_WHO_NAMED)
1937 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1)); 1937 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
1938 else if (group) 1938 else if (group)
1939 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1)); 1939 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
1940 else 1940 else
1941 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1)); 1941 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
1942 if (status < 0) 1942 if (status < 0)
1943 return nfserrno(status); 1943 return nfserrno(status);
1944 *p = xdr_encode_opaque(*p, NULL, status); 1944 *p = xdr_encode_opaque(*p, NULL, status);
1945 *buflen -= (XDR_QUADLEN(status) << 2) + 4; 1945 *buflen -= (XDR_QUADLEN(status) << 2) + 4;
1946 BUG_ON(*buflen < 0); 1946 BUG_ON(*buflen < 0);
1947 return 0; 1947 return 0;
1948 } 1948 }
1949 1949
1950 static inline __be32 1950 static inline __be32
1951 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen) 1951 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen)
1952 { 1952 {
1953 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen); 1953 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
1954 } 1954 }
1955 1955
1956 static inline __be32 1956 static inline __be32
1957 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen) 1957 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen)
1958 { 1958 {
1959 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen); 1959 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
1960 } 1960 }
1961 1961
1962 static inline __be32 1962 static inline __be32
1963 nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group, 1963 nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1964 __be32 **p, int *buflen) 1964 __be32 **p, int *buflen)
1965 { 1965 {
1966 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen); 1966 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
1967 } 1967 }
1968 1968
1969 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ 1969 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
1970 FATTR4_WORD0_RDATTR_ERROR) 1970 FATTR4_WORD0_RDATTR_ERROR)
1971 #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID 1971 #define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
1972 1972
1973 static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) 1973 static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
1974 { 1974 {
1975 /* As per referral draft: */ 1975 /* As per referral draft: */
1976 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS || 1976 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
1977 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) { 1977 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
1978 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR || 1978 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
1979 *bmval0 & FATTR4_WORD0_FS_LOCATIONS) 1979 *bmval0 & FATTR4_WORD0_FS_LOCATIONS)
1980 *rdattr_err = NFSERR_MOVED; 1980 *rdattr_err = NFSERR_MOVED;
1981 else 1981 else
1982 return nfserr_moved; 1982 return nfserr_moved;
1983 } 1983 }
1984 *bmval0 &= WORD0_ABSENT_FS_ATTRS; 1984 *bmval0 &= WORD0_ABSENT_FS_ATTRS;
1985 *bmval1 &= WORD1_ABSENT_FS_ATTRS; 1985 *bmval1 &= WORD1_ABSENT_FS_ATTRS;
1986 return 0; 1986 return 0;
1987 } 1987 }
1988 1988
1989 1989
1990 static int get_parent_attributes(struct svc_export *exp, struct kstat *stat) 1990 static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
1991 { 1991 {
1992 struct path path = exp->ex_path; 1992 struct path path = exp->ex_path;
1993 int err; 1993 int err;
1994 1994
1995 path_get(&path); 1995 path_get(&path);
1996 while (follow_up(&path)) { 1996 while (follow_up(&path)) {
1997 if (path.dentry != path.mnt->mnt_root) 1997 if (path.dentry != path.mnt->mnt_root)
1998 break; 1998 break;
1999 } 1999 }
2000 err = vfs_getattr(path.mnt, path.dentry, stat); 2000 err = vfs_getattr(path.mnt, path.dentry, stat);
2001 path_put(&path); 2001 path_put(&path);
2002 return err; 2002 return err;
2003 } 2003 }
2004 2004
2005 /* 2005 /*
2006 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle 2006 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
2007 * ourselves. 2007 * ourselves.
2008 * 2008 *
2009 * @countp is the buffer size in _words_; upon successful return this becomes 2009 * countp is the buffer size in _words_
2010 * replaced with the number of words written.
2011 */ 2010 */
2012 __be32 2011 __be32
2013 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 2012 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
2014 struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, 2013 struct dentry *dentry, __be32 **buffer, int count, u32 *bmval,
2015 struct svc_rqst *rqstp, int ignore_crossmnt) 2014 struct svc_rqst *rqstp, int ignore_crossmnt)
2016 { 2015 {
2017 u32 bmval0 = bmval[0]; 2016 u32 bmval0 = bmval[0];
2018 u32 bmval1 = bmval[1]; 2017 u32 bmval1 = bmval[1];
2019 u32 bmval2 = bmval[2]; 2018 u32 bmval2 = bmval[2];
2020 struct kstat stat; 2019 struct kstat stat;
2021 struct svc_fh tempfh; 2020 struct svc_fh tempfh;
2022 struct kstatfs statfs; 2021 struct kstatfs statfs;
2023 int buflen = *countp << 2; 2022 int buflen = count << 2;
2024 __be32 *attrlenp; 2023 __be32 *attrlenp;
2025 u32 dummy; 2024 u32 dummy;
2026 u64 dummy64; 2025 u64 dummy64;
2027 u32 rdattr_err = 0; 2026 u32 rdattr_err = 0;
2028 __be32 *p = buffer; 2027 __be32 *p = *buffer;
2029 __be32 status; 2028 __be32 status;
2030 int err; 2029 int err;
2031 int aclsupport = 0; 2030 int aclsupport = 0;
2032 struct nfs4_acl *acl = NULL; 2031 struct nfs4_acl *acl = NULL;
2033 struct nfsd4_compoundres *resp = rqstp->rq_resp; 2032 struct nfsd4_compoundres *resp = rqstp->rq_resp;
2034 u32 minorversion = resp->cstate.minorversion; 2033 u32 minorversion = resp->cstate.minorversion;
2035 struct path path = { 2034 struct path path = {
2036 .mnt = exp->ex_path.mnt, 2035 .mnt = exp->ex_path.mnt,
2037 .dentry = dentry, 2036 .dentry = dentry,
2038 }; 2037 };
2039 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 2038 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2040 2039
2041 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); 2040 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
2042 BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion)); 2041 BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
2043 BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion)); 2042 BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
2044 BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion)); 2043 BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
2045 2044
2046 if (exp->ex_fslocs.migrated) { 2045 if (exp->ex_fslocs.migrated) {
2047 BUG_ON(bmval[2]); 2046 BUG_ON(bmval[2]);
2048 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err); 2047 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
2049 if (status) 2048 if (status)
2050 goto out; 2049 goto out;
2051 } 2050 }
2052 2051
2053 err = vfs_getattr(exp->ex_path.mnt, dentry, &stat); 2052 err = vfs_getattr(exp->ex_path.mnt, dentry, &stat);
2054 if (err) 2053 if (err)
2055 goto out_nfserr; 2054 goto out_nfserr;
2056 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | 2055 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL |
2057 FATTR4_WORD0_MAXNAME)) || 2056 FATTR4_WORD0_MAXNAME)) ||
2058 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | 2057 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
2059 FATTR4_WORD1_SPACE_TOTAL))) { 2058 FATTR4_WORD1_SPACE_TOTAL))) {
2060 err = vfs_statfs(&path, &statfs); 2059 err = vfs_statfs(&path, &statfs);
2061 if (err) 2060 if (err)
2062 goto out_nfserr; 2061 goto out_nfserr;
2063 } 2062 }
2064 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { 2063 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
2065 fh_init(&tempfh, NFS4_FHSIZE); 2064 fh_init(&tempfh, NFS4_FHSIZE);
2066 status = fh_compose(&tempfh, exp, dentry, NULL); 2065 status = fh_compose(&tempfh, exp, dentry, NULL);
2067 if (status) 2066 if (status)
2068 goto out; 2067 goto out;
2069 fhp = &tempfh; 2068 fhp = &tempfh;
2070 } 2069 }
2071 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT 2070 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
2072 | FATTR4_WORD0_SUPPORTED_ATTRS)) { 2071 | FATTR4_WORD0_SUPPORTED_ATTRS)) {
2073 err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl); 2072 err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
2074 aclsupport = (err == 0); 2073 aclsupport = (err == 0);
2075 if (bmval0 & FATTR4_WORD0_ACL) { 2074 if (bmval0 & FATTR4_WORD0_ACL) {
2076 if (err == -EOPNOTSUPP) 2075 if (err == -EOPNOTSUPP)
2077 bmval0 &= ~FATTR4_WORD0_ACL; 2076 bmval0 &= ~FATTR4_WORD0_ACL;
2078 else if (err == -EINVAL) { 2077 else if (err == -EINVAL) {
2079 status = nfserr_attrnotsupp; 2078 status = nfserr_attrnotsupp;
2080 goto out; 2079 goto out;
2081 } else if (err != 0) 2080 } else if (err != 0)
2082 goto out_nfserr; 2081 goto out_nfserr;
2083 } 2082 }
2084 } 2083 }
2085 2084
2086 if (bmval2) { 2085 if (bmval2) {
2087 if ((buflen -= 16) < 0) 2086 if ((buflen -= 16) < 0)
2088 goto out_resource; 2087 goto out_resource;
2089 WRITE32(3); 2088 WRITE32(3);
2090 WRITE32(bmval0); 2089 WRITE32(bmval0);
2091 WRITE32(bmval1); 2090 WRITE32(bmval1);
2092 WRITE32(bmval2); 2091 WRITE32(bmval2);
2093 } else if (bmval1) { 2092 } else if (bmval1) {
2094 if ((buflen -= 12) < 0) 2093 if ((buflen -= 12) < 0)
2095 goto out_resource; 2094 goto out_resource;
2096 WRITE32(2); 2095 WRITE32(2);
2097 WRITE32(bmval0); 2096 WRITE32(bmval0);
2098 WRITE32(bmval1); 2097 WRITE32(bmval1);
2099 } else { 2098 } else {
2100 if ((buflen -= 8) < 0) 2099 if ((buflen -= 8) < 0)
2101 goto out_resource; 2100 goto out_resource;
2102 WRITE32(1); 2101 WRITE32(1);
2103 WRITE32(bmval0); 2102 WRITE32(bmval0);
2104 } 2103 }
2105 attrlenp = p++; /* to be backfilled later */ 2104 attrlenp = p++; /* to be backfilled later */
2106 2105
2107 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 2106 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
2108 u32 word0 = nfsd_suppattrs0(minorversion); 2107 u32 word0 = nfsd_suppattrs0(minorversion);
2109 u32 word1 = nfsd_suppattrs1(minorversion); 2108 u32 word1 = nfsd_suppattrs1(minorversion);
2110 u32 word2 = nfsd_suppattrs2(minorversion); 2109 u32 word2 = nfsd_suppattrs2(minorversion);
2111 2110
2112 if (!aclsupport) 2111 if (!aclsupport)
2113 word0 &= ~FATTR4_WORD0_ACL; 2112 word0 &= ~FATTR4_WORD0_ACL;
2114 if (!word2) { 2113 if (!word2) {
2115 if ((buflen -= 12) < 0) 2114 if ((buflen -= 12) < 0)
2116 goto out_resource; 2115 goto out_resource;
2117 WRITE32(2); 2116 WRITE32(2);
2118 WRITE32(word0); 2117 WRITE32(word0);
2119 WRITE32(word1); 2118 WRITE32(word1);
2120 } else { 2119 } else {
2121 if ((buflen -= 16) < 0) 2120 if ((buflen -= 16) < 0)
2122 goto out_resource; 2121 goto out_resource;
2123 WRITE32(3); 2122 WRITE32(3);
2124 WRITE32(word0); 2123 WRITE32(word0);
2125 WRITE32(word1); 2124 WRITE32(word1);
2126 WRITE32(word2); 2125 WRITE32(word2);
2127 } 2126 }
2128 } 2127 }
2129 if (bmval0 & FATTR4_WORD0_TYPE) { 2128 if (bmval0 & FATTR4_WORD0_TYPE) {
2130 if ((buflen -= 4) < 0) 2129 if ((buflen -= 4) < 0)
2131 goto out_resource; 2130 goto out_resource;
2132 dummy = nfs4_file_type(stat.mode); 2131 dummy = nfs4_file_type(stat.mode);
2133 if (dummy == NF4BAD) 2132 if (dummy == NF4BAD)
2134 goto out_serverfault; 2133 goto out_serverfault;
2135 WRITE32(dummy); 2134 WRITE32(dummy);
2136 } 2135 }
2137 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { 2136 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
2138 if ((buflen -= 4) < 0) 2137 if ((buflen -= 4) < 0)
2139 goto out_resource; 2138 goto out_resource;
2140 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) 2139 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
2141 WRITE32(NFS4_FH_PERSISTENT); 2140 WRITE32(NFS4_FH_PERSISTENT);
2142 else 2141 else
2143 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME); 2142 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
2144 } 2143 }
2145 if (bmval0 & FATTR4_WORD0_CHANGE) { 2144 if (bmval0 & FATTR4_WORD0_CHANGE) {
2146 if ((buflen -= 8) < 0) 2145 if ((buflen -= 8) < 0)
2147 goto out_resource; 2146 goto out_resource;
2148 write_change(&p, &stat, dentry->d_inode); 2147 write_change(&p, &stat, dentry->d_inode);
2149 } 2148 }
2150 if (bmval0 & FATTR4_WORD0_SIZE) { 2149 if (bmval0 & FATTR4_WORD0_SIZE) {
2151 if ((buflen -= 8) < 0) 2150 if ((buflen -= 8) < 0)
2152 goto out_resource; 2151 goto out_resource;
2153 WRITE64(stat.size); 2152 WRITE64(stat.size);
2154 } 2153 }
2155 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) { 2154 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
2156 if ((buflen -= 4) < 0) 2155 if ((buflen -= 4) < 0)
2157 goto out_resource; 2156 goto out_resource;
2158 WRITE32(1); 2157 WRITE32(1);
2159 } 2158 }
2160 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) { 2159 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
2161 if ((buflen -= 4) < 0) 2160 if ((buflen -= 4) < 0)
2162 goto out_resource; 2161 goto out_resource;
2163 WRITE32(1); 2162 WRITE32(1);
2164 } 2163 }
2165 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) { 2164 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
2166 if ((buflen -= 4) < 0) 2165 if ((buflen -= 4) < 0)
2167 goto out_resource; 2166 goto out_resource;
2168 WRITE32(0); 2167 WRITE32(0);
2169 } 2168 }
2170 if (bmval0 & FATTR4_WORD0_FSID) { 2169 if (bmval0 & FATTR4_WORD0_FSID) {
2171 if ((buflen -= 16) < 0) 2170 if ((buflen -= 16) < 0)
2172 goto out_resource; 2171 goto out_resource;
2173 if (exp->ex_fslocs.migrated) { 2172 if (exp->ex_fslocs.migrated) {
2174 WRITE64(NFS4_REFERRAL_FSID_MAJOR); 2173 WRITE64(NFS4_REFERRAL_FSID_MAJOR);
2175 WRITE64(NFS4_REFERRAL_FSID_MINOR); 2174 WRITE64(NFS4_REFERRAL_FSID_MINOR);
2176 } else switch(fsid_source(fhp)) { 2175 } else switch(fsid_source(fhp)) {
2177 case FSIDSOURCE_FSID: 2176 case FSIDSOURCE_FSID:
2178 WRITE64((u64)exp->ex_fsid); 2177 WRITE64((u64)exp->ex_fsid);
2179 WRITE64((u64)0); 2178 WRITE64((u64)0);
2180 break; 2179 break;
2181 case FSIDSOURCE_DEV: 2180 case FSIDSOURCE_DEV:
2182 WRITE32(0); 2181 WRITE32(0);
2183 WRITE32(MAJOR(stat.dev)); 2182 WRITE32(MAJOR(stat.dev));
2184 WRITE32(0); 2183 WRITE32(0);
2185 WRITE32(MINOR(stat.dev)); 2184 WRITE32(MINOR(stat.dev));
2186 break; 2185 break;
2187 case FSIDSOURCE_UUID: 2186 case FSIDSOURCE_UUID:
2188 WRITEMEM(exp->ex_uuid, 16); 2187 WRITEMEM(exp->ex_uuid, 16);
2189 break; 2188 break;
2190 } 2189 }
2191 } 2190 }
2192 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { 2191 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
2193 if ((buflen -= 4) < 0) 2192 if ((buflen -= 4) < 0)
2194 goto out_resource; 2193 goto out_resource;
2195 WRITE32(0); 2194 WRITE32(0);
2196 } 2195 }
2197 if (bmval0 & FATTR4_WORD0_LEASE_TIME) { 2196 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
2198 if ((buflen -= 4) < 0) 2197 if ((buflen -= 4) < 0)
2199 goto out_resource; 2198 goto out_resource;
2200 WRITE32(nn->nfsd4_lease); 2199 WRITE32(nn->nfsd4_lease);
2201 } 2200 }
2202 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { 2201 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
2203 if ((buflen -= 4) < 0) 2202 if ((buflen -= 4) < 0)
2204 goto out_resource; 2203 goto out_resource;
2205 WRITE32(rdattr_err); 2204 WRITE32(rdattr_err);
2206 } 2205 }
2207 if (bmval0 & FATTR4_WORD0_ACL) { 2206 if (bmval0 & FATTR4_WORD0_ACL) {
2208 struct nfs4_ace *ace; 2207 struct nfs4_ace *ace;
2209 2208
2210 if (acl == NULL) { 2209 if (acl == NULL) {
2211 if ((buflen -= 4) < 0) 2210 if ((buflen -= 4) < 0)
2212 goto out_resource; 2211 goto out_resource;
2213 2212
2214 WRITE32(0); 2213 WRITE32(0);
2215 goto out_acl; 2214 goto out_acl;
2216 } 2215 }
2217 if ((buflen -= 4) < 0) 2216 if ((buflen -= 4) < 0)
2218 goto out_resource; 2217 goto out_resource;
2219 WRITE32(acl->naces); 2218 WRITE32(acl->naces);
2220 2219
2221 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { 2220 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
2222 if ((buflen -= 4*3) < 0) 2221 if ((buflen -= 4*3) < 0)
2223 goto out_resource; 2222 goto out_resource;
2224 WRITE32(ace->type); 2223 WRITE32(ace->type);
2225 WRITE32(ace->flag); 2224 WRITE32(ace->flag);
2226 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); 2225 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
2227 status = nfsd4_encode_aclname(rqstp, ace->whotype, 2226 status = nfsd4_encode_aclname(rqstp, ace->whotype,
2228 ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP, 2227 ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
2229 &p, &buflen); 2228 &p, &buflen);
2230 if (status == nfserr_resource) 2229 if (status == nfserr_resource)
2231 goto out_resource; 2230 goto out_resource;
2232 if (status) 2231 if (status)
2233 goto out; 2232 goto out;
2234 } 2233 }
2235 } 2234 }
2236 out_acl: 2235 out_acl:
2237 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) { 2236 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
2238 if ((buflen -= 4) < 0) 2237 if ((buflen -= 4) < 0)
2239 goto out_resource; 2238 goto out_resource;
2240 WRITE32(aclsupport ? 2239 WRITE32(aclsupport ?
2241 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0); 2240 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
2242 } 2241 }
2243 if (bmval0 & FATTR4_WORD0_CANSETTIME) { 2242 if (bmval0 & FATTR4_WORD0_CANSETTIME) {
2244 if ((buflen -= 4) < 0) 2243 if ((buflen -= 4) < 0)
2245 goto out_resource; 2244 goto out_resource;
2246 WRITE32(1); 2245 WRITE32(1);
2247 } 2246 }
2248 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { 2247 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
2249 if ((buflen -= 4) < 0) 2248 if ((buflen -= 4) < 0)
2250 goto out_resource; 2249 goto out_resource;
2251 WRITE32(0); 2250 WRITE32(0);
2252 } 2251 }
2253 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { 2252 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
2254 if ((buflen -= 4) < 0) 2253 if ((buflen -= 4) < 0)
2255 goto out_resource; 2254 goto out_resource;
2256 WRITE32(1); 2255 WRITE32(1);
2257 } 2256 }
2258 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) { 2257 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
2259 if ((buflen -= 4) < 0) 2258 if ((buflen -= 4) < 0)
2260 goto out_resource; 2259 goto out_resource;
2261 WRITE32(1); 2260 WRITE32(1);
2262 } 2261 }
2263 if (bmval0 & FATTR4_WORD0_FILEHANDLE) { 2262 if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
2264 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4; 2263 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4;
2265 if (buflen < 0) 2264 if (buflen < 0)
2266 goto out_resource; 2265 goto out_resource;
2267 WRITE32(fhp->fh_handle.fh_size); 2266 WRITE32(fhp->fh_handle.fh_size);
2268 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size); 2267 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
2269 } 2268 }
2270 if (bmval0 & FATTR4_WORD0_FILEID) { 2269 if (bmval0 & FATTR4_WORD0_FILEID) {
2271 if ((buflen -= 8) < 0) 2270 if ((buflen -= 8) < 0)
2272 goto out_resource; 2271 goto out_resource;
2273 WRITE64(stat.ino); 2272 WRITE64(stat.ino);
2274 } 2273 }
2275 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { 2274 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
2276 if ((buflen -= 8) < 0) 2275 if ((buflen -= 8) < 0)
2277 goto out_resource; 2276 goto out_resource;
2278 WRITE64((u64) statfs.f_ffree); 2277 WRITE64((u64) statfs.f_ffree);
2279 } 2278 }
2280 if (bmval0 & FATTR4_WORD0_FILES_FREE) { 2279 if (bmval0 & FATTR4_WORD0_FILES_FREE) {
2281 if ((buflen -= 8) < 0) 2280 if ((buflen -= 8) < 0)
2282 goto out_resource; 2281 goto out_resource;
2283 WRITE64((u64) statfs.f_ffree); 2282 WRITE64((u64) statfs.f_ffree);
2284 } 2283 }
2285 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) { 2284 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
2286 if ((buflen -= 8) < 0) 2285 if ((buflen -= 8) < 0)
2287 goto out_resource; 2286 goto out_resource;
2288 WRITE64((u64) statfs.f_files); 2287 WRITE64((u64) statfs.f_files);
2289 } 2288 }
2290 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { 2289 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
2291 status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); 2290 status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen);
2292 if (status == nfserr_resource) 2291 if (status == nfserr_resource)
2293 goto out_resource; 2292 goto out_resource;
2294 if (status) 2293 if (status)
2295 goto out; 2294 goto out;
2296 } 2295 }
2297 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { 2296 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
2298 if ((buflen -= 4) < 0) 2297 if ((buflen -= 4) < 0)
2299 goto out_resource; 2298 goto out_resource;
2300 WRITE32(1); 2299 WRITE32(1);
2301 } 2300 }
2302 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) { 2301 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
2303 if ((buflen -= 8) < 0) 2302 if ((buflen -= 8) < 0)
2304 goto out_resource; 2303 goto out_resource;
2305 WRITE64(~(u64)0); 2304 WRITE64(~(u64)0);
2306 } 2305 }
2307 if (bmval0 & FATTR4_WORD0_MAXLINK) { 2306 if (bmval0 & FATTR4_WORD0_MAXLINK) {
2308 if ((buflen -= 4) < 0) 2307 if ((buflen -= 4) < 0)
2309 goto out_resource; 2308 goto out_resource;
2310 WRITE32(255); 2309 WRITE32(255);
2311 } 2310 }
2312 if (bmval0 & FATTR4_WORD0_MAXNAME) { 2311 if (bmval0 & FATTR4_WORD0_MAXNAME) {
2313 if ((buflen -= 4) < 0) 2312 if ((buflen -= 4) < 0)
2314 goto out_resource; 2313 goto out_resource;
2315 WRITE32(statfs.f_namelen); 2314 WRITE32(statfs.f_namelen);
2316 } 2315 }
2317 if (bmval0 & FATTR4_WORD0_MAXREAD) { 2316 if (bmval0 & FATTR4_WORD0_MAXREAD) {
2318 if ((buflen -= 8) < 0) 2317 if ((buflen -= 8) < 0)
2319 goto out_resource; 2318 goto out_resource;
2320 WRITE64((u64) svc_max_payload(rqstp)); 2319 WRITE64((u64) svc_max_payload(rqstp));
2321 } 2320 }
2322 if (bmval0 & FATTR4_WORD0_MAXWRITE) { 2321 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
2323 if ((buflen -= 8) < 0) 2322 if ((buflen -= 8) < 0)
2324 goto out_resource; 2323 goto out_resource;
2325 WRITE64((u64) svc_max_payload(rqstp)); 2324 WRITE64((u64) svc_max_payload(rqstp));
2326 } 2325 }
2327 if (bmval1 & FATTR4_WORD1_MODE) { 2326 if (bmval1 & FATTR4_WORD1_MODE) {
2328 if ((buflen -= 4) < 0) 2327 if ((buflen -= 4) < 0)
2329 goto out_resource; 2328 goto out_resource;
2330 WRITE32(stat.mode & S_IALLUGO); 2329 WRITE32(stat.mode & S_IALLUGO);
2331 } 2330 }
2332 if (bmval1 & FATTR4_WORD1_NO_TRUNC) { 2331 if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
2333 if ((buflen -= 4) < 0) 2332 if ((buflen -= 4) < 0)
2334 goto out_resource; 2333 goto out_resource;
2335 WRITE32(1); 2334 WRITE32(1);
2336 } 2335 }
2337 if (bmval1 & FATTR4_WORD1_NUMLINKS) { 2336 if (bmval1 & FATTR4_WORD1_NUMLINKS) {
2338 if ((buflen -= 4) < 0) 2337 if ((buflen -= 4) < 0)
2339 goto out_resource; 2338 goto out_resource;
2340 WRITE32(stat.nlink); 2339 WRITE32(stat.nlink);
2341 } 2340 }
2342 if (bmval1 & FATTR4_WORD1_OWNER) { 2341 if (bmval1 & FATTR4_WORD1_OWNER) {
2343 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); 2342 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen);
2344 if (status == nfserr_resource) 2343 if (status == nfserr_resource)
2345 goto out_resource; 2344 goto out_resource;
2346 if (status) 2345 if (status)
2347 goto out; 2346 goto out;
2348 } 2347 }
2349 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { 2348 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
2350 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); 2349 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen);
2351 if (status == nfserr_resource) 2350 if (status == nfserr_resource)
2352 goto out_resource; 2351 goto out_resource;
2353 if (status) 2352 if (status)
2354 goto out; 2353 goto out;
2355 } 2354 }
2356 if (bmval1 & FATTR4_WORD1_RAWDEV) { 2355 if (bmval1 & FATTR4_WORD1_RAWDEV) {
2357 if ((buflen -= 8) < 0) 2356 if ((buflen -= 8) < 0)
2358 goto out_resource; 2357 goto out_resource;
2359 WRITE32((u32) MAJOR(stat.rdev)); 2358 WRITE32((u32) MAJOR(stat.rdev));
2360 WRITE32((u32) MINOR(stat.rdev)); 2359 WRITE32((u32) MINOR(stat.rdev));
2361 } 2360 }
2362 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) { 2361 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
2363 if ((buflen -= 8) < 0) 2362 if ((buflen -= 8) < 0)
2364 goto out_resource; 2363 goto out_resource;
2365 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize; 2364 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
2366 WRITE64(dummy64); 2365 WRITE64(dummy64);
2367 } 2366 }
2368 if (bmval1 & FATTR4_WORD1_SPACE_FREE) { 2367 if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
2369 if ((buflen -= 8) < 0) 2368 if ((buflen -= 8) < 0)
2370 goto out_resource; 2369 goto out_resource;
2371 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize; 2370 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
2372 WRITE64(dummy64); 2371 WRITE64(dummy64);
2373 } 2372 }
2374 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) { 2373 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
2375 if ((buflen -= 8) < 0) 2374 if ((buflen -= 8) < 0)
2376 goto out_resource; 2375 goto out_resource;
2377 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize; 2376 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
2378 WRITE64(dummy64); 2377 WRITE64(dummy64);
2379 } 2378 }
2380 if (bmval1 & FATTR4_WORD1_SPACE_USED) { 2379 if (bmval1 & FATTR4_WORD1_SPACE_USED) {
2381 if ((buflen -= 8) < 0) 2380 if ((buflen -= 8) < 0)
2382 goto out_resource; 2381 goto out_resource;
2383 dummy64 = (u64)stat.blocks << 9; 2382 dummy64 = (u64)stat.blocks << 9;
2384 WRITE64(dummy64); 2383 WRITE64(dummy64);
2385 } 2384 }
2386 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { 2385 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
2387 if ((buflen -= 12) < 0) 2386 if ((buflen -= 12) < 0)
2388 goto out_resource; 2387 goto out_resource;
2389 WRITE32(0); 2388 WRITE32(0);
2390 WRITE32(stat.atime.tv_sec); 2389 WRITE32(stat.atime.tv_sec);
2391 WRITE32(stat.atime.tv_nsec); 2390 WRITE32(stat.atime.tv_nsec);
2392 } 2391 }
2393 if (bmval1 & FATTR4_WORD1_TIME_DELTA) { 2392 if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
2394 if ((buflen -= 12) < 0) 2393 if ((buflen -= 12) < 0)
2395 goto out_resource; 2394 goto out_resource;
2396 WRITE32(0); 2395 WRITE32(0);
2397 WRITE32(1); 2396 WRITE32(1);
2398 WRITE32(0); 2397 WRITE32(0);
2399 } 2398 }
2400 if (bmval1 & FATTR4_WORD1_TIME_METADATA) { 2399 if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
2401 if ((buflen -= 12) < 0) 2400 if ((buflen -= 12) < 0)
2402 goto out_resource; 2401 goto out_resource;
2403 WRITE32(0); 2402 WRITE32(0);
2404 WRITE32(stat.ctime.tv_sec); 2403 WRITE32(stat.ctime.tv_sec);
2405 WRITE32(stat.ctime.tv_nsec); 2404 WRITE32(stat.ctime.tv_nsec);
2406 } 2405 }
2407 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { 2406 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
2408 if ((buflen -= 12) < 0) 2407 if ((buflen -= 12) < 0)
2409 goto out_resource; 2408 goto out_resource;
2410 WRITE32(0); 2409 WRITE32(0);
2411 WRITE32(stat.mtime.tv_sec); 2410 WRITE32(stat.mtime.tv_sec);
2412 WRITE32(stat.mtime.tv_nsec); 2411 WRITE32(stat.mtime.tv_nsec);
2413 } 2412 }
2414 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { 2413 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
2415 if ((buflen -= 8) < 0) 2414 if ((buflen -= 8) < 0)
2416 goto out_resource; 2415 goto out_resource;
2417 /* 2416 /*
2418 * Get parent's attributes if not ignoring crossmount 2417 * Get parent's attributes if not ignoring crossmount
2419 * and this is the root of a cross-mounted filesystem. 2418 * and this is the root of a cross-mounted filesystem.
2420 */ 2419 */
2421 if (ignore_crossmnt == 0 && 2420 if (ignore_crossmnt == 0 &&
2422 dentry == exp->ex_path.mnt->mnt_root) 2421 dentry == exp->ex_path.mnt->mnt_root)
2423 get_parent_attributes(exp, &stat); 2422 get_parent_attributes(exp, &stat);
2424 WRITE64(stat.ino); 2423 WRITE64(stat.ino);
2425 } 2424 }
2426 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) { 2425 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2427 WRITE32(3); 2426 WRITE32(3);
2428 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0); 2427 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
2429 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1); 2428 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1);
2430 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2); 2429 WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2);
2431 } 2430 }
2432 2431
2433 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 2432 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2434 *countp = p - buffer; 2433 *buffer = p;
2435 status = nfs_ok; 2434 status = nfs_ok;
2436 2435
2437 out: 2436 out:
2438 kfree(acl); 2437 kfree(acl);
2439 if (fhp == &tempfh) 2438 if (fhp == &tempfh)
2440 fh_put(&tempfh); 2439 fh_put(&tempfh);
2441 return status; 2440 return status;
2442 out_nfserr: 2441 out_nfserr:
2443 status = nfserrno(err); 2442 status = nfserrno(err);
2444 goto out; 2443 goto out;
2445 out_resource: 2444 out_resource:
2446 *countp = 0;
2447 status = nfserr_resource; 2445 status = nfserr_resource;
2448 goto out; 2446 goto out;
2449 out_serverfault: 2447 out_serverfault:
2450 status = nfserr_serverfault; 2448 status = nfserr_serverfault;
2451 goto out; 2449 goto out;
2452 } 2450 }
2453 2451
2454 static inline int attributes_need_mount(u32 *bmval) 2452 static inline int attributes_need_mount(u32 *bmval)
2455 { 2453 {
2456 if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME)) 2454 if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
2457 return 1; 2455 return 1;
2458 if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID) 2456 if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
2459 return 1; 2457 return 1;
2460 return 0; 2458 return 0;
2461 } 2459 }
2462 2460
2463 static __be32 2461 static __be32
2464 nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, 2462 nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
2465 const char *name, int namlen, __be32 *p, int *buflen) 2463 const char *name, int namlen, __be32 **p, int buflen)
2466 { 2464 {
2467 struct svc_export *exp = cd->rd_fhp->fh_export; 2465 struct svc_export *exp = cd->rd_fhp->fh_export;
2468 struct dentry *dentry; 2466 struct dentry *dentry;
2469 __be32 nfserr; 2467 __be32 nfserr;
2470 int ignore_crossmnt = 0; 2468 int ignore_crossmnt = 0;
2471 2469
2472 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); 2470 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
2473 if (IS_ERR(dentry)) 2471 if (IS_ERR(dentry))
2474 return nfserrno(PTR_ERR(dentry)); 2472 return nfserrno(PTR_ERR(dentry));
2475 if (!dentry->d_inode) { 2473 if (!dentry->d_inode) {
2476 /* 2474 /*
2477 * nfsd_buffered_readdir drops the i_mutex between 2475 * nfsd_buffered_readdir drops the i_mutex between
2478 * readdir and calling this callback, leaving a window 2476 * readdir and calling this callback, leaving a window
2479 * where this directory entry could have gone away. 2477 * where this directory entry could have gone away.
2480 */ 2478 */
2481 dput(dentry); 2479 dput(dentry);
2482 return nfserr_noent; 2480 return nfserr_noent;
2483 } 2481 }
2484 2482
2485 exp_get(exp); 2483 exp_get(exp);
2486 /* 2484 /*
2487 * In the case of a mountpoint, the client may be asking for 2485 * In the case of a mountpoint, the client may be asking for
2488 * attributes that are only properties of the underlying filesystem 2486 * attributes that are only properties of the underlying filesystem
2489 * as opposed to the cross-mounted file system. In such a case, 2487 * as opposed to the cross-mounted file system. In such a case,
2490 * we will not follow the cross mount and will fill the attribtutes 2488 * we will not follow the cross mount and will fill the attribtutes
2491 * directly from the mountpoint dentry. 2489 * directly from the mountpoint dentry.
2492 */ 2490 */
2493 if (nfsd_mountpoint(dentry, exp)) { 2491 if (nfsd_mountpoint(dentry, exp)) {
2494 int err; 2492 int err;
2495 2493
2496 if (!(exp->ex_flags & NFSEXP_V4ROOT) 2494 if (!(exp->ex_flags & NFSEXP_V4ROOT)
2497 && !attributes_need_mount(cd->rd_bmval)) { 2495 && !attributes_need_mount(cd->rd_bmval)) {
2498 ignore_crossmnt = 1; 2496 ignore_crossmnt = 1;
2499 goto out_encode; 2497 goto out_encode;
2500 } 2498 }
2501 /* 2499 /*
2502 * Why the heck aren't we just using nfsd_lookup?? 2500 * Why the heck aren't we just using nfsd_lookup??
2503 * Different "."/".." handling? Something else? 2501 * Different "."/".." handling? Something else?
2504 * At least, add a comment here to explain.... 2502 * At least, add a comment here to explain....
2505 */ 2503 */
2506 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); 2504 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
2507 if (err) { 2505 if (err) {
2508 nfserr = nfserrno(err); 2506 nfserr = nfserrno(err);
2509 goto out_put; 2507 goto out_put;
2510 } 2508 }
2511 nfserr = check_nfsd_access(exp, cd->rd_rqstp); 2509 nfserr = check_nfsd_access(exp, cd->rd_rqstp);
2512 if (nfserr) 2510 if (nfserr)
2513 goto out_put; 2511 goto out_put;
2514 2512
2515 } 2513 }
2516 out_encode: 2514 out_encode:
2517 nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, 2515 nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
2518 cd->rd_rqstp, ignore_crossmnt); 2516 cd->rd_rqstp, ignore_crossmnt);
2519 out_put: 2517 out_put:
2520 dput(dentry); 2518 dput(dentry);
2521 exp_put(exp); 2519 exp_put(exp);
2522 return nfserr; 2520 return nfserr;
2523 } 2521 }
2524 2522
2525 static __be32 * 2523 static __be32 *
2526 nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) 2524 nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr)
2527 { 2525 {
2528 __be32 *attrlenp; 2526 __be32 *attrlenp;
2529 2527
2530 if (buflen < 6) 2528 if (buflen < 6)
2531 return NULL; 2529 return NULL;
2532 *p++ = htonl(2); 2530 *p++ = htonl(2);
2533 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ 2531 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
2534 *p++ = htonl(0); /* bmval1 */ 2532 *p++ = htonl(0); /* bmval1 */
2535 2533
2536 attrlenp = p++; 2534 attrlenp = p++;
2537 *p++ = nfserr; /* no htonl */ 2535 *p++ = nfserr; /* no htonl */
2538 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 2536 *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2539 return p; 2537 return p;
2540 } 2538 }
2541 2539
2542 static int 2540 static int
2543 nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, 2541 nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2544 loff_t offset, u64 ino, unsigned int d_type) 2542 loff_t offset, u64 ino, unsigned int d_type)
2545 { 2543 {
2546 struct readdir_cd *ccd = ccdv; 2544 struct readdir_cd *ccd = ccdv;
2547 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); 2545 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
2548 int buflen; 2546 int buflen;
2549 __be32 *p = cd->buffer; 2547 __be32 *p = cd->buffer;
2550 __be32 *cookiep; 2548 __be32 *cookiep;
2551 __be32 nfserr = nfserr_toosmall; 2549 __be32 nfserr = nfserr_toosmall;
2552 2550
2553 /* In nfsv4, "." and ".." never make it onto the wire.. */ 2551 /* In nfsv4, "." and ".." never make it onto the wire.. */
2554 if (name && isdotent(name, namlen)) { 2552 if (name && isdotent(name, namlen)) {
2555 cd->common.err = nfs_ok; 2553 cd->common.err = nfs_ok;
2556 return 0; 2554 return 0;
2557 } 2555 }
2558 2556
2559 if (cd->offset) 2557 if (cd->offset)
2560 xdr_encode_hyper(cd->offset, (u64) offset); 2558 xdr_encode_hyper(cd->offset, (u64) offset);
2561 2559
2562 buflen = cd->buflen - 4 - XDR_QUADLEN(namlen); 2560 buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
2563 if (buflen < 0) 2561 if (buflen < 0)
2564 goto fail; 2562 goto fail;
2565 2563
2566 *p++ = xdr_one; /* mark entry present */ 2564 *p++ = xdr_one; /* mark entry present */
2567 cookiep = p; 2565 cookiep = p;
2568 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ 2566 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
2569 p = xdr_encode_array(p, name, namlen); /* name length & name */ 2567 p = xdr_encode_array(p, name, namlen); /* name length & name */
2570 2568
2571 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen); 2569 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, &p, buflen);
2572 switch (nfserr) { 2570 switch (nfserr) {
2573 case nfs_ok: 2571 case nfs_ok:
2574 p += buflen;
2575 break; 2572 break;
2576 case nfserr_resource: 2573 case nfserr_resource:
2577 nfserr = nfserr_toosmall; 2574 nfserr = nfserr_toosmall;
2578 goto fail; 2575 goto fail;
2579 case nfserr_noent: 2576 case nfserr_noent:
2580 goto skip_entry; 2577 goto skip_entry;
2581 default: 2578 default:
2582 /* 2579 /*
2583 * If the client requested the RDATTR_ERROR attribute, 2580 * If the client requested the RDATTR_ERROR attribute,
2584 * we stuff the error code into this attribute 2581 * we stuff the error code into this attribute
2585 * and continue. If this attribute was not requested, 2582 * and continue. If this attribute was not requested,
2586 * then in accordance with the spec, we fail the 2583 * then in accordance with the spec, we fail the
2587 * entire READDIR operation(!) 2584 * entire READDIR operation(!)
2588 */ 2585 */
2589 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) 2586 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
2590 goto fail; 2587 goto fail;
2591 p = nfsd4_encode_rdattr_error(p, buflen, nfserr); 2588 p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
2592 if (p == NULL) { 2589 if (p == NULL) {
2593 nfserr = nfserr_toosmall; 2590 nfserr = nfserr_toosmall;
2594 goto fail; 2591 goto fail;
2595 } 2592 }
2596 } 2593 }
2597 cd->buflen -= (p - cd->buffer); 2594 cd->buflen -= (p - cd->buffer);
2598 cd->buffer = p; 2595 cd->buffer = p;
2599 cd->offset = cookiep; 2596 cd->offset = cookiep;
2600 skip_entry: 2597 skip_entry:
2601 cd->common.err = nfs_ok; 2598 cd->common.err = nfs_ok;
2602 return 0; 2599 return 0;
2603 fail: 2600 fail:
2604 cd->common.err = nfserr; 2601 cd->common.err = nfserr;
2605 return -EINVAL; 2602 return -EINVAL;
2606 } 2603 }
2607 2604
2608 static void 2605 static void
2609 nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid) 2606 nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
2610 { 2607 {
2611 __be32 *p; 2608 __be32 *p;
2612 2609
2613 RESERVE_SPACE(sizeof(stateid_t)); 2610 RESERVE_SPACE(sizeof(stateid_t));
2614 WRITE32(sid->si_generation); 2611 WRITE32(sid->si_generation);
2615 WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t)); 2612 WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
2616 ADJUST_ARGS(); 2613 ADJUST_ARGS();
2617 } 2614 }
2618 2615
2619 static __be32 2616 static __be32
2620 nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access) 2617 nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
2621 { 2618 {
2622 __be32 *p; 2619 __be32 *p;
2623 2620
2624 if (!nfserr) { 2621 if (!nfserr) {
2625 RESERVE_SPACE(8); 2622 RESERVE_SPACE(8);
2626 WRITE32(access->ac_supported); 2623 WRITE32(access->ac_supported);
2627 WRITE32(access->ac_resp_access); 2624 WRITE32(access->ac_resp_access);
2628 ADJUST_ARGS(); 2625 ADJUST_ARGS();
2629 } 2626 }
2630 return nfserr; 2627 return nfserr;
2631 } 2628 }
2632 2629
2633 static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts) 2630 static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts)
2634 { 2631 {
2635 __be32 *p; 2632 __be32 *p;
2636 2633
2637 if (!nfserr) { 2634 if (!nfserr) {
2638 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8); 2635 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 8);
2639 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN); 2636 WRITEMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
2640 WRITE32(bcts->dir); 2637 WRITE32(bcts->dir);
2641 /* Sorry, we do not yet support RDMA over 4.1: */ 2638 /* Sorry, we do not yet support RDMA over 4.1: */
2642 WRITE32(0); 2639 WRITE32(0);
2643 ADJUST_ARGS(); 2640 ADJUST_ARGS();
2644 } 2641 }
2645 return nfserr; 2642 return nfserr;
2646 } 2643 }
2647 2644
2648 static __be32 2645 static __be32
2649 nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) 2646 nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
2650 { 2647 {
2651 ENCODE_SEQID_OP_HEAD; 2648 ENCODE_SEQID_OP_HEAD;
2652 2649
2653 if (!nfserr) 2650 if (!nfserr)
2654 nfsd4_encode_stateid(resp, &close->cl_stateid); 2651 nfsd4_encode_stateid(resp, &close->cl_stateid);
2655 2652
2656 encode_seqid_op_tail(resp, save, nfserr); 2653 encode_seqid_op_tail(resp, save, nfserr);
2657 return nfserr; 2654 return nfserr;
2658 } 2655 }
2659 2656
2660 2657
2661 static __be32 2658 static __be32
2662 nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit) 2659 nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
2663 { 2660 {
2664 __be32 *p; 2661 __be32 *p;
2665 2662
2666 if (!nfserr) { 2663 if (!nfserr) {
2667 RESERVE_SPACE(NFS4_VERIFIER_SIZE); 2664 RESERVE_SPACE(NFS4_VERIFIER_SIZE);
2668 WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE); 2665 WRITEMEM(commit->co_verf.data, NFS4_VERIFIER_SIZE);
2669 ADJUST_ARGS(); 2666 ADJUST_ARGS();
2670 } 2667 }
2671 return nfserr; 2668 return nfserr;
2672 } 2669 }
2673 2670
2674 static __be32 2671 static __be32
2675 nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create) 2672 nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
2676 { 2673 {
2677 __be32 *p; 2674 __be32 *p;
2678 2675
2679 if (!nfserr) { 2676 if (!nfserr) {
2680 RESERVE_SPACE(32); 2677 RESERVE_SPACE(32);
2681 write_cinfo(&p, &create->cr_cinfo); 2678 write_cinfo(&p, &create->cr_cinfo);
2682 WRITE32(2); 2679 WRITE32(2);
2683 WRITE32(create->cr_bmval[0]); 2680 WRITE32(create->cr_bmval[0]);
2684 WRITE32(create->cr_bmval[1]); 2681 WRITE32(create->cr_bmval[1]);
2685 ADJUST_ARGS(); 2682 ADJUST_ARGS();
2686 } 2683 }
2687 return nfserr; 2684 return nfserr;
2688 } 2685 }
2689 2686
2690 static __be32 2687 static __be32
2691 nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr) 2688 nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
2692 { 2689 {
2693 struct svc_fh *fhp = getattr->ga_fhp; 2690 struct svc_fh *fhp = getattr->ga_fhp;
2694 int buflen; 2691 int buflen;
2695 2692
2696 if (nfserr) 2693 if (nfserr)
2697 return nfserr; 2694 return nfserr;
2698 2695
2699 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); 2696 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
2700 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, 2697 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
2701 resp->p, &buflen, getattr->ga_bmval, 2698 &resp->p, buflen, getattr->ga_bmval,
2702 resp->rqstp, 0); 2699 resp->rqstp, 0);
2703 if (!nfserr)
2704 resp->p += buflen;
2705 return nfserr; 2700 return nfserr;
2706 } 2701 }
2707 2702
2708 static __be32 2703 static __be32
2709 nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp) 2704 nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp)
2710 { 2705 {
2711 struct svc_fh *fhp = *fhpp; 2706 struct svc_fh *fhp = *fhpp;
2712 unsigned int len; 2707 unsigned int len;
2713 __be32 *p; 2708 __be32 *p;
2714 2709
2715 if (!nfserr) { 2710 if (!nfserr) {
2716 len = fhp->fh_handle.fh_size; 2711 len = fhp->fh_handle.fh_size;
2717 RESERVE_SPACE(len + 4); 2712 RESERVE_SPACE(len + 4);
2718 WRITE32(len); 2713 WRITE32(len);
2719 WRITEMEM(&fhp->fh_handle.fh_base, len); 2714 WRITEMEM(&fhp->fh_handle.fh_base, len);
2720 ADJUST_ARGS(); 2715 ADJUST_ARGS();
2721 } 2716 }
2722 return nfserr; 2717 return nfserr;
2723 } 2718 }
2724 2719
2725 /* 2720 /*
2726 * Including all fields other than the name, a LOCK4denied structure requires 2721 * Including all fields other than the name, a LOCK4denied structure requires
2727 * 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes. 2722 * 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.
2728 */ 2723 */
2729 static void 2724 static void
2730 nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld) 2725 nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
2731 { 2726 {
2732 struct xdr_netobj *conf = &ld->ld_owner; 2727 struct xdr_netobj *conf = &ld->ld_owner;
2733 __be32 *p; 2728 __be32 *p;
2734 2729
2735 RESERVE_SPACE(32 + XDR_LEN(conf->len)); 2730 RESERVE_SPACE(32 + XDR_LEN(conf->len));
2736 WRITE64(ld->ld_start); 2731 WRITE64(ld->ld_start);
2737 WRITE64(ld->ld_length); 2732 WRITE64(ld->ld_length);
2738 WRITE32(ld->ld_type); 2733 WRITE32(ld->ld_type);
2739 if (conf->len) { 2734 if (conf->len) {
2740 WRITEMEM(&ld->ld_clientid, 8); 2735 WRITEMEM(&ld->ld_clientid, 8);
2741 WRITE32(conf->len); 2736 WRITE32(conf->len);
2742 WRITEMEM(conf->data, conf->len); 2737 WRITEMEM(conf->data, conf->len);
2743 kfree(conf->data); 2738 kfree(conf->data);
2744 } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ 2739 } else { /* non - nfsv4 lock in conflict, no clientid nor owner */
2745 WRITE64((u64)0); /* clientid */ 2740 WRITE64((u64)0); /* clientid */
2746 WRITE32(0); /* length of owner name */ 2741 WRITE32(0); /* length of owner name */
2747 } 2742 }
2748 ADJUST_ARGS(); 2743 ADJUST_ARGS();
2749 } 2744 }
2750 2745
2751 static __be32 2746 static __be32
2752 nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) 2747 nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
2753 { 2748 {
2754 ENCODE_SEQID_OP_HEAD; 2749 ENCODE_SEQID_OP_HEAD;
2755 2750
2756 if (!nfserr) 2751 if (!nfserr)
2757 nfsd4_encode_stateid(resp, &lock->lk_resp_stateid); 2752 nfsd4_encode_stateid(resp, &lock->lk_resp_stateid);
2758 else if (nfserr == nfserr_denied) 2753 else if (nfserr == nfserr_denied)
2759 nfsd4_encode_lock_denied(resp, &lock->lk_denied); 2754 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
2760 2755
2761 encode_seqid_op_tail(resp, save, nfserr); 2756 encode_seqid_op_tail(resp, save, nfserr);
2762 return nfserr; 2757 return nfserr;
2763 } 2758 }
2764 2759
2765 static __be32 2760 static __be32
2766 nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt) 2761 nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
2767 { 2762 {
2768 if (nfserr == nfserr_denied) 2763 if (nfserr == nfserr_denied)
2769 nfsd4_encode_lock_denied(resp, &lockt->lt_denied); 2764 nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
2770 return nfserr; 2765 return nfserr;
2771 } 2766 }
2772 2767
2773 static __be32 2768 static __be32
2774 nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) 2769 nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
2775 { 2770 {
2776 ENCODE_SEQID_OP_HEAD; 2771 ENCODE_SEQID_OP_HEAD;
2777 2772
2778 if (!nfserr) 2773 if (!nfserr)
2779 nfsd4_encode_stateid(resp, &locku->lu_stateid); 2774 nfsd4_encode_stateid(resp, &locku->lu_stateid);
2780 2775
2781 encode_seqid_op_tail(resp, save, nfserr); 2776 encode_seqid_op_tail(resp, save, nfserr);
2782 return nfserr; 2777 return nfserr;
2783 } 2778 }
2784 2779
2785 2780
2786 static __be32 2781 static __be32
2787 nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link) 2782 nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
2788 { 2783 {
2789 __be32 *p; 2784 __be32 *p;
2790 2785
2791 if (!nfserr) { 2786 if (!nfserr) {
2792 RESERVE_SPACE(20); 2787 RESERVE_SPACE(20);
2793 write_cinfo(&p, &link->li_cinfo); 2788 write_cinfo(&p, &link->li_cinfo);
2794 ADJUST_ARGS(); 2789 ADJUST_ARGS();
2795 } 2790 }
2796 return nfserr; 2791 return nfserr;
2797 } 2792 }
2798 2793
2799 2794
2800 static __be32 2795 static __be32
2801 nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) 2796 nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
2802 { 2797 {
2803 __be32 *p; 2798 __be32 *p;
2804 ENCODE_SEQID_OP_HEAD; 2799 ENCODE_SEQID_OP_HEAD;
2805 2800
2806 if (nfserr) 2801 if (nfserr)
2807 goto out; 2802 goto out;
2808 2803
2809 nfsd4_encode_stateid(resp, &open->op_stateid); 2804 nfsd4_encode_stateid(resp, &open->op_stateid);
2810 RESERVE_SPACE(40); 2805 RESERVE_SPACE(40);
2811 write_cinfo(&p, &open->op_cinfo); 2806 write_cinfo(&p, &open->op_cinfo);
2812 WRITE32(open->op_rflags); 2807 WRITE32(open->op_rflags);
2813 WRITE32(2); 2808 WRITE32(2);
2814 WRITE32(open->op_bmval[0]); 2809 WRITE32(open->op_bmval[0]);
2815 WRITE32(open->op_bmval[1]); 2810 WRITE32(open->op_bmval[1]);
2816 WRITE32(open->op_delegate_type); 2811 WRITE32(open->op_delegate_type);
2817 ADJUST_ARGS(); 2812 ADJUST_ARGS();
2818 2813
2819 switch (open->op_delegate_type) { 2814 switch (open->op_delegate_type) {
2820 case NFS4_OPEN_DELEGATE_NONE: 2815 case NFS4_OPEN_DELEGATE_NONE:
2821 break; 2816 break;
2822 case NFS4_OPEN_DELEGATE_READ: 2817 case NFS4_OPEN_DELEGATE_READ:
2823 nfsd4_encode_stateid(resp, &open->op_delegate_stateid); 2818 nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
2824 RESERVE_SPACE(20); 2819 RESERVE_SPACE(20);
2825 WRITE32(open->op_recall); 2820 WRITE32(open->op_recall);
2826 2821
2827 /* 2822 /*
2828 * TODO: ACE's in delegations 2823 * TODO: ACE's in delegations
2829 */ 2824 */
2830 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2825 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2831 WRITE32(0); 2826 WRITE32(0);
2832 WRITE32(0); 2827 WRITE32(0);
2833 WRITE32(0); /* XXX: is NULL principal ok? */ 2828 WRITE32(0); /* XXX: is NULL principal ok? */
2834 ADJUST_ARGS(); 2829 ADJUST_ARGS();
2835 break; 2830 break;
2836 case NFS4_OPEN_DELEGATE_WRITE: 2831 case NFS4_OPEN_DELEGATE_WRITE:
2837 nfsd4_encode_stateid(resp, &open->op_delegate_stateid); 2832 nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
2838 RESERVE_SPACE(32); 2833 RESERVE_SPACE(32);
2839 WRITE32(0); 2834 WRITE32(0);
2840 2835
2841 /* 2836 /*
2842 * TODO: space_limit's in delegations 2837 * TODO: space_limit's in delegations
2843 */ 2838 */
2844 WRITE32(NFS4_LIMIT_SIZE); 2839 WRITE32(NFS4_LIMIT_SIZE);
2845 WRITE32(~(u32)0); 2840 WRITE32(~(u32)0);
2846 WRITE32(~(u32)0); 2841 WRITE32(~(u32)0);
2847 2842
2848 /* 2843 /*
2849 * TODO: ACE's in delegations 2844 * TODO: ACE's in delegations
2850 */ 2845 */
2851 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2846 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2852 WRITE32(0); 2847 WRITE32(0);
2853 WRITE32(0); 2848 WRITE32(0);
2854 WRITE32(0); /* XXX: is NULL principal ok? */ 2849 WRITE32(0); /* XXX: is NULL principal ok? */
2855 ADJUST_ARGS(); 2850 ADJUST_ARGS();
2856 break; 2851 break;
2857 case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */ 2852 case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */
2858 switch (open->op_why_no_deleg) { 2853 switch (open->op_why_no_deleg) {
2859 case WND4_CONTENTION: 2854 case WND4_CONTENTION:
2860 case WND4_RESOURCE: 2855 case WND4_RESOURCE:
2861 RESERVE_SPACE(8); 2856 RESERVE_SPACE(8);
2862 WRITE32(open->op_why_no_deleg); 2857 WRITE32(open->op_why_no_deleg);
2863 WRITE32(0); /* deleg signaling not supported yet */ 2858 WRITE32(0); /* deleg signaling not supported yet */
2864 break; 2859 break;
2865 default: 2860 default:
2866 RESERVE_SPACE(4); 2861 RESERVE_SPACE(4);
2867 WRITE32(open->op_why_no_deleg); 2862 WRITE32(open->op_why_no_deleg);
2868 } 2863 }
2869 ADJUST_ARGS(); 2864 ADJUST_ARGS();
2870 break; 2865 break;
2871 default: 2866 default:
2872 BUG(); 2867 BUG();
2873 } 2868 }
2874 /* XXX save filehandle here */ 2869 /* XXX save filehandle here */
2875 out: 2870 out:
2876 encode_seqid_op_tail(resp, save, nfserr); 2871 encode_seqid_op_tail(resp, save, nfserr);
2877 return nfserr; 2872 return nfserr;
2878 } 2873 }
2879 2874
2880 static __be32 2875 static __be32
2881 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) 2876 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
2882 { 2877 {
2883 ENCODE_SEQID_OP_HEAD; 2878 ENCODE_SEQID_OP_HEAD;
2884 2879
2885 if (!nfserr) 2880 if (!nfserr)
2886 nfsd4_encode_stateid(resp, &oc->oc_resp_stateid); 2881 nfsd4_encode_stateid(resp, &oc->oc_resp_stateid);
2887 2882
2888 encode_seqid_op_tail(resp, save, nfserr); 2883 encode_seqid_op_tail(resp, save, nfserr);
2889 return nfserr; 2884 return nfserr;
2890 } 2885 }
2891 2886
2892 static __be32 2887 static __be32
2893 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) 2888 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
2894 { 2889 {
2895 ENCODE_SEQID_OP_HEAD; 2890 ENCODE_SEQID_OP_HEAD;
2896 2891
2897 if (!nfserr) 2892 if (!nfserr)
2898 nfsd4_encode_stateid(resp, &od->od_stateid); 2893 nfsd4_encode_stateid(resp, &od->od_stateid);
2899 2894
2900 encode_seqid_op_tail(resp, save, nfserr); 2895 encode_seqid_op_tail(resp, save, nfserr);
2901 return nfserr; 2896 return nfserr;
2902 } 2897 }
2903 2898
2904 static __be32 2899 static __be32
2905 nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, 2900 nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2906 struct nfsd4_read *read) 2901 struct nfsd4_read *read)
2907 { 2902 {
2908 u32 eof; 2903 u32 eof;
2909 int v; 2904 int v;
2910 struct page *page; 2905 struct page *page;
2911 unsigned long maxcount; 2906 unsigned long maxcount;
2912 long len; 2907 long len;
2913 __be32 *p; 2908 __be32 *p;
2914 2909
2915 if (nfserr) 2910 if (nfserr)
2916 return nfserr; 2911 return nfserr;
2917 if (resp->xbuf->page_len) 2912 if (resp->xbuf->page_len)
2918 return nfserr_resource; 2913 return nfserr_resource;
2919 2914
2920 RESERVE_SPACE(8); /* eof flag and byte count */ 2915 RESERVE_SPACE(8); /* eof flag and byte count */
2921 2916
2922 maxcount = svc_max_payload(resp->rqstp); 2917 maxcount = svc_max_payload(resp->rqstp);
2923 if (maxcount > read->rd_length) 2918 if (maxcount > read->rd_length)
2924 maxcount = read->rd_length; 2919 maxcount = read->rd_length;
2925 2920
2926 len = maxcount; 2921 len = maxcount;
2927 v = 0; 2922 v = 0;
2928 while (len > 0) { 2923 while (len > 0) {
2929 page = *(resp->rqstp->rq_next_page); 2924 page = *(resp->rqstp->rq_next_page);
2930 if (!page) { /* ran out of pages */ 2925 if (!page) { /* ran out of pages */
2931 maxcount -= len; 2926 maxcount -= len;
2932 break; 2927 break;
2933 } 2928 }
2934 resp->rqstp->rq_vec[v].iov_base = page_address(page); 2929 resp->rqstp->rq_vec[v].iov_base = page_address(page);
2935 resp->rqstp->rq_vec[v].iov_len = 2930 resp->rqstp->rq_vec[v].iov_len =
2936 len < PAGE_SIZE ? len : PAGE_SIZE; 2931 len < PAGE_SIZE ? len : PAGE_SIZE;
2937 resp->rqstp->rq_next_page++; 2932 resp->rqstp->rq_next_page++;
2938 v++; 2933 v++;
2939 len -= PAGE_SIZE; 2934 len -= PAGE_SIZE;
2940 } 2935 }
2941 read->rd_vlen = v; 2936 read->rd_vlen = v;
2942 2937
2943 nfserr = nfsd_read_file(read->rd_rqstp, read->rd_fhp, read->rd_filp, 2938 nfserr = nfsd_read_file(read->rd_rqstp, read->rd_fhp, read->rd_filp,
2944 read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, 2939 read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen,
2945 &maxcount); 2940 &maxcount);
2946 2941
2947 if (nfserr) 2942 if (nfserr)
2948 return nfserr; 2943 return nfserr;
2949 eof = (read->rd_offset + maxcount >= 2944 eof = (read->rd_offset + maxcount >=
2950 read->rd_fhp->fh_dentry->d_inode->i_size); 2945 read->rd_fhp->fh_dentry->d_inode->i_size);
2951 2946
2952 WRITE32(eof); 2947 WRITE32(eof);
2953 WRITE32(maxcount); 2948 WRITE32(maxcount);
2954 ADJUST_ARGS(); 2949 ADJUST_ARGS();
2955 resp->xbuf->head[0].iov_len = (char*)p 2950 resp->xbuf->head[0].iov_len = (char*)p
2956 - (char*)resp->xbuf->head[0].iov_base; 2951 - (char*)resp->xbuf->head[0].iov_base;
2957 resp->xbuf->page_len = maxcount; 2952 resp->xbuf->page_len = maxcount;
2958 2953
2959 /* Use rest of head for padding and remaining ops: */ 2954 /* Use rest of head for padding and remaining ops: */
2960 resp->xbuf->tail[0].iov_base = p; 2955 resp->xbuf->tail[0].iov_base = p;
2961 resp->xbuf->tail[0].iov_len = 0; 2956 resp->xbuf->tail[0].iov_len = 0;
2962 if (maxcount&3) { 2957 if (maxcount&3) {
2963 RESERVE_SPACE(4); 2958 RESERVE_SPACE(4);
2964 WRITE32(0); 2959 WRITE32(0);
2965 resp->xbuf->tail[0].iov_base += maxcount&3; 2960 resp->xbuf->tail[0].iov_base += maxcount&3;
2966 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 2961 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2967 ADJUST_ARGS(); 2962 ADJUST_ARGS();
2968 } 2963 }
2969 return 0; 2964 return 0;
2970 } 2965 }
2971 2966
2972 static __be32 2967 static __be32
2973 nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink) 2968 nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
2974 { 2969 {
2975 int maxcount; 2970 int maxcount;
2976 char *page; 2971 char *page;
2977 __be32 *p; 2972 __be32 *p;
2978 2973
2979 if (nfserr) 2974 if (nfserr)
2980 return nfserr; 2975 return nfserr;
2981 if (resp->xbuf->page_len) 2976 if (resp->xbuf->page_len)
2982 return nfserr_resource; 2977 return nfserr_resource;
2983 if (!*resp->rqstp->rq_next_page) 2978 if (!*resp->rqstp->rq_next_page)
2984 return nfserr_resource; 2979 return nfserr_resource;
2985 2980
2986 page = page_address(*(resp->rqstp->rq_next_page++)); 2981 page = page_address(*(resp->rqstp->rq_next_page++));
2987 2982
2988 maxcount = PAGE_SIZE; 2983 maxcount = PAGE_SIZE;
2989 RESERVE_SPACE(4); 2984 RESERVE_SPACE(4);
2990 2985
2991 /* 2986 /*
2992 * XXX: By default, the ->readlink() VFS op will truncate symlinks 2987 * XXX: By default, the ->readlink() VFS op will truncate symlinks
2993 * if they would overflow the buffer. Is this kosher in NFSv4? If 2988 * if they would overflow the buffer. Is this kosher in NFSv4? If
2994 * not, one easy fix is: if ->readlink() precisely fills the buffer, 2989 * not, one easy fix is: if ->readlink() precisely fills the buffer,
2995 * assume that truncation occurred, and return NFS4ERR_RESOURCE. 2990 * assume that truncation occurred, and return NFS4ERR_RESOURCE.
2996 */ 2991 */
2997 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount); 2992 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2998 if (nfserr == nfserr_isdir) 2993 if (nfserr == nfserr_isdir)
2999 return nfserr_inval; 2994 return nfserr_inval;
3000 if (nfserr) 2995 if (nfserr)
3001 return nfserr; 2996 return nfserr;
3002 2997
3003 WRITE32(maxcount); 2998 WRITE32(maxcount);
3004 ADJUST_ARGS(); 2999 ADJUST_ARGS();
3005 resp->xbuf->head[0].iov_len = (char*)p 3000 resp->xbuf->head[0].iov_len = (char*)p
3006 - (char*)resp->xbuf->head[0].iov_base; 3001 - (char*)resp->xbuf->head[0].iov_base;
3007 resp->xbuf->page_len = maxcount; 3002 resp->xbuf->page_len = maxcount;
3008 3003
3009 /* Use rest of head for padding and remaining ops: */ 3004 /* Use rest of head for padding and remaining ops: */
3010 resp->xbuf->tail[0].iov_base = p; 3005 resp->xbuf->tail[0].iov_base = p;
3011 resp->xbuf->tail[0].iov_len = 0; 3006 resp->xbuf->tail[0].iov_len = 0;
3012 if (maxcount&3) { 3007 if (maxcount&3) {
3013 RESERVE_SPACE(4); 3008 RESERVE_SPACE(4);
3014 WRITE32(0); 3009 WRITE32(0);
3015 resp->xbuf->tail[0].iov_base += maxcount&3; 3010 resp->xbuf->tail[0].iov_base += maxcount&3;
3016 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 3011 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
3017 ADJUST_ARGS(); 3012 ADJUST_ARGS();
3018 } 3013 }
3019 return 0; 3014 return 0;
3020 } 3015 }
3021 3016
3022 static __be32 3017 static __be32
3023 nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir) 3018 nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
3024 { 3019 {
3025 int maxcount; 3020 int maxcount;
3026 loff_t offset; 3021 loff_t offset;
3027 __be32 *page, *savep, *tailbase; 3022 __be32 *page, *savep, *tailbase;
3028 __be32 *p; 3023 __be32 *p;
3029 3024
3030 if (nfserr) 3025 if (nfserr)
3031 return nfserr; 3026 return nfserr;
3032 if (resp->xbuf->page_len) 3027 if (resp->xbuf->page_len)
3033 return nfserr_resource; 3028 return nfserr_resource;
3034 if (!*resp->rqstp->rq_next_page) 3029 if (!*resp->rqstp->rq_next_page)
3035 return nfserr_resource; 3030 return nfserr_resource;
3036 3031
3037 RESERVE_SPACE(NFS4_VERIFIER_SIZE); 3032 RESERVE_SPACE(NFS4_VERIFIER_SIZE);
3038 savep = p; 3033 savep = p;
3039 3034
3040 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */ 3035 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
3041 WRITE32(0); 3036 WRITE32(0);
3042 WRITE32(0); 3037 WRITE32(0);
3043 ADJUST_ARGS(); 3038 ADJUST_ARGS();
3044 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 3039 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
3045 tailbase = p; 3040 tailbase = p;
3046 3041
3047 maxcount = PAGE_SIZE; 3042 maxcount = PAGE_SIZE;
3048 if (maxcount > readdir->rd_maxcount) 3043 if (maxcount > readdir->rd_maxcount)
3049 maxcount = readdir->rd_maxcount; 3044 maxcount = readdir->rd_maxcount;
3050 3045
3051 /* 3046 /*
3052 * Convert from bytes to words, account for the two words already 3047 * Convert from bytes to words, account for the two words already
3053 * written, make sure to leave two words at the end for the next 3048 * written, make sure to leave two words at the end for the next
3054 * pointer and eof field. 3049 * pointer and eof field.
3055 */ 3050 */
3056 maxcount = (maxcount >> 2) - 4; 3051 maxcount = (maxcount >> 2) - 4;
3057 if (maxcount < 0) { 3052 if (maxcount < 0) {
3058 nfserr = nfserr_toosmall; 3053 nfserr = nfserr_toosmall;
3059 goto err_no_verf; 3054 goto err_no_verf;
3060 } 3055 }
3061 3056
3062 page = page_address(*(resp->rqstp->rq_next_page++)); 3057 page = page_address(*(resp->rqstp->rq_next_page++));
3063 readdir->common.err = 0; 3058 readdir->common.err = 0;
3064 readdir->buflen = maxcount; 3059 readdir->buflen = maxcount;
3065 readdir->buffer = page; 3060 readdir->buffer = page;
3066 readdir->offset = NULL; 3061 readdir->offset = NULL;
3067 3062
3068 offset = readdir->rd_cookie; 3063 offset = readdir->rd_cookie;
3069 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, 3064 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
3070 &offset, 3065 &offset,
3071 &readdir->common, nfsd4_encode_dirent); 3066 &readdir->common, nfsd4_encode_dirent);
3072 if (nfserr == nfs_ok && 3067 if (nfserr == nfs_ok &&
3073 readdir->common.err == nfserr_toosmall && 3068 readdir->common.err == nfserr_toosmall &&
3074 readdir->buffer == page) 3069 readdir->buffer == page)
3075 nfserr = nfserr_toosmall; 3070 nfserr = nfserr_toosmall;
3076 if (nfserr) 3071 if (nfserr)
3077 goto err_no_verf; 3072 goto err_no_verf;
3078 3073
3079 if (readdir->offset) 3074 if (readdir->offset)
3080 xdr_encode_hyper(readdir->offset, offset); 3075 xdr_encode_hyper(readdir->offset, offset);
3081 3076
3082 p = readdir->buffer; 3077 p = readdir->buffer;
3083 *p++ = 0; /* no more entries */ 3078 *p++ = 0; /* no more entries */
3084 *p++ = htonl(readdir->common.err == nfserr_eof); 3079 *p++ = htonl(readdir->common.err == nfserr_eof);
3085 resp->xbuf->page_len = ((char*)p) - 3080 resp->xbuf->page_len = ((char*)p) -
3086 (char*)page_address(*(resp->rqstp->rq_next_page-1)); 3081 (char*)page_address(*(resp->rqstp->rq_next_page-1));
3087 3082
3088 /* Use rest of head for padding and remaining ops: */ 3083 /* Use rest of head for padding and remaining ops: */
3089 resp->xbuf->tail[0].iov_base = tailbase; 3084 resp->xbuf->tail[0].iov_base = tailbase;
3090 resp->xbuf->tail[0].iov_len = 0; 3085 resp->xbuf->tail[0].iov_len = 0;
3091 resp->p = resp->xbuf->tail[0].iov_base; 3086 resp->p = resp->xbuf->tail[0].iov_base;
3092 resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4; 3087 resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4;
3093 3088
3094 return 0; 3089 return 0;
3095 err_no_verf: 3090 err_no_verf:
3096 p = savep; 3091 p = savep;
3097 ADJUST_ARGS(); 3092 ADJUST_ARGS();
3098 return nfserr; 3093 return nfserr;
3099 } 3094 }
3100 3095
3101 static __be32 3096 static __be32
3102 nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove) 3097 nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
3103 { 3098 {
3104 __be32 *p; 3099 __be32 *p;
3105 3100
3106 if (!nfserr) { 3101 if (!nfserr) {
3107 RESERVE_SPACE(20); 3102 RESERVE_SPACE(20);
3108 write_cinfo(&p, &remove->rm_cinfo); 3103 write_cinfo(&p, &remove->rm_cinfo);
3109 ADJUST_ARGS(); 3104 ADJUST_ARGS();
3110 } 3105 }
3111 return nfserr; 3106 return nfserr;
3112 } 3107 }
3113 3108
3114 static __be32 3109 static __be32
3115 nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename) 3110 nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
3116 { 3111 {
3117 __be32 *p; 3112 __be32 *p;
3118 3113
3119 if (!nfserr) { 3114 if (!nfserr) {
3120 RESERVE_SPACE(40); 3115 RESERVE_SPACE(40);
3121 write_cinfo(&p, &rename->rn_sinfo); 3116 write_cinfo(&p, &rename->rn_sinfo);
3122 write_cinfo(&p, &rename->rn_tinfo); 3117 write_cinfo(&p, &rename->rn_tinfo);
3123 ADJUST_ARGS(); 3118 ADJUST_ARGS();
3124 } 3119 }
3125 return nfserr; 3120 return nfserr;
3126 } 3121 }
3127 3122
3128 static __be32 3123 static __be32
3129 nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp, 3124 nfsd4_do_encode_secinfo(struct nfsd4_compoundres *resp,
3130 __be32 nfserr,struct svc_export *exp) 3125 __be32 nfserr,struct svc_export *exp)
3131 { 3126 {
3132 int i = 0; 3127 int i = 0;
3133 u32 nflavs; 3128 u32 nflavs;
3134 struct exp_flavor_info *flavs; 3129 struct exp_flavor_info *flavs;
3135 struct exp_flavor_info def_flavs[2]; 3130 struct exp_flavor_info def_flavs[2];
3136 __be32 *p; 3131 __be32 *p;
3137 3132
3138 if (nfserr) 3133 if (nfserr)
3139 goto out; 3134 goto out;
3140 if (exp->ex_nflavors) { 3135 if (exp->ex_nflavors) {
3141 flavs = exp->ex_flavors; 3136 flavs = exp->ex_flavors;
3142 nflavs = exp->ex_nflavors; 3137 nflavs = exp->ex_nflavors;
3143 } else { /* Handling of some defaults in absence of real secinfo: */ 3138 } else { /* Handling of some defaults in absence of real secinfo: */
3144 flavs = def_flavs; 3139 flavs = def_flavs;
3145 if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) { 3140 if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
3146 nflavs = 2; 3141 nflavs = 2;
3147 flavs[0].pseudoflavor = RPC_AUTH_UNIX; 3142 flavs[0].pseudoflavor = RPC_AUTH_UNIX;
3148 flavs[1].pseudoflavor = RPC_AUTH_NULL; 3143 flavs[1].pseudoflavor = RPC_AUTH_NULL;
3149 } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) { 3144 } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
3150 nflavs = 1; 3145 nflavs = 1;
3151 flavs[0].pseudoflavor 3146 flavs[0].pseudoflavor
3152 = svcauth_gss_flavor(exp->ex_client); 3147 = svcauth_gss_flavor(exp->ex_client);
3153 } else { 3148 } else {
3154 nflavs = 1; 3149 nflavs = 1;
3155 flavs[0].pseudoflavor 3150 flavs[0].pseudoflavor
3156 = exp->ex_client->flavour->flavour; 3151 = exp->ex_client->flavour->flavour;
3157 } 3152 }
3158 } 3153 }
3159 3154
3160 RESERVE_SPACE(4); 3155 RESERVE_SPACE(4);
3161 WRITE32(nflavs); 3156 WRITE32(nflavs);
3162 ADJUST_ARGS(); 3157 ADJUST_ARGS();
3163 for (i = 0; i < nflavs; i++) { 3158 for (i = 0; i < nflavs; i++) {
3164 u32 flav = flavs[i].pseudoflavor; 3159 u32 flav = flavs[i].pseudoflavor;
3165 struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav); 3160 struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
3166 3161
3167 if (gm) { 3162 if (gm) {
3168 RESERVE_SPACE(4); 3163 RESERVE_SPACE(4);
3169 WRITE32(RPC_AUTH_GSS); 3164 WRITE32(RPC_AUTH_GSS);
3170 ADJUST_ARGS(); 3165 ADJUST_ARGS();
3171 RESERVE_SPACE(4 + gm->gm_oid.len); 3166 RESERVE_SPACE(4 + gm->gm_oid.len);
3172 WRITE32(gm->gm_oid.len); 3167 WRITE32(gm->gm_oid.len);
3173 WRITEMEM(gm->gm_oid.data, gm->gm_oid.len); 3168 WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
3174 ADJUST_ARGS(); 3169 ADJUST_ARGS();
3175 RESERVE_SPACE(4); 3170 RESERVE_SPACE(4);
3176 WRITE32(0); /* qop */ 3171 WRITE32(0); /* qop */
3177 ADJUST_ARGS(); 3172 ADJUST_ARGS();
3178 RESERVE_SPACE(4); 3173 RESERVE_SPACE(4);
3179 WRITE32(gss_pseudoflavor_to_service(gm, flav)); 3174 WRITE32(gss_pseudoflavor_to_service(gm, flav));
3180 ADJUST_ARGS(); 3175 ADJUST_ARGS();
3181 gss_mech_put(gm); 3176 gss_mech_put(gm);
3182 } else { 3177 } else {
3183 RESERVE_SPACE(4); 3178 RESERVE_SPACE(4);
3184 WRITE32(flav); 3179 WRITE32(flav);
3185 ADJUST_ARGS(); 3180 ADJUST_ARGS();
3186 } 3181 }
3187 } 3182 }
3188 out: 3183 out:
3189 if (exp) 3184 if (exp)
3190 exp_put(exp); 3185 exp_put(exp);
3191 return nfserr; 3186 return nfserr;
3192 } 3187 }
3193 3188
3194 static __be32 3189 static __be32
3195 nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr, 3190 nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
3196 struct nfsd4_secinfo *secinfo) 3191 struct nfsd4_secinfo *secinfo)
3197 { 3192 {
3198 return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->si_exp); 3193 return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->si_exp);
3199 } 3194 }
3200 3195
3201 static __be32 3196 static __be32
3202 nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr, 3197 nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr,
3203 struct nfsd4_secinfo_no_name *secinfo) 3198 struct nfsd4_secinfo_no_name *secinfo)
3204 { 3199 {
3205 return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->sin_exp); 3200 return nfsd4_do_encode_secinfo(resp, nfserr, secinfo->sin_exp);
3206 } 3201 }
3207 3202
3208 /* 3203 /*
3209 * The SETATTR encode routine is special -- it always encodes a bitmap, 3204 * The SETATTR encode routine is special -- it always encodes a bitmap,
3210 * regardless of the error status. 3205 * regardless of the error status.
3211 */ 3206 */
3212 static __be32 3207 static __be32
3213 nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr) 3208 nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
3214 { 3209 {
3215 __be32 *p; 3210 __be32 *p;
3216 3211
3217 RESERVE_SPACE(12); 3212 RESERVE_SPACE(12);
3218 if (nfserr) { 3213 if (nfserr) {
3219 WRITE32(2); 3214 WRITE32(2);
3220 WRITE32(0); 3215 WRITE32(0);
3221 WRITE32(0); 3216 WRITE32(0);
3222 } 3217 }
3223 else { 3218 else {
3224 WRITE32(2); 3219 WRITE32(2);
3225 WRITE32(setattr->sa_bmval[0]); 3220 WRITE32(setattr->sa_bmval[0]);
3226 WRITE32(setattr->sa_bmval[1]); 3221 WRITE32(setattr->sa_bmval[1]);
3227 } 3222 }
3228 ADJUST_ARGS(); 3223 ADJUST_ARGS();
3229 return nfserr; 3224 return nfserr;
3230 } 3225 }
3231 3226
3232 static __be32 3227 static __be32
3233 nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd) 3228 nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
3234 { 3229 {
3235 __be32 *p; 3230 __be32 *p;
3236 3231
3237 if (!nfserr) { 3232 if (!nfserr) {
3238 RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE); 3233 RESERVE_SPACE(8 + NFS4_VERIFIER_SIZE);
3239 WRITEMEM(&scd->se_clientid, 8); 3234 WRITEMEM(&scd->se_clientid, 8);
3240 WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE); 3235 WRITEMEM(&scd->se_confirm, NFS4_VERIFIER_SIZE);
3241 ADJUST_ARGS(); 3236 ADJUST_ARGS();
3242 } 3237 }
3243 else if (nfserr == nfserr_clid_inuse) { 3238 else if (nfserr == nfserr_clid_inuse) {
3244 RESERVE_SPACE(8); 3239 RESERVE_SPACE(8);
3245 WRITE32(0); 3240 WRITE32(0);
3246 WRITE32(0); 3241 WRITE32(0);
3247 ADJUST_ARGS(); 3242 ADJUST_ARGS();
3248 } 3243 }
3249 return nfserr; 3244 return nfserr;
3250 } 3245 }
3251 3246
3252 static __be32 3247 static __be32
3253 nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write) 3248 nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
3254 { 3249 {
3255 __be32 *p; 3250 __be32 *p;
3256 3251
3257 if (!nfserr) { 3252 if (!nfserr) {
3258 RESERVE_SPACE(16); 3253 RESERVE_SPACE(16);
3259 WRITE32(write->wr_bytes_written); 3254 WRITE32(write->wr_bytes_written);
3260 WRITE32(write->wr_how_written); 3255 WRITE32(write->wr_how_written);
3261 WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE); 3256 WRITEMEM(write->wr_verifier.data, NFS4_VERIFIER_SIZE);
3262 ADJUST_ARGS(); 3257 ADJUST_ARGS();
3263 } 3258 }
3264 return nfserr; 3259 return nfserr;
3265 } 3260 }
3266 3261
3267 static __be32 3262 static __be32
3268 nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr, 3263 nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
3269 struct nfsd4_exchange_id *exid) 3264 struct nfsd4_exchange_id *exid)
3270 { 3265 {
3271 __be32 *p; 3266 __be32 *p;
3272 char *major_id; 3267 char *major_id;
3273 char *server_scope; 3268 char *server_scope;
3274 int major_id_sz; 3269 int major_id_sz;
3275 int server_scope_sz; 3270 int server_scope_sz;
3276 uint64_t minor_id = 0; 3271 uint64_t minor_id = 0;
3277 3272
3278 if (nfserr) 3273 if (nfserr)
3279 return nfserr; 3274 return nfserr;
3280 3275
3281 major_id = utsname()->nodename; 3276 major_id = utsname()->nodename;
3282 major_id_sz = strlen(major_id); 3277 major_id_sz = strlen(major_id);
3283 server_scope = utsname()->nodename; 3278 server_scope = utsname()->nodename;
3284 server_scope_sz = strlen(server_scope); 3279 server_scope_sz = strlen(server_scope);
3285 3280
3286 RESERVE_SPACE( 3281 RESERVE_SPACE(
3287 8 /* eir_clientid */ + 3282 8 /* eir_clientid */ +
3288 4 /* eir_sequenceid */ + 3283 4 /* eir_sequenceid */ +
3289 4 /* eir_flags */ + 3284 4 /* eir_flags */ +
3290 4 /* spr_how (SP4_NONE) */ + 3285 4 /* spr_how (SP4_NONE) */ +
3291 8 /* so_minor_id */ + 3286 8 /* so_minor_id */ +
3292 4 /* so_major_id.len */ + 3287 4 /* so_major_id.len */ +
3293 (XDR_QUADLEN(major_id_sz) * 4) + 3288 (XDR_QUADLEN(major_id_sz) * 4) +
3294 4 /* eir_server_scope.len */ + 3289 4 /* eir_server_scope.len */ +
3295 (XDR_QUADLEN(server_scope_sz) * 4) + 3290 (XDR_QUADLEN(server_scope_sz) * 4) +
3296 4 /* eir_server_impl_id.count (0) */); 3291 4 /* eir_server_impl_id.count (0) */);
3297 3292
3298 WRITEMEM(&exid->clientid, 8); 3293 WRITEMEM(&exid->clientid, 8);
3299 WRITE32(exid->seqid); 3294 WRITE32(exid->seqid);
3300 WRITE32(exid->flags); 3295 WRITE32(exid->flags);
3301 3296
3302 /* state_protect4_r. Currently only support SP4_NONE */ 3297 /* state_protect4_r. Currently only support SP4_NONE */
3303 BUG_ON(exid->spa_how != SP4_NONE); 3298 BUG_ON(exid->spa_how != SP4_NONE);
3304 WRITE32(exid->spa_how); 3299 WRITE32(exid->spa_how);
3305 3300
3306 /* The server_owner struct */ 3301 /* The server_owner struct */
3307 WRITE64(minor_id); /* Minor id */ 3302 WRITE64(minor_id); /* Minor id */
3308 /* major id */ 3303 /* major id */
3309 WRITE32(major_id_sz); 3304 WRITE32(major_id_sz);
3310 WRITEMEM(major_id, major_id_sz); 3305 WRITEMEM(major_id, major_id_sz);
3311 3306
3312 /* Server scope */ 3307 /* Server scope */
3313 WRITE32(server_scope_sz); 3308 WRITE32(server_scope_sz);
3314 WRITEMEM(server_scope, server_scope_sz); 3309 WRITEMEM(server_scope, server_scope_sz);
3315 3310
3316 /* Implementation id */ 3311 /* Implementation id */
3317 WRITE32(0); /* zero length nfs_impl_id4 array */ 3312 WRITE32(0); /* zero length nfs_impl_id4 array */
3318 ADJUST_ARGS(); 3313 ADJUST_ARGS();
3319 return 0; 3314 return 0;
3320 } 3315 }
3321 3316
3322 static __be32 3317 static __be32
3323 nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr, 3318 nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr,
3324 struct nfsd4_create_session *sess) 3319 struct nfsd4_create_session *sess)
3325 { 3320 {
3326 __be32 *p; 3321 __be32 *p;
3327 3322
3328 if (nfserr) 3323 if (nfserr)
3329 return nfserr; 3324 return nfserr;
3330 3325
3331 RESERVE_SPACE(24); 3326 RESERVE_SPACE(24);
3332 WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN); 3327 WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN);
3333 WRITE32(sess->seqid); 3328 WRITE32(sess->seqid);
3334 WRITE32(sess->flags); 3329 WRITE32(sess->flags);
3335 ADJUST_ARGS(); 3330 ADJUST_ARGS();
3336 3331
3337 RESERVE_SPACE(28); 3332 RESERVE_SPACE(28);
3338 WRITE32(0); /* headerpadsz */ 3333 WRITE32(0); /* headerpadsz */
3339 WRITE32(sess->fore_channel.maxreq_sz); 3334 WRITE32(sess->fore_channel.maxreq_sz);
3340 WRITE32(sess->fore_channel.maxresp_sz); 3335 WRITE32(sess->fore_channel.maxresp_sz);
3341 WRITE32(sess->fore_channel.maxresp_cached); 3336 WRITE32(sess->fore_channel.maxresp_cached);
3342 WRITE32(sess->fore_channel.maxops); 3337 WRITE32(sess->fore_channel.maxops);
3343 WRITE32(sess->fore_channel.maxreqs); 3338 WRITE32(sess->fore_channel.maxreqs);
3344 WRITE32(sess->fore_channel.nr_rdma_attrs); 3339 WRITE32(sess->fore_channel.nr_rdma_attrs);
3345 ADJUST_ARGS(); 3340 ADJUST_ARGS();
3346 3341
3347 if (sess->fore_channel.nr_rdma_attrs) { 3342 if (sess->fore_channel.nr_rdma_attrs) {
3348 RESERVE_SPACE(4); 3343 RESERVE_SPACE(4);
3349 WRITE32(sess->fore_channel.rdma_attrs); 3344 WRITE32(sess->fore_channel.rdma_attrs);
3350 ADJUST_ARGS(); 3345 ADJUST_ARGS();
3351 } 3346 }
3352 3347
3353 RESERVE_SPACE(28); 3348 RESERVE_SPACE(28);
3354 WRITE32(0); /* headerpadsz */ 3349 WRITE32(0); /* headerpadsz */
3355 WRITE32(sess->back_channel.maxreq_sz); 3350 WRITE32(sess->back_channel.maxreq_sz);
3356 WRITE32(sess->back_channel.maxresp_sz); 3351 WRITE32(sess->back_channel.maxresp_sz);
3357 WRITE32(sess->back_channel.maxresp_cached); 3352 WRITE32(sess->back_channel.maxresp_cached);
3358 WRITE32(sess->back_channel.maxops); 3353 WRITE32(sess->back_channel.maxops);
3359 WRITE32(sess->back_channel.maxreqs); 3354 WRITE32(sess->back_channel.maxreqs);
3360 WRITE32(sess->back_channel.nr_rdma_attrs); 3355 WRITE32(sess->back_channel.nr_rdma_attrs);
3361 ADJUST_ARGS(); 3356 ADJUST_ARGS();
3362 3357
3363 if (sess->back_channel.nr_rdma_attrs) { 3358 if (sess->back_channel.nr_rdma_attrs) {
3364 RESERVE_SPACE(4); 3359 RESERVE_SPACE(4);
3365 WRITE32(sess->back_channel.rdma_attrs); 3360 WRITE32(sess->back_channel.rdma_attrs);
3366 ADJUST_ARGS(); 3361 ADJUST_ARGS();
3367 } 3362 }
3368 return 0; 3363 return 0;
3369 } 3364 }
3370 3365
3371 static __be32 3366 static __be32
3372 nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, __be32 nfserr, 3367 nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, __be32 nfserr,
3373 struct nfsd4_destroy_session *destroy_session) 3368 struct nfsd4_destroy_session *destroy_session)
3374 { 3369 {
3375 return nfserr; 3370 return nfserr;
3376 } 3371 }
3377 3372
3378 static __be32 3373 static __be32
3379 nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, 3374 nfsd4_encode_free_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
3380 struct nfsd4_free_stateid *free_stateid) 3375 struct nfsd4_free_stateid *free_stateid)
3381 { 3376 {
3382 __be32 *p; 3377 __be32 *p;
3383 3378
3384 if (nfserr) 3379 if (nfserr)
3385 return nfserr; 3380 return nfserr;
3386 3381
3387 RESERVE_SPACE(4); 3382 RESERVE_SPACE(4);
3388 *p++ = nfserr; 3383 *p++ = nfserr;
3389 ADJUST_ARGS(); 3384 ADJUST_ARGS();
3390 return nfserr; 3385 return nfserr;
3391 } 3386 }
3392 3387
3393 static __be32 3388 static __be32
3394 nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr, 3389 nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
3395 struct nfsd4_sequence *seq) 3390 struct nfsd4_sequence *seq)
3396 { 3391 {
3397 __be32 *p; 3392 __be32 *p;
3398 3393
3399 if (nfserr) 3394 if (nfserr)
3400 return nfserr; 3395 return nfserr;
3401 3396
3402 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 20); 3397 RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 20);
3403 WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN); 3398 WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
3404 WRITE32(seq->seqid); 3399 WRITE32(seq->seqid);
3405 WRITE32(seq->slotid); 3400 WRITE32(seq->slotid);
3406 /* Note slotid's are numbered from zero: */ 3401 /* Note slotid's are numbered from zero: */
3407 WRITE32(seq->maxslots - 1); /* sr_highest_slotid */ 3402 WRITE32(seq->maxslots - 1); /* sr_highest_slotid */
3408 WRITE32(seq->maxslots - 1); /* sr_target_highest_slotid */ 3403 WRITE32(seq->maxslots - 1); /* sr_target_highest_slotid */
3409 WRITE32(seq->status_flags); 3404 WRITE32(seq->status_flags);
3410 3405
3411 ADJUST_ARGS(); 3406 ADJUST_ARGS();
3412 resp->cstate.datap = p; /* DRC cache data pointer */ 3407 resp->cstate.datap = p; /* DRC cache data pointer */
3413 return 0; 3408 return 0;
3414 } 3409 }
3415 3410
3416 static __be32 3411 static __be32
3417 nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr, 3412 nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
3418 struct nfsd4_test_stateid *test_stateid) 3413 struct nfsd4_test_stateid *test_stateid)
3419 { 3414 {
3420 struct nfsd4_test_stateid_id *stateid, *next; 3415 struct nfsd4_test_stateid_id *stateid, *next;
3421 __be32 *p; 3416 __be32 *p;
3422 3417
3423 RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids)); 3418 RESERVE_SPACE(4 + (4 * test_stateid->ts_num_ids));
3424 *p++ = htonl(test_stateid->ts_num_ids); 3419 *p++ = htonl(test_stateid->ts_num_ids);
3425 3420
3426 list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) { 3421 list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) {
3427 *p++ = stateid->ts_id_status; 3422 *p++ = stateid->ts_id_status;
3428 } 3423 }
3429 3424
3430 ADJUST_ARGS(); 3425 ADJUST_ARGS();
3431 return nfserr; 3426 return nfserr;
3432 } 3427 }
3433 3428
3434 static __be32 3429 static __be32
3435 nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p) 3430 nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
3436 { 3431 {
3437 return nfserr; 3432 return nfserr;
3438 } 3433 }
3439 3434
3440 typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *); 3435 typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
3441 3436
3442 /* 3437 /*
3443 * Note: nfsd4_enc_ops vector is shared for v4.0 and v4.1 3438 * Note: nfsd4_enc_ops vector is shared for v4.0 and v4.1
3444 * since we don't need to filter out obsolete ops as this is 3439 * since we don't need to filter out obsolete ops as this is
3445 * done in the decoding phase. 3440 * done in the decoding phase.
3446 */ 3441 */
3447 static nfsd4_enc nfsd4_enc_ops[] = { 3442 static nfsd4_enc nfsd4_enc_ops[] = {
3448 [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access, 3443 [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access,
3449 [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close, 3444 [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close,
3450 [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit, 3445 [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit,
3451 [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create, 3446 [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create,
3452 [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop, 3447 [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop,
3453 [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop, 3448 [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop,
3454 [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr, 3449 [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr,
3455 [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh, 3450 [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh,
3456 [OP_LINK] = (nfsd4_enc)nfsd4_encode_link, 3451 [OP_LINK] = (nfsd4_enc)nfsd4_encode_link,
3457 [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock, 3452 [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock,
3458 [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt, 3453 [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt,
3459 [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku, 3454 [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku,
3460 [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop, 3455 [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop,
3461 [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop, 3456 [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop,
3462 [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop, 3457 [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop,
3463 [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open, 3458 [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open,
3464 [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop, 3459 [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop,
3465 [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm, 3460 [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm,
3466 [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade, 3461 [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade,
3467 [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop, 3462 [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop,
3468 [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop, 3463 [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop,
3469 [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop, 3464 [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop,
3470 [OP_READ] = (nfsd4_enc)nfsd4_encode_read, 3465 [OP_READ] = (nfsd4_enc)nfsd4_encode_read,
3471 [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir, 3466 [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir,
3472 [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink, 3467 [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink,
3473 [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove, 3468 [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove,
3474 [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename, 3469 [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename,
3475 [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop, 3470 [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop,
3476 [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop, 3471 [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop,
3477 [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop, 3472 [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop,
3478 [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo, 3473 [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo,
3479 [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr, 3474 [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr,
3480 [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid, 3475 [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid,
3481 [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop, 3476 [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
3482 [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop, 3477 [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop,
3483 [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write, 3478 [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write,
3484 [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop, 3479 [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop,
3485 3480
3486 /* NFSv4.1 operations */ 3481 /* NFSv4.1 operations */
3487 [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop, 3482 [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop,
3488 [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session, 3483 [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session,
3489 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id, 3484 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
3490 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session, 3485 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
3491 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session, 3486 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_destroy_session,
3492 [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_free_stateid, 3487 [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_free_stateid,
3493 [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, 3488 [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
3494 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop, 3489 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop,
3495 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop, 3490 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
3496 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop, 3491 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop,
3497 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop, 3492 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop,
3498 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop, 3493 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop,
3499 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name, 3494 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name,
3500 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence, 3495 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence,
3501 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop, 3496 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop,
3502 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_test_stateid, 3497 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_test_stateid,
3503 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop, 3498 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
3504 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop, 3499 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop,
3505 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop, 3500 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop,
3506 }; 3501 };
3507 3502
3508 /* 3503 /*
3509 * Calculate the total amount of memory that the compound response has taken 3504 * Calculate the total amount of memory that the compound response has taken
3510 * after encoding the current operation with pad. 3505 * after encoding the current operation with pad.
3511 * 3506 *
3512 * pad: if operation is non-idempotent, pad was calculate by op_rsize_bop() 3507 * pad: if operation is non-idempotent, pad was calculate by op_rsize_bop()
3513 * which was specified at nfsd4_operation, else pad is zero. 3508 * which was specified at nfsd4_operation, else pad is zero.
3514 * 3509 *
3515 * Compare this length to the session se_fmaxresp_sz and se_fmaxresp_cached. 3510 * Compare this length to the session se_fmaxresp_sz and se_fmaxresp_cached.
3516 * 3511 *
3517 * Our se_fmaxresp_cached will always be a multiple of PAGE_SIZE, and so 3512 * Our se_fmaxresp_cached will always be a multiple of PAGE_SIZE, and so
3518 * will be at least a page and will therefore hold the xdr_buf head. 3513 * will be at least a page and will therefore hold the xdr_buf head.
3519 */ 3514 */
3520 __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad) 3515 __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 pad)
3521 { 3516 {
3522 struct xdr_buf *xb = &resp->rqstp->rq_res; 3517 struct xdr_buf *xb = &resp->rqstp->rq_res;
3523 struct nfsd4_session *session = NULL; 3518 struct nfsd4_session *session = NULL;
3524 struct nfsd4_slot *slot = resp->cstate.slot; 3519 struct nfsd4_slot *slot = resp->cstate.slot;
3525 u32 length, tlen = 0; 3520 u32 length, tlen = 0;
3526 3521
3527 if (!nfsd4_has_session(&resp->cstate)) 3522 if (!nfsd4_has_session(&resp->cstate))
3528 return 0; 3523 return 0;
3529 3524
3530 session = resp->cstate.session; 3525 session = resp->cstate.session;
3531 if (session == NULL) 3526 if (session == NULL)
3532 return 0; 3527 return 0;
3533 3528
3534 if (xb->page_len == 0) { 3529 if (xb->page_len == 0) {
3535 length = (char *)resp->p - (char *)xb->head[0].iov_base + pad; 3530 length = (char *)resp->p - (char *)xb->head[0].iov_base + pad;
3536 } else { 3531 } else {
3537 if (xb->tail[0].iov_base && xb->tail[0].iov_len > 0) 3532 if (xb->tail[0].iov_base && xb->tail[0].iov_len > 0)
3538 tlen = (char *)resp->p - (char *)xb->tail[0].iov_base; 3533 tlen = (char *)resp->p - (char *)xb->tail[0].iov_base;
3539 3534
3540 length = xb->head[0].iov_len + xb->page_len + tlen + pad; 3535 length = xb->head[0].iov_len + xb->page_len + tlen + pad;
3541 } 3536 }
3542 dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__, 3537 dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__,
3543 length, xb->page_len, tlen, pad); 3538 length, xb->page_len, tlen, pad);
3544 3539
3545 if (length > session->se_fchannel.maxresp_sz) 3540 if (length > session->se_fchannel.maxresp_sz)
3546 return nfserr_rep_too_big; 3541 return nfserr_rep_too_big;
3547 3542
3548 if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) && 3543 if ((slot->sl_flags & NFSD4_SLOT_CACHETHIS) &&
3549 length > session->se_fchannel.maxresp_cached) 3544 length > session->se_fchannel.maxresp_cached)
3550 return nfserr_rep_too_big_to_cache; 3545 return nfserr_rep_too_big_to_cache;
3551 3546
3552 return 0; 3547 return 0;
3553 } 3548 }
3554 3549
3555 void 3550 void
3556 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 3551 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3557 { 3552 {
3558 __be32 *statp; 3553 __be32 *statp;
3559 __be32 *p; 3554 __be32 *p;
3560 3555
3561 RESERVE_SPACE(8); 3556 RESERVE_SPACE(8);
3562 WRITE32(op->opnum); 3557 WRITE32(op->opnum);
3563 statp = p++; /* to be backfilled at the end */ 3558 statp = p++; /* to be backfilled at the end */
3564 ADJUST_ARGS(); 3559 ADJUST_ARGS();
3565 3560
3566 if (op->opnum == OP_ILLEGAL) 3561 if (op->opnum == OP_ILLEGAL)
3567 goto status; 3562 goto status;
3568 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) || 3563 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
3569 !nfsd4_enc_ops[op->opnum]); 3564 !nfsd4_enc_ops[op->opnum]);
3570 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u); 3565 op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u);
3571 /* nfsd4_check_drc_limit guarantees enough room for error status */ 3566 /* nfsd4_check_drc_limit guarantees enough room for error status */
3572 if (!op->status) 3567 if (!op->status)
3573 op->status = nfsd4_check_resp_size(resp, 0); 3568 op->status = nfsd4_check_resp_size(resp, 0);
3574 status: 3569 status:
3575 /* 3570 /*
3576 * Note: We write the status directly, instead of using WRITE32(), 3571 * Note: We write the status directly, instead of using WRITE32(),
3577 * since it is already in network byte order. 3572 * since it is already in network byte order.
3578 */ 3573 */
3579 *statp = op->status; 3574 *statp = op->status;
3580 } 3575 }
3581 3576
3582 /* 3577 /*
3583 * Encode the reply stored in the stateowner reply cache 3578 * Encode the reply stored in the stateowner reply cache
3584 * 3579 *
3585 * XDR note: do not encode rp->rp_buflen: the buffer contains the 3580 * XDR note: do not encode rp->rp_buflen: the buffer contains the
3586 * previously sent already encoded operation. 3581 * previously sent already encoded operation.
3587 * 3582 *
3588 * called with nfs4_lock_state() held 3583 * called with nfs4_lock_state() held
3589 */ 3584 */
3590 void 3585 void
3591 nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 3586 nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3592 { 3587 {
3593 __be32 *p; 3588 __be32 *p;
3594 struct nfs4_replay *rp = op->replay; 3589 struct nfs4_replay *rp = op->replay;
3595 3590
3596 BUG_ON(!rp); 3591 BUG_ON(!rp);
3597 3592
3598 RESERVE_SPACE(8); 3593 RESERVE_SPACE(8);
3599 WRITE32(op->opnum); 3594 WRITE32(op->opnum);
3600 *p++ = rp->rp_status; /* already xdr'ed */ 3595 *p++ = rp->rp_status; /* already xdr'ed */
3601 ADJUST_ARGS(); 3596 ADJUST_ARGS();
3602 3597
3603 RESERVE_SPACE(rp->rp_buflen); 3598 RESERVE_SPACE(rp->rp_buflen);
3604 WRITEMEM(rp->rp_buf, rp->rp_buflen); 3599 WRITEMEM(rp->rp_buf, rp->rp_buflen);
3605 ADJUST_ARGS(); 3600 ADJUST_ARGS();
3606 } 3601 }
3607 3602
3608 int 3603 int
3609 nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) 3604 nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
3610 { 3605 {
3611 return xdr_ressize_check(rqstp, p); 3606 return xdr_ressize_check(rqstp, p);
3612 } 3607 }
3613 3608
3614 int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp) 3609 int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp)
3615 { 3610 {
3616 struct svc_rqst *rqstp = rq; 3611 struct svc_rqst *rqstp = rq;
3617 struct nfsd4_compoundargs *args = rqstp->rq_argp; 3612 struct nfsd4_compoundargs *args = rqstp->rq_argp;
3618 3613
3619 if (args->ops != args->iops) { 3614 if (args->ops != args->iops) {
3620 kfree(args->ops); 3615 kfree(args->ops);
3621 args->ops = args->iops; 3616 args->ops = args->iops;
3622 } 3617 }
3623 kfree(args->tmpp); 3618 kfree(args->tmpp);
3624 args->tmpp = NULL; 3619 args->tmpp = NULL;
3625 while (args->to_free) { 3620 while (args->to_free) {
3626 struct tmpbuf *tb = args->to_free; 3621 struct tmpbuf *tb = args->to_free;
3627 args->to_free = tb->next; 3622 args->to_free = tb->next;
3628 tb->release(tb->buf); 3623 tb->release(tb->buf);
3629 kfree(tb); 3624 kfree(tb);
3630 } 3625 }
3631 return 1; 3626 return 1;
3632 } 3627 }
3633 3628
3634 int 3629 int
3635 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) 3630 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
3636 { 3631 {
3637 args->p = p; 3632 args->p = p;
3638 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; 3633 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
3639 args->pagelist = rqstp->rq_arg.pages; 3634 args->pagelist = rqstp->rq_arg.pages;
3640 args->pagelen = rqstp->rq_arg.page_len; 3635 args->pagelen = rqstp->rq_arg.page_len;
3641 args->tmpp = NULL; 3636 args->tmpp = NULL;
3642 args->to_free = NULL; 3637 args->to_free = NULL;
3643 args->ops = args->iops; 3638 args->ops = args->iops;
3644 args->rqstp = rqstp; 3639 args->rqstp = rqstp;
3645 3640
3646 return !nfsd4_decode_compound(args); 3641 return !nfsd4_decode_compound(args);
3647 } 3642 }
3648 3643
3649 int 3644 int
3650 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp) 3645 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp)
3651 { 3646 {
3652 /* 3647 /*
3653 * All that remains is to write the tag and operation count... 3648 * All that remains is to write the tag and operation count...
3654 */ 3649 */
3655 struct nfsd4_compound_state *cs = &resp->cstate; 3650 struct nfsd4_compound_state *cs = &resp->cstate;
3656 struct kvec *iov; 3651 struct kvec *iov;
3657 p = resp->tagp; 3652 p = resp->tagp;
3658 *p++ = htonl(resp->taglen); 3653 *p++ = htonl(resp->taglen);
3659 memcpy(p, resp->tag, resp->taglen); 3654 memcpy(p, resp->tag, resp->taglen);
3660 p += XDR_QUADLEN(resp->taglen); 3655 p += XDR_QUADLEN(resp->taglen);
3661 *p++ = htonl(resp->opcnt); 3656 *p++ = htonl(resp->opcnt);
3662 3657
3663 if (rqstp->rq_res.page_len) 3658 if (rqstp->rq_res.page_len)
3664 iov = &rqstp->rq_res.tail[0]; 3659 iov = &rqstp->rq_res.tail[0];
3665 else 3660 else
3666 iov = &rqstp->rq_res.head[0]; 3661 iov = &rqstp->rq_res.head[0];
3667 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; 3662 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
3668 BUG_ON(iov->iov_len > PAGE_SIZE); 3663 BUG_ON(iov->iov_len > PAGE_SIZE);
3669 if (nfsd4_has_session(cs)) { 3664 if (nfsd4_has_session(cs)) {
3670 if (cs->status != nfserr_replay_cache) { 3665 if (cs->status != nfserr_replay_cache) {
3671 nfsd4_store_cache_entry(resp); 3666 nfsd4_store_cache_entry(resp);
3672 cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE; 3667 cs->slot->sl_flags &= ~NFSD4_SLOT_INUSE;
3673 } 3668 }
3674 /* Renew the clientid on success and on replay */ 3669 /* Renew the clientid on success and on replay */
3675 release_session_client(cs->session); 3670 release_session_client(cs->session);
3676 nfsd4_put_session(cs->session); 3671 nfsd4_put_session(cs->session);
3677 } 3672 }
3678 return 1; 3673 return 1;
3679 } 3674 }
3680 3675
3681 /* 3676 /*
3682 * Local variables: 3677 * Local variables:
3683 * c-basic-offset: 8 3678 * c-basic-offset: 8
3684 * End: 3679 * End:
3685 */ 3680 */
3686 3681
1 /* 1 /*
2 * Server-side types for NFSv4. 2 * Server-side types for NFSv4.
3 * 3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan. 4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Kendrick Smith <kmsmith@umich.edu> 7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <andros@umich.edu> 8 * Andy Adamson <andros@umich.edu>
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 13 *
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its 19 * 3. Neither the name of the University nor the names of its
20 * contributors may be used to endorse or promote products derived 20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission. 21 * from this software without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * 34 *
35 */ 35 */
36 36
37 #ifndef _LINUX_NFSD_XDR4_H 37 #ifndef _LINUX_NFSD_XDR4_H
38 #define _LINUX_NFSD_XDR4_H 38 #define _LINUX_NFSD_XDR4_H
39 39
40 #include "state.h" 40 #include "state.h"
41 #include "nfsd.h" 41 #include "nfsd.h"
42 42
43 #define NFSD4_MAX_TAGLEN 128 43 #define NFSD4_MAX_TAGLEN 128
44 #define XDR_LEN(n) (((n) + 3) & ~3) 44 #define XDR_LEN(n) (((n) + 3) & ~3)
45 45
46 #define CURRENT_STATE_ID_FLAG (1<<0) 46 #define CURRENT_STATE_ID_FLAG (1<<0)
47 #define SAVED_STATE_ID_FLAG (1<<1) 47 #define SAVED_STATE_ID_FLAG (1<<1)
48 48
49 #define SET_STATE_ID(c, f) ((c)->sid_flags |= (f)) 49 #define SET_STATE_ID(c, f) ((c)->sid_flags |= (f))
50 #define HAS_STATE_ID(c, f) ((c)->sid_flags & (f)) 50 #define HAS_STATE_ID(c, f) ((c)->sid_flags & (f))
51 #define CLEAR_STATE_ID(c, f) ((c)->sid_flags &= ~(f)) 51 #define CLEAR_STATE_ID(c, f) ((c)->sid_flags &= ~(f))
52 52
53 struct nfsd4_compound_state { 53 struct nfsd4_compound_state {
54 struct svc_fh current_fh; 54 struct svc_fh current_fh;
55 struct svc_fh save_fh; 55 struct svc_fh save_fh;
56 struct nfs4_stateowner *replay_owner; 56 struct nfs4_stateowner *replay_owner;
57 /* For sessions DRC */ 57 /* For sessions DRC */
58 struct nfsd4_session *session; 58 struct nfsd4_session *session;
59 struct nfsd4_slot *slot; 59 struct nfsd4_slot *slot;
60 __be32 *datap; 60 __be32 *datap;
61 size_t iovlen; 61 size_t iovlen;
62 u32 minorversion; 62 u32 minorversion;
63 __be32 status; 63 __be32 status;
64 stateid_t current_stateid; 64 stateid_t current_stateid;
65 stateid_t save_stateid; 65 stateid_t save_stateid;
66 /* to indicate current and saved state id presents */ 66 /* to indicate current and saved state id presents */
67 u32 sid_flags; 67 u32 sid_flags;
68 }; 68 };
69 69
70 static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs) 70 static inline bool nfsd4_has_session(struct nfsd4_compound_state *cs)
71 { 71 {
72 return cs->slot != NULL; 72 return cs->slot != NULL;
73 } 73 }
74 74
75 struct nfsd4_change_info { 75 struct nfsd4_change_info {
76 u32 atomic; 76 u32 atomic;
77 bool change_supported; 77 bool change_supported;
78 u32 before_ctime_sec; 78 u32 before_ctime_sec;
79 u32 before_ctime_nsec; 79 u32 before_ctime_nsec;
80 u64 before_change; 80 u64 before_change;
81 u32 after_ctime_sec; 81 u32 after_ctime_sec;
82 u32 after_ctime_nsec; 82 u32 after_ctime_nsec;
83 u64 after_change; 83 u64 after_change;
84 }; 84 };
85 85
86 struct nfsd4_access { 86 struct nfsd4_access {
87 u32 ac_req_access; /* request */ 87 u32 ac_req_access; /* request */
88 u32 ac_supported; /* response */ 88 u32 ac_supported; /* response */
89 u32 ac_resp_access; /* response */ 89 u32 ac_resp_access; /* response */
90 }; 90 };
91 91
92 struct nfsd4_close { 92 struct nfsd4_close {
93 u32 cl_seqid; /* request */ 93 u32 cl_seqid; /* request */
94 stateid_t cl_stateid; /* request+response */ 94 stateid_t cl_stateid; /* request+response */
95 }; 95 };
96 96
97 struct nfsd4_commit { 97 struct nfsd4_commit {
98 u64 co_offset; /* request */ 98 u64 co_offset; /* request */
99 u32 co_count; /* request */ 99 u32 co_count; /* request */
100 nfs4_verifier co_verf; /* response */ 100 nfs4_verifier co_verf; /* response */
101 }; 101 };
102 102
103 struct nfsd4_create { 103 struct nfsd4_create {
104 u32 cr_namelen; /* request */ 104 u32 cr_namelen; /* request */
105 char * cr_name; /* request */ 105 char * cr_name; /* request */
106 u32 cr_type; /* request */ 106 u32 cr_type; /* request */
107 union { /* request */ 107 union { /* request */
108 struct { 108 struct {
109 u32 namelen; 109 u32 namelen;
110 char *name; 110 char *name;
111 } link; /* NF4LNK */ 111 } link; /* NF4LNK */
112 struct { 112 struct {
113 u32 specdata1; 113 u32 specdata1;
114 u32 specdata2; 114 u32 specdata2;
115 } dev; /* NF4BLK, NF4CHR */ 115 } dev; /* NF4BLK, NF4CHR */
116 } u; 116 } u;
117 u32 cr_bmval[3]; /* request */ 117 u32 cr_bmval[3]; /* request */
118 struct iattr cr_iattr; /* request */ 118 struct iattr cr_iattr; /* request */
119 struct nfsd4_change_info cr_cinfo; /* response */ 119 struct nfsd4_change_info cr_cinfo; /* response */
120 struct nfs4_acl *cr_acl; 120 struct nfs4_acl *cr_acl;
121 }; 121 };
122 #define cr_linklen u.link.namelen 122 #define cr_linklen u.link.namelen
123 #define cr_linkname u.link.name 123 #define cr_linkname u.link.name
124 #define cr_specdata1 u.dev.specdata1 124 #define cr_specdata1 u.dev.specdata1
125 #define cr_specdata2 u.dev.specdata2 125 #define cr_specdata2 u.dev.specdata2
126 126
127 struct nfsd4_delegreturn { 127 struct nfsd4_delegreturn {
128 stateid_t dr_stateid; 128 stateid_t dr_stateid;
129 }; 129 };
130 130
131 struct nfsd4_getattr { 131 struct nfsd4_getattr {
132 u32 ga_bmval[3]; /* request */ 132 u32 ga_bmval[3]; /* request */
133 struct svc_fh *ga_fhp; /* response */ 133 struct svc_fh *ga_fhp; /* response */
134 }; 134 };
135 135
136 struct nfsd4_link { 136 struct nfsd4_link {
137 u32 li_namelen; /* request */ 137 u32 li_namelen; /* request */
138 char * li_name; /* request */ 138 char * li_name; /* request */
139 struct nfsd4_change_info li_cinfo; /* response */ 139 struct nfsd4_change_info li_cinfo; /* response */
140 }; 140 };
141 141
142 struct nfsd4_lock_denied { 142 struct nfsd4_lock_denied {
143 clientid_t ld_clientid; 143 clientid_t ld_clientid;
144 struct xdr_netobj ld_owner; 144 struct xdr_netobj ld_owner;
145 u64 ld_start; 145 u64 ld_start;
146 u64 ld_length; 146 u64 ld_length;
147 u32 ld_type; 147 u32 ld_type;
148 }; 148 };
149 149
150 struct nfsd4_lock { 150 struct nfsd4_lock {
151 /* request */ 151 /* request */
152 u32 lk_type; 152 u32 lk_type;
153 u32 lk_reclaim; /* boolean */ 153 u32 lk_reclaim; /* boolean */
154 u64 lk_offset; 154 u64 lk_offset;
155 u64 lk_length; 155 u64 lk_length;
156 u32 lk_is_new; 156 u32 lk_is_new;
157 union { 157 union {
158 struct { 158 struct {
159 u32 open_seqid; 159 u32 open_seqid;
160 stateid_t open_stateid; 160 stateid_t open_stateid;
161 u32 lock_seqid; 161 u32 lock_seqid;
162 clientid_t clientid; 162 clientid_t clientid;
163 struct xdr_netobj owner; 163 struct xdr_netobj owner;
164 } new; 164 } new;
165 struct { 165 struct {
166 stateid_t lock_stateid; 166 stateid_t lock_stateid;
167 u32 lock_seqid; 167 u32 lock_seqid;
168 } old; 168 } old;
169 } v; 169 } v;
170 170
171 /* response */ 171 /* response */
172 union { 172 union {
173 struct { 173 struct {
174 stateid_t stateid; 174 stateid_t stateid;
175 } ok; 175 } ok;
176 struct nfsd4_lock_denied denied; 176 struct nfsd4_lock_denied denied;
177 } u; 177 } u;
178 }; 178 };
179 #define lk_new_open_seqid v.new.open_seqid 179 #define lk_new_open_seqid v.new.open_seqid
180 #define lk_new_open_stateid v.new.open_stateid 180 #define lk_new_open_stateid v.new.open_stateid
181 #define lk_new_lock_seqid v.new.lock_seqid 181 #define lk_new_lock_seqid v.new.lock_seqid
182 #define lk_new_clientid v.new.clientid 182 #define lk_new_clientid v.new.clientid
183 #define lk_new_owner v.new.owner 183 #define lk_new_owner v.new.owner
184 #define lk_old_lock_stateid v.old.lock_stateid 184 #define lk_old_lock_stateid v.old.lock_stateid
185 #define lk_old_lock_seqid v.old.lock_seqid 185 #define lk_old_lock_seqid v.old.lock_seqid
186 186
187 #define lk_rflags u.ok.rflags 187 #define lk_rflags u.ok.rflags
188 #define lk_resp_stateid u.ok.stateid 188 #define lk_resp_stateid u.ok.stateid
189 #define lk_denied u.denied 189 #define lk_denied u.denied
190 190
191 191
192 struct nfsd4_lockt { 192 struct nfsd4_lockt {
193 u32 lt_type; 193 u32 lt_type;
194 clientid_t lt_clientid; 194 clientid_t lt_clientid;
195 struct xdr_netobj lt_owner; 195 struct xdr_netobj lt_owner;
196 u64 lt_offset; 196 u64 lt_offset;
197 u64 lt_length; 197 u64 lt_length;
198 struct nfsd4_lock_denied lt_denied; 198 struct nfsd4_lock_denied lt_denied;
199 }; 199 };
200 200
201 201
202 struct nfsd4_locku { 202 struct nfsd4_locku {
203 u32 lu_type; 203 u32 lu_type;
204 u32 lu_seqid; 204 u32 lu_seqid;
205 stateid_t lu_stateid; 205 stateid_t lu_stateid;
206 u64 lu_offset; 206 u64 lu_offset;
207 u64 lu_length; 207 u64 lu_length;
208 }; 208 };
209 209
210 210
211 struct nfsd4_lookup { 211 struct nfsd4_lookup {
212 u32 lo_len; /* request */ 212 u32 lo_len; /* request */
213 char * lo_name; /* request */ 213 char * lo_name; /* request */
214 }; 214 };
215 215
216 struct nfsd4_putfh { 216 struct nfsd4_putfh {
217 u32 pf_fhlen; /* request */ 217 u32 pf_fhlen; /* request */
218 char *pf_fhval; /* request */ 218 char *pf_fhval; /* request */
219 }; 219 };
220 220
221 struct nfsd4_open { 221 struct nfsd4_open {
222 u32 op_claim_type; /* request */ 222 u32 op_claim_type; /* request */
223 struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */ 223 struct xdr_netobj op_fname; /* request - everything but CLAIM_PREV */
224 u32 op_delegate_type; /* request - CLAIM_PREV only */ 224 u32 op_delegate_type; /* request - CLAIM_PREV only */
225 stateid_t op_delegate_stateid; /* request - response */ 225 stateid_t op_delegate_stateid; /* request - response */
226 u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */ 226 u32 op_why_no_deleg; /* response - DELEG_NONE_EXT only */
227 u32 op_create; /* request */ 227 u32 op_create; /* request */
228 u32 op_createmode; /* request */ 228 u32 op_createmode; /* request */
229 u32 op_bmval[3]; /* request */ 229 u32 op_bmval[3]; /* request */
230 struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */ 230 struct iattr iattr; /* UNCHECKED4, GUARDED4, EXCLUSIVE4_1 */
231 nfs4_verifier op_verf __attribute__((aligned(32))); 231 nfs4_verifier op_verf __attribute__((aligned(32)));
232 /* EXCLUSIVE4 */ 232 /* EXCLUSIVE4 */
233 clientid_t op_clientid; /* request */ 233 clientid_t op_clientid; /* request */
234 struct xdr_netobj op_owner; /* request */ 234 struct xdr_netobj op_owner; /* request */
235 u32 op_seqid; /* request */ 235 u32 op_seqid; /* request */
236 u32 op_share_access; /* request */ 236 u32 op_share_access; /* request */
237 u32 op_share_deny; /* request */ 237 u32 op_share_deny; /* request */
238 u32 op_deleg_want; /* request */ 238 u32 op_deleg_want; /* request */
239 stateid_t op_stateid; /* response */ 239 stateid_t op_stateid; /* response */
240 u32 op_recall; /* recall */ 240 u32 op_recall; /* recall */
241 struct nfsd4_change_info op_cinfo; /* response */ 241 struct nfsd4_change_info op_cinfo; /* response */
242 u32 op_rflags; /* response */ 242 u32 op_rflags; /* response */
243 bool op_truncate; /* used during processing */ 243 bool op_truncate; /* used during processing */
244 bool op_created; /* used during processing */ 244 bool op_created; /* used during processing */
245 struct nfs4_openowner *op_openowner; /* used during processing */ 245 struct nfs4_openowner *op_openowner; /* used during processing */
246 struct nfs4_file *op_file; /* used during processing */ 246 struct nfs4_file *op_file; /* used during processing */
247 struct nfs4_ol_stateid *op_stp; /* used during processing */ 247 struct nfs4_ol_stateid *op_stp; /* used during processing */
248 struct nfs4_acl *op_acl; 248 struct nfs4_acl *op_acl;
249 }; 249 };
250 #define op_iattr iattr 250 #define op_iattr iattr
251 251
252 struct nfsd4_open_confirm { 252 struct nfsd4_open_confirm {
253 stateid_t oc_req_stateid /* request */; 253 stateid_t oc_req_stateid /* request */;
254 u32 oc_seqid /* request */; 254 u32 oc_seqid /* request */;
255 stateid_t oc_resp_stateid /* response */; 255 stateid_t oc_resp_stateid /* response */;
256 }; 256 };
257 257
258 struct nfsd4_open_downgrade { 258 struct nfsd4_open_downgrade {
259 stateid_t od_stateid; 259 stateid_t od_stateid;
260 u32 od_seqid; 260 u32 od_seqid;
261 u32 od_share_access; /* request */ 261 u32 od_share_access; /* request */
262 u32 od_deleg_want; /* request */ 262 u32 od_deleg_want; /* request */
263 u32 od_share_deny; /* request */ 263 u32 od_share_deny; /* request */
264 }; 264 };
265 265
266 266
267 struct nfsd4_read { 267 struct nfsd4_read {
268 stateid_t rd_stateid; /* request */ 268 stateid_t rd_stateid; /* request */
269 u64 rd_offset; /* request */ 269 u64 rd_offset; /* request */
270 u32 rd_length; /* request */ 270 u32 rd_length; /* request */
271 int rd_vlen; 271 int rd_vlen;
272 struct file *rd_filp; 272 struct file *rd_filp;
273 273
274 struct svc_rqst *rd_rqstp; /* response */ 274 struct svc_rqst *rd_rqstp; /* response */
275 struct svc_fh * rd_fhp; /* response */ 275 struct svc_fh * rd_fhp; /* response */
276 }; 276 };
277 277
278 struct nfsd4_readdir { 278 struct nfsd4_readdir {
279 u64 rd_cookie; /* request */ 279 u64 rd_cookie; /* request */
280 nfs4_verifier rd_verf; /* request */ 280 nfs4_verifier rd_verf; /* request */
281 u32 rd_dircount; /* request */ 281 u32 rd_dircount; /* request */
282 u32 rd_maxcount; /* request */ 282 u32 rd_maxcount; /* request */
283 u32 rd_bmval[3]; /* request */ 283 u32 rd_bmval[3]; /* request */
284 struct svc_rqst *rd_rqstp; /* response */ 284 struct svc_rqst *rd_rqstp; /* response */
285 struct svc_fh * rd_fhp; /* response */ 285 struct svc_fh * rd_fhp; /* response */
286 286
287 struct readdir_cd common; 287 struct readdir_cd common;
288 __be32 * buffer; 288 __be32 * buffer;
289 int buflen; 289 int buflen;
290 __be32 * offset; 290 __be32 * offset;
291 }; 291 };
292 292
293 struct nfsd4_release_lockowner { 293 struct nfsd4_release_lockowner {
294 clientid_t rl_clientid; 294 clientid_t rl_clientid;
295 struct xdr_netobj rl_owner; 295 struct xdr_netobj rl_owner;
296 }; 296 };
297 struct nfsd4_readlink { 297 struct nfsd4_readlink {
298 struct svc_rqst *rl_rqstp; /* request */ 298 struct svc_rqst *rl_rqstp; /* request */
299 struct svc_fh * rl_fhp; /* request */ 299 struct svc_fh * rl_fhp; /* request */
300 }; 300 };
301 301
302 struct nfsd4_remove { 302 struct nfsd4_remove {
303 u32 rm_namelen; /* request */ 303 u32 rm_namelen; /* request */
304 char * rm_name; /* request */ 304 char * rm_name; /* request */
305 struct nfsd4_change_info rm_cinfo; /* response */ 305 struct nfsd4_change_info rm_cinfo; /* response */
306 }; 306 };
307 307
308 struct nfsd4_rename { 308 struct nfsd4_rename {
309 u32 rn_snamelen; /* request */ 309 u32 rn_snamelen; /* request */
310 char * rn_sname; /* request */ 310 char * rn_sname; /* request */
311 u32 rn_tnamelen; /* request */ 311 u32 rn_tnamelen; /* request */
312 char * rn_tname; /* request */ 312 char * rn_tname; /* request */
313 struct nfsd4_change_info rn_sinfo; /* response */ 313 struct nfsd4_change_info rn_sinfo; /* response */
314 struct nfsd4_change_info rn_tinfo; /* response */ 314 struct nfsd4_change_info rn_tinfo; /* response */
315 }; 315 };
316 316
317 struct nfsd4_secinfo { 317 struct nfsd4_secinfo {
318 u32 si_namelen; /* request */ 318 u32 si_namelen; /* request */
319 char *si_name; /* request */ 319 char *si_name; /* request */
320 struct svc_export *si_exp; /* response */ 320 struct svc_export *si_exp; /* response */
321 }; 321 };
322 322
323 struct nfsd4_secinfo_no_name { 323 struct nfsd4_secinfo_no_name {
324 u32 sin_style; /* request */ 324 u32 sin_style; /* request */
325 struct svc_export *sin_exp; /* response */ 325 struct svc_export *sin_exp; /* response */
326 }; 326 };
327 327
328 struct nfsd4_setattr { 328 struct nfsd4_setattr {
329 stateid_t sa_stateid; /* request */ 329 stateid_t sa_stateid; /* request */
330 u32 sa_bmval[3]; /* request */ 330 u32 sa_bmval[3]; /* request */
331 struct iattr sa_iattr; /* request */ 331 struct iattr sa_iattr; /* request */
332 struct nfs4_acl *sa_acl; 332 struct nfs4_acl *sa_acl;
333 }; 333 };
334 334
335 struct nfsd4_setclientid { 335 struct nfsd4_setclientid {
336 nfs4_verifier se_verf; /* request */ 336 nfs4_verifier se_verf; /* request */
337 struct xdr_netobj se_name; 337 struct xdr_netobj se_name;
338 u32 se_callback_prog; /* request */ 338 u32 se_callback_prog; /* request */
339 u32 se_callback_netid_len; /* request */ 339 u32 se_callback_netid_len; /* request */
340 char * se_callback_netid_val; /* request */ 340 char * se_callback_netid_val; /* request */
341 u32 se_callback_addr_len; /* request */ 341 u32 se_callback_addr_len; /* request */
342 char * se_callback_addr_val; /* request */ 342 char * se_callback_addr_val; /* request */
343 u32 se_callback_ident; /* request */ 343 u32 se_callback_ident; /* request */
344 clientid_t se_clientid; /* response */ 344 clientid_t se_clientid; /* response */
345 nfs4_verifier se_confirm; /* response */ 345 nfs4_verifier se_confirm; /* response */
346 }; 346 };
347 347
348 struct nfsd4_setclientid_confirm { 348 struct nfsd4_setclientid_confirm {
349 clientid_t sc_clientid; 349 clientid_t sc_clientid;
350 nfs4_verifier sc_confirm; 350 nfs4_verifier sc_confirm;
351 }; 351 };
352 352
353 struct nfsd4_saved_compoundargs { 353 struct nfsd4_saved_compoundargs {
354 __be32 *p; 354 __be32 *p;
355 __be32 *end; 355 __be32 *end;
356 int pagelen; 356 int pagelen;
357 struct page **pagelist; 357 struct page **pagelist;
358 }; 358 };
359 359
360 struct nfsd4_test_stateid_id { 360 struct nfsd4_test_stateid_id {
361 __be32 ts_id_status; 361 __be32 ts_id_status;
362 stateid_t ts_id_stateid; 362 stateid_t ts_id_stateid;
363 struct list_head ts_id_list; 363 struct list_head ts_id_list;
364 }; 364 };
365 365
366 struct nfsd4_test_stateid { 366 struct nfsd4_test_stateid {
367 u32 ts_num_ids; 367 u32 ts_num_ids;
368 struct list_head ts_stateid_list; 368 struct list_head ts_stateid_list;
369 }; 369 };
370 370
371 struct nfsd4_free_stateid { 371 struct nfsd4_free_stateid {
372 stateid_t fr_stateid; /* request */ 372 stateid_t fr_stateid; /* request */
373 __be32 fr_status; /* response */ 373 __be32 fr_status; /* response */
374 }; 374 };
375 375
376 /* also used for NVERIFY */ 376 /* also used for NVERIFY */
377 struct nfsd4_verify { 377 struct nfsd4_verify {
378 u32 ve_bmval[3]; /* request */ 378 u32 ve_bmval[3]; /* request */
379 u32 ve_attrlen; /* request */ 379 u32 ve_attrlen; /* request */
380 char * ve_attrval; /* request */ 380 char * ve_attrval; /* request */
381 }; 381 };
382 382
383 struct nfsd4_write { 383 struct nfsd4_write {
384 stateid_t wr_stateid; /* request */ 384 stateid_t wr_stateid; /* request */
385 u64 wr_offset; /* request */ 385 u64 wr_offset; /* request */
386 u32 wr_stable_how; /* request */ 386 u32 wr_stable_how; /* request */
387 u32 wr_buflen; /* request */ 387 u32 wr_buflen; /* request */
388 struct kvec wr_head; 388 struct kvec wr_head;
389 struct page ** wr_pagelist; /* request */ 389 struct page ** wr_pagelist; /* request */
390 390
391 u32 wr_bytes_written; /* response */ 391 u32 wr_bytes_written; /* response */
392 u32 wr_how_written; /* response */ 392 u32 wr_how_written; /* response */
393 nfs4_verifier wr_verifier; /* response */ 393 nfs4_verifier wr_verifier; /* response */
394 }; 394 };
395 395
396 struct nfsd4_exchange_id { 396 struct nfsd4_exchange_id {
397 nfs4_verifier verifier; 397 nfs4_verifier verifier;
398 struct xdr_netobj clname; 398 struct xdr_netobj clname;
399 u32 flags; 399 u32 flags;
400 clientid_t clientid; 400 clientid_t clientid;
401 u32 seqid; 401 u32 seqid;
402 int spa_how; 402 int spa_how;
403 }; 403 };
404 404
405 struct nfsd4_sequence { 405 struct nfsd4_sequence {
406 struct nfs4_sessionid sessionid; /* request/response */ 406 struct nfs4_sessionid sessionid; /* request/response */
407 u32 seqid; /* request/response */ 407 u32 seqid; /* request/response */
408 u32 slotid; /* request/response */ 408 u32 slotid; /* request/response */
409 u32 maxslots; /* request/response */ 409 u32 maxslots; /* request/response */
410 u32 cachethis; /* request */ 410 u32 cachethis; /* request */
411 #if 0 411 #if 0
412 u32 target_maxslots; /* response */ 412 u32 target_maxslots; /* response */
413 #endif /* not yet */ 413 #endif /* not yet */
414 u32 status_flags; /* response */ 414 u32 status_flags; /* response */
415 }; 415 };
416 416
417 struct nfsd4_destroy_session { 417 struct nfsd4_destroy_session {
418 struct nfs4_sessionid sessionid; 418 struct nfs4_sessionid sessionid;
419 }; 419 };
420 420
421 struct nfsd4_destroy_clientid { 421 struct nfsd4_destroy_clientid {
422 clientid_t clientid; 422 clientid_t clientid;
423 }; 423 };
424 424
425 struct nfsd4_reclaim_complete { 425 struct nfsd4_reclaim_complete {
426 u32 rca_one_fs; 426 u32 rca_one_fs;
427 }; 427 };
428 428
429 struct nfsd4_op { 429 struct nfsd4_op {
430 int opnum; 430 int opnum;
431 __be32 status; 431 __be32 status;
432 union { 432 union {
433 struct nfsd4_access access; 433 struct nfsd4_access access;
434 struct nfsd4_close close; 434 struct nfsd4_close close;
435 struct nfsd4_commit commit; 435 struct nfsd4_commit commit;
436 struct nfsd4_create create; 436 struct nfsd4_create create;
437 struct nfsd4_delegreturn delegreturn; 437 struct nfsd4_delegreturn delegreturn;
438 struct nfsd4_getattr getattr; 438 struct nfsd4_getattr getattr;
439 struct svc_fh * getfh; 439 struct svc_fh * getfh;
440 struct nfsd4_link link; 440 struct nfsd4_link link;
441 struct nfsd4_lock lock; 441 struct nfsd4_lock lock;
442 struct nfsd4_lockt lockt; 442 struct nfsd4_lockt lockt;
443 struct nfsd4_locku locku; 443 struct nfsd4_locku locku;
444 struct nfsd4_lookup lookup; 444 struct nfsd4_lookup lookup;
445 struct nfsd4_verify nverify; 445 struct nfsd4_verify nverify;
446 struct nfsd4_open open; 446 struct nfsd4_open open;
447 struct nfsd4_open_confirm open_confirm; 447 struct nfsd4_open_confirm open_confirm;
448 struct nfsd4_open_downgrade open_downgrade; 448 struct nfsd4_open_downgrade open_downgrade;
449 struct nfsd4_putfh putfh; 449 struct nfsd4_putfh putfh;
450 struct nfsd4_read read; 450 struct nfsd4_read read;
451 struct nfsd4_readdir readdir; 451 struct nfsd4_readdir readdir;
452 struct nfsd4_readlink readlink; 452 struct nfsd4_readlink readlink;
453 struct nfsd4_remove remove; 453 struct nfsd4_remove remove;
454 struct nfsd4_rename rename; 454 struct nfsd4_rename rename;
455 clientid_t renew; 455 clientid_t renew;
456 struct nfsd4_secinfo secinfo; 456 struct nfsd4_secinfo secinfo;
457 struct nfsd4_setattr setattr; 457 struct nfsd4_setattr setattr;
458 struct nfsd4_setclientid setclientid; 458 struct nfsd4_setclientid setclientid;
459 struct nfsd4_setclientid_confirm setclientid_confirm; 459 struct nfsd4_setclientid_confirm setclientid_confirm;
460 struct nfsd4_verify verify; 460 struct nfsd4_verify verify;
461 struct nfsd4_write write; 461 struct nfsd4_write write;
462 struct nfsd4_release_lockowner release_lockowner; 462 struct nfsd4_release_lockowner release_lockowner;
463 463
464 /* NFSv4.1 */ 464 /* NFSv4.1 */
465 struct nfsd4_exchange_id exchange_id; 465 struct nfsd4_exchange_id exchange_id;
466 struct nfsd4_backchannel_ctl backchannel_ctl; 466 struct nfsd4_backchannel_ctl backchannel_ctl;
467 struct nfsd4_bind_conn_to_session bind_conn_to_session; 467 struct nfsd4_bind_conn_to_session bind_conn_to_session;
468 struct nfsd4_create_session create_session; 468 struct nfsd4_create_session create_session;
469 struct nfsd4_destroy_session destroy_session; 469 struct nfsd4_destroy_session destroy_session;
470 struct nfsd4_sequence sequence; 470 struct nfsd4_sequence sequence;
471 struct nfsd4_reclaim_complete reclaim_complete; 471 struct nfsd4_reclaim_complete reclaim_complete;
472 struct nfsd4_test_stateid test_stateid; 472 struct nfsd4_test_stateid test_stateid;
473 struct nfsd4_free_stateid free_stateid; 473 struct nfsd4_free_stateid free_stateid;
474 } u; 474 } u;
475 struct nfs4_replay * replay; 475 struct nfs4_replay * replay;
476 }; 476 };
477 477
478 bool nfsd4_cache_this_op(struct nfsd4_op *); 478 bool nfsd4_cache_this_op(struct nfsd4_op *);
479 479
480 struct nfsd4_compoundargs { 480 struct nfsd4_compoundargs {
481 /* scratch variables for XDR decode */ 481 /* scratch variables for XDR decode */
482 __be32 * p; 482 __be32 * p;
483 __be32 * end; 483 __be32 * end;
484 struct page ** pagelist; 484 struct page ** pagelist;
485 int pagelen; 485 int pagelen;
486 __be32 tmp[8]; 486 __be32 tmp[8];
487 __be32 * tmpp; 487 __be32 * tmpp;
488 struct tmpbuf { 488 struct tmpbuf {
489 struct tmpbuf *next; 489 struct tmpbuf *next;
490 void (*release)(const void *); 490 void (*release)(const void *);
491 void *buf; 491 void *buf;
492 } *to_free; 492 } *to_free;
493 493
494 struct svc_rqst *rqstp; 494 struct svc_rqst *rqstp;
495 495
496 u32 taglen; 496 u32 taglen;
497 char * tag; 497 char * tag;
498 u32 minorversion; 498 u32 minorversion;
499 u32 opcnt; 499 u32 opcnt;
500 struct nfsd4_op *ops; 500 struct nfsd4_op *ops;
501 struct nfsd4_op iops[8]; 501 struct nfsd4_op iops[8];
502 int cachetype; 502 int cachetype;
503 }; 503 };
504 504
505 struct nfsd4_compoundres { 505 struct nfsd4_compoundres {
506 /* scratch variables for XDR encode */ 506 /* scratch variables for XDR encode */
507 __be32 * p; 507 __be32 * p;
508 __be32 * end; 508 __be32 * end;
509 struct xdr_buf * xbuf; 509 struct xdr_buf * xbuf;
510 struct svc_rqst * rqstp; 510 struct svc_rqst * rqstp;
511 511
512 u32 taglen; 512 u32 taglen;
513 char * tag; 513 char * tag;
514 u32 opcnt; 514 u32 opcnt;
515 __be32 * tagp; /* tag, opcount encode location */ 515 __be32 * tagp; /* tag, opcount encode location */
516 struct nfsd4_compound_state cstate; 516 struct nfsd4_compound_state cstate;
517 }; 517 };
518 518
519 static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp) 519 static inline bool nfsd4_is_solo_sequence(struct nfsd4_compoundres *resp)
520 { 520 {
521 struct nfsd4_compoundargs *args = resp->rqstp->rq_argp; 521 struct nfsd4_compoundargs *args = resp->rqstp->rq_argp;
522 return resp->opcnt == 1 && args->ops[0].opnum == OP_SEQUENCE; 522 return resp->opcnt == 1 && args->ops[0].opnum == OP_SEQUENCE;
523 } 523 }
524 524
525 static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp) 525 static inline bool nfsd4_not_cached(struct nfsd4_compoundres *resp)
526 { 526 {
527 return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS) 527 return !(resp->cstate.slot->sl_flags & NFSD4_SLOT_CACHETHIS)
528 || nfsd4_is_solo_sequence(resp); 528 || nfsd4_is_solo_sequence(resp);
529 } 529 }
530 530
531 static inline bool nfsd4_last_compound_op(struct svc_rqst *rqstp) 531 static inline bool nfsd4_last_compound_op(struct svc_rqst *rqstp)
532 { 532 {
533 struct nfsd4_compoundres *resp = rqstp->rq_resp; 533 struct nfsd4_compoundres *resp = rqstp->rq_resp;
534 struct nfsd4_compoundargs *argp = rqstp->rq_argp; 534 struct nfsd4_compoundargs *argp = rqstp->rq_argp;
535 535
536 return argp->opcnt == resp->opcnt; 536 return argp->opcnt == resp->opcnt;
537 } 537 }
538 538
539 #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) 539 #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs)
540 540
541 static inline void 541 static inline void
542 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) 542 set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp)
543 { 543 {
544 BUG_ON(!fhp->fh_pre_saved); 544 BUG_ON(!fhp->fh_pre_saved);
545 cinfo->atomic = fhp->fh_post_saved; 545 cinfo->atomic = fhp->fh_post_saved;
546 cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode); 546 cinfo->change_supported = IS_I_VERSION(fhp->fh_dentry->d_inode);
547 547
548 cinfo->before_change = fhp->fh_pre_change; 548 cinfo->before_change = fhp->fh_pre_change;
549 cinfo->after_change = fhp->fh_post_change; 549 cinfo->after_change = fhp->fh_post_change;
550 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; 550 cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec;
551 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; 551 cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec;
552 cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; 552 cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec;
553 cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; 553 cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec;
554 554
555 } 555 }
556 556
557 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); 557 int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *);
558 int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *, 558 int nfs4svc_decode_compoundargs(struct svc_rqst *, __be32 *,
559 struct nfsd4_compoundargs *); 559 struct nfsd4_compoundargs *);
560 int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *, 560 int nfs4svc_encode_compoundres(struct svc_rqst *, __be32 *,
561 struct nfsd4_compoundres *); 561 struct nfsd4_compoundres *);
562 __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32); 562 __be32 nfsd4_check_resp_size(struct nfsd4_compoundres *, u32);
563 void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *); 563 void nfsd4_encode_operation(struct nfsd4_compoundres *, struct nfsd4_op *);
564 void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op); 564 void nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op);
565 __be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 565 __be32 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
566 struct dentry *dentry, __be32 *buffer, int *countp, 566 struct dentry *dentry, __be32 **buffer, int countp,
567 u32 *bmval, struct svc_rqst *, int ignore_crossmnt); 567 u32 *bmval, struct svc_rqst *, int ignore_crossmnt);
568 extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp, 568 extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
569 struct nfsd4_compound_state *, 569 struct nfsd4_compound_state *,
570 struct nfsd4_setclientid *setclid); 570 struct nfsd4_setclientid *setclid);
571 extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, 571 extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
572 struct nfsd4_compound_state *, 572 struct nfsd4_compound_state *,
573 struct nfsd4_setclientid_confirm *setclientid_confirm); 573 struct nfsd4_setclientid_confirm *setclientid_confirm);
574 extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp); 574 extern void nfsd4_store_cache_entry(struct nfsd4_compoundres *resp);
575 extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp, 575 extern __be32 nfsd4_replay_cache_entry(struct nfsd4_compoundres *resp,
576 struct nfsd4_sequence *seq); 576 struct nfsd4_sequence *seq);
577 extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp, 577 extern __be32 nfsd4_exchange_id(struct svc_rqst *rqstp,
578 struct nfsd4_compound_state *, struct nfsd4_exchange_id *); 578 struct nfsd4_compound_state *, struct nfsd4_exchange_id *);
579 extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *); 579 extern __be32 nfsd4_backchannel_ctl(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_backchannel_ctl *);
580 extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *); 580 extern __be32 nfsd4_bind_conn_to_session(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_bind_conn_to_session *);
581 extern __be32 nfsd4_create_session(struct svc_rqst *, 581 extern __be32 nfsd4_create_session(struct svc_rqst *,
582 struct nfsd4_compound_state *, 582 struct nfsd4_compound_state *,
583 struct nfsd4_create_session *); 583 struct nfsd4_create_session *);
584 extern __be32 nfsd4_sequence(struct svc_rqst *, 584 extern __be32 nfsd4_sequence(struct svc_rqst *,
585 struct nfsd4_compound_state *, 585 struct nfsd4_compound_state *,
586 struct nfsd4_sequence *); 586 struct nfsd4_sequence *);
587 extern __be32 nfsd4_destroy_session(struct svc_rqst *, 587 extern __be32 nfsd4_destroy_session(struct svc_rqst *,
588 struct nfsd4_compound_state *, 588 struct nfsd4_compound_state *,
589 struct nfsd4_destroy_session *); 589 struct nfsd4_destroy_session *);
590 extern __be32 nfsd4_destroy_clientid(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_destroy_clientid *); 590 extern __be32 nfsd4_destroy_clientid(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_destroy_clientid *);
591 __be32 nfsd4_reclaim_complete(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_reclaim_complete *); 591 __be32 nfsd4_reclaim_complete(struct svc_rqst *, struct nfsd4_compound_state *, struct nfsd4_reclaim_complete *);
592 extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *, 592 extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *,
593 struct nfsd4_open *open, struct nfsd_net *nn); 593 struct nfsd4_open *open, struct nfsd_net *nn);
594 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp, 594 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
595 struct svc_fh *current_fh, struct nfsd4_open *open); 595 struct svc_fh *current_fh, struct nfsd4_open *open);
596 extern void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status); 596 extern void nfsd4_cleanup_open_state(struct nfsd4_open *open, __be32 status);
597 extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp, 597 extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
598 struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc); 598 struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc);
599 extern __be32 nfsd4_close(struct svc_rqst *rqstp, 599 extern __be32 nfsd4_close(struct svc_rqst *rqstp,
600 struct nfsd4_compound_state *, 600 struct nfsd4_compound_state *,
601 struct nfsd4_close *close); 601 struct nfsd4_close *close);
602 extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp, 602 extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
603 struct nfsd4_compound_state *, 603 struct nfsd4_compound_state *,
604 struct nfsd4_open_downgrade *od); 604 struct nfsd4_open_downgrade *od);
605 extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *, 605 extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
606 struct nfsd4_lock *lock); 606 struct nfsd4_lock *lock);
607 extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, 607 extern __be32 nfsd4_lockt(struct svc_rqst *rqstp,
608 struct nfsd4_compound_state *, 608 struct nfsd4_compound_state *,
609 struct nfsd4_lockt *lockt); 609 struct nfsd4_lockt *lockt);
610 extern __be32 nfsd4_locku(struct svc_rqst *rqstp, 610 extern __be32 nfsd4_locku(struct svc_rqst *rqstp,
611 struct nfsd4_compound_state *, 611 struct nfsd4_compound_state *,
612 struct nfsd4_locku *locku); 612 struct nfsd4_locku *locku);
613 extern __be32 613 extern __be32
614 nfsd4_release_lockowner(struct svc_rqst *rqstp, 614 nfsd4_release_lockowner(struct svc_rqst *rqstp,
615 struct nfsd4_compound_state *, 615 struct nfsd4_compound_state *,
616 struct nfsd4_release_lockowner *rlockowner); 616 struct nfsd4_release_lockowner *rlockowner);
617 extern int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp); 617 extern int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp);
618 extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp, 618 extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
619 struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr); 619 struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
620 extern __be32 nfsd4_renew(struct svc_rqst *rqstp, 620 extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
621 struct nfsd4_compound_state *, clientid_t *clid); 621 struct nfsd4_compound_state *, clientid_t *clid);
622 extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp, 622 extern __be32 nfsd4_test_stateid(struct svc_rqst *rqstp,
623 struct nfsd4_compound_state *, struct nfsd4_test_stateid *test_stateid); 623 struct nfsd4_compound_state *, struct nfsd4_test_stateid *test_stateid);
624 extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp, 624 extern __be32 nfsd4_free_stateid(struct svc_rqst *rqstp,
625 struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid); 625 struct nfsd4_compound_state *, struct nfsd4_free_stateid *free_stateid);
626 #endif 626 #endif
627 627
628 /* 628 /*
629 * Local variables: 629 * Local variables:
630 * c-basic-offset: 8 630 * c-basic-offset: 8
631 * End: 631 * End:
632 */ 632 */
633 633