Chuck and Jim pointed out that crc32 is probably more heavyweight than we really need for generating these checksums, and recommended looking at using the same routines that are used to generate checksums for IP packets. This patch converts the code to use csum_partial instead of crc32. Unfortunately, I don't have a great way to verify the overhead of calculating the checksum here, so I don't know of a good way to verify that this is significantly cheaper than crc32... Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/nfsd/cache.h | 2 +- fs/nfsd/nfscache.c | 33 +++++++++++++++------------------ 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h index 4822db3..87fd141 100644 --- a/fs/nfsd/cache.h +++ b/fs/nfsd/cache.h @@ -30,7 +30,7 @@ struct svc_cacherep { u32 c_proc; u32 c_vers; unsigned int c_len; - u32 c_crc; + __wsum c_csum; unsigned long c_timestamp; union { struct kvec u_vec; diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c index bd3d8e2..40db57e 100644 --- a/fs/nfsd/nfscache.c +++ b/fs/nfsd/nfscache.c @@ -11,7 +11,7 @@ #include <linux/slab.h> #include <linux/sunrpc/addr.h> #include <linux/highmem.h> -#include <linux/crc32.h> +#include <net/checksum.h> #include "nfsd.h" #include "cache.h" @@ -25,7 +25,6 @@ static struct list_head lru_head; static struct kmem_cache *drc_slab; static unsigned int num_drc_entries; static unsigned int max_drc_entries; -static u32 crc_seed; /* * Calculate the hash index from an XID. @@ -133,8 +132,6 @@ int nfsd_reply_cache_init(void) max_drc_entries = nfsd_cache_size_limit(); num_drc_entries = 0; - /* Is a random seed any better than some well-defined constant? */ - get_random_bytes(&crc_seed, sizeof(crc_seed)); return 0; out_nomem: printk(KERN_ERR "nfsd: failed to allocate reply cache\n"); @@ -245,12 +242,12 @@ nfsd_reply_cache_shrink(struct shrinker *shrink, struct shrink_control *sc) /* * Walk an xdr_buf and get a CRC for at most the first RC_CSUMLEN bytes */ -static u32 -nfsd_cache_crc(struct svc_rqst *rqstp) +static __wsum +nfsd_cache_csum(struct svc_rqst *rqstp) { int idx; unsigned int base; - u32 crc; + __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, @@ -258,7 +255,7 @@ nfsd_cache_crc(struct svc_rqst *rqstp) size_t len = min(buf->head[0].iov_len, csum_len); /* rq_arg.head first */ - crc = crc32(crc_seed, p, len); + csum = csum_partial(p, len, 0); csum_len -= len; /* Continue into page array */ @@ -267,12 +264,12 @@ nfsd_cache_crc(struct svc_rqst *rqstp) while (csum_len) { p = page_address(buf->pages[idx]) + base; len = min(PAGE_SIZE - base, csum_len); - crc = crc32(crc, p, len); + csum = csum_partial(p, len, csum); csum_len -= len; base = 0; ++idx; } - return crc; + return csum; } /* @@ -281,7 +278,7 @@ nfsd_cache_crc(struct svc_rqst *rqstp) * NULL on failure. */ static struct svc_cacherep * -nfsd_cache_search(struct svc_rqst *rqstp, u32 crc) +nfsd_cache_search(struct svc_rqst *rqstp, __wsum csum) { struct svc_cacherep *rp; struct hlist_node *hn; @@ -295,7 +292,7 @@ nfsd_cache_search(struct svc_rqst *rqstp, u32 crc) 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 && crc == rp->c_crc && + 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; @@ -315,8 +312,8 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) __be32 xid = rqstp->rq_xid; u32 proto = rqstp->rq_prot, vers = rqstp->rq_vers, - proc = rqstp->rq_proc, - crc; + proc = rqstp->rq_proc; + __wsum csum; unsigned long age; int type = rqstp->rq_cachetype; int rtn; @@ -327,12 +324,12 @@ nfsd_cache_lookup(struct svc_rqst *rqstp) return RC_DOIT; } - crc = nfsd_cache_crc(rqstp); + csum = nfsd_cache_csum(rqstp); spin_lock(&cache_lock); rtn = RC_DOIT; - rp = nfsd_cache_search(rqstp, crc); + rp = nfsd_cache_search(rqstp, csum); if (rp) goto found_entry; @@ -360,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, crc); + found = nfsd_cache_search(rqstp, csum); if (found) { nfsd_reply_cache_free_locked(rp); rp = found; @@ -387,7 +384,7 @@ setup_entry: rp->c_prot = proto; rp->c_vers = vers; rp->c_len = rqstp->rq_arg.len; - rp->c_crc = crc; + rp->c_csum = csum; hash_refile(rp); lru_put_end(rp); -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html