diff options
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index e8158741e8b5..d71f14517b9c 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/param.h> | 45 | #include <linux/param.h> |
46 | #include <linux/major.h> | 46 | #include <linux/major.h> |
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/file.h> | ||
48 | 49 | ||
49 | #include <linux/sunrpc/svc.h> | 50 | #include <linux/sunrpc/svc.h> |
50 | #include <linux/nfsd/nfsd.h> | 51 | #include <linux/nfsd/nfsd.h> |
@@ -198,6 +199,11 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open | |||
198 | if (status) | 199 | if (status) |
199 | goto out; | 200 | goto out; |
200 | switch (open->op_claim_type) { | 201 | switch (open->op_claim_type) { |
202 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: | ||
203 | status = nfserr_inval; | ||
204 | if (open->op_create) | ||
205 | goto out; | ||
206 | /* fall through */ | ||
201 | case NFS4_OPEN_CLAIM_NULL: | 207 | case NFS4_OPEN_CLAIM_NULL: |
202 | /* | 208 | /* |
203 | * (1) set CURRENT_FH to the file being opened, | 209 | * (1) set CURRENT_FH to the file being opened, |
@@ -220,7 +226,6 @@ nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open | |||
220 | if (status) | 226 | if (status) |
221 | goto out; | 227 | goto out; |
222 | break; | 228 | break; |
223 | case NFS4_OPEN_CLAIM_DELEGATE_CUR: | ||
224 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: | 229 | case NFS4_OPEN_CLAIM_DELEGATE_PREV: |
225 | printk("NFSD: unsupported OPEN claim type %d\n", | 230 | printk("NFSD: unsupported OPEN claim type %d\n", |
226 | open->op_claim_type); | 231 | open->op_claim_type); |
@@ -473,26 +478,27 @@ static inline int | |||
473 | nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) | 478 | nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) |
474 | { | 479 | { |
475 | int status; | 480 | int status; |
476 | struct file *filp = NULL; | ||
477 | 481 | ||
478 | /* no need to check permission - this will be done in nfsd_read() */ | 482 | /* no need to check permission - this will be done in nfsd_read() */ |
479 | 483 | ||
484 | read->rd_filp = NULL; | ||
480 | if (read->rd_offset >= OFFSET_MAX) | 485 | if (read->rd_offset >= OFFSET_MAX) |
481 | return nfserr_inval; | 486 | return nfserr_inval; |
482 | 487 | ||
483 | nfs4_lock_state(); | 488 | nfs4_lock_state(); |
484 | /* check stateid */ | 489 | /* check stateid */ |
485 | if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, | 490 | if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, |
486 | CHECK_FH | RD_STATE, &filp))) { | 491 | CHECK_FH | RD_STATE, &read->rd_filp))) { |
487 | dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); | 492 | dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); |
488 | goto out; | 493 | goto out; |
489 | } | 494 | } |
495 | if (read->rd_filp) | ||
496 | get_file(read->rd_filp); | ||
490 | status = nfs_ok; | 497 | status = nfs_ok; |
491 | out: | 498 | out: |
492 | nfs4_unlock_state(); | 499 | nfs4_unlock_state(); |
493 | read->rd_rqstp = rqstp; | 500 | read->rd_rqstp = rqstp; |
494 | read->rd_fhp = current_fh; | 501 | read->rd_fhp = current_fh; |
495 | read->rd_filp = filp; | ||
496 | return status; | 502 | return status; |
497 | } | 503 | } |
498 | 504 | ||
@@ -532,6 +538,8 @@ nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_rem | |||
532 | { | 538 | { |
533 | int status; | 539 | int status; |
534 | 540 | ||
541 | if (nfs4_in_grace()) | ||
542 | return nfserr_grace; | ||
535 | status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen); | 543 | status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen); |
536 | if (status == nfserr_symlink) | 544 | if (status == nfserr_symlink) |
537 | return nfserr_notdir; | 545 | return nfserr_notdir; |
@@ -550,6 +558,9 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, | |||
550 | 558 | ||
551 | if (!save_fh->fh_dentry) | 559 | if (!save_fh->fh_dentry) |
552 | return status; | 560 | return status; |
561 | if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags | ||
562 | & NFSEXP_NOSUBTREECHECK)) | ||
563 | return nfserr_grace; | ||
553 | status = nfsd_rename(rqstp, save_fh, rename->rn_sname, | 564 | status = nfsd_rename(rqstp, save_fh, rename->rn_sname, |
554 | rename->rn_snamelen, current_fh, | 565 | rename->rn_snamelen, current_fh, |
555 | rename->rn_tname, rename->rn_tnamelen); | 566 | rename->rn_tname, rename->rn_tnamelen); |
@@ -624,6 +635,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ | |||
624 | dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); | 635 | dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); |
625 | goto out; | 636 | goto out; |
626 | } | 637 | } |
638 | if (filp) | ||
639 | get_file(filp); | ||
627 | nfs4_unlock_state(); | 640 | nfs4_unlock_state(); |
628 | 641 | ||
629 | write->wr_bytes_written = write->wr_buflen; | 642 | write->wr_bytes_written = write->wr_buflen; |
@@ -635,6 +648,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ | |||
635 | status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, | 648 | status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, |
636 | write->wr_vec, write->wr_vlen, write->wr_buflen, | 649 | write->wr_vec, write->wr_vlen, write->wr_buflen, |
637 | &write->wr_how_written); | 650 | &write->wr_how_written); |
651 | if (filp) | ||
652 | fput(filp); | ||
638 | 653 | ||
639 | if (status == nfserr_symlink) | 654 | if (status == nfserr_symlink) |
640 | status = nfserr_inval; | 655 | status = nfserr_inval; |
@@ -923,6 +938,9 @@ encode_op: | |||
923 | nfs4_put_stateowner(replay_owner); | 938 | nfs4_put_stateowner(replay_owner); |
924 | replay_owner = NULL; | 939 | replay_owner = NULL; |
925 | } | 940 | } |
941 | /* XXX Ugh, we need to get rid of this kind of special case: */ | ||
942 | if (op->opnum == OP_READ && op->u.read.rd_filp) | ||
943 | fput(op->u.read.rd_filp); | ||
926 | } | 944 | } |
927 | 945 | ||
928 | out: | 946 | out: |