Author: rmacklem Date: Sun Apr 5 21:08:17 2020 New Revision: 359643 URL: https://svnweb.freebsd.org/changeset/base/359643
Log: 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 Reported by: da...@cs.huji.ac.il MFC after: 2 weeks Modified: head/sys/rpc/clnt_dg.c Modified: head/sys/rpc/clnt_dg.c ============================================================================== --- head/sys/rpc/clnt_dg.c Sun Apr 5 19:25:46 2020 (r359642) +++ head/sys/rpc/clnt_dg.c Sun Apr 5 21:08:17 2020 (r359643) @@ -94,6 +94,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 @@ -193,6 +195,7 @@ clnt_dg_create( struct __rpc_sockinfo si; XDR xdrs; int error; + uint32_t newxid; if (svcaddr == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNADDR; @@ -245,8 +248,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); @@ -418,8 +423,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); @@ -865,13 +869,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: _______________________________________________ svn-src-all@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"