diff options
author | J.Bruce Fields <bfields@fieldses.org> | 2006-12-13 03:35:27 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-13 12:05:54 -0500 |
commit | ca3643171bc6e08b7c4d1f9a2ce659541a01a7fe (patch) | |
tree | 2128accc9584e7dd69f6b62c62ef6631f5da231f /fs/nfsd | |
parent | 01f3bd1f03599470e4695392b6ae055ed8506978 (diff) |
[PATCH] knfsd: nfsd4: pass saved and current fh together into nfsd4 operations
Pass the saved and current filehandles together into all the nfsd4 compound
operations.
I want a unified interface to these operations so we can just call them by
pointer and throw out the huge switch statement.
Also I'll eventually want a structure like this--that holds the state used
during compound processing--for deferral.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 348 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 68 |
2 files changed, 244 insertions, 172 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 793a0b0a6cdd..1b6756aa013c 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -162,7 +162,8 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ | |||
162 | 162 | ||
163 | 163 | ||
164 | static inline __be32 | 164 | static inline __be32 |
165 | nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner) | 165 | nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
166 | struct nfsd4_open *open, struct nfs4_stateowner **replay_owner) | ||
166 | { | 167 | { |
167 | __be32 status; | 168 | __be32 status; |
168 | dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n", | 169 | dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n", |
@@ -179,11 +180,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open | |||
179 | status = nfsd4_process_open1(open); | 180 | status = nfsd4_process_open1(open); |
180 | if (status == nfserr_replay_me) { | 181 | if (status == nfserr_replay_me) { |
181 | struct nfs4_replay *rp = &open->op_stateowner->so_replay; | 182 | struct nfs4_replay *rp = &open->op_stateowner->so_replay; |
182 | fh_put(current_fh); | 183 | fh_put(&cstate->current_fh); |
183 | current_fh->fh_handle.fh_size = rp->rp_openfh_len; | 184 | cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len; |
184 | memcpy(¤t_fh->fh_handle.fh_base, rp->rp_openfh, | 185 | memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh, |
185 | rp->rp_openfh_len); | 186 | rp->rp_openfh_len); |
186 | status = fh_verify(rqstp, current_fh, 0, MAY_NOP); | 187 | status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); |
187 | if (status) | 188 | if (status) |
188 | dprintk("nfsd4_open: replay failed" | 189 | dprintk("nfsd4_open: replay failed" |
189 | " restoring previous filehandle\n"); | 190 | " restoring previous filehandle\n"); |
@@ -215,7 +216,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open | |||
215 | * (3) set open->op_truncate if the file is to be | 216 | * (3) set open->op_truncate if the file is to be |
216 | * truncated after opening, (4) do permission checking. | 217 | * truncated after opening, (4) do permission checking. |
217 | */ | 218 | */ |
218 | status = do_open_lookup(rqstp, current_fh, open); | 219 | status = do_open_lookup(rqstp, &cstate->current_fh, |
220 | open); | ||
219 | if (status) | 221 | if (status) |
220 | goto out; | 222 | goto out; |
221 | break; | 223 | break; |
@@ -227,7 +229,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open | |||
227 | * open->op_truncate if the file is to be truncated | 229 | * open->op_truncate if the file is to be truncated |
228 | * after opening, (3) do permission checking. | 230 | * after opening, (3) do permission checking. |
229 | */ | 231 | */ |
230 | status = do_open_fhandle(rqstp, current_fh, open); | 232 | status = do_open_fhandle(rqstp, &cstate->current_fh, |
233 | open); | ||
231 | if (status) | 234 | if (status) |
232 | goto out; | 235 | goto out; |
233 | break; | 236 | break; |
@@ -248,7 +251,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open | |||
248 | * successful, it (1) truncates the file if open->op_truncate was | 251 | * successful, it (1) truncates the file if open->op_truncate was |
249 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. | 252 | * set, (2) sets open->op_stateid, (3) sets open->op_delegation. |
250 | */ | 253 | */ |
251 | status = nfsd4_process_open2(rqstp, current_fh, open); | 254 | status = nfsd4_process_open2(rqstp, &cstate->current_fh, open); |
252 | out: | 255 | out: |
253 | if (open->op_stateowner) { | 256 | if (open->op_stateowner) { |
254 | nfs4_get_stateowner(open->op_stateowner); | 257 | nfs4_get_stateowner(open->op_stateowner); |
@@ -262,52 +265,54 @@ out: | |||
262 | * filehandle-manipulating ops. | 265 | * filehandle-manipulating ops. |
263 | */ | 266 | */ |
264 | static inline __be32 | 267 | static inline __be32 |
265 | nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh) | 268 | nfsd4_getfh(struct nfsd4_compound_state *cstate, struct svc_fh **getfh) |
266 | { | 269 | { |
267 | if (!current_fh->fh_dentry) | 270 | if (!cstate->current_fh.fh_dentry) |
268 | return nfserr_nofilehandle; | 271 | return nfserr_nofilehandle; |
269 | 272 | ||
270 | *getfh = current_fh; | 273 | *getfh = &cstate->current_fh; |
271 | return nfs_ok; | 274 | return nfs_ok; |
272 | } | 275 | } |
273 | 276 | ||
274 | static inline __be32 | 277 | static inline __be32 |
275 | nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh) | 278 | nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
279 | struct nfsd4_putfh *putfh) | ||
276 | { | 280 | { |
277 | fh_put(current_fh); | 281 | fh_put(&cstate->current_fh); |
278 | current_fh->fh_handle.fh_size = putfh->pf_fhlen; | 282 | cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen; |
279 | memcpy(¤t_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen); | 283 | memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval, |
280 | return fh_verify(rqstp, current_fh, 0, MAY_NOP); | 284 | putfh->pf_fhlen); |
285 | return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); | ||
281 | } | 286 | } |
282 | 287 | ||
283 | static inline __be32 | 288 | static inline __be32 |
284 | nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) | 289 | nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate) |
285 | { | 290 | { |
286 | __be32 status; | 291 | __be32 status; |
287 | 292 | ||
288 | fh_put(current_fh); | 293 | fh_put(&cstate->current_fh); |
289 | status = exp_pseudoroot(rqstp->rq_client, current_fh, | 294 | status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh, |
290 | &rqstp->rq_chandle); | 295 | &rqstp->rq_chandle); |
291 | return status; | 296 | return status; |
292 | } | 297 | } |
293 | 298 | ||
294 | static inline __be32 | 299 | static inline __be32 |
295 | nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh) | 300 | nfsd4_restorefh(struct nfsd4_compound_state *cstate) |
296 | { | 301 | { |
297 | if (!save_fh->fh_dentry) | 302 | if (!cstate->save_fh.fh_dentry) |
298 | return nfserr_restorefh; | 303 | return nfserr_restorefh; |
299 | 304 | ||
300 | fh_dup2(current_fh, save_fh); | 305 | fh_dup2(&cstate->current_fh, &cstate->save_fh); |
301 | return nfs_ok; | 306 | return nfs_ok; |
302 | } | 307 | } |
303 | 308 | ||
304 | static inline __be32 | 309 | static inline __be32 |
305 | nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) | 310 | nfsd4_savefh(struct nfsd4_compound_state *cstate) |
306 | { | 311 | { |
307 | if (!current_fh->fh_dentry) | 312 | if (!cstate->current_fh.fh_dentry) |
308 | return nfserr_nofilehandle; | 313 | return nfserr_nofilehandle; |
309 | 314 | ||
310 | fh_dup2(save_fh, current_fh); | 315 | fh_dup2(&cstate->save_fh, &cstate->current_fh); |
311 | return nfs_ok; | 316 | return nfs_ok; |
312 | } | 317 | } |
313 | 318 | ||
@@ -315,17 +320,20 @@ nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) | |||
315 | * misc nfsv4 ops | 320 | * misc nfsv4 ops |
316 | */ | 321 | */ |
317 | static inline __be32 | 322 | static inline __be32 |
318 | nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access) | 323 | nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
324 | struct nfsd4_access *access) | ||
319 | { | 325 | { |
320 | if (access->ac_req_access & ~NFS3_ACCESS_FULL) | 326 | if (access->ac_req_access & ~NFS3_ACCESS_FULL) |
321 | return nfserr_inval; | 327 | return nfserr_inval; |
322 | 328 | ||
323 | access->ac_resp_access = access->ac_req_access; | 329 | access->ac_resp_access = access->ac_req_access; |
324 | return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported); | 330 | return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access, |
331 | &access->ac_supported); | ||
325 | } | 332 | } |
326 | 333 | ||
327 | static inline __be32 | 334 | static inline __be32 |
328 | nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit) | 335 | nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
336 | struct nfsd4_commit *commit) | ||
329 | { | 337 | { |
330 | __be32 status; | 338 | __be32 status; |
331 | 339 | ||
@@ -333,14 +341,16 @@ nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_com | |||
333 | *p++ = nfssvc_boot.tv_sec; | 341 | *p++ = nfssvc_boot.tv_sec; |
334 | *p++ = nfssvc_boot.tv_usec; | 342 | *p++ = nfssvc_boot.tv_usec; |
335 | 343 | ||
336 | status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count); | 344 | status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset, |
345 | commit->co_count); | ||
337 | if (status == nfserr_symlink) | 346 | if (status == nfserr_symlink) |
338 | status = nfserr_inval; | 347 | status = nfserr_inval; |
339 | return status; | 348 | return status; |
340 | } | 349 | } |
341 | 350 | ||
342 | static __be32 | 351 | static __be32 |
343 | nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create) | 352 | nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
353 | struct nfsd4_create *create) | ||
344 | { | 354 | { |
345 | struct svc_fh resfh; | 355 | struct svc_fh resfh; |
346 | __be32 status; | 356 | __be32 status; |
@@ -348,7 +358,7 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre | |||
348 | 358 | ||
349 | fh_init(&resfh, NFS4_FHSIZE); | 359 | fh_init(&resfh, NFS4_FHSIZE); |
350 | 360 | ||
351 | status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE); | 361 | status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE); |
352 | if (status == nfserr_symlink) | 362 | if (status == nfserr_symlink) |
353 | status = nfserr_notdir; | 363 | status = nfserr_notdir; |
354 | if (status) | 364 | if (status) |
@@ -365,9 +375,10 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre | |||
365 | */ | 375 | */ |
366 | create->cr_linkname[create->cr_linklen] = 0; | 376 | create->cr_linkname[create->cr_linklen] = 0; |
367 | 377 | ||
368 | status = nfsd_symlink(rqstp, current_fh, create->cr_name, | 378 | status = nfsd_symlink(rqstp, &cstate->current_fh, |
369 | create->cr_namelen, create->cr_linkname, | 379 | create->cr_name, create->cr_namelen, |
370 | create->cr_linklen, &resfh, &create->cr_iattr); | 380 | create->cr_linkname, create->cr_linklen, |
381 | &resfh, &create->cr_iattr); | ||
371 | break; | 382 | break; |
372 | 383 | ||
373 | case NF4BLK: | 384 | case NF4BLK: |
@@ -375,9 +386,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre | |||
375 | if (MAJOR(rdev) != create->cr_specdata1 || | 386 | if (MAJOR(rdev) != create->cr_specdata1 || |
376 | MINOR(rdev) != create->cr_specdata2) | 387 | MINOR(rdev) != create->cr_specdata2) |
377 | return nfserr_inval; | 388 | return nfserr_inval; |
378 | status = nfsd_create(rqstp, current_fh, create->cr_name, | 389 | status = nfsd_create(rqstp, &cstate->current_fh, |
379 | create->cr_namelen, &create->cr_iattr, | 390 | create->cr_name, create->cr_namelen, |
380 | S_IFBLK, rdev, &resfh); | 391 | &create->cr_iattr, S_IFBLK, rdev, &resfh); |
381 | break; | 392 | break; |
382 | 393 | ||
383 | case NF4CHR: | 394 | case NF4CHR: |
@@ -385,28 +396,28 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre | |||
385 | if (MAJOR(rdev) != create->cr_specdata1 || | 396 | if (MAJOR(rdev) != create->cr_specdata1 || |
386 | MINOR(rdev) != create->cr_specdata2) | 397 | MINOR(rdev) != create->cr_specdata2) |
387 | return nfserr_inval; | 398 | return nfserr_inval; |
388 | status = nfsd_create(rqstp, current_fh, create->cr_name, | 399 | status = nfsd_create(rqstp, &cstate->current_fh, |
389 | create->cr_namelen, &create->cr_iattr, | 400 | create->cr_name, create->cr_namelen, |
390 | S_IFCHR, rdev, &resfh); | 401 | &create->cr_iattr,S_IFCHR, rdev, &resfh); |
391 | break; | 402 | break; |
392 | 403 | ||
393 | case NF4SOCK: | 404 | case NF4SOCK: |
394 | status = nfsd_create(rqstp, current_fh, create->cr_name, | 405 | status = nfsd_create(rqstp, &cstate->current_fh, |
395 | create->cr_namelen, &create->cr_iattr, | 406 | create->cr_name, create->cr_namelen, |
396 | S_IFSOCK, 0, &resfh); | 407 | &create->cr_iattr, S_IFSOCK, 0, &resfh); |
397 | break; | 408 | break; |
398 | 409 | ||
399 | case NF4FIFO: | 410 | case NF4FIFO: |
400 | status = nfsd_create(rqstp, current_fh, create->cr_name, | 411 | status = nfsd_create(rqstp, &cstate->current_fh, |
401 | create->cr_namelen, &create->cr_iattr, | 412 | create->cr_name, create->cr_namelen, |
402 | S_IFIFO, 0, &resfh); | 413 | &create->cr_iattr, S_IFIFO, 0, &resfh); |
403 | break; | 414 | break; |
404 | 415 | ||
405 | case NF4DIR: | 416 | case NF4DIR: |
406 | create->cr_iattr.ia_valid &= ~ATTR_SIZE; | 417 | create->cr_iattr.ia_valid &= ~ATTR_SIZE; |
407 | status = nfsd_create(rqstp, current_fh, create->cr_name, | 418 | status = nfsd_create(rqstp, &cstate->current_fh, |
408 | create->cr_namelen, &create->cr_iattr, | 419 | create->cr_name, create->cr_namelen, |
409 | S_IFDIR, 0, &resfh); | 420 | &create->cr_iattr, S_IFDIR, 0, &resfh); |
410 | break; | 421 | break; |
411 | 422 | ||
412 | default: | 423 | default: |
@@ -414,9 +425,9 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre | |||
414 | } | 425 | } |
415 | 426 | ||
416 | if (!status) { | 427 | if (!status) { |
417 | fh_unlock(current_fh); | 428 | fh_unlock(&cstate->current_fh); |
418 | set_change_info(&create->cr_cinfo, current_fh); | 429 | set_change_info(&create->cr_cinfo, &cstate->current_fh); |
419 | fh_dup2(current_fh, &resfh); | 430 | fh_dup2(&cstate->current_fh, &resfh); |
420 | } | 431 | } |
421 | 432 | ||
422 | fh_put(&resfh); | 433 | fh_put(&resfh); |
@@ -424,11 +435,12 @@ nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_cre | |||
424 | } | 435 | } |
425 | 436 | ||
426 | static inline __be32 | 437 | static inline __be32 |
427 | nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr) | 438 | nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
439 | struct nfsd4_getattr *getattr) | ||
428 | { | 440 | { |
429 | __be32 status; | 441 | __be32 status; |
430 | 442 | ||
431 | status = fh_verify(rqstp, current_fh, 0, MAY_NOP); | 443 | status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); |
432 | if (status) | 444 | if (status) |
433 | return status; | 445 | return status; |
434 | 446 | ||
@@ -438,26 +450,27 @@ nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ge | |||
438 | getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0; | 450 | getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0; |
439 | getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1; | 451 | getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1; |
440 | 452 | ||
441 | getattr->ga_fhp = current_fh; | 453 | getattr->ga_fhp = &cstate->current_fh; |
442 | return nfs_ok; | 454 | return nfs_ok; |
443 | } | 455 | } |
444 | 456 | ||
445 | static inline __be32 | 457 | static inline __be32 |
446 | nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh, | 458 | nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
447 | struct svc_fh *save_fh, struct nfsd4_link *link) | 459 | struct nfsd4_link *link) |
448 | { | 460 | { |
449 | __be32 status = nfserr_nofilehandle; | 461 | __be32 status = nfserr_nofilehandle; |
450 | 462 | ||
451 | if (!save_fh->fh_dentry) | 463 | if (!cstate->save_fh.fh_dentry) |
452 | return status; | 464 | return status; |
453 | status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh); | 465 | status = nfsd_link(rqstp, &cstate->current_fh, |
466 | link->li_name, link->li_namelen, &cstate->save_fh); | ||
454 | if (!status) | 467 | if (!status) |
455 | set_change_info(&link->li_cinfo, current_fh); | 468 | set_change_info(&link->li_cinfo, &cstate->current_fh); |
456 | return status; | 469 | return status; |
457 | } | 470 | } |
458 | 471 | ||
459 | static __be32 | 472 | static __be32 |
460 | nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) | 473 | nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate) |
461 | { | 474 | { |
462 | struct svc_fh tmp_fh; | 475 | struct svc_fh tmp_fh; |
463 | __be32 ret; | 476 | __be32 ret; |
@@ -466,22 +479,27 @@ nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) | |||
466 | if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh, | 479 | if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh, |
467 | &rqstp->rq_chandle)) != 0) | 480 | &rqstp->rq_chandle)) != 0) |
468 | return ret; | 481 | return ret; |
469 | if (tmp_fh.fh_dentry == current_fh->fh_dentry) { | 482 | if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) { |
470 | fh_put(&tmp_fh); | 483 | fh_put(&tmp_fh); |
471 | return nfserr_noent; | 484 | return nfserr_noent; |
472 | } | 485 | } |
473 | fh_put(&tmp_fh); | 486 | fh_put(&tmp_fh); |
474 | return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh); | 487 | return nfsd_lookup(rqstp, &cstate->current_fh, |
488 | "..", 2, &cstate->current_fh); | ||
475 | } | 489 | } |
476 | 490 | ||
477 | static inline __be32 | 491 | static inline __be32 |
478 | nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup) | 492 | nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
493 | struct nfsd4_lookup *lookup) | ||
479 | { | 494 | { |
480 | return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh); | 495 | return nfsd_lookup(rqstp, &cstate->current_fh, |
496 | lookup->lo_name, lookup->lo_len, | ||
497 | &cstate->current_fh); | ||
481 | } | 498 | } |
482 | 499 | ||
483 | static inline __be32 | 500 | static inline __be32 |
484 | nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) | 501 | nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
502 | struct nfsd4_read *read) | ||
485 | { | 503 | { |
486 | __be32 status; | 504 | __be32 status; |
487 | 505 | ||
@@ -493,7 +511,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read | |||
493 | 511 | ||
494 | nfs4_lock_state(); | 512 | nfs4_lock_state(); |
495 | /* check stateid */ | 513 | /* check stateid */ |
496 | if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, | 514 | if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh, |
515 | &read->rd_stateid, | ||
497 | CHECK_FH | RD_STATE, &read->rd_filp))) { | 516 | CHECK_FH | RD_STATE, &read->rd_filp))) { |
498 | dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); | 517 | dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); |
499 | goto out; | 518 | goto out; |
@@ -504,12 +523,13 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read | |||
504 | out: | 523 | out: |
505 | nfs4_unlock_state(); | 524 | nfs4_unlock_state(); |
506 | read->rd_rqstp = rqstp; | 525 | read->rd_rqstp = rqstp; |
507 | read->rd_fhp = current_fh; | 526 | read->rd_fhp = &cstate->current_fh; |
508 | return status; | 527 | return status; |
509 | } | 528 | } |
510 | 529 | ||
511 | static inline __be32 | 530 | static inline __be32 |
512 | nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir) | 531 | nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
532 | struct nfsd4_readdir *readdir) | ||
513 | { | 533 | { |
514 | u64 cookie = readdir->rd_cookie; | 534 | u64 cookie = readdir->rd_cookie; |
515 | static const nfs4_verifier zeroverf; | 535 | static const nfs4_verifier zeroverf; |
@@ -527,48 +547,51 @@ nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_re | |||
527 | return nfserr_bad_cookie; | 547 | return nfserr_bad_cookie; |
528 | 548 | ||
529 | readdir->rd_rqstp = rqstp; | 549 | readdir->rd_rqstp = rqstp; |
530 | readdir->rd_fhp = current_fh; | 550 | readdir->rd_fhp = &cstate->current_fh; |
531 | return nfs_ok; | 551 | return nfs_ok; |
532 | } | 552 | } |
533 | 553 | ||
534 | static inline __be32 | 554 | static inline __be32 |
535 | nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink) | 555 | nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
556 | struct nfsd4_readlink *readlink) | ||
536 | { | 557 | { |
537 | readlink->rl_rqstp = rqstp; | 558 | readlink->rl_rqstp = rqstp; |
538 | readlink->rl_fhp = current_fh; | 559 | readlink->rl_fhp = &cstate->current_fh; |
539 | return nfs_ok; | 560 | return nfs_ok; |
540 | } | 561 | } |
541 | 562 | ||
542 | static inline __be32 | 563 | static inline __be32 |
543 | nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove) | 564 | nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
565 | struct nfsd4_remove *remove) | ||
544 | { | 566 | { |
545 | __be32 status; | 567 | __be32 status; |
546 | 568 | ||
547 | if (nfs4_in_grace()) | 569 | if (nfs4_in_grace()) |
548 | return nfserr_grace; | 570 | return nfserr_grace; |
549 | status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen); | 571 | status = nfsd_unlink(rqstp, &cstate->current_fh, 0, |
572 | remove->rm_name, remove->rm_namelen); | ||
550 | if (status == nfserr_symlink) | 573 | if (status == nfserr_symlink) |
551 | return nfserr_notdir; | 574 | return nfserr_notdir; |
552 | if (!status) { | 575 | if (!status) { |
553 | fh_unlock(current_fh); | 576 | fh_unlock(&cstate->current_fh); |
554 | set_change_info(&remove->rm_cinfo, current_fh); | 577 | set_change_info(&remove->rm_cinfo, &cstate->current_fh); |
555 | } | 578 | } |
556 | return status; | 579 | return status; |
557 | } | 580 | } |
558 | 581 | ||
559 | static inline __be32 | 582 | static inline __be32 |
560 | nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, | 583 | nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
561 | struct svc_fh *save_fh, struct nfsd4_rename *rename) | 584 | struct nfsd4_rename *rename) |
562 | { | 585 | { |
563 | __be32 status = nfserr_nofilehandle; | 586 | __be32 status = nfserr_nofilehandle; |
564 | 587 | ||
565 | if (!save_fh->fh_dentry) | 588 | if (!cstate->save_fh.fh_dentry) |
566 | return status; | 589 | return status; |
567 | if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags | 590 | if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags |
568 | & NFSEXP_NOSUBTREECHECK)) | 591 | & NFSEXP_NOSUBTREECHECK)) |
569 | return nfserr_grace; | 592 | return nfserr_grace; |
570 | status = nfsd_rename(rqstp, save_fh, rename->rn_sname, | 593 | status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, |
571 | rename->rn_snamelen, current_fh, | 594 | rename->rn_snamelen, &cstate->current_fh, |
572 | rename->rn_tname, rename->rn_tnamelen); | 595 | rename->rn_tname, rename->rn_tnamelen); |
573 | 596 | ||
574 | /* the underlying filesystem returns different error's than required | 597 | /* the underlying filesystem returns different error's than required |
@@ -576,27 +599,28 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, | |||
576 | if (status == nfserr_isdir) | 599 | if (status == nfserr_isdir) |
577 | status = nfserr_exist; | 600 | status = nfserr_exist; |
578 | else if ((status == nfserr_notdir) && | 601 | else if ((status == nfserr_notdir) && |
579 | (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) && | 602 | (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) && |
580 | S_ISDIR(current_fh->fh_dentry->d_inode->i_mode))) | 603 | S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode))) |
581 | status = nfserr_exist; | 604 | status = nfserr_exist; |
582 | else if (status == nfserr_symlink) | 605 | else if (status == nfserr_symlink) |
583 | status = nfserr_notdir; | 606 | status = nfserr_notdir; |
584 | 607 | ||
585 | if (!status) { | 608 | if (!status) { |
586 | set_change_info(&rename->rn_sinfo, current_fh); | 609 | set_change_info(&rename->rn_sinfo, &cstate->current_fh); |
587 | set_change_info(&rename->rn_tinfo, save_fh); | 610 | set_change_info(&rename->rn_tinfo, &cstate->save_fh); |
588 | } | 611 | } |
589 | return status; | 612 | return status; |
590 | } | 613 | } |
591 | 614 | ||
592 | static inline __be32 | 615 | static inline __be32 |
593 | nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr) | 616 | nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
617 | struct nfsd4_setattr *setattr) | ||
594 | { | 618 | { |
595 | __be32 status = nfs_ok; | 619 | __be32 status = nfs_ok; |
596 | 620 | ||
597 | if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { | 621 | if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { |
598 | nfs4_lock_state(); | 622 | nfs4_lock_state(); |
599 | status = nfs4_preprocess_stateid_op(current_fh, | 623 | status = nfs4_preprocess_stateid_op(&cstate->current_fh, |
600 | &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL); | 624 | &setattr->sa_stateid, CHECK_FH | WR_STATE, NULL); |
601 | nfs4_unlock_state(); | 625 | nfs4_unlock_state(); |
602 | if (status) { | 626 | if (status) { |
@@ -606,16 +630,18 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se | |||
606 | } | 630 | } |
607 | status = nfs_ok; | 631 | status = nfs_ok; |
608 | if (setattr->sa_acl != NULL) | 632 | if (setattr->sa_acl != NULL) |
609 | status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl); | 633 | status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh, |
634 | setattr->sa_acl); | ||
610 | if (status) | 635 | if (status) |
611 | return status; | 636 | return status; |
612 | status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, | 637 | status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr, |
613 | 0, (time_t)0); | 638 | 0, (time_t)0); |
614 | return status; | 639 | return status; |
615 | } | 640 | } |
616 | 641 | ||
617 | static inline __be32 | 642 | static inline __be32 |
618 | nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write) | 643 | nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
644 | struct nfsd4_write *write) | ||
619 | { | 645 | { |
620 | stateid_t *stateid = &write->wr_stateid; | 646 | stateid_t *stateid = &write->wr_stateid; |
621 | struct file *filp = NULL; | 647 | struct file *filp = NULL; |
@@ -628,7 +654,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ | |||
628 | return nfserr_inval; | 654 | return nfserr_inval; |
629 | 655 | ||
630 | nfs4_lock_state(); | 656 | nfs4_lock_state(); |
631 | status = nfs4_preprocess_stateid_op(current_fh, stateid, | 657 | status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid, |
632 | CHECK_FH | WR_STATE, &filp); | 658 | CHECK_FH | WR_STATE, &filp); |
633 | if (filp) | 659 | if (filp) |
634 | get_file(filp); | 660 | get_file(filp); |
@@ -645,9 +671,9 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ | |||
645 | *p++ = nfssvc_boot.tv_sec; | 671 | *p++ = nfssvc_boot.tv_sec; |
646 | *p++ = nfssvc_boot.tv_usec; | 672 | *p++ = nfssvc_boot.tv_usec; |
647 | 673 | ||
648 | status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, | 674 | status = nfsd_write(rqstp, &cstate->current_fh, filp, |
649 | rqstp->rq_vec, write->wr_vlen, write->wr_buflen, | 675 | write->wr_offset, rqstp->rq_vec, write->wr_vlen, |
650 | &write->wr_how_written); | 676 | write->wr_buflen, &write->wr_how_written); |
651 | if (filp) | 677 | if (filp) |
652 | fput(filp); | 678 | fput(filp); |
653 | 679 | ||
@@ -662,13 +688,14 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ | |||
662 | * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK. | 688 | * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK. |
663 | */ | 689 | */ |
664 | static __be32 | 690 | static __be32 |
665 | nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify) | 691 | nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
692 | struct nfsd4_verify *verify) | ||
666 | { | 693 | { |
667 | __be32 *buf, *p; | 694 | __be32 *buf, *p; |
668 | int count; | 695 | int count; |
669 | __be32 status; | 696 | __be32 status; |
670 | 697 | ||
671 | status = fh_verify(rqstp, current_fh, 0, MAY_NOP); | 698 | status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP); |
672 | if (status) | 699 | if (status) |
673 | return status; | 700 | return status; |
674 | 701 | ||
@@ -689,8 +716,9 @@ nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ver | |||
689 | if (!buf) | 716 | if (!buf) |
690 | return nfserr_resource; | 717 | return nfserr_resource; |
691 | 718 | ||
692 | status = nfsd4_encode_fattr(current_fh, current_fh->fh_export, | 719 | status = nfsd4_encode_fattr(&cstate->current_fh, |
693 | current_fh->fh_dentry, buf, | 720 | cstate->current_fh.fh_export, |
721 | cstate->current_fh.fh_dentry, buf, | ||
694 | &count, verify->ve_bmval, | 722 | &count, verify->ve_bmval, |
695 | rqstp); | 723 | rqstp); |
696 | 724 | ||
@@ -727,6 +755,26 @@ static inline void nfsd4_increment_op_stats(u32 opnum) | |||
727 | nfsdstats.nfs4_opcount[opnum]++; | 755 | nfsdstats.nfs4_opcount[opnum]++; |
728 | } | 756 | } |
729 | 757 | ||
758 | static void cstate_free(struct nfsd4_compound_state *cstate) | ||
759 | { | ||
760 | if (cstate == NULL) | ||
761 | return; | ||
762 | fh_put(&cstate->current_fh); | ||
763 | fh_put(&cstate->save_fh); | ||
764 | kfree(cstate); | ||
765 | } | ||
766 | |||
767 | static struct nfsd4_compound_state *cstate_alloc(void) | ||
768 | { | ||
769 | struct nfsd4_compound_state *cstate; | ||
770 | |||
771 | cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL); | ||
772 | if (cstate == NULL) | ||
773 | return NULL; | ||
774 | fh_init(&cstate->current_fh, NFS4_FHSIZE); | ||
775 | fh_init(&cstate->save_fh, NFS4_FHSIZE); | ||
776 | return cstate; | ||
777 | } | ||
730 | 778 | ||
731 | /* | 779 | /* |
732 | * COMPOUND call. | 780 | * COMPOUND call. |
@@ -737,21 +785,15 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
737 | struct nfsd4_compoundres *resp) | 785 | struct nfsd4_compoundres *resp) |
738 | { | 786 | { |
739 | struct nfsd4_op *op; | 787 | struct nfsd4_op *op; |
740 | struct svc_fh *current_fh = NULL; | 788 | struct nfsd4_compound_state *cstate = NULL; |
741 | struct svc_fh *save_fh = NULL; | ||
742 | struct nfs4_stateowner *replay_owner = NULL; | 789 | struct nfs4_stateowner *replay_owner = NULL; |
743 | int slack_bytes; | 790 | int slack_bytes; |
744 | __be32 status; | 791 | __be32 status; |
745 | 792 | ||
746 | status = nfserr_resource; | 793 | status = nfserr_resource; |
747 | current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL); | 794 | cstate = cstate_alloc(); |
748 | if (current_fh == NULL) | 795 | if (cstate == NULL) |
749 | goto out; | ||
750 | fh_init(current_fh, NFS4_FHSIZE); | ||
751 | save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL); | ||
752 | if (save_fh == NULL) | ||
753 | goto out; | 796 | goto out; |
754 | fh_init(save_fh, NFS4_FHSIZE); | ||
755 | 797 | ||
756 | resp->xbuf = &rqstp->rq_res; | 798 | resp->xbuf = &rqstp->rq_res; |
757 | resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; | 799 | resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; |
@@ -802,7 +844,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
802 | * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH | 844 | * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH |
803 | * require a valid current filehandle | 845 | * require a valid current filehandle |
804 | */ | 846 | */ |
805 | if (!current_fh->fh_dentry) { | 847 | if (!cstate->current_fh.fh_dentry) { |
806 | if (!((op->opnum == OP_PUTFH) || | 848 | if (!((op->opnum == OP_PUTFH) || |
807 | (op->opnum == OP_PUTROOTFH) || | 849 | (op->opnum == OP_PUTROOTFH) || |
808 | (op->opnum == OP_SETCLIENTID) || | 850 | (op->opnum == OP_SETCLIENTID) || |
@@ -817,7 +859,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
817 | /* Check must be done at start of each operation, except | 859 | /* Check must be done at start of each operation, except |
818 | * for GETATTR and ops not listed as returning NFS4ERR_MOVED | 860 | * for GETATTR and ops not listed as returning NFS4ERR_MOVED |
819 | */ | 861 | */ |
820 | else if (current_fh->fh_export->ex_fslocs.migrated && | 862 | else if (cstate->current_fh.fh_export->ex_fslocs.migrated && |
821 | !((op->opnum == OP_GETATTR) || | 863 | !((op->opnum == OP_GETATTR) || |
822 | (op->opnum == OP_PUTROOTFH) || | 864 | (op->opnum == OP_PUTROOTFH) || |
823 | (op->opnum == OP_PUTPUBFH) || | 865 | (op->opnum == OP_PUTPUBFH) || |
@@ -829,90 +871,110 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
829 | } | 871 | } |
830 | switch (op->opnum) { | 872 | switch (op->opnum) { |
831 | case OP_ACCESS: | 873 | case OP_ACCESS: |
832 | op->status = nfsd4_access(rqstp, current_fh, &op->u.access); | 874 | op->status = nfsd4_access(rqstp, cstate, |
875 | &op->u.access); | ||
833 | break; | 876 | break; |
834 | case OP_CLOSE: | 877 | case OP_CLOSE: |
835 | op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner); | 878 | op->status = nfsd4_close(rqstp, cstate, |
879 | &op->u.close, &replay_owner); | ||
836 | break; | 880 | break; |
837 | case OP_COMMIT: | 881 | case OP_COMMIT: |
838 | op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit); | 882 | op->status = nfsd4_commit(rqstp, cstate, |
883 | &op->u.commit); | ||
839 | break; | 884 | break; |
840 | case OP_CREATE: | 885 | case OP_CREATE: |
841 | op->status = nfsd4_create(rqstp, current_fh, &op->u.create); | 886 | op->status = nfsd4_create(rqstp, cstate, |
887 | &op->u.create); | ||
842 | break; | 888 | break; |
843 | case OP_DELEGRETURN: | 889 | case OP_DELEGRETURN: |
844 | op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn); | 890 | op->status = nfsd4_delegreturn(rqstp, cstate, |
891 | &op->u.delegreturn); | ||
845 | break; | 892 | break; |
846 | case OP_GETATTR: | 893 | case OP_GETATTR: |
847 | op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr); | 894 | op->status = nfsd4_getattr(rqstp, cstate, |
895 | &op->u.getattr); | ||
848 | break; | 896 | break; |
849 | case OP_GETFH: | 897 | case OP_GETFH: |
850 | op->status = nfsd4_getfh(current_fh, &op->u.getfh); | 898 | op->status = nfsd4_getfh(cstate, &op->u.getfh); |
851 | break; | 899 | break; |
852 | case OP_LINK: | 900 | case OP_LINK: |
853 | op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link); | 901 | op->status = nfsd4_link(rqstp, cstate, &op->u.link); |
854 | break; | 902 | break; |
855 | case OP_LOCK: | 903 | case OP_LOCK: |
856 | op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner); | 904 | op->status = nfsd4_lock(rqstp, cstate, &op->u.lock, |
905 | &replay_owner); | ||
857 | break; | 906 | break; |
858 | case OP_LOCKT: | 907 | case OP_LOCKT: |
859 | op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt); | 908 | op->status = nfsd4_lockt(rqstp, cstate, &op->u.lockt); |
860 | break; | 909 | break; |
861 | case OP_LOCKU: | 910 | case OP_LOCKU: |
862 | op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner); | 911 | op->status = nfsd4_locku(rqstp, cstate, &op->u.locku, |
912 | &replay_owner); | ||
863 | break; | 913 | break; |
864 | case OP_LOOKUP: | 914 | case OP_LOOKUP: |
865 | op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup); | 915 | op->status = nfsd4_lookup(rqstp, cstate, |
916 | &op->u.lookup); | ||
866 | break; | 917 | break; |
867 | case OP_LOOKUPP: | 918 | case OP_LOOKUPP: |
868 | op->status = nfsd4_lookupp(rqstp, current_fh); | 919 | op->status = nfsd4_lookupp(rqstp, cstate); |
869 | break; | 920 | break; |
870 | case OP_NVERIFY: | 921 | case OP_NVERIFY: |
871 | op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify); | 922 | op->status = nfsd4_verify(rqstp, cstate, |
923 | &op->u.nverify); | ||
872 | if (op->status == nfserr_not_same) | 924 | if (op->status == nfserr_not_same) |
873 | op->status = nfs_ok; | 925 | op->status = nfs_ok; |
874 | break; | 926 | break; |
875 | case OP_OPEN: | 927 | case OP_OPEN: |
876 | op->status = nfsd4_open(rqstp, current_fh, &op->u.open, &replay_owner); | 928 | op->status = nfsd4_open(rqstp, cstate, |
929 | &op->u.open, &replay_owner); | ||
877 | break; | 930 | break; |
878 | case OP_OPEN_CONFIRM: | 931 | case OP_OPEN_CONFIRM: |
879 | op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner); | 932 | op->status = nfsd4_open_confirm(rqstp, cstate, |
933 | &op->u.open_confirm, | ||
934 | &replay_owner); | ||
880 | break; | 935 | break; |
881 | case OP_OPEN_DOWNGRADE: | 936 | case OP_OPEN_DOWNGRADE: |
882 | op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner); | 937 | op->status = nfsd4_open_downgrade(rqstp, cstate, |
938 | &op->u.open_downgrade, | ||
939 | &replay_owner); | ||
883 | break; | 940 | break; |
884 | case OP_PUTFH: | 941 | case OP_PUTFH: |
885 | op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh); | 942 | op->status = nfsd4_putfh(rqstp, cstate, &op->u.putfh); |
886 | break; | 943 | break; |
887 | case OP_PUTROOTFH: | 944 | case OP_PUTROOTFH: |
888 | op->status = nfsd4_putrootfh(rqstp, current_fh); | 945 | op->status = nfsd4_putrootfh(rqstp, cstate); |
889 | break; | 946 | break; |
890 | case OP_READ: | 947 | case OP_READ: |
891 | op->status = nfsd4_read(rqstp, current_fh, &op->u.read); | 948 | op->status = nfsd4_read(rqstp, cstate, &op->u.read); |
892 | break; | 949 | break; |
893 | case OP_READDIR: | 950 | case OP_READDIR: |
894 | op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir); | 951 | op->status = nfsd4_readdir(rqstp, cstate, |
952 | &op->u.readdir); | ||
895 | break; | 953 | break; |
896 | case OP_READLINK: | 954 | case OP_READLINK: |
897 | op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink); | 955 | op->status = nfsd4_readlink(rqstp, cstate, |
956 | &op->u.readlink); | ||
898 | break; | 957 | break; |
899 | case OP_REMOVE: | 958 | case OP_REMOVE: |
900 | op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove); | 959 | op->status = nfsd4_remove(rqstp, cstate, |
960 | &op->u.remove); | ||
901 | break; | 961 | break; |
902 | case OP_RENAME: | 962 | case OP_RENAME: |
903 | op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename); | 963 | op->status = nfsd4_rename(rqstp, cstate, |
964 | &op->u.rename); | ||
904 | break; | 965 | break; |
905 | case OP_RENEW: | 966 | case OP_RENEW: |
906 | op->status = nfsd4_renew(&op->u.renew); | 967 | op->status = nfsd4_renew(&op->u.renew); |
907 | break; | 968 | break; |
908 | case OP_RESTOREFH: | 969 | case OP_RESTOREFH: |
909 | op->status = nfsd4_restorefh(current_fh, save_fh); | 970 | op->status = nfsd4_restorefh(cstate); |
910 | break; | 971 | break; |
911 | case OP_SAVEFH: | 972 | case OP_SAVEFH: |
912 | op->status = nfsd4_savefh(current_fh, save_fh); | 973 | op->status = nfsd4_savefh(cstate); |
913 | break; | 974 | break; |
914 | case OP_SETATTR: | 975 | case OP_SETATTR: |
915 | op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr); | 976 | op->status = nfsd4_setattr(rqstp, cstate, |
977 | &op->u.setattr); | ||
916 | break; | 978 | break; |
917 | case OP_SETCLIENTID: | 979 | case OP_SETCLIENTID: |
918 | op->status = nfsd4_setclientid(rqstp, &op->u.setclientid); | 980 | op->status = nfsd4_setclientid(rqstp, &op->u.setclientid); |
@@ -921,12 +983,13 @@ nfsd4_proc_compound(struct svc_rqst *rqstp, | |||
921 | op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm); | 983 | op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm); |
922 | break; | 984 | break; |
923 | case OP_VERIFY: | 985 | case OP_VERIFY: |
924 | op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify); | 986 | op->status = nfsd4_verify(rqstp, cstate, |
987 | &op->u.verify); | ||
925 | if (op->status == nfserr_same) | 988 | if (op->status == nfserr_same) |
926 | op->status = nfs_ok; | 989 | op->status = nfs_ok; |
927 | break; | 990 | break; |
928 | case OP_WRITE: | 991 | case OP_WRITE: |
929 | op->status = nfsd4_write(rqstp, current_fh, &op->u.write); | 992 | op->status = nfsd4_write(rqstp, cstate, &op->u.write); |
930 | break; | 993 | break; |
931 | case OP_RELEASE_LOCKOWNER: | 994 | case OP_RELEASE_LOCKOWNER: |
932 | op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner); | 995 | op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner); |
@@ -958,12 +1021,7 @@ encode_op: | |||
958 | 1021 | ||
959 | out: | 1022 | out: |
960 | nfsd4_release_compoundargs(args); | 1023 | nfsd4_release_compoundargs(args); |
961 | if (current_fh) | 1024 | cstate_free(cstate); |
962 | fh_put(current_fh); | ||
963 | kfree(current_fh); | ||
964 | if (save_fh) | ||
965 | fh_put(save_fh); | ||
966 | kfree(save_fh); | ||
967 | return status; | 1025 | return status; |
968 | } | 1026 | } |
969 | 1027 | ||
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 393624340d13..f0a994e3b2c5 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -2241,24 +2241,26 @@ check_replay: | |||
2241 | } | 2241 | } |
2242 | 2242 | ||
2243 | __be32 | 2243 | __be32 |
2244 | nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner) | 2244 | nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
2245 | struct nfsd4_open_confirm *oc, | ||
2246 | struct nfs4_stateowner **replay_owner) | ||
2245 | { | 2247 | { |
2246 | __be32 status; | 2248 | __be32 status; |
2247 | struct nfs4_stateowner *sop; | 2249 | struct nfs4_stateowner *sop; |
2248 | struct nfs4_stateid *stp; | 2250 | struct nfs4_stateid *stp; |
2249 | 2251 | ||
2250 | dprintk("NFSD: nfsd4_open_confirm on file %.*s\n", | 2252 | dprintk("NFSD: nfsd4_open_confirm on file %.*s\n", |
2251 | (int)current_fh->fh_dentry->d_name.len, | 2253 | (int)cstate->current_fh.fh_dentry->d_name.len, |
2252 | current_fh->fh_dentry->d_name.name); | 2254 | cstate->current_fh.fh_dentry->d_name.name); |
2253 | 2255 | ||
2254 | status = fh_verify(rqstp, current_fh, S_IFREG, 0); | 2256 | status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0); |
2255 | if (status) | 2257 | if (status) |
2256 | return status; | 2258 | return status; |
2257 | 2259 | ||
2258 | nfs4_lock_state(); | 2260 | nfs4_lock_state(); |
2259 | 2261 | ||
2260 | if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid, | 2262 | if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, |
2261 | &oc->oc_req_stateid, | 2263 | oc->oc_seqid, &oc->oc_req_stateid, |
2262 | CHECK_FH | CONFIRM | OPEN_STATE, | 2264 | CHECK_FH | CONFIRM | OPEN_STATE, |
2263 | &oc->oc_stateowner, &stp, NULL))) | 2265 | &oc->oc_stateowner, &stp, NULL))) |
2264 | goto out; | 2266 | goto out; |
@@ -2310,22 +2312,26 @@ reset_union_bmap_deny(unsigned long deny, unsigned long *bmap) | |||
2310 | } | 2312 | } |
2311 | 2313 | ||
2312 | __be32 | 2314 | __be32 |
2313 | nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner) | 2315 | nfsd4_open_downgrade(struct svc_rqst *rqstp, |
2316 | struct nfsd4_compound_state *cstate, | ||
2317 | struct nfsd4_open_downgrade *od, | ||
2318 | struct nfs4_stateowner **replay_owner) | ||
2314 | { | 2319 | { |
2315 | __be32 status; | 2320 | __be32 status; |
2316 | struct nfs4_stateid *stp; | 2321 | struct nfs4_stateid *stp; |
2317 | unsigned int share_access; | 2322 | unsigned int share_access; |
2318 | 2323 | ||
2319 | dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", | 2324 | dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", |
2320 | (int)current_fh->fh_dentry->d_name.len, | 2325 | (int)cstate->current_fh.fh_dentry->d_name.len, |
2321 | current_fh->fh_dentry->d_name.name); | 2326 | cstate->current_fh.fh_dentry->d_name.name); |
2322 | 2327 | ||
2323 | if (!access_valid(od->od_share_access) | 2328 | if (!access_valid(od->od_share_access) |
2324 | || !deny_valid(od->od_share_deny)) | 2329 | || !deny_valid(od->od_share_deny)) |
2325 | return nfserr_inval; | 2330 | return nfserr_inval; |
2326 | 2331 | ||
2327 | nfs4_lock_state(); | 2332 | nfs4_lock_state(); |
2328 | if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, | 2333 | if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, |
2334 | od->od_seqid, | ||
2329 | &od->od_stateid, | 2335 | &od->od_stateid, |
2330 | CHECK_FH | OPEN_STATE, | 2336 | CHECK_FH | OPEN_STATE, |
2331 | &od->od_stateowner, &stp, NULL))) | 2337 | &od->od_stateowner, &stp, NULL))) |
@@ -2365,18 +2371,20 @@ out: | |||
2365 | * nfs4_unlock_state() called after encode | 2371 | * nfs4_unlock_state() called after encode |
2366 | */ | 2372 | */ |
2367 | __be32 | 2373 | __be32 |
2368 | nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner) | 2374 | nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
2375 | struct nfsd4_close *close, struct nfs4_stateowner **replay_owner) | ||
2369 | { | 2376 | { |
2370 | __be32 status; | 2377 | __be32 status; |
2371 | struct nfs4_stateid *stp; | 2378 | struct nfs4_stateid *stp; |
2372 | 2379 | ||
2373 | dprintk("NFSD: nfsd4_close on file %.*s\n", | 2380 | dprintk("NFSD: nfsd4_close on file %.*s\n", |
2374 | (int)current_fh->fh_dentry->d_name.len, | 2381 | (int)cstate->current_fh.fh_dentry->d_name.len, |
2375 | current_fh->fh_dentry->d_name.name); | 2382 | cstate->current_fh.fh_dentry->d_name.name); |
2376 | 2383 | ||
2377 | nfs4_lock_state(); | 2384 | nfs4_lock_state(); |
2378 | /* check close_lru for replay */ | 2385 | /* check close_lru for replay */ |
2379 | if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, | 2386 | if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, |
2387 | close->cl_seqid, | ||
2380 | &close->cl_stateid, | 2388 | &close->cl_stateid, |
2381 | CHECK_FH | OPEN_STATE | CLOSE_STATE, | 2389 | CHECK_FH | OPEN_STATE | CLOSE_STATE, |
2382 | &close->cl_stateowner, &stp, NULL))) | 2390 | &close->cl_stateowner, &stp, NULL))) |
@@ -2404,15 +2412,17 @@ out: | |||
2404 | } | 2412 | } |
2405 | 2413 | ||
2406 | __be32 | 2414 | __be32 |
2407 | nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr) | 2415 | nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
2416 | struct nfsd4_delegreturn *dr) | ||
2408 | { | 2417 | { |
2409 | __be32 status; | 2418 | __be32 status; |
2410 | 2419 | ||
2411 | if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) | 2420 | if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) |
2412 | goto out; | 2421 | goto out; |
2413 | 2422 | ||
2414 | nfs4_lock_state(); | 2423 | nfs4_lock_state(); |
2415 | status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL); | 2424 | status = nfs4_preprocess_stateid_op(&cstate->current_fh, |
2425 | &dr->dr_stateid, DELEG_RET, NULL); | ||
2416 | nfs4_unlock_state(); | 2426 | nfs4_unlock_state(); |
2417 | out: | 2427 | out: |
2418 | return status; | 2428 | return status; |
@@ -2635,7 +2645,8 @@ check_lock_length(u64 offset, u64 length) | |||
2635 | * LOCK operation | 2645 | * LOCK operation |
2636 | */ | 2646 | */ |
2637 | __be32 | 2647 | __be32 |
2638 | nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) | 2648 | nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
2649 | struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) | ||
2639 | { | 2650 | { |
2640 | struct nfs4_stateowner *open_sop = NULL; | 2651 | struct nfs4_stateowner *open_sop = NULL; |
2641 | struct nfs4_stateowner *lock_sop = NULL; | 2652 | struct nfs4_stateowner *lock_sop = NULL; |
@@ -2654,7 +2665,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2654 | if (check_lock_length(lock->lk_offset, lock->lk_length)) | 2665 | if (check_lock_length(lock->lk_offset, lock->lk_length)) |
2655 | return nfserr_inval; | 2666 | return nfserr_inval; |
2656 | 2667 | ||
2657 | if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) { | 2668 | if ((status = fh_verify(rqstp, &cstate->current_fh, |
2669 | S_IFREG, MAY_LOCK))) { | ||
2658 | dprintk("NFSD: nfsd4_lock: permission denied!\n"); | 2670 | dprintk("NFSD: nfsd4_lock: permission denied!\n"); |
2659 | return status; | 2671 | return status; |
2660 | } | 2672 | } |
@@ -2675,7 +2687,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2675 | goto out; | 2687 | goto out; |
2676 | 2688 | ||
2677 | /* validate and update open stateid and open seqid */ | 2689 | /* validate and update open stateid and open seqid */ |
2678 | status = nfs4_preprocess_seqid_op(current_fh, | 2690 | status = nfs4_preprocess_seqid_op(&cstate->current_fh, |
2679 | lock->lk_new_open_seqid, | 2691 | lock->lk_new_open_seqid, |
2680 | &lock->lk_new_open_stateid, | 2692 | &lock->lk_new_open_stateid, |
2681 | CHECK_FH | OPEN_STATE, | 2693 | CHECK_FH | OPEN_STATE, |
@@ -2702,7 +2714,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2702 | goto out; | 2714 | goto out; |
2703 | } else { | 2715 | } else { |
2704 | /* lock (lock owner + lock stateid) already exists */ | 2716 | /* lock (lock owner + lock stateid) already exists */ |
2705 | status = nfs4_preprocess_seqid_op(current_fh, | 2717 | status = nfs4_preprocess_seqid_op(&cstate->current_fh, |
2706 | lock->lk_old_lock_seqid, | 2718 | lock->lk_old_lock_seqid, |
2707 | &lock->lk_old_lock_stateid, | 2719 | &lock->lk_old_lock_stateid, |
2708 | CHECK_FH | LOCK_STATE, | 2720 | CHECK_FH | LOCK_STATE, |
@@ -2794,7 +2806,8 @@ out: | |||
2794 | * LOCKT operation | 2806 | * LOCKT operation |
2795 | */ | 2807 | */ |
2796 | __be32 | 2808 | __be32 |
2797 | nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt) | 2809 | nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
2810 | struct nfsd4_lockt *lockt) | ||
2798 | { | 2811 | { |
2799 | struct inode *inode; | 2812 | struct inode *inode; |
2800 | struct file file; | 2813 | struct file file; |
@@ -2815,14 +2828,14 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2815 | if (STALE_CLIENTID(&lockt->lt_clientid)) | 2828 | if (STALE_CLIENTID(&lockt->lt_clientid)) |
2816 | goto out; | 2829 | goto out; |
2817 | 2830 | ||
2818 | if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) { | 2831 | if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) { |
2819 | dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n"); | 2832 | dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n"); |
2820 | if (status == nfserr_symlink) | 2833 | if (status == nfserr_symlink) |
2821 | status = nfserr_inval; | 2834 | status = nfserr_inval; |
2822 | goto out; | 2835 | goto out; |
2823 | } | 2836 | } |
2824 | 2837 | ||
2825 | inode = current_fh->fh_dentry->d_inode; | 2838 | inode = cstate->current_fh.fh_dentry->d_inode; |
2826 | locks_init_lock(&file_lock); | 2839 | locks_init_lock(&file_lock); |
2827 | switch (lockt->lt_type) { | 2840 | switch (lockt->lt_type) { |
2828 | case NFS4_READ_LT: | 2841 | case NFS4_READ_LT: |
@@ -2861,7 +2874,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2861 | * only the dentry:inode set. | 2874 | * only the dentry:inode set. |
2862 | */ | 2875 | */ |
2863 | memset(&file, 0, sizeof (struct file)); | 2876 | memset(&file, 0, sizeof (struct file)); |
2864 | file.f_path.dentry = current_fh->fh_dentry; | 2877 | file.f_path.dentry = cstate->current_fh.fh_dentry; |
2865 | 2878 | ||
2866 | status = nfs_ok; | 2879 | status = nfs_ok; |
2867 | if (posix_test_lock(&file, &file_lock, &conflock)) { | 2880 | if (posix_test_lock(&file, &file_lock, &conflock)) { |
@@ -2874,7 +2887,8 @@ out: | |||
2874 | } | 2887 | } |
2875 | 2888 | ||
2876 | __be32 | 2889 | __be32 |
2877 | nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner) | 2890 | nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
2891 | struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner) | ||
2878 | { | 2892 | { |
2879 | struct nfs4_stateid *stp; | 2893 | struct nfs4_stateid *stp; |
2880 | struct file *filp = NULL; | 2894 | struct file *filp = NULL; |
@@ -2891,7 +2905,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2891 | 2905 | ||
2892 | nfs4_lock_state(); | 2906 | nfs4_lock_state(); |
2893 | 2907 | ||
2894 | if ((status = nfs4_preprocess_seqid_op(current_fh, | 2908 | if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, |
2895 | locku->lu_seqid, | 2909 | locku->lu_seqid, |
2896 | &locku->lu_stateid, | 2910 | &locku->lu_stateid, |
2897 | CHECK_FH | LOCK_STATE, | 2911 | CHECK_FH | LOCK_STATE, |