Date: Sat, 22 Nov 2014 16:27:51 +0000 (UTC) From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r274855 - projects/routing/sys/netinet Message-ID: <201411221627.sAMGRptb055672@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: melifaro Date: Sat Nov 22 16:27:51 2014 New Revision: 274855 URL: https://svnweb.freebsd.org/changeset/base/274855 Log: Convert &in_ifaddr_lock to dual-locking model: use rwlock accessible via external functions (IN_IFADDR_CFG_* -> in_ifaddr_cfg_*()) for all control plane tasks use rmlock (IN_IFADDR_RUN_*) for fast-path lookups. Modified: projects/routing/sys/netinet/in.c projects/routing/sys/netinet/in_mcast.c projects/routing/sys/netinet/in_pcb.c projects/routing/sys/netinet/in_var.h projects/routing/sys/netinet/ip_input.c Modified: projects/routing/sys/netinet/in.c ============================================================================== --- projects/routing/sys/netinet/in.c Sat Nov 22 16:03:18 2014 (r274854) +++ projects/routing/sys/netinet/in.c Sat Nov 22 16:27:51 2014 (r274855) @@ -92,6 +92,62 @@ VNET_DECLARE(struct inpcbinfo, ripcbinfo static struct sx in_control_sx; SX_SYSINIT(in_control_sx, &in_control_sx, "in_control"); +struct rmlock in_ifaddr_lock; /* XXX: padding ? */ +struct rwlock in_ifaddr_cfg_lock; +RM_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock"); +RW_SYSINIT(in_ifaddr_cfg_lock, &in_ifaddr_cfg_lock, "in_ifaddr_cfg_lock"); + +void +in_ifaddr_cfg_rlock() +{ + + rw_rlock(&in_ifaddr_cfg_lock); +} + +void +in_ifaddr_cfg_runlock() +{ + + rw_runlock(&in_ifaddr_cfg_lock); +} + +void +in_ifaddr_cfg_wlock() +{ + + rw_wlock(&in_ifaddr_cfg_lock); +} + +void +in_ifaddr_cfg_wunlock() +{ + + rw_wunlock(&in_ifaddr_cfg_lock); +} + +void +in_ifaddr_cfg_lock_assert(int what) +{ + + rw_assert(&in_ifaddr_cfg_lock, what); +} + +void +in_ifaddr_wlock() +{ + + in_ifaddr_cfg_wlock(); + IN_IFADDR_RUN_WLOCK(); +} + +void +in_ifaddr_wunlock() +{ + + in_ifaddr_cfg_wunlock(); + IN_IFADDR_RUN_WUNLOCK(); +} + /* * Return 1 if an internet address is for a ``local'' host * (one to which we have a connection). @@ -101,15 +157,16 @@ in_localaddr(struct in_addr in) { register u_long i = ntohl(in.s_addr); register struct in_ifaddr *ia; + IN_IFADDR_RUN_TRACKER; - IN_IFADDR_RLOCK(); + IN_IFADDR_RUN_RLOCK(); TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { if ((i & ia->ia_subnetmask) == ia->ia_subnet) { IN_IFADDR_RUNLOCK(); return (1); } } - IN_IFADDR_RUNLOCK(); + IN_IFADDR_RUN_RUNLOCK(); return (0); } @@ -121,15 +178,16 @@ int in_localip(struct in_addr in) { struct in_ifaddr *ia; + IN_IFADDR_RUN_TRACKER; - IN_IFADDR_RLOCK(); + IN_IFADDR_RUN_RLOCK(); LIST_FOREACH(ia, INADDR_HASH(in.s_addr), ia_hash) { if (IA_SIN(ia)->sin_addr.s_addr == in.s_addr) { IN_IFADDR_RUNLOCK(); return (1); } } - IN_IFADDR_RUNLOCK(); + IN_IFADDR_RUN_RUNLOCK(); return (0); } @@ -142,8 +200,9 @@ in_localip_more(struct in_ifaddr *ia) { in_addr_t in = IA_SIN(ia)->sin_addr.s_addr; struct in_ifaddr *it; + IN_IFADDR_RUN_TRACKER; - IN_IFADDR_RLOCK(); + IN_IFADDR_RUN_RLOCK(); LIST_FOREACH(it, INADDR_HASH(in), ia_hash) { if (it != ia && IA_SIN(it)->sin_addr.s_addr == in) { ifa_ref(&it->ia_ifa); @@ -151,7 +210,7 @@ in_localip_more(struct in_ifaddr *ia) return (it); } } - IN_IFADDR_RUNLOCK(); + IN_IFADDR_RUN_RUNLOCK(); return (NULL); } Modified: projects/routing/sys/netinet/in_mcast.c ============================================================================== --- projects/routing/sys/netinet/in_mcast.c Sat Nov 22 16:03:18 2014 (r274854) +++ projects/routing/sys/netinet/in_mcast.c Sat Nov 22 16:27:51 2014 (r274855) @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/protosw.h> +#include <sys/rmlock.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> @@ -86,6 +87,8 @@ static MALLOC_DEFINE(M_IPMOPTS, "ip_mopt static MALLOC_DEFINE(M_IPMSOURCE, "ip_msource", "IPv4 multicast IGMP-layer source filter"); +IN_IFADDR_FAST_LOCK_DECLARATION; + /* * Locking: * - Lock order is: Giant, INP_WLOCK, IN_MULTI_LOCK, IGMP_LOCK, IF_ADDR_LOCK. @@ -1887,6 +1890,7 @@ inp_lookup_mcast_ifp(const struct inpcb const struct sockaddr_in *gsin, const struct in_addr ina) { struct ifnet *ifp; + IN_IFADDR_RUN_TRACKER; KASSERT(gsin->sin_family == AF_INET, ("%s: not AF_INET", __func__)); KASSERT(IN_MULTICAST(ntohl(gsin->sin_addr.s_addr)), @@ -1906,7 +1910,7 @@ inp_lookup_mcast_ifp(const struct inpcb struct ifnet *mifp; mifp = NULL; - IN_IFADDR_RLOCK(); + IN_IFADDR_RUN_RLOCK(); TAILQ_FOREACH(ia, &V_in_ifaddrhead, ia_link) { mifp = ia->ia_ifp; if (!(mifp->if_flags & IFF_LOOPBACK) && @@ -1915,7 +1919,7 @@ inp_lookup_mcast_ifp(const struct inpcb break; } } - IN_IFADDR_RUNLOCK(); + IN_IFADDR_RUN_RUNLOCK(); } } Modified: projects/routing/sys/netinet/in_pcb.c ============================================================================== --- projects/routing/sys/netinet/in_pcb.c Sat Nov 22 16:03:18 2014 (r274854) +++ projects/routing/sys/netinet/in_pcb.c Sat Nov 22 16:27:51 2014 (r274855) @@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$"); #include <sys/callout.h> #include <sys/domain.h> #include <sys/protosw.h> +#include <sys/rmlock.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/priv.h> @@ -101,6 +102,8 @@ __FBSDID("$FreeBSD$"); #include <security/mac/mac_framework.h> +IN_IFADDR_FAST_LOCK_DECLARATION; + static struct callout ipport_tick_callout; /* @@ -1006,6 +1009,7 @@ in_pcbconnect_setup(struct inpcb *inp, s struct in_addr laddr, faddr; u_short lport, fport; int error; + IN_IFADDR_RUN_TRACKER; /* * Because a global state change doesn't actually occur here, a read @@ -1036,20 +1040,20 @@ in_pcbconnect_setup(struct inpcb *inp, s * choose the broadcast address for that interface. */ if (faddr.s_addr == INADDR_ANY) { - IN_IFADDR_RLOCK(); + IN_IFADDR_RUN_RLOCK(); faddr = IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr; - IN_IFADDR_RUNLOCK(); + IN_IFADDR_RUN_RUNLOCK(); if (cred != NULL && (error = prison_get_ip4(cred, &faddr)) != 0) return (error); } else if (faddr.s_addr == (u_long)INADDR_BROADCAST) { - IN_IFADDR_RLOCK(); + IN_IFADDR_RUN_RLOCK(); if (TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags & IFF_BROADCAST) faddr = satosin(&TAILQ_FIRST( &V_in_ifaddrhead)->ia_broadaddr)->sin_addr; - IN_IFADDR_RUNLOCK(); + IN_IFADDR_RUN_RUNLOCK(); } } if (laddr.s_addr == INADDR_ANY) { Modified: projects/routing/sys/netinet/in_var.h ============================================================================== --- projects/routing/sys/netinet/in_var.h Sat Nov 22 16:03:18 2014 (r274854) +++ projects/routing/sys/netinet/in_var.h Sat Nov 22 16:27:51 2014 (r274855) @@ -118,15 +118,39 @@ VNET_DECLARE(u_long, in_ifaddrhmask); / #define INADDR_HASH(x) \ (&V_in_ifaddrhashtbl[INADDR_HASHVAL(x) & V_in_ifaddrhmask]) -extern struct rwlock in_ifaddr_lock; - -#define IN_IFADDR_LOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_LOCKED) -#define IN_IFADDR_RLOCK() rw_rlock(&in_ifaddr_lock) -#define IN_IFADDR_RLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_RLOCKED) -#define IN_IFADDR_RUNLOCK() rw_runlock(&in_ifaddr_lock) -#define IN_IFADDR_WLOCK() rw_wlock(&in_ifaddr_lock) -#define IN_IFADDR_WLOCK_ASSERT() rw_assert(&in_ifaddr_lock, RA_WLOCKED) -#define IN_IFADDR_WUNLOCK() rw_wunlock(&in_ifaddr_lock) +/* ifaddr lock: control plane */ +#define IN_IFADDR_CFG_RLOCK() in_ifaddr_cfg_rlock() +#define IN_IFADDR_CFG_RUNLOCK() in_ifaddr_cfg_runlock() +#define IN_IFADDR_CFG_WLOCK() in_ifaddr_cfg_wlock() +#define IN_IFADDR_CFG_WUNLOCK() in_ifaddr_cfg_wunlock() +#define IN_IFADDR_CFG_LOCK_ASSERT() in_ifaddr_cfg_lock_assert(RA_LOCKED) +#define IN_IFADDR_CFG_RLOCK_ASSERT() in_ifaddr_cfg_lock_assert(RA_RLOCKED) +#define IN_IFADDR_CFG_WLOCK_ASSERT() in_ifaddr_cfg_lock_assert(RA_WLOCKED) +void in_ifaddr_cfg_rlock(void); +void in_ifaddr_cfg_runlock(void); +void in_ifaddr_cfg_wlock(void); +void in_ifaddr_cfg_wunlock(void); +void in_ifaddr_cfg_lock_assert(int what); + +/* ifaddr: wrappers */ +#define IN_IFADDR_RLOCK IN_IFADDR_CFG_RLOCK +#define IN_IFADDR_RUNLOCK IN_IFADDR_CFG_RUNLOCK +#define IN_IFADDR_WLOCK() in_ifaddr_wlock() +#define IN_IFADDR_WUNLOCK() in_ifaddr_wunlock() +void in_ifaddr_wlock(void); +void in_ifaddr_wunlock(void); + +/* ifaddr lock: fast path */ +#define IN_IFADDR_FAST_LOCK_DECLARATION extern struct rmlock in_ifaddr_lock + +#define IN_IFADDR_RUN_RLOCK() rm_rlock(&in_ifaddr_lock, &ifa_rm_tracker) +#define IN_IFADDR_RUN_RUNLOCK() rm_runlock(&in_ifaddr_lock, &ifa_rm_tracker) +#define IN_IFADDR_RUN_WLOCK() rm_wlock(&in_ifaddr_lock) +#define IN_IFADDR_RUN_WUNLOCK() rm_wunlock(&in_ifaddr_lock) +#define IN_IFADDR_RUN_TRACKER struct rm_priotracker ifa_rm_tracker +#define IN_IFADDR_RUN_LOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_LOCKED) +#define IN_IFADDR_RUN_RLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_RLOCKED) +#define IN_IFADDR_RUN_WLOCK_ASSERT() rm_assert(&in_ifaddr_lock, RA_WLOCKED) /* * Macro for finding the internet address structure (in_ifaddr) Modified: projects/routing/sys/netinet/ip_input.c ============================================================================== --- projects/routing/sys/netinet/ip_input.c Sat Nov 22 16:03:18 2014 (r274854) +++ projects/routing/sys/netinet/ip_input.c Sat Nov 22 16:27:51 2014 (r274855) @@ -90,9 +90,6 @@ __FBSDID("$FreeBSD$"); CTASSERT(sizeof(struct ip) == 20); #endif -struct rwlock in_ifaddr_lock; -RW_SYSINIT(in_ifaddr_lock, &in_ifaddr_lock, "in_ifaddr_lock"); - VNET_DEFINE(int, rsvp_on); VNET_DEFINE(int, ipforwarding); @@ -646,7 +643,7 @@ passin: /* * Check for exact addresses in the hash bucket. */ - /* IN_IFADDR_RLOCK(); */ + /* IN_IFADDR_RUN_RLOCK(); */ LIST_FOREACH(ia, INADDR_HASH(ip->ip_dst.s_addr), ia_hash) { /* * If the address matches, verify that the packet @@ -662,7 +659,7 @@ passin: goto ours; } } - /* IN_IFADDR_RUNLOCK(); */ + /* IN_IFADDR_RUN_RUNLOCK(); */ /* * Check for broadcast addresses.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201411221627.sAMGRptb055672>