Index: art.c =================================================================== RCS file: /cvs/src/sys/net/art.c,v retrieving revision 1.20 diff -u -p -r1.20 art.c --- art.c 22 Jun 2016 06:32:32 -0000 1.20 +++ art.c 22 Jun 2016 10:16:52 -0000 @@ -152,6 +152,7 @@ art_alloc(unsigned int rtableid, unsigne ar->ar_off = off; ar->ar_rtableid = rtableid; + mtx_init(&ar->ar_lock, IPL_SOFTNET); return (ar); } @@ -378,7 +379,7 @@ art_insert(struct art_root *ar, struct a struct art_node *node; int i, j; - KERNEL_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&ar->ar_lock); KASSERT(plen >= 0 && plen <= ar->ar_alen); at = srp_get_locked(&ar->ar_root); @@ -482,7 +483,7 @@ art_delete(struct art_root *ar, struct a struct art_node *node; int i, j; - KERNEL_ASSERT_LOCKED(); + MUTEX_ASSERT_LOCKED(&ar->ar_lock); KASSERT(plen >= 0 && plen <= ar->ar_alen); at = srp_get_locked(&ar->ar_root); @@ -613,7 +614,7 @@ art_walk(struct art_root *ar, int (*f)(s struct art_node *node; int error = 0; - KERNEL_LOCK(); + mtx_enter(&ar->ar_lock); at = srp_get_locked(&ar->ar_root); if (at != NULL) { art_table_ref(ar, at); @@ -631,7 +632,7 @@ art_walk(struct art_root *ar, int (*f)(s art_table_free(ar, at); } - KERNEL_UNLOCK(); + mtx_leave(&ar->ar_lock); return (error); } @@ -708,9 +709,9 @@ art_walk_apply(struct art_root *ar, if ((an != NULL) && (an != next)) { /* this assumes an->an_dst is not used by f */ - KERNEL_UNLOCK(); + mtx_leave(&ar->ar_lock); error = (*f)(an, arg); - KERNEL_LOCK(); + mtx_enter(&ar->ar_lock); } return (error); Index: art.h =================================================================== RCS file: /cvs/src/sys/net/art.h,v retrieving revision 1.14 diff -u -p -r1.14 art.h --- art.h 14 Jun 2016 04:42:02 -0000 1.14 +++ art.h 22 Jun 2016 10:16:52 -0000 @@ -26,6 +26,7 @@ */ struct art_root { struct srp ar_root; /* First table */ + struct mutex ar_lock; /* Serialise modifications */ uint8_t ar_bits[ART_MAXLVL]; /* Per level stride */ uint8_t ar_nlvl; /* Number of levels */ uint8_t ar_alen; /* Address length in bits */ Index: rtable.c =================================================================== RCS file: /cvs/src/sys/net/rtable.c,v retrieving revision 1.48 diff -u -p -r1.48 rtable.c --- rtable.c 22 Jun 2016 06:32:32 -0000 1.48 +++ rtable.c 22 Jun 2016 10:16:52 -0000 @@ -515,6 +515,10 @@ static inline uint8_t *satoaddr(struct a void rtentry_ref(void *, void *); void rtentry_unref(void *, void *); +#ifndef SMALL_KERNEL +void art_mpath_insert(struct art_node *, struct rtentry *); +#endif + struct srpl_rc rt_rc = SRPL_RC_INITIALIZER(rtentry_ref, rtentry_unref, NULL); void @@ -679,8 +683,6 @@ rtable_insert(unsigned int rtableid, str unsigned int rt_flags; int error = 0; - KERNEL_ASSERT_LOCKED(); - ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) return (EAFNOSUPPORT); @@ -691,6 +693,7 @@ rtable_insert(unsigned int rtableid, str return (EINVAL); rtref(rt); /* guarantee rtfree won't do anything during insert */ + mtx_enter(&ar->ar_lock); #ifndef SMALL_KERNEL /* Do not permit exactly the same dst/mask/gw pair. */ @@ -766,15 +769,14 @@ rtable_insert(unsigned int rtableid, str } } - SRPL_INSERT_HEAD_LOCKED(&rt_rc, &an->an_rtlist, rt, rt_next); - /* Put newly inserted entry at the right place. */ - rtable_mpath_reprio(rtableid, dst, mask, rt->rt_priority, rt); + art_mpath_insert(an, rt); #else error = EEXIST; #endif /* SMALL_KERNEL */ } leave: + mtx_leave(&ar->ar_lock); rtfree(rt); return (error); } @@ -792,6 +794,7 @@ rtable_delete(unsigned int rtableid, str struct rtentry *mrt; int npaths = 0; #endif /* SMALL_KERNEL */ + int error = 0; ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) @@ -800,15 +803,17 @@ rtable_delete(unsigned int rtableid, str addr = satoaddr(ar, dst); plen = rtable_satoplen(dst->sa_family, mask); - KERNEL_ASSERT_LOCKED(); - + rtref(rt); /* guarantee rtfree won't do anything under ar_lock */ + mtx_enter(&ar->ar_lock); an = art_lookup(ar, addr, plen, &sr); srp_leave(&sr); /* an can't go away while we have the lock */ /* Make sure we've got a perfect match. */ if (an == NULL || an->an_plen != plen || - memcmp(an->an_dst, dst, dst->sa_len)) - return (ESRCH); + memcmp(an->an_dst, dst, dst->sa_len)) { + error = ESRCH; + goto leave; + } #ifndef SMALL_KERNEL /* @@ -827,18 +832,26 @@ rtable_delete(unsigned int rtableid, str an->an_dst = mrt->rt_dest; if (npaths == 2) mrt->rt_flags &= ~RTF_MPATH; - return (0); + + goto leave; } #endif /* SMALL_KERNEL */ - if (art_delete(ar, an, addr, plen) == NULL) - return (ESRCH); + if (art_delete(ar, an, addr, plen) == NULL) { + /* XXX panic */ + error = ESRCH; + goto leave; + } KASSERT(rt->rt_refcnt >= 1); SRPL_REMOVE_LOCKED(&rt_rc, &an->an_rtlist, rt, rtentry, rt_next); - art_put(an); - return (0); + +leave: + mtx_leave(&ar->ar_lock); + rtfree(rt); + + return (error); } struct rtable_walk_cookie { @@ -905,7 +918,7 @@ rtable_mpath_reprio(unsigned int rtablei struct srp_ref sr; uint8_t *addr; int plen; - struct rtentry *mrt, *prt = NULL; + int error = 0; ar = rtable_get(rtableid, dst->sa_family); if (ar == NULL) @@ -914,8 +927,7 @@ rtable_mpath_reprio(unsigned int rtablei addr = satoaddr(ar, dst); plen = rtable_satoplen(dst->sa_family, mask); - KERNEL_ASSERT_LOCKED(); - + mtx_enter(&ar->ar_lock); an = art_lookup(ar, addr, plen, &sr); srp_leave(&sr); /* an can't go away while we have the lock */ @@ -923,10 +935,24 @@ rtable_mpath_reprio(unsigned int rtablei if (an == NULL || an->an_plen != plen || memcmp(an->an_dst, dst, dst->sa_len)) return (ESRCH); + else { + rtref(rt); /* keep rt alive in between remove and insert */ + SRPL_REMOVE_LOCKED(&rt_rc, &an->an_rtlist, + rt, rtentry, rt_next); + rt->rt_priority = prio; + art_mpath_insert(an, rt); + rtfree(rt); + } + mtx_leave(&ar->ar_lock); - rtref(rt); /* keep rt alive in between remove and add */ - SRPL_REMOVE_LOCKED(&rt_rc, &an->an_rtlist, rt, rtentry, rt_next); - rt->rt_priority = prio; + return (error); +} + +void +art_mpath_insert(struct art_node *an, struct rtentry *rt) +{ + struct rtentry *mrt, *prt = NULL; + uint8_t prio = rt->rt_priority; if ((mrt = SRPL_FIRST_LOCKED(&an->an_rtlist)) != NULL) { /* @@ -957,9 +983,6 @@ rtable_mpath_reprio(unsigned int rtablei } else { SRPL_INSERT_HEAD_LOCKED(&rt_rc, &an->an_rtlist, rt, rt_next); } - rtfree(rt); - - return (0); } struct rtentry *