Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 20 Apr 2020 01:26:18 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r360110 - stable/11/sys/rpc
Message-ID:  <202004200126.03K1QI6q022076@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Mon Apr 20 01:26:18 2020
New Revision: 360110
URL: https://svnweb.freebsd.org/changeset/base/360110

Log:
  MFC: r359643
  Change the xid for client side krpc over UDP to a global value.
  
  Without this patch, the xid used for the client side krpc requests over
  UDP was initialized for each "connection". A "connection" for UDP is
  rather sketchy and for the kernel NLM a new one is created every 2minutes.
  A problem with client side interoperability with a Netapp server for the NLM
  was reported and it is believed to be caused by reuse of the same xid.
  Although this was never completely diagnosed by the reporter, I could see
  how the same xid might get reused, since it is initialized to a value
  based on the TOD clock every two minutes.
  I suspect initializing the value for every "connection" was inherited from
  userland library code, where having a global xid was not practical.
  However, implementing a global "xid" for the kernel rpc is straightforward
  and will ensure that an xid value is not reused for a long time. This
  patch does that and is hoped it will fix the Netapp interoperability
  problem.
  
  PR:		245022

Modified:
  stable/11/sys/rpc/clnt_dg.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/rpc/clnt_dg.c
==============================================================================
--- stable/11/sys/rpc/clnt_dg.c	Mon Apr 20 01:17:00 2020	(r360109)
+++ stable/11/sys/rpc/clnt_dg.c	Mon Apr 20 01:26:18 2020	(r360110)
@@ -92,6 +92,8 @@ static struct clnt_ops clnt_dg_ops = {
 	.cl_control =	clnt_dg_control
 };
 
+static volatile uint32_t rpc_xid = 0;
+
 /*
  * A pending RPC request which awaits a reply. Requests which have
  * received their reply will have cr_xid set to zero and cr_mrep to
@@ -191,6 +193,7 @@ clnt_dg_create(
 	struct __rpc_sockinfo si;
 	XDR xdrs;
 	int error;
+	uint32_t newxid;
 
 	if (svcaddr == NULL) {
 		rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
@@ -243,8 +246,10 @@ clnt_dg_create(
 	cu->cu_sent = 0;
 	cu->cu_cwnd_wait = FALSE;
 	(void) getmicrotime(&now);
-	cu->cu_xid = __RPC_GETXID(&now);
-	call_msg.rm_xid = cu->cu_xid;
+	/* Clip at 28bits so that it will not wrap around. */
+	newxid = __RPC_GETXID(&now) & 0xfffffff;
+	atomic_cmpset_32(&rpc_xid, 0, newxid);
+	call_msg.rm_xid = atomic_fetchadd_32(&rpc_xid, 1);
 	call_msg.rm_call.cb_prog = program;
 	call_msg.rm_call.cb_vers = version;
 	xdrmem_create(&xdrs, cu->cu_mcallc, MCALL_MSG_SIZE, XDR_ENCODE);
@@ -420,8 +425,7 @@ clnt_dg_call(
 call_again:
 	mtx_assert(&cs->cs_lock, MA_OWNED);
 
-	cu->cu_xid++;
-	xid = cu->cu_xid;
+	xid = atomic_fetchadd_32(&rpc_xid, 1);
 
 send_again:
 	mtx_unlock(&cs->cs_lock);
@@ -867,13 +871,13 @@ clnt_dg_control(CLIENT *cl, u_int request, void *info)
 		(void) memcpy(&cu->cu_raddr, addr, addr->sa_len);
 		break;
 	case CLGET_XID:
-		*(uint32_t *)info = cu->cu_xid;
+		*(uint32_t *)info = atomic_load_32(&rpc_xid);
 		break;
 
 	case CLSET_XID:
 		/* This will set the xid of the NEXT call */
 		/* decrement by 1 as clnt_dg_call() increments once */
-		cu->cu_xid = *(uint32_t *)info - 1;
+		atomic_store_32(&rpc_xid, *(uint32_t *)info - 1);
 		break;
 
 	case CLGET_VERS:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004200126.03K1QI6q022076>