aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
authorJeff Layton <jeff.layton@primarydata.com>2019-08-18 14:18:48 -0400
committerJ. Bruce Fields <bfields@redhat.com>2019-08-19 11:00:39 -0400
commit65294c1f2c5e72b15b76e16c8c8cfd9359fc9f6f (patch)
tree9b088b0f2e2fba280862b489910b1aeb0460c8c3 /fs/nfsd/vfs.c
parent7239a40ca8bfd88dc5d2f66a14882054fe8e3b92 (diff)
nfsd: add a new struct file caching facility to nfsd
Currently, NFSv2/3 reads and writes have to open a file, do the read or write and then close it again for each RPC. This is highly inefficient, especially when the underlying filesystem has a relatively slow open routine. This patch adds a new open file cache to knfsd. Rather than doing an open for each RPC, the read/write handlers can call into this cache to see if there is one already there for the correct filehandle and NFS_MAY_READ/WRITE flags. If there isn't an entry, then we create a new one and attempt to perform the open. If there is, then we wait until the entry is fully instantiated and return it if it is at the end of the wait. If it's not, then we attempt to take over construction. Since the main goal is to speed up NFSv2/3 I/O, we don't want to close these files on last put of these objects. We need to keep them around for a little while since we never know when the next READ/WRITE will come in. Cache entries have a hardcoded 1s timeout, and we have a recurring workqueue job that walks the cache and purges any entries that have expired. Signed-off-by: Jeff Layton <jeff.layton@primarydata.com> Signed-off-by: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Richard Sharpe <richard.sharpe@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c65
1 files changed, 43 insertions, 22 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c85783e536d5..5983206ab036 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -699,7 +699,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
699} 699}
700#endif /* CONFIG_NFSD_V3 */ 700#endif /* CONFIG_NFSD_V3 */
701 701
702static int nfsd_open_break_lease(struct inode *inode, int access) 702int nfsd_open_break_lease(struct inode *inode, int access)
703{ 703{
704 unsigned int mode; 704 unsigned int mode;
705 705
@@ -715,8 +715,8 @@ static int nfsd_open_break_lease(struct inode *inode, int access)
715 * and additional flags. 715 * and additional flags.
716 * N.B. After this call fhp needs an fh_put 716 * N.B. After this call fhp needs an fh_put
717 */ 717 */
718__be32 718static __be32
719nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, 719__nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
720 int may_flags, struct file **filp) 720 int may_flags, struct file **filp)
721{ 721{
722 struct path path; 722 struct path path;
@@ -726,25 +726,6 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
726 __be32 err; 726 __be32 err;
727 int host_err = 0; 727 int host_err = 0;
728 728
729 validate_process_creds();
730
731 /*
732 * If we get here, then the client has already done an "open",
733 * and (hopefully) checked permission - so allow OWNER_OVERRIDE
734 * in case a chmod has now revoked permission.
735 *
736 * Arguably we should also allow the owner override for
737 * directories, but we never have and it doesn't seem to have
738 * caused anyone a problem. If we were to change this, note
739 * also that our filldir callbacks would need a variant of
740 * lookup_one_len that doesn't check permissions.
741 */
742 if (type == S_IFREG)
743 may_flags |= NFSD_MAY_OWNER_OVERRIDE;
744 err = fh_verify(rqstp, fhp, type, may_flags);
745 if (err)
746 goto out;
747
748 path.mnt = fhp->fh_export->ex_path.mnt; 729 path.mnt = fhp->fh_export->ex_path.mnt;
749 path.dentry = fhp->fh_dentry; 730 path.dentry = fhp->fh_dentry;
750 inode = d_inode(path.dentry); 731 inode = d_inode(path.dentry);
@@ -798,10 +779,50 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
798out_nfserr: 779out_nfserr:
799 err = nfserrno(host_err); 780 err = nfserrno(host_err);
800out: 781out:
782 return err;
783}
784
785__be32
786nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
787 int may_flags, struct file **filp)
788{
789 __be32 err;
790
791 validate_process_creds();
792 /*
793 * If we get here, then the client has already done an "open",
794 * and (hopefully) checked permission - so allow OWNER_OVERRIDE
795 * in case a chmod has now revoked permission.
796 *
797 * Arguably we should also allow the owner override for
798 * directories, but we never have and it doesn't seem to have
799 * caused anyone a problem. If we were to change this, note
800 * also that our filldir callbacks would need a variant of
801 * lookup_one_len that doesn't check permissions.
802 */
803 if (type == S_IFREG)
804 may_flags |= NFSD_MAY_OWNER_OVERRIDE;
805 err = fh_verify(rqstp, fhp, type, may_flags);
806 if (!err)
807 err = __nfsd_open(rqstp, fhp, type, may_flags, filp);
808 validate_process_creds();
809 return err;
810}
811
812__be32
813nfsd_open_verified(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
814 int may_flags, struct file **filp)
815{
816 __be32 err;
817
818 validate_process_creds();
819 err = __nfsd_open(rqstp, fhp, type, may_flags, filp);
801 validate_process_creds(); 820 validate_process_creds();
802 return err; 821 return err;
803} 822}
804 823
824
825
805struct raparms * 826struct raparms *
806nfsd_init_raparms(struct file *file) 827nfsd_init_raparms(struct file *file)
807{ 828{