[patch 19/29] knfsd: faster probing in the reply cache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Slightly reorganise the CPU-intensive hash chain probing to check
for more commonly varying entry keys first, and to reduce arithmetic
operations by hoisting out an invariant.  This slightly reduces the
CPU time spent in nfsd_cache_lookup() under heavy nonidempotent loads.

This code predates the IPv6 support in the NFS server but should be
harmless with IPv6 clients.

Signed-off-by: Greg Banks <gnb@xxxxxxx>
---

 fs/nfsd/nfscache.c |   25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

Index: bfields/fs/nfsd/nfscache.c
===================================================================
--- bfields.orig/fs/nfsd/nfscache.c
+++ bfields/fs/nfsd/nfscache.c
@@ -108,6 +108,23 @@ static inline u32 request_hash(u32 xid, 
 	return h;
 }
 
+
+/*
+ * Fast compare of two sockaddr_in's.  Ignore the zero padding at
+ * the end of a sockaddr_in; compares sin_family and sin_port in
+ * one comparison.  Returns 1 if identical, 0 otherwise.
+ *
+ * Alignment issues prevent us from comparing all the relevant
+ * fields in a single 64b comparison on 64b platforms: the most
+ * we can assume is that sin_addr is 32b-aligned.
+ */
+static inline int
+compare_sockaddr_in(const struct sockaddr_in *sina, const struct sockaddr_in *sinb)
+{
+	return ((*(u32 *)&sina->sin_family == *(u32 *)&sinb->sin_family) &&
+		(sina->sin_addr.s_addr == sinb->sin_addr.s_addr));
+}
+
 static int	nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
 
 /*
@@ -263,12 +280,14 @@ nfsd_cache_lookup(struct svc_rqst *rqstp
 	rtn = RC_DOIT;
 
 	rh = &b->hash[h];
+	age = jiffies - 120*HZ;
 	hlist_for_each_entry(rp, hn, rh, c_hash) {
 		if (rp->c_state != RC_UNUSED &&
-		    xid == rp->c_xid && proc == rp->c_proc &&
+		    xid == rp->c_xid &&
+		    compare_sockaddr_in(svc_addr_in(rqstp), &rp->c_addr) &&
+		    proc == rp->c_proc &&
 		    proto == rp->c_prot && vers == rp->c_vers &&
-		    time_before(jiffies, rp->c_timestamp + 120*HZ) &&
-		    memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, sizeof(rp->c_addr))==0) {
+		    time_after(rp->c_timestamp, age)) {
 			nfsdstats.rchits++;
 			goto found_entry;
 		}

--
Greg
--
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

[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux