aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ.Bruce Fields <bfields@fieldses.org>2006-12-13 03:35:27 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-13 12:05:54 -0500
commitca3643171bc6e08b7c4d1f9a2ce659541a01a7fe (patch)
tree2128accc9584e7dd69f6b62c62ef6631f5da231f
parent01f3bd1f03599470e4695392b6ae055ed8506978 (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>
-rw-r--r--fs/nfsd/nfs4proc.c348
-rw-r--r--fs/nfsd/nfs4state.c68
-rw-r--r--include/linux/nfsd/xdr4.h22
3 files changed, 259 insertions, 179 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
164static inline __be32 164static inline __be32
165nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner) 165nfsd4_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(&current_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);
252out: 255out:
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 */
264static inline __be32 267static inline __be32
265nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh) 268nfsd4_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
274static inline __be32 277static inline __be32
275nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh) 278nfsd4_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(&current_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
283static inline __be32 288static inline __be32
284nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) 289nfsd4_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
294static inline __be32 299static inline __be32
295nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh) 300nfsd4_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
304static inline __be32 309static inline __be32
305nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) 310nfsd4_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 */
317static inline __be32 322static inline __be32
318nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access) 323nfsd4_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
327static inline __be32 334static inline __be32
328nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit) 335nfsd4_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
342static __be32 351static __be32
343nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create) 352nfsd4_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
426static inline __be32 437static inline __be32
427nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr) 438nfsd4_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
445static inline __be32 457static inline __be32
446nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh, 458nfsd4_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
459static __be32 472static __be32
460nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) 473nfsd4_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
477static inline __be32 491static inline __be32
478nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup) 492nfsd4_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
483static inline __be32 500static inline __be32
484nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) 501nfsd4_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
504out: 523out:
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
511static inline __be32 530static inline __be32
512nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir) 531nfsd4_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
534static inline __be32 554static inline __be32
535nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink) 555nfsd4_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
542static inline __be32 563static inline __be32
543nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove) 564nfsd4_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
559static inline __be32 582static inline __be32
560nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, 583nfsd4_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
592static inline __be32 615static inline __be32
593nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr) 616nfsd4_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
617static inline __be32 642static inline __be32
618nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write) 643nfsd4_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 */
664static __be32 690static __be32
665nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify) 691nfsd4_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
758static 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
767static 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
959out: 1022out:
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
2244nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner) 2244nfsd4_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
2313nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner) 2315nfsd4_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
2368nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner) 2374nfsd4_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
2407nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr) 2415nfsd4_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();
2417out: 2427out:
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
2638nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner) 2648nfsd4_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
2797nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt) 2809nfsd4_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
2877nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner) 2890nfsd4_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,
diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
index 45ca01b5f844..594b8ca69755 100644
--- a/include/linux/nfsd/xdr4.h
+++ b/include/linux/nfsd/xdr4.h
@@ -44,6 +44,11 @@
44#define NFSD4_MAX_TAGLEN 128 44#define NFSD4_MAX_TAGLEN 128
45#define XDR_LEN(n) (((n) + 3) & ~3) 45#define XDR_LEN(n) (((n) + 3) & ~3)
46 46
47struct nfsd4_compound_state {
48 struct svc_fh current_fh;
49 struct svc_fh save_fh;
50};
51
47struct nfsd4_change_info { 52struct nfsd4_change_info {
48 u32 atomic; 53 u32 atomic;
49 u32 before_ctime_sec; 54 u32 before_ctime_sec;
@@ -437,20 +442,23 @@ extern __be32 nfsd4_process_open1(struct nfsd4_open *open);
437extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp, 442extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
438 struct svc_fh *current_fh, struct nfsd4_open *open); 443 struct svc_fh *current_fh, struct nfsd4_open *open);
439extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp, 444extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
440 struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, 445 struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc,
441 struct nfs4_stateowner **); 446 struct nfs4_stateowner **);
442extern __be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, 447extern __be32 nfsd4_close(struct svc_rqst *rqstp,
448 struct nfsd4_compound_state *,
443 struct nfsd4_close *close, 449 struct nfsd4_close *close,
444 struct nfs4_stateowner **replay_owner); 450 struct nfs4_stateowner **replay_owner);
445extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp, 451extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
446 struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, 452 struct nfsd4_compound_state *, struct nfsd4_open_downgrade *od,
447 struct nfs4_stateowner **replay_owner); 453 struct nfs4_stateowner **replay_owner);
448extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, 454extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
449 struct nfsd4_lock *lock, 455 struct nfsd4_lock *lock,
450 struct nfs4_stateowner **replay_owner); 456 struct nfs4_stateowner **replay_owner);
451extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, 457extern __be32 nfsd4_lockt(struct svc_rqst *rqstp,
458 struct nfsd4_compound_state *,
452 struct nfsd4_lockt *lockt); 459 struct nfsd4_lockt *lockt);
453extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, 460extern __be32 nfsd4_locku(struct svc_rqst *rqstp,
461 struct nfsd4_compound_state *,
454 struct nfsd4_locku *locku, 462 struct nfsd4_locku *locku,
455 struct nfs4_stateowner **replay_owner); 463 struct nfs4_stateowner **replay_owner);
456extern __be32 464extern __be32
@@ -458,7 +466,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
458 struct nfsd4_release_lockowner *rlockowner); 466 struct nfsd4_release_lockowner *rlockowner);
459extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *); 467extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
460extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp, 468extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
461 struct svc_fh *current_fh, struct nfsd4_delegreturn *dr); 469 struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
462#endif 470#endif
463 471
464/* 472/*