aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorNeilBrown <neilb@cse.unsw.edu.au>2005-06-24 01:03:13 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-24 03:06:30 -0400
commit7e06b7f9e9537cb826f3cff95816fc4384b67806 (patch)
treeb6f41e8c458756da5ccf82e075c76b1be329959b /fs/nfsd
parent46be925fa6f4796e732e16a020fa0ef9d48ea7c8 (diff)
[PATCH] knfsd: nfs4: hold filp while reading or writing
We're trying to read and write from a struct file that we may not hold a reference to any more (since a close could be processed as soon as we drop the state lock). Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au> 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.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index ac4878ac2213..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>
@@ -477,26 +478,27 @@ static inline int
477nfsd4_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)
478{ 479{
479 int status; 480 int status;
480 struct file *filp = NULL;
481 481
482 /* 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() */
483 483
484 read->rd_filp = NULL;
484 if (read->rd_offset >= OFFSET_MAX) 485 if (read->rd_offset >= OFFSET_MAX)
485 return nfserr_inval; 486 return nfserr_inval;
486 487
487 nfs4_lock_state(); 488 nfs4_lock_state();
488 /* check stateid */ 489 /* check stateid */
489 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 490 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
490 CHECK_FH | RD_STATE, &filp))) { 491 CHECK_FH | RD_STATE, &read->rd_filp))) {
491 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 492 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
492 goto out; 493 goto out;
493 } 494 }
495 if (read->rd_filp)
496 get_file(read->rd_filp);
494 status = nfs_ok; 497 status = nfs_ok;
495out: 498out:
496 nfs4_unlock_state(); 499 nfs4_unlock_state();
497 read->rd_rqstp = rqstp; 500 read->rd_rqstp = rqstp;
498 read->rd_fhp = current_fh; 501 read->rd_fhp = current_fh;
499 read->rd_filp = filp;
500 return status; 502 return status;
501} 503}
502 504
@@ -633,6 +635,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
633 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 635 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
634 goto out; 636 goto out;
635 } 637 }
638 if (filp)
639 get_file(filp);
636 nfs4_unlock_state(); 640 nfs4_unlock_state();
637 641
638 write->wr_bytes_written = write->wr_buflen; 642 write->wr_bytes_written = write->wr_buflen;
@@ -644,6 +648,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
644 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, 648 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset,
645 write->wr_vec, write->wr_vlen, write->wr_buflen, 649 write->wr_vec, write->wr_vlen, write->wr_buflen,
646 &write->wr_how_written); 650 &write->wr_how_written);
651 if (filp)
652 fput(filp);
647 653
648 if (status == nfserr_symlink) 654 if (status == nfserr_symlink)
649 status = nfserr_inval; 655 status = nfserr_inval;
@@ -932,6 +938,9 @@ encode_op:
932 nfs4_put_stateowner(replay_owner); 938 nfs4_put_stateowner(replay_owner);
933 replay_owner = NULL; 939 replay_owner = NULL;
934 } 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);
935 } 944 }
936 945
937out: 946out: