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>