aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4proc.c')
-rw-r--r--fs/nfsd/nfs4proc.c26
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
473nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) 478nfsd4_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;
491out: 498out:
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
928out: 946out: