Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 359731
b: refs/heads/master
c: 01a7dec
h: refs/heads/master
i:
  359729: 076320a
  359727: 42da1f2
v: v3
  • Loading branch information
Jeff Layton authored and J. Bruce Fields committed Feb 8, 2013
1 parent 235ad23 commit 6f36272
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 4 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4c190e2f913f038c9c91ee63b59cd037260ba353
refs/heads/master: 01a7decf75930925322c5efc87af0b5e58eb8650
5 changes: 5 additions & 0 deletions trunk/fs/nfsd/cache.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct svc_cacherep {
u32 c_prot;
u32 c_proc;
u32 c_vers;
unsigned int c_len;
__wsum c_csum;
unsigned long c_timestamp;
union {
struct kvec u_vec;
Expand Down Expand Up @@ -73,6 +75,9 @@ enum {
/* Cache entries expire after this time period */
#define RC_EXPIRE (120 * HZ)

/* Checksum this amount of the request */
#define RC_CSUMLEN (256U)

int nfsd_reply_cache_init(void);
void nfsd_reply_cache_shutdown(void);
int nfsd_cache_lookup(struct svc_rqst *);
Expand Down
47 changes: 44 additions & 3 deletions trunk/fs/nfsd/nfscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/sunrpc/addr.h>
#include <linux/highmem.h>
#include <net/checksum.h>

#include "nfsd.h"
#include "cache.h"
Expand Down Expand Up @@ -130,6 +131,7 @@ int nfsd_reply_cache_init(void)
INIT_LIST_HEAD(&lru_head);
max_drc_entries = nfsd_cache_size_limit();
num_drc_entries = 0;

return 0;
out_nomem:
printk(KERN_ERR "nfsd: failed to allocate reply cache\n");
Expand Down Expand Up @@ -237,13 +239,46 @@ nfsd_reply_cache_shrink(struct shrinker *shrink, struct shrink_control *sc)
return num;
}

/*
* Walk an xdr_buf and get a CRC for at most the first RC_CSUMLEN bytes
*/
static __wsum
nfsd_cache_csum(struct svc_rqst *rqstp)
{
int idx;
unsigned int base;
__wsum csum;
struct xdr_buf *buf = &rqstp->rq_arg;
const unsigned char *p = buf->head[0].iov_base;
size_t csum_len = min_t(size_t, buf->head[0].iov_len + buf->page_len,
RC_CSUMLEN);
size_t len = min(buf->head[0].iov_len, csum_len);

/* rq_arg.head first */
csum = csum_partial(p, len, 0);
csum_len -= len;

/* Continue into page array */
idx = buf->page_base / PAGE_SIZE;
base = buf->page_base & ~PAGE_MASK;
while (csum_len) {
p = page_address(buf->pages[idx]) + base;
len = min(PAGE_SIZE - base, csum_len);
csum = csum_partial(p, len, csum);
csum_len -= len;
base = 0;
++idx;
}
return csum;
}

/*
* Search the request hash for an entry that matches the given rqstp.
* Must be called with cache_lock held. Returns the found entry or
* NULL on failure.
*/
static struct svc_cacherep *
nfsd_cache_search(struct svc_rqst *rqstp)
nfsd_cache_search(struct svc_rqst *rqstp, __wsum csum)
{
struct svc_cacherep *rp;
struct hlist_node *hn;
Expand All @@ -257,6 +292,7 @@ nfsd_cache_search(struct svc_rqst *rqstp)
hlist_for_each_entry(rp, hn, rh, c_hash) {
if (xid == rp->c_xid && proc == rp->c_proc &&
proto == rp->c_prot && vers == rp->c_vers &&
rqstp->rq_arg.len == rp->c_len && csum == rp->c_csum &&
rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) &&
rpc_get_port(svc_addr(rqstp)) == rpc_get_port((struct sockaddr *)&rp->c_addr))
return rp;
Expand All @@ -277,6 +313,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
u32 proto = rqstp->rq_prot,
vers = rqstp->rq_vers,
proc = rqstp->rq_proc;
__wsum csum;
unsigned long age;
int type = rqstp->rq_cachetype;
int rtn;
Expand All @@ -287,10 +324,12 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
return RC_DOIT;
}

csum = nfsd_cache_csum(rqstp);

spin_lock(&cache_lock);
rtn = RC_DOIT;

rp = nfsd_cache_search(rqstp);
rp = nfsd_cache_search(rqstp, csum);
if (rp)
goto found_entry;

Expand Down Expand Up @@ -318,7 +357,7 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
* Must search again just in case someone inserted one
* after we dropped the lock above.
*/
found = nfsd_cache_search(rqstp);
found = nfsd_cache_search(rqstp, csum);
if (found) {
nfsd_reply_cache_free_locked(rp);
rp = found;
Expand All @@ -344,6 +383,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp)
rpc_set_port((struct sockaddr *)&rp->c_addr, rpc_get_port(svc_addr(rqstp)));
rp->c_prot = proto;
rp->c_vers = vers;
rp->c_len = rqstp->rq_arg.len;
rp->c_csum = csum;

hash_refile(rp);
lru_put_end(rp);
Expand Down

0 comments on commit 6f36272

Please sign in to comment.