summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jeff.layton@primarydata.com>2019-08-18 14:18:56 -0400
committerJ. Bruce Fields <bfields@redhat.com>2019-08-19 11:09:09 -0400
commit501cb1849f865960501d19d54e6a5af306f9b6fd (patch)
treed2f4514084d664ce8d54fb7303d637949532c1ea
parent6b556ca2872be223176c1a1e249606248ce0b201 (diff)
nfsd: rip out the raparms cache
The raparms cache was set up in order to ensure that we carry readahead information forward from one RPC call to the next. In other words, it was set up because each RPC call was forced to open a struct file, then close it, causing the loss of readahead information that is normally cached in that struct file, and used to keep the page cache filled when a user calls read() multiple times on the same file descriptor. Now that we cache the struct file, and reuse it for all the I/O calls to a given file by a given user, we no longer have to keep a separate readahead cache. Signed-off-by: Jeff Layton <jeff.layton@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>
-rw-r--r--fs/nfsd/nfssvc.c13
-rw-r--r--fs/nfsd/vfs.c149
-rw-r--r--fs/nfsd/vfs.h6
3 files changed, 1 insertions, 167 deletions
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index a6b1eab7b722..d02712ca2685 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -317,22 +317,12 @@ static int nfsd_startup_generic(int nrservs)
317 ret = nfsd_file_cache_init(); 317 ret = nfsd_file_cache_init();
318 if (ret) 318 if (ret)
319 goto dec_users; 319 goto dec_users;
320 /*
321 * Readahead param cache - will no-op if it already exists.
322 * (Note therefore results will be suboptimal if number of
323 * threads is modified after nfsd start.)
324 */
325 ret = nfsd_racache_init(2*nrservs);
326 if (ret)
327 goto out_file_cache;
328 320
329 ret = nfs4_state_start(); 321 ret = nfs4_state_start();
330 if (ret) 322 if (ret)
331 goto out_racache; 323 goto out_file_cache;
332 return 0; 324 return 0;
333 325
334out_racache:
335 nfsd_racache_shutdown();
336out_file_cache: 326out_file_cache:
337 nfsd_file_cache_shutdown(); 327 nfsd_file_cache_shutdown();
338dec_users: 328dec_users:
@@ -347,7 +337,6 @@ static void nfsd_shutdown_generic(void)
347 337
348 nfs4_state_shutdown(); 338 nfs4_state_shutdown();
349 nfsd_file_cache_shutdown(); 339 nfsd_file_cache_shutdown();
350 nfsd_racache_shutdown();
351} 340}
352 341
353static bool nfsd_needs_lockd(struct nfsd_net *nn) 342static bool nfsd_needs_lockd(struct nfsd_net *nn)
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index ec254bff1893..8e2c8f36eba3 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -49,34 +49,6 @@
49 49
50#define NFSDDBG_FACILITY NFSDDBG_FILEOP 50#define NFSDDBG_FACILITY NFSDDBG_FILEOP
51 51
52
53/*
54 * This is a cache of readahead params that help us choose the proper
55 * readahead strategy. Initially, we set all readahead parameters to 0
56 * and let the VFS handle things.
57 * If you increase the number of cached files very much, you'll need to
58 * add a hash table here.
59 */
60struct raparms {
61 struct raparms *p_next;
62 unsigned int p_count;
63 ino_t p_ino;
64 dev_t p_dev;
65 int p_set;
66 struct file_ra_state p_ra;
67 unsigned int p_hindex;
68};
69
70struct raparm_hbucket {
71 struct raparms *pb_head;
72 spinlock_t pb_lock;
73} ____cacheline_aligned_in_smp;
74
75#define RAPARM_HASH_BITS 4
76#define RAPARM_HASH_SIZE (1<<RAPARM_HASH_BITS)
77#define RAPARM_HASH_MASK (RAPARM_HASH_SIZE-1)
78static struct raparm_hbucket raparm_hash[RAPARM_HASH_SIZE];
79
80/* 52/*
81 * Called from nfsd_lookup and encode_dirent. Check if we have crossed 53 * Called from nfsd_lookup and encode_dirent. Check if we have crossed
82 * a mount point. 54 * a mount point.
@@ -822,67 +794,6 @@ nfsd_open_verified(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
822 return err; 794 return err;
823} 795}
824 796
825
826
827struct raparms *
828nfsd_init_raparms(struct file *file)
829{
830 struct inode *inode = file_inode(file);
831 dev_t dev = inode->i_sb->s_dev;
832 ino_t ino = inode->i_ino;
833 struct raparms *ra, **rap, **frap = NULL;
834 int depth = 0;
835 unsigned int hash;
836 struct raparm_hbucket *rab;
837
838 hash = jhash_2words(dev, ino, 0xfeedbeef) & RAPARM_HASH_MASK;
839 rab = &raparm_hash[hash];
840
841 spin_lock(&rab->pb_lock);
842 for (rap = &rab->pb_head; (ra = *rap); rap = &ra->p_next) {
843 if (ra->p_ino == ino && ra->p_dev == dev)
844 goto found;
845 depth++;
846 if (ra->p_count == 0)
847 frap = rap;
848 }
849 depth = nfsdstats.ra_size;
850 if (!frap) {
851 spin_unlock(&rab->pb_lock);
852 return NULL;
853 }
854 rap = frap;
855 ra = *frap;
856 ra->p_dev = dev;
857 ra->p_ino = ino;
858 ra->p_set = 0;
859 ra->p_hindex = hash;
860found:
861 if (rap != &rab->pb_head) {
862 *rap = ra->p_next;
863 ra->p_next = rab->pb_head;
864 rab->pb_head = ra;
865 }
866 ra->p_count++;
867 nfsdstats.ra_depth[depth*10/nfsdstats.ra_size]++;
868 spin_unlock(&rab->pb_lock);
869
870 if (ra->p_set)
871 file->f_ra = ra->p_ra;
872 return ra;
873}
874
875void nfsd_put_raparams(struct file *file, struct raparms *ra)
876{
877 struct raparm_hbucket *rab = &raparm_hash[ra->p_hindex];
878
879 spin_lock(&rab->pb_lock);
880 ra->p_ra = file->f_ra;
881 ra->p_set = 1;
882 ra->p_count--;
883 spin_unlock(&rab->pb_lock);
884}
885
886/* 797/*
887 * Grab and keep cached pages associated with a file in the svc_rqst 798 * Grab and keep cached pages associated with a file in the svc_rqst
888 * so that they can be passed to the network sendmsg/sendpage routines 799 * so that they can be passed to the network sendmsg/sendpage routines
@@ -2094,63 +2005,3 @@ nfsd_permission(struct svc_rqst *rqstp, struct svc_export *exp,
2094 2005
2095 return err? nfserrno(err) : 0; 2006 return err? nfserrno(err) : 0;
2096} 2007}
2097
2098void
2099nfsd_racache_shutdown(void)
2100{
2101 struct raparms *raparm, *last_raparm;
2102 unsigned int i;
2103
2104 dprintk("nfsd: freeing readahead buffers.\n");
2105
2106 for (i = 0; i < RAPARM_HASH_SIZE; i++) {
2107 raparm = raparm_hash[i].pb_head;
2108 while(raparm) {
2109 last_raparm = raparm;
2110 raparm = raparm->p_next;
2111 kfree(last_raparm);
2112 }
2113 raparm_hash[i].pb_head = NULL;
2114 }
2115}
2116/*
2117 * Initialize readahead param cache
2118 */
2119int
2120nfsd_racache_init(int cache_size)
2121{
2122 int i;
2123 int j = 0;
2124 int nperbucket;
2125 struct raparms **raparm = NULL;
2126
2127
2128 if (raparm_hash[0].pb_head)
2129 return 0;
2130 nperbucket = DIV_ROUND_UP(cache_size, RAPARM_HASH_SIZE);
2131 nperbucket = max(2, nperbucket);
2132 cache_size = nperbucket * RAPARM_HASH_SIZE;
2133
2134 dprintk("nfsd: allocating %d readahead buffers.\n", cache_size);
2135
2136 for (i = 0; i < RAPARM_HASH_SIZE; i++) {
2137 spin_lock_init(&raparm_hash[i].pb_lock);
2138
2139 raparm = &raparm_hash[i].pb_head;
2140 for (j = 0; j < nperbucket; j++) {
2141 *raparm = kzalloc(sizeof(struct raparms), GFP_KERNEL);
2142 if (!*raparm)
2143 goto out_nomem;
2144 raparm = &(*raparm)->p_next;
2145 }
2146 *raparm = NULL;
2147 }
2148
2149 nfsdstats.ra_size = cache_size;
2150 return 0;
2151
2152out_nomem:
2153 dprintk("nfsd: kmalloc failed, freeing readahead buffers\n");
2154 nfsd_racache_shutdown();
2155 return -ENOMEM;
2156}
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h
index 31fdae34e028..e0f7792165a6 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -40,8 +40,6 @@
40typedef int (*nfsd_filldir_t)(void *, const char *, int, loff_t, u64, unsigned); 40typedef int (*nfsd_filldir_t)(void *, const char *, int, loff_t, u64, unsigned);
41 41
42/* nfsd/vfs.c */ 42/* nfsd/vfs.c */
43int nfsd_racache_init(int);
44void nfsd_racache_shutdown(void);
45int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, 43int nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
46 struct svc_export **expp); 44 struct svc_export **expp);
47__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *, 45__be32 nfsd_lookup(struct svc_rqst *, struct svc_fh *,
@@ -80,7 +78,6 @@ __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t,
80 int, struct file **); 78 int, struct file **);
81__be32 nfsd_open_verified(struct svc_rqst *, struct svc_fh *, umode_t, 79__be32 nfsd_open_verified(struct svc_rqst *, struct svc_fh *, umode_t,
82 int, struct file **); 80 int, struct file **);
83struct raparms;
84__be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, 81__be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
85 struct file *file, loff_t offset, 82 struct file *file, loff_t offset,
86 unsigned long *count); 83 unsigned long *count);
@@ -118,9 +115,6 @@ __be32 nfsd_statfs(struct svc_rqst *, struct svc_fh *,
118__be32 nfsd_permission(struct svc_rqst *, struct svc_export *, 115__be32 nfsd_permission(struct svc_rqst *, struct svc_export *,
119 struct dentry *, int); 116 struct dentry *, int);
120 117
121struct raparms *nfsd_init_raparms(struct file *file);
122void nfsd_put_raparams(struct file *file, struct raparms *ra);
123
124static inline int fh_want_write(struct svc_fh *fh) 118static inline int fh_want_write(struct svc_fh *fh)
125{ 119{
126 int ret; 120 int ret;