From owner-svn-src-stable@FreeBSD.ORG Tue Oct 29 09:57:01 2013 Return-Path: Delivered-To: svn-src-stable@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTP id 1735782C; Tue, 29 Oct 2013 09:57:01 +0000 (UTC) (envelope-from melifaro@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id EB4EE2830; Tue, 29 Oct 2013 09:57:00 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r9T9v0c0002797; Tue, 29 Oct 2013 09:57:00 GMT (envelope-from melifaro@svn.freebsd.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.7/8.14.5/Submit) id r9T9v0Ws002796; Tue, 29 Oct 2013 09:57:00 GMT (envelope-from melifaro@svn.freebsd.org) Message-Id: <201310290957.r9T9v0Ws002796@svn.freebsd.org> From: "Alexander V. Chernikov" Date: Tue, 29 Oct 2013 09:57:00 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r257323 - stable/9/sys/netgraph X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Oct 2013 09:57:01 -0000 Author: melifaro Date: Tue Oct 29 09:57:00 2013 New Revision: 257323 URL: http://svnweb.freebsd.org/changeset/base/257323 Log: Merge r256550. Improve locking model used to protect netgraph topology: use rwlocks instead of mutexes on node traversal. Reviewed by: glebius Tested by: Eugene Grosbein Sponsored by: Yandex LLC Modified: stable/9/sys/netgraph/ng_base.c Directory Properties: stable/9/sys/ (props changed) Modified: stable/9/sys/netgraph/ng_base.c ============================================================================== --- stable/9/sys/netgraph/ng_base.c Tue Oct 29 09:52:15 2013 (r257322) +++ stable/9/sys/netgraph/ng_base.c Tue Oct 29 09:57:00 2013 (r257323) @@ -74,7 +74,12 @@ MODULE_VERSION(netgraph, NG_ABI_VERSION); /* Mutex to protect topology events. */ -static struct mtx ng_topo_mtx; +static struct rwlock ng_topo_lock; +#define TOPOLOGY_RLOCK() rw_rlock(&ng_topo_lock) +#define TOPOLOGY_RUNLOCK() rw_runlock(&ng_topo_lock) +#define TOPOLOGY_WLOCK() rw_wlock(&ng_topo_lock) +#define TOPOLOGY_WUNLOCK() rw_wunlock(&ng_topo_lock) +#define TOPOLOGY_NOTOWNED() rw_assert(&ng_topo_lock, RA_UNLOCKED) #ifdef NETGRAPH_DEBUG static struct mtx ng_nodelist_mtx; /* protects global node/hook lists */ @@ -1162,7 +1167,7 @@ ng_destroy_hook(hook_p hook) * Protect divorce process with mutex, to avoid races on * simultaneous disconnect. */ - mtx_lock(&ng_topo_mtx); + TOPOLOGY_WLOCK(); hook->hk_flags |= HK_INVALID; @@ -1182,17 +1187,17 @@ ng_destroy_hook(hook_p hook) * If it's already divorced from a node, * just free it. */ - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); } else { - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); ng_rmhook_self(peer); /* Send it a surprise */ } NG_HOOK_UNREF(peer); /* account for peer link */ NG_HOOK_UNREF(hook); /* account for peer link */ } else - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); - mtx_assert(&ng_topo_mtx, MA_NOTOWNED); + TOPOLOGY_NOTOWNED(); /* * Remove the hook from the node's list to avoid possible recursion @@ -1233,9 +1238,9 @@ ng_bypass(hook_p hook1, hook_p hook2) TRAP_ERROR(); return (EINVAL); } - mtx_lock(&ng_topo_mtx); + TOPOLOGY_WLOCK(); if (NG_HOOK_NOT_VALID(hook1) || NG_HOOK_NOT_VALID(hook2)) { - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); return (EINVAL); } hook1->hk_peer->hk_peer = hook2->hk_peer; @@ -1243,7 +1248,7 @@ ng_bypass(hook_p hook1, hook_p hook2) hook1->hk_peer = &ng_deadhook; hook2->hk_peer = &ng_deadhook; - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); NG_HOOK_UNREF(hook1); NG_HOOK_UNREF(hook2); @@ -1440,15 +1445,15 @@ ng_con_part2(node_p node, item_p item, h /* * Acquire topo mutex to avoid race with ng_destroy_hook(). */ - mtx_lock(&ng_topo_mtx); + TOPOLOGY_RLOCK(); peer = hook->hk_peer; if (peer == &ng_deadhook) { - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_RUNLOCK(); printf("failed in ng_con_part2(B)\n"); ng_destroy_hook(hook); ERROUT(ENOENT); } - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_RUNLOCK(); if ((error = ng_send_fn2(peer->hk_node, peer, item, &ng_con_part3, NULL, 0, NG_REUSE_ITEM))) { @@ -1793,14 +1798,14 @@ ng_path2noderef(node_p here, const char /* We have a segment, so look for a hook by that name */ hook = ng_findhook(node, segment); - mtx_lock(&ng_topo_mtx); + TOPOLOGY_WLOCK(); /* Can't get there from here... */ if (hook == NULL || NG_HOOK_PEER(hook) == NULL || NG_HOOK_NOT_VALID(hook) || NG_HOOK_NOT_VALID(NG_HOOK_PEER(hook))) { TRAP_ERROR(); NG_NODE_UNREF(node); - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); return (ENOENT); } @@ -1817,7 +1822,7 @@ ng_path2noderef(node_p here, const char NG_NODE_UNREF(oldnode); /* XXX another race */ if (NG_NODE_NOT_VALID(node)) { NG_NODE_UNREF(node); /* XXX more races */ - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); TRAP_ERROR(); return (ENXIO); } @@ -1830,11 +1835,11 @@ ng_path2noderef(node_p here, const char } else *lasthook = NULL; } - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); *destp = node; return (0); } - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_WUNLOCK(); } } @@ -3202,8 +3207,7 @@ ngb_mod_event(module_t mod, int event, v rw_init(&ng_typelist_lock, "netgraph types"); rw_init(&ng_idhash_lock, "netgraph idhash"); rw_init(&ng_namehash_lock, "netgraph namehash"); - mtx_init(&ng_topo_mtx, "netgraph topology mutex", NULL, - MTX_DEF); + rw_init(&ng_topo_lock, "netgraph topology mutex"); #ifdef NETGRAPH_DEBUG mtx_init(&ng_nodelist_mtx, "netgraph nodelist mutex", NULL, MTX_DEF); @@ -3579,13 +3583,13 @@ ng_address_hook(node_p here, item_p item * that the peer is still connected (even if invalid,) we know * that the peer node is present, though maybe invalid. */ - mtx_lock(&ng_topo_mtx); + TOPOLOGY_RLOCK(); if ((hook == NULL) || NG_HOOK_NOT_VALID(hook) || NG_HOOK_NOT_VALID(peer = NG_HOOK_PEER(hook)) || NG_NODE_NOT_VALID(peernode = NG_PEER_NODE(hook))) { NG_FREE_ITEM(item); TRAP_ERROR(); - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_RUNLOCK(); return (ENETDOWN); } @@ -3598,7 +3602,7 @@ ng_address_hook(node_p here, item_p item NGI_SET_NODE(item, peernode); SET_RETADDR(item, here, retaddr); - mtx_unlock(&ng_topo_mtx); + TOPOLOGY_RUNLOCK(); return (0); }