aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
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 /fs/nfsd/vfs.c
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>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c149
1 files changed, 0 insertions, 149 deletions
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}