1 /* 2 * linux/fs/nfsd/nfscache.c 3 * 4 * Request reply cache. This is currently a global cache, but this may 5 * change in the future and be a per-client cache. 6 * 7 * This code is heavily inspired by the 44BSD implementation, although 8 * it does things a bit differently. 9 * 10 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/time.h> 15 #include <linux/slab.h> 16 #include <linux/string.h> 17 #include <linux/spinlock.h> 18 #include <linux/list.h> 19 20 #include <linux/sunrpc/svc.h> 21 #include <linux/nfsd/nfsd.h> 22 #include <linux/nfsd/cache.h> 23 24 /* Size of reply cache. Common values are: 25 * 4.3BSD: 128 26 * 4.4BSD: 256 27 * Solaris2: 1024 28 * DEC Unix: 512-4096 29 */ 30 #define CACHESIZE 1024 31 #define HASHSIZE 64 32 #define REQHASH(xid) (((((__force __u32)xid) >> 24) ^ ((__force __u32)xid)) & (HASHSIZE-1)) 33 34 static struct hlist_head * hash_list; 35 static struct list_head lru_head; 36 static int cache_disabled = 1; 37 38 static int nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec); 39 40 /* 41 * locking for the reply cache: 42 * A cache entry is "single use" if c_state == RC_INPROG 43 * Otherwise, it when accessing _prev or _next, the lock must be held. 44 */ 45 static DEFINE_SPINLOCK(cache_lock); 46 47 int nfsd_reply_cache_init(void) 48 { 49 struct svc_cacherep *rp; 50 int i; 51 52 INIT_LIST_HEAD(&lru_head); 53 i = CACHESIZE; 54 while (i) { 55 rp = kmalloc(sizeof(*rp), GFP_KERNEL); 56 if (!rp) 57 goto out_nomem; 58 list_add(&rp->c_lru, &lru_head); 59 rp->c_state = RC_UNUSED; 60 rp->c_type = RC_NOCACHE; 61 INIT_HLIST_NODE(&rp->c_hash); 62 i--; 63 } 64 65 hash_list = kcalloc (HASHSIZE, sizeof(struct hlist_head), GFP_KERNEL); 66 if (!hash_list) 67 goto out_nomem; 68 69 cache_disabled = 0; 70 return 0; 71 out_nomem: 72 printk(KERN_ERR "nfsd: failed to allocate reply cache\n"); 73 nfsd_reply_cache_shutdown(); 74 return -ENOMEM; 75 } 76 77 void nfsd_reply_cache_shutdown(void) 78 { 79 struct svc_cacherep *rp; 80 81 while (!list_empty(&lru_head)) { 82 rp = list_entry(lru_head.next, struct svc_cacherep, c_lru); 83 if (rp->c_state == RC_DONE && rp->c_type == RC_REPLBUFF) 84 kfree(rp->c_replvec.iov_base); 85 list_del(&rp->c_lru); 86 kfree(rp); 87 } 88 89 cache_disabled = 1; 90 91 kfree (hash_list); 92 hash_list = NULL; 93 } 94 95 /* 96 * Move cache entry to end of LRU list 97 */ 98 static void 99 lru_put_end(struct svc_cacherep *rp) 100 { 101 list_move_tail(&rp->c_lru, &lru_head); 102 } 103 104 /* 105 * Move a cache entry from one hash list to another 106 */ 107 static void 108 hash_refile(struct svc_cacherep *rp) 109 { 110 hlist_del_init(&rp->c_hash); 111 hlist_add_head(&rp->c_hash, hash_list + REQHASH(rp->c_xid)); 112 } 113 114 /* 115 * Try to find an entry matching the current call in the cache. When none 116 * is found, we grab the oldest unlocked entry off the LRU list. 117 * Note that no operation within the loop may sleep. 118 */ 119 int 120 nfsd_cache_lookup(struct svc_rqst *rqstp, int type) 121 { 122 struct hlist_node *hn; 123 struct hlist_head *rh; 124 struct svc_cacherep *rp; 125 __be32 xid = rqstp->rq_xid; 126 u32 proto = rqstp->rq_prot, 127 vers = rqstp->rq_vers, 128 proc = rqstp->rq_proc; 129 unsigned long age; 130 int rtn; 131 132 rqstp->rq_cacherep = NULL; 133 if (cache_disabled || type == RC_NOCACHE) { 134 nfsdstats.rcnocache++; 135 return RC_DOIT; 136 } 137 138 spin_lock(&cache_lock); 139 rtn = RC_DOIT; 140 141 rh = &hash_list[REQHASH(xid)]; 142 hlist_for_each_entry(rp, hn, rh, c_hash) { 143 if (rp->c_state != RC_UNUSED && 144 xid == rp->c_xid && proc == rp->c_proc && 145 proto == rp->c_prot && vers == rp->c_vers && 146 time_before(jiffies, rp->c_timestamp + 120*HZ) && 147 memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, sizeof(rp->c_addr))==0) { 148 nfsdstats.rchits++; 149 goto found_entry; 150 } 151 } 152 nfsdstats.rcmisses++; 153 154 /* This loop shouldn't take more than a few iterations normally */ 155 { 156 int safe = 0; 157 list_for_each_entry(rp, &lru_head, c_lru) { 158 if (rp->c_state != RC_INPROG) 159 break; 160 if (safe++ > CACHESIZE) { 161 printk("nfsd: loop in repcache LRU list\n"); 162 cache_disabled = 1; 163 goto out; 164 } 165 } 166 } 167 168 /* This should not happen */ 169 if (rp == NULL) { 170 static int complaints; 171 172 printk(KERN_WARNING "nfsd: all repcache entries locked!\n"); 173 if (++complaints > 5) { 174 printk(KERN_WARNING "nfsd: disabling repcache.\n"); 175 cache_disabled = 1; 176 } 177 goto out; 178 } 179 180 rqstp->rq_cacherep = rp; 181 rp->c_state = RC_INPROG; 182 rp->c_xid = xid; 183 rp->c_proc = proc; 184 memcpy(&rp->c_addr, svc_addr_in(rqstp), sizeof(rp->c_addr)); 185 rp->c_prot = proto; 186 rp->c_vers = vers; 187 rp->c_timestamp = jiffies; 188 189 hash_refile(rp); 190 191 /* release any buffer */ 192 if (rp->c_type == RC_REPLBUFF) { 193 kfree(rp->c_replvec.iov_base); 194 rp->c_replvec.iov_base = NULL; 195 } 196 rp->c_type = RC_NOCACHE; 197 out: 198 spin_unlock(&cache_lock); 199 return rtn; 200 201 found_entry: 202 /* We found a matching entry which is either in progress or done. */ 203 age = jiffies - rp->c_timestamp; 204 rp->c_timestamp = jiffies; 205 lru_put_end(rp); 206 207 rtn = RC_DROPIT; 208 /* Request being processed or excessive rexmits */ 209 if (rp->c_state == RC_INPROG || age < RC_DELAY) 210 goto out; 211 212 /* From the hall of fame of impractical attacks: 213 * Is this a user who tries to snoop on the cache? */ 214 rtn = RC_DOIT; 215 if (!rqstp->rq_secure && rp->c_secure) 216 goto out; 217 218 /* Compose RPC reply header */ 219 switch (rp->c_type) { 220 case RC_NOCACHE: 221 break; 222 case RC_REPLSTAT: 223 svc_putu32(&rqstp->rq_res.head[0], rp->c_replstat); 224 rtn = RC_REPLY; 225 break; 226 case RC_REPLBUFF: 227 if (!nfsd_cache_append(rqstp, &rp->c_replvec)) 228 goto out; /* should not happen */ 229 rtn = RC_REPLY; 230 break; 231 default: 232 printk(KERN_WARNING "nfsd: bad repcache type %d\n", rp->c_type); 233 rp->c_state = RC_UNUSED; 234 } 235 236 goto out; 237 } 238 239 /* 240 * Update a cache entry. This is called from nfsd_dispatch when 241 * the procedure has been executed and the complete reply is in 242 * rqstp->rq_res. 243 * 244 * We're copying around data here rather than swapping buffers because 245 * the toplevel loop requires max-sized buffers, which would be a waste 246 * of memory for a cache with a max reply size of 100 bytes (diropokres). 247 * 248 * If we should start to use different types of cache entries tailored 249 * specifically for attrstat and fh's, we may save even more space. 250 * 251 * Also note that a cachetype of RC_NOCACHE can legally be passed when 252 * nfsd failed to encode a reply that otherwise would have been cached. 253 * In this case, nfsd_cache_update is called with statp == NULL. 254 */ 255 void 256 nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp) 257 { 258 struct svc_cacherep *rp; 259 struct kvec *resv = &rqstp->rq_res.head[0], *cachv; 260 int len; 261 262 if (!(rp = rqstp->rq_cacherep) || cache_disabled) 263 return; 264 265 len = resv->iov_len - ((char*)statp - (char*)resv->iov_base); 266 len >>= 2; 267 268 /* Don't cache excessive amounts of data and XDR failures */ 269 if (!statp || len > (256 >> 2)) { 270 rp->c_state = RC_UNUSED; 271 return; 272 } 273 274 switch (cachetype) { 275 case RC_REPLSTAT: 276 if (len != 1) 277 printk("nfsd: RC_REPLSTAT/reply len %d!\n",len); 278 rp->c_replstat = *statp; 279 break; 280 case RC_REPLBUFF: 281 cachv = &rp->c_replvec; 282 cachv->iov_base = kmalloc(len << 2, GFP_KERNEL); 283 if (!cachv->iov_base) { 284 spin_lock(&cache_lock); 285 rp->c_state = RC_UNUSED; 286 spin_unlock(&cache_lock); 287 return; 288 } 289 cachv->iov_len = len << 2; 290 memcpy(cachv->iov_base, statp, len << 2); 291 break; 292 } 293 spin_lock(&cache_lock); 294 lru_put_end(rp); 295 rp->c_secure = rqstp->rq_secure; 296 rp->c_type = cachetype; 297 rp->c_state = RC_DONE; 298 rp->c_timestamp = jiffies; 299 spin_unlock(&cache_lock); 300 return; 301 } 302 303 /* 304 * Copy cached reply to current reply buffer. Should always fit. 305 * FIXME as reply is in a page, we should just attach the page, and 306 * keep a refcount.... 307 */ 308 static int 309 nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *data) 310 { 311 struct kvec *vec = &rqstp->rq_res.head[0]; 312 313 if (vec->iov_len + data->iov_len > PAGE_SIZE) { 314 printk(KERN_WARNING "nfsd: cached reply too large (%Zd).\n", 315 data->iov_len); 316 return 0; 317 } 318 memcpy((char*)vec->iov_base + vec->iov_len, data->iov_base, data->iov_len); 319 vec->iov_len += data->iov_len; 320 return 1; 321 } 322