From owner-svn-src-all@FreeBSD.ORG Thu Jun 4 14:13:07 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0635B1065673; Thu, 4 Jun 2009 14:13:07 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E76538FC15; Thu, 4 Jun 2009 14:13:06 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n54ED6ua094087; Thu, 4 Jun 2009 14:13:06 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n54ED66W094084; Thu, 4 Jun 2009 14:13:06 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <200906041413.n54ED66W094084@svn.freebsd.org> From: Rick Macklem Date: Thu, 4 Jun 2009 14:13:06 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r193436 - head/sys/rpc X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 04 Jun 2009 14:13:07 -0000 Author: rmacklem Date: Thu Jun 4 14:13:06 2009 New Revision: 193436 URL: http://svn.freebsd.org/changeset/base/193436 Log: Fix two races in the server side krpc w.r.t upcalls: Add a flag so that soupcall_clear() is only called once to cancel an upcall. Move the test for xprt_registered in the upcall down to after the mtx_lock() of the pool mutex, to catch the case where it is unregistered while the upcall is waiting for the mutex. Also, move the mtx_destroy() of the pool mutex to after SVC_RELEASE(), so that it isn't destroyed before the upcalls are disabled. Reviewed by: dfr, jhb Tested by: pho Approved by: kib (mentor) Modified: head/sys/rpc/svc.c head/sys/rpc/svc.h head/sys/rpc/svc_vc.c Modified: head/sys/rpc/svc.c ============================================================================== --- head/sys/rpc/svc.c Thu Jun 4 12:27:57 2009 (r193435) +++ head/sys/rpc/svc.c Thu Jun 4 14:13:06 2009 (r193436) @@ -175,12 +175,12 @@ svcpool_destroy(SVCPOOL *pool) mtx_lock(&pool->sp_lock); } - mtx_destroy(&pool->sp_lock); - TAILQ_FOREACH_SAFE(xprt, &cleanup, xp_link, nxprt) { SVC_RELEASE(xprt); } + mtx_destroy(&pool->sp_lock); + if (pool->sp_rcache) replay_freecache(pool->sp_rcache); @@ -353,15 +353,16 @@ xprt_active(SVCXPRT *xprt) { SVCPOOL *pool = xprt->xp_pool; + mtx_lock(&pool->sp_lock); + if (!xprt->xp_registered) { /* * Race with xprt_unregister - we lose. */ + mtx_unlock(&pool->sp_lock); return; } - mtx_lock(&pool->sp_lock); - if (!xprt->xp_active) { TAILQ_INSERT_TAIL(&pool->sp_active, xprt, xp_alink); xprt->xp_active = TRUE; Modified: head/sys/rpc/svc.h ============================================================================== --- head/sys/rpc/svc.h Thu Jun 4 12:27:57 2009 (r193435) +++ head/sys/rpc/svc.h Thu Jun 4 14:13:06 2009 (r193436) @@ -166,6 +166,7 @@ typedef struct __rpc_svcxprt { int xp_idletimeout; /* idle time before closing */ time_t xp_lastactive; /* time of last RPC */ u_int64_t xp_sockref; /* set by nfsv4 to identify socket */ + int xp_upcallset; /* socket upcall is set up */ #else int xp_fd; u_short xp_port; /* associated port number */ Modified: head/sys/rpc/svc_vc.c ============================================================================== --- head/sys/rpc/svc_vc.c Thu Jun 4 12:27:57 2009 (r193435) +++ head/sys/rpc/svc_vc.c Thu Jun 4 14:13:06 2009 (r193436) @@ -160,6 +160,7 @@ svc_vc_create(SVCPOOL *pool, struct sock solisten(so, SOMAXCONN, curthread); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -234,6 +235,7 @@ svc_vc_create_conn(SVCPOOL *pool, struct xprt_register(xprt); SOCKBUF_LOCK(&so->so_rcv); + xprt->xp_upcallset = 1; soupcall_set(so, SO_RCV, svc_vc_soupcall, xprt); SOCKBUF_UNLOCK(&so->so_rcv); @@ -352,7 +354,10 @@ svc_vc_rendezvous_recv(SVCXPRT *xprt, st if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); sx_xunlock(&xprt->xp_lock); @@ -397,7 +402,10 @@ static void svc_vc_destroy_common(SVCXPRT *xprt) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); sx_destroy(&xprt->xp_lock); @@ -632,7 +640,10 @@ svc_vc_recv(SVCXPRT *xprt, struct rpc_ms if (error) { SOCKBUF_LOCK(&xprt->xp_socket->so_rcv); - soupcall_clear(xprt->xp_socket, SO_RCV); + if (xprt->xp_upcallset) { + xprt->xp_upcallset = 0; + soupcall_clear(xprt->xp_socket, SO_RCV); + } SOCKBUF_UNLOCK(&xprt->xp_socket->so_rcv); xprt_inactive(xprt); cd->strm_stat = XPRT_DIED;