diff options
author | NeilBrown <neilb@cse.unsw.edu.au> | 2005-06-24 01:03:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:06:30 -0400 |
commit | 7e06b7f9e9537cb826f3cff95816fc4384b67806 (patch) | |
tree | b6f41e8c458756da5ccf82e075c76b1be329959b /fs | |
parent | 46be925fa6f4796e732e16a020fa0ef9d48ea7c8 (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')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index ac4878ac221..d71f14517b9 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 | |||
477 | 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) |
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; |
495 | out: | 498 | out: |
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 | ||
937 | out: | 946 | out: |