From owner-p4-projects@FreeBSD.ORG Thu Sep 13 01:38:07 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 439C716A46D; Thu, 13 Sep 2007 01:38:07 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0F69A16A419 for ; Thu, 13 Sep 2007 01:38:07 +0000 (UTC) (envelope-from kmacy@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 0888C13C4A8 for ; Thu, 13 Sep 2007 01:38:07 +0000 (UTC) (envelope-from kmacy@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id l8D1c6U5014864 for ; Thu, 13 Sep 2007 01:38:06 GMT (envelope-from kmacy@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id l8D1c6tR014861 for perforce@freebsd.org; Thu, 13 Sep 2007 01:38:06 GMT (envelope-from kmacy@freebsd.org) Date: Thu, 13 Sep 2007 01:38:06 GMT Message-Id: <200709130138.l8D1c6tR014861@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to kmacy@freebsd.org using -f From: Kip Macy To: Perforce Change Reviews Cc: Subject: PERFORCE change 126352 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Sep 2007 01:38:07 -0000 http://perforce.freebsd.org/chv.cgi?CH=126352 Change 126352 by kmacy@kmacy_home:ethng on 2007/09/13 01:37:50 add rtalloc2 which does the same work as rtalloc1 but: - internally locks the route shared except when bumping the refcount - returns the route unlocked plug locking holes introduced in previous revision of rtalloc1 Affected files ... .. //depot/projects/ethng/src/sys/net/route.c#5 edit Differences ... ==== //depot/projects/ethng/src/sys/net/route.c#5 (text+ko) ==== @@ -114,9 +114,7 @@ RTFREE(rt); ro->ro_rt = NULL; } - ro->ro_rt = rtalloc1(&ro->ro_dst, 1, ignore); - if (ro->ro_rt) - RT_UNLOCK(ro->ro_rt); + ro->ro_rt = rtalloc2(&ro->ro_dst, 1, ignore); } /* @@ -153,8 +151,121 @@ */ newrt = rt = RNTORT(rn); nflags = rt->rt_flags & ~ignflags; + if (report && (nflags & RTF_CLONING)) { + RADIX_NODE_HEAD_UNLOCK_SHARED(rnh); + RADIX_NODE_HEAD_LOCK(rnh); + /* + * We are apparently adding (report = 0 in delete). + * If it requires that it be cloned, do so. + * (This implies it wasn't a HOST route.) + */ + err = rtrequest(RTM_RESOLVE, dst, NULL, + NULL, 0, &newrt); + if (err) { + if (!((rn = rnh->rnh_matchaddr(dst, rnh)) && + (rn->rn_flags & RNF_ROOT) == 0)) { + RADIX_NODE_HEAD_UNLOCK(rnh); + goto miss2; + } + /* + * If the cloning didn't succeed, maybe + * what we have will do. Return that. + */ + newrt = rt; /* existing route */ + RT_LOCK(newrt); + RADIX_NODE_HEAD_UNLOCK(rnh); + RT_ADDREF(newrt); + goto miss2; + } + KASSERT(newrt, ("no route and no error")); + RT_LOCK(newrt); + RADIX_NODE_HEAD_UNLOCK(rnh); + if (newrt->rt_flags & RTF_XRESOLVE) { + /* + * If the new route specifies it be + * externally resolved, then go do that. + */ + msgtype = RTM_RESOLVE; + goto miss2; + } + /* Inform listeners of the new route. */ + bzero(&info, sizeof(info)); + info.rti_info[RTAX_DST] = rt_key(newrt); + info.rti_info[RTAX_NETMASK] = rt_mask(newrt); + info.rti_info[RTAX_GATEWAY] = newrt->rt_gateway; + if (newrt->rt_ifp != NULL) { + info.rti_info[RTAX_IFP] = + newrt->rt_ifp->if_addr->ifa_addr; + info.rti_info[RTAX_IFA] = newrt->rt_ifa->ifa_addr; + } + rt_missmsg(RTM_ADD, &info, newrt->rt_flags, 0); + } else { + KASSERT(rt == newrt, ("locking wrong route")); + RT_LOCK(newrt); + RADIX_NODE_HEAD_UNLOCK_SHARED(rnh); + RT_ADDREF(newrt); + } + } else { + /* + * Either we hit the root or couldn't find any match, + * Which basically means + * "caint get there frm here" + */ + rtstat.rts_unreach++; RADIX_NODE_HEAD_UNLOCK_SHARED(rnh); + miss2: if (report) { + /* + * If required, report the failure to the supervising + * Authorities. + * For a delete, this is not an error. (report == 0) + */ + bzero(&info, sizeof(info)); + info.rti_info[RTAX_DST] = dst; + rt_missmsg(msgtype, &info, 0, err); + } + } + if (newrt) + RT_LOCK_ASSERT(newrt); + return (newrt); +} + +/* + * Look up the route that matches the address given + * Or, at least try.. Create a cloned route if needed. + * + * The returned route, if any, is locked. + */ +struct rtentry * +rtalloc2(struct sockaddr *dst, int report, u_long ignflags) +{ + struct radix_node_head *rnh = rt_tables[dst->sa_family]; + struct rtentry *rt; + struct radix_node *rn; + struct rtentry *newrt; + struct rt_addrinfo info; + u_long nflags; + int err = 0, msgtype = RTM_MISS; + + newrt = NULL; + /* + * Look up the address in the table for that Address Family + */ + if (rnh == NULL) { + rtstat.rts_unreach++; + goto miss2; + } + RADIX_NODE_HEAD_LOCK_SHARED(rnh); + if ((rn = rnh->rnh_matchaddr(dst, rnh)) && + (rn->rn_flags & RNF_ROOT) == 0) { + /* + * If we find it and it's not the root node, then + * get a reference on the rtentry associated. + */ + newrt = rt = RNTORT(rn); + nflags = rt->rt_flags & ~ignflags; if (report && (nflags & RTF_CLONING)) { + RADIX_NODE_HEAD_UNLOCK_SHARED(rnh); + RADIX_NODE_HEAD_LOCK(rnh); /* * We are apparently adding (report = 0 in delete). * If it requires that it be cloned, do so. @@ -163,29 +274,32 @@ err = rtrequest(RTM_RESOLVE, dst, NULL, NULL, 0, &newrt); if (err) { - RADIX_NODE_HEAD_LOCK_SHARED(rnh); if (!((rn = rnh->rnh_matchaddr(dst, rnh)) && - (rn->rn_flags & RNF_ROOT) == 0)) - goto miss; + (rn->rn_flags & RNF_ROOT) == 0)) { + RADIX_NODE_HEAD_UNLOCK(rnh); + goto miss2; + } /* * If the cloning didn't succeed, maybe * what we have will do. Return that. */ newrt = rt; /* existing route */ RT_LOCK(newrt); - RADIX_NODE_HEAD_UNLOCK_SHARED(rnh); + RADIX_NODE_HEAD_UNLOCK(rnh); RT_ADDREF(newrt); - goto miss; + RT_LOCK_DOWNGRADE(newrt); + goto miss2; } + RT_LOCK_SHARED(newrt); + RADIX_NODE_HEAD_UNLOCK(rnh); KASSERT(newrt, ("no route and no error")); - RT_LOCK(newrt); if (newrt->rt_flags & RTF_XRESOLVE) { /* * If the new route specifies it be * externally resolved, then go do that. */ msgtype = RTM_RESOLVE; - goto miss; + goto miss2; } /* Inform listeners of the new route. */ bzero(&info, sizeof(info)); @@ -201,7 +315,9 @@ } else { KASSERT(rt == newrt, ("locking wrong route")); RT_LOCK(newrt); + RADIX_NODE_HEAD_UNLOCK_SHARED(rnh); RT_ADDREF(newrt); + RT_LOCK_DOWNGRADE(newrt); } } else { /* @@ -210,7 +326,6 @@ * "caint get there frm here" */ rtstat.rts_unreach++; - miss: RADIX_NODE_HEAD_UNLOCK_SHARED(rnh); miss2: if (report) { /* @@ -225,6 +340,9 @@ } if (newrt) RT_LOCK_ASSERT(newrt); + + RT_UNLOCK_SHARED(newrt); + return (newrt); }