summaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2018-10-03 13:11:51 -0400
committerJ. Bruce Fields <bfields@redhat.com>2018-10-29 16:58:04 -0400
commited00c2f65267f3a5a8727ac74a90d32470f91679 (patch)
tree8a95e9d7ad98c0a8ddd4e7ffb19b7ab9c9bb32c3 /fs/nfsd
parent76ecec21197ab23bb821d8bf584949013efd0494 (diff)
downloadlinux-ed00c2f65267f3a5a8727ac74a90d32470f91679.tar.bz2
knfsd: Further simplify the cache lookup
Order the structure so that the key can be compared using memcmp(). Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/cache.h19
-rw-r--r--fs/nfsd/nfscache.c45
2 files changed, 27 insertions, 37 deletions
diff --git a/fs/nfsd/cache.h b/fs/nfsd/cache.h
index b7559c6f2b97..745c861237ca 100644
--- a/fs/nfsd/cache.h
+++ b/fs/nfsd/cache.h
@@ -19,18 +19,21 @@
* is much larger than a sockaddr_in6.
*/
struct svc_cacherep {
- struct list_head c_lru;
+ struct {
+ /* Keep often-read xid, csum in the same cache line: */
+ __be32 k_xid;
+ __wsum k_csum;
+ u32 k_proc;
+ u32 k_prot;
+ u32 k_vers;
+ unsigned int k_len;
+ struct sockaddr_in6 k_addr;
+ } c_key;
+ struct list_head c_lru;
unsigned char c_state, /* unused, inprog, done */
c_type, /* status, buffer */
c_secure : 1; /* req came from port < 1024 */
- struct sockaddr_in6 c_addr;
- __be32 c_xid;
- 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;
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index 527ce4c65765..230cc83921ad 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -131,15 +131,15 @@ nfsd_reply_cache_alloc(struct svc_rqst *rqstp, __wsum csum)
rp->c_type = RC_NOCACHE;
INIT_LIST_HEAD(&rp->c_lru);
- rp->c_xid = rqstp->rq_xid;
- rp->c_proc = rqstp->rq_proc;
- memset(&rp->c_addr, 0, sizeof(rp->c_addr));
- rpc_copy_addr((struct sockaddr *)&rp->c_addr, svc_addr(rqstp));
- rpc_set_port((struct sockaddr *)&rp->c_addr, rpc_get_port(svc_addr(rqstp)));
- rp->c_prot = rqstp->rq_prot;
- rp->c_vers = rqstp->rq_vers;
- rp->c_len = rqstp->rq_arg.len;
- rp->c_csum = csum;
+ memset(&rp->c_key, 0, sizeof(rp->c_key));
+ rp->c_key.k_xid = rqstp->rq_xid;
+ rp->c_key.k_proc = rqstp->rq_proc;
+ rpc_copy_addr((struct sockaddr *)&rp->c_key.k_addr, svc_addr(rqstp));
+ rpc_set_port((struct sockaddr *)&rp->c_key.k_addr, rpc_get_port(svc_addr(rqstp)));
+ rp->c_key.k_prot = rqstp->rq_prot;
+ rp->c_key.k_vers = rqstp->rq_vers;
+ rp->c_key.k_len = rqstp->rq_arg.len;
+ rp->c_key.k_csum = csum;
}
return rp;
}
@@ -330,27 +330,14 @@ nfsd_cache_csum(struct svc_rqst *rqstp)
return csum;
}
-static bool
-nfsd_cache_match(const struct svc_cacherep *key, const struct svc_cacherep *rp)
+static int
+nfsd_cache_key_cmp(const struct svc_cacherep *key, const struct svc_cacherep *rp)
{
- /* Check RPC XID first */
- if (key->c_xid != rp->c_xid)
- return false;
- /* compare checksum of NFS data */
- if (key->c_csum != rp->c_csum) {
+ if (key->c_key.k_xid == rp->c_key.k_xid &&
+ key->c_key.k_csum != rp->c_key.k_csum)
++payload_misses;
- return false;
- }
-
- /* Other discriminators */
- if (key->c_proc != rp->c_proc ||
- key->c_prot != rp->c_prot ||
- key->c_vers != rp->c_vers ||
- key->c_len != rp->c_len ||
- memcmp(&key->c_addr, &rp->c_addr, sizeof(key->c_addr)) != 0)
- return false;
- return true;
+ return memcmp(&key->c_key, &rp->c_key, sizeof(key->c_key));
}
/*
@@ -367,7 +354,7 @@ nfsd_cache_insert(struct nfsd_drc_bucket *b, struct svc_cacherep *key)
list_for_each_entry(rp, rh, c_lru) {
++entries;
- if (nfsd_cache_match(key, rp)) {
+ if (nfsd_cache_key_cmp(key, rp) == 0) {
ret = rp;
break;
}
@@ -510,7 +497,7 @@ nfsd_cache_update(struct svc_rqst *rqstp, int cachetype, __be32 *statp)
if (!rp)
return;
- hash = nfsd_cache_hash(rp->c_xid);
+ hash = nfsd_cache_hash(rp->c_key.k_xid);
b = &drc_hashtbl[hash];
len = resv->iov_len - ((char*)statp - (char*)resv->iov_base);