From: Trond Myklebust <trond.myklebust@fys.uio.no>

This patch makes the sunrpc XID identifier a per-transport socket
variable. Allows us to eliminate the global spinlock Olaf introduced...


---

 include/linux/sunrpc/xprt.h |    6 +++++-
 net/sunrpc/xprt.c           |   27 +++++++++++----------------
 2 files changed, 16 insertions(+), 17 deletions(-)

diff -puN include/linux/sunrpc/xprt.h~nfs-remove-XID-spinlock include/linux/sunrpc/xprt.h
--- 25/include/linux/sunrpc/xprt.h~nfs-remove-XID-spinlock	2004-02-28 18:21:15.000000000 -0800
+++ 25-akpm/include/linux/sunrpc/xprt.h	2004-02-28 18:21:15.000000000 -0800
@@ -102,7 +102,6 @@ struct rpc_rqst {
 	struct xdr_buf		rq_private_buf;		/* The receive buffer
 							 * used in the softirq.
 							 */
-
 	/*
 	 * For authentication (e.g. auth_des)
 	 */
@@ -155,6 +154,11 @@ struct rpc_xprt {
 				stream     : 1;	/* TCP */
 
 	/*
+	 * XID
+	 */
+	__u32			xid;		/* Next XID value to use */
+
+	/*
 	 * State of TCP reply receive stuff
 	 */
 	u32			tcp_recm,	/* Fragment header */
diff -puN net/sunrpc/xprt.c~nfs-remove-XID-spinlock net/sunrpc/xprt.c
--- 25/net/sunrpc/xprt.c~nfs-remove-XID-spinlock	2004-02-28 18:21:15.000000000 -0800
+++ 25-akpm/net/sunrpc/xprt.c	2004-02-28 18:21:15.000000000 -0800
@@ -57,6 +57,7 @@
 #include <linux/sunrpc/clnt.h>
 #include <linux/file.h>
 #include <linux/workqueue.h>
+#include <linux/random.h>
 
 #include <net/sock.h>
 #include <net/checksum.h>
@@ -1322,22 +1323,14 @@ do_xprt_reserve(struct rpc_task *task)
 /*
  * Allocate a 'unique' XID
  */
-static u32
-xprt_alloc_xid(void)
+static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt)
 {
-	static spinlock_t xid_lock = SPIN_LOCK_UNLOCKED;
-	static int need_init = 1;
-	static u32 xid;
-	u32 ret;
-
-	spin_lock(&xid_lock);
-	if (unlikely(need_init)) {
-		xid = get_seconds() << 12;
-		need_init = 0;
-	}
-	ret = xid++;
-	spin_unlock(&xid_lock);
-	return ret;
+	return xprt->xid++;
+}
+
+static inline void xprt_init_xid(struct rpc_xprt *xprt)
+{
+	get_random_bytes(&xprt->xid, sizeof(xprt->xid));
 }
 
 /*
@@ -1351,7 +1344,7 @@ xprt_request_init(struct rpc_task *task,
 	req->rq_timeout = xprt->timeout;
 	req->rq_task	= task;
 	req->rq_xprt    = xprt;
-	req->rq_xid     = xprt_alloc_xid();
+	req->rq_xid     = xprt_alloc_xid(xprt);
 	INIT_LIST_HEAD(&req->rq_list);
 	dprintk("RPC: %4d reserved req %p xid %08x\n", task->tk_pid,
 			req, req->rq_xid);
@@ -1472,6 +1465,8 @@ xprt_setup(int proto, struct sockaddr_in
 	req->rq_next = NULL;
 	xprt->free = xprt->slot;
 
+	xprt_init_xid(xprt);
+
 	/* Check whether we want to use a reserved port */
 	xprt->resvport = capable(CAP_NET_BIND_SERVICE) ? 1 : 0;
 

_