diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-06-21 19:30:33 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-06-21 19:30:33 +0000 |
commit | 1f7e54e8c51edb13935d195e0c1f2ec68c672794 (patch) | |
tree | 2cfffa4418c1fa90f1e9d094aa882742d0ababb9 /sys/net | |
parent | 2fc79768f33d575d200ae1482dc23207f9d93703 (diff) | |
download | FreeBSD-src-1f7e54e8c51edb13935d195e0c1f2ec68c672794.zip FreeBSD-src-1f7e54e8c51edb13935d195e0c1f2ec68c672794.tar.gz |
Clean up common ifaddr management:
- Unify reference count and lock initialization in a single function,
ifa_init().
- Move tear-down from a macro (IFAFREE) to a function ifa_free().
- Move reference count bump from a macro (IFAREF) to a function ifa_ref().
- Instead of using a u_int protected by a mutex to refcount(9) for
reference count management.
The ifa_mtx is now used for exactly one ioctl, and possibly should be
removed.
MFC after: 3 weeks
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if.c | 39 | ||||
-rw-r--r-- | sys/net/if_var.h | 27 | ||||
-rw-r--r-- | sys/net/route.c | 12 | ||||
-rw-r--r-- | sys/net/rtsock.c | 4 |
4 files changed, 47 insertions, 35 deletions
diff --git a/sys/net/if.c b/sys/net/if.c index c5e1a56..fa708e9 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -758,7 +758,7 @@ if_attach_internal(struct ifnet *ifp, int vmove) socksize = roundup2(socksize, sizeof(long)); ifasize = sizeof(*ifa) + 2 * socksize; ifa = malloc(ifasize, M_IFADDR, M_WAITOK | M_ZERO); - IFA_LOCK_INIT(ifa); + ifa_init(ifa); sdl = (struct sockaddr_dl *)(ifa + 1); sdl->sdl_len = socksize; sdl->sdl_family = AF_LINK; @@ -775,7 +775,6 @@ if_attach_internal(struct ifnet *ifp, int vmove) sdl->sdl_len = masklen; while (namelen != 0) sdl->sdl_data[--namelen] = 0xff; - ifa->ifa_refcnt = 1; TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); /* Reliably crash if used uninitialized. */ ifp->if_broadcastaddr = NULL; @@ -896,7 +895,7 @@ if_purgeaddrs(struct ifnet *ifp) } #endif /* INET6 */ TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); - IFAFREE(ifa); + ifa_free(ifa); } } @@ -1013,7 +1012,7 @@ if_detach_internal(struct ifnet *ifp, int vmove) if (!TAILQ_EMPTY(&ifp->if_addrhead)) { ifa = TAILQ_FIRST(&ifp->if_addrhead); TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); - IFAFREE(ifa); + ifa_free(ifa); } } @@ -1420,6 +1419,34 @@ if_rtdel(struct radix_node *rn, void *arg) } /* + * Reference count functions for ifaddrs. + */ +void +ifa_init(struct ifaddr *ifa) +{ + + mtx_init(&ifa->ifa_mtx, "ifaddr", NULL, MTX_DEF); + refcount_init(&ifa->ifa_refcnt, 1); +} + +void +ifa_ref(struct ifaddr *ifa) +{ + + refcount_acquire(&ifa->ifa_refcnt); +} + +void +ifa_free(struct ifaddr *ifa) +{ + + if (refcount_release(&ifa->ifa_refcnt)) { + mtx_destroy(&ifa->ifa_mtx); + free(ifa, M_IFADDR); + } +} + +/* * XXX: Because sockaddr_dl has deeper structure than the sockaddr * structs used to represent other address families, it is necessary * to perform a different comparison. @@ -1711,10 +1738,10 @@ link_rtrequest(int cmd, struct rtentry *rt, struct rt_addrinfo *info) return; ifa = ifaof_ifpforaddr(dst, ifp); if (ifa) { - IFAREF(ifa); /* XXX */ + ifa_ref(ifa); /* XXX */ oifa = rt->rt_ifa; rt->rt_ifa = ifa; - IFAFREE(oifa); + ifa_free(oifa); if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest) ifa->ifa_rtrequest(cmd, rt, info); } diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 556aace..cbd274a 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -706,11 +706,14 @@ struct ifaddr { /* for compatibility with other BSDs */ #define ifa_list ifa_link -#define IFA_LOCK_INIT(ifa) \ - mtx_init(&(ifa)->ifa_mtx, "ifaddr", NULL, MTX_DEF) +#ifdef _KERNEL #define IFA_LOCK(ifa) mtx_lock(&(ifa)->ifa_mtx) #define IFA_UNLOCK(ifa) mtx_unlock(&(ifa)->ifa_mtx) -#define IFA_DESTROY(ifa) mtx_destroy(&(ifa)->ifa_mtx) + +void ifa_free(struct ifaddr *ifa); +void ifa_init(struct ifaddr *ifa); +void ifa_ref(struct ifaddr *ifa); +#endif /* * The prefix structure contains information about one prefix @@ -741,24 +744,6 @@ struct ifmultiaddr { }; #ifdef _KERNEL -#define IFAFREE(ifa) \ - do { \ - IFA_LOCK(ifa); \ - KASSERT((ifa)->ifa_refcnt > 0, \ - ("ifa %p !(ifa_refcnt > 0)", ifa)); \ - if (--(ifa)->ifa_refcnt == 0) { \ - IFA_DESTROY(ifa); \ - free(ifa, M_IFADDR); \ - } else \ - IFA_UNLOCK(ifa); \ - } while (0) - -#define IFAREF(ifa) \ - do { \ - IFA_LOCK(ifa); \ - ++(ifa)->ifa_refcnt; \ - IFA_UNLOCK(ifa); \ - } while (0) extern struct rwlock ifnet_lock; #define IFNET_LOCK_INIT() \ diff --git a/sys/net/route.c b/sys/net/route.c index aaa38d7..1705e98 100644 --- a/sys/net/route.c +++ b/sys/net/route.c @@ -474,7 +474,7 @@ rtfree(struct rtentry *rt) * e.g other routes and ifaddrs. */ if (rt->rt_ifa) - IFAFREE(rt->rt_ifa); + ifa_free(rt->rt_ifa); /* * The key is separatly alloc'd so free it (see rt_setgate()). * This also frees the gateway, as they are always malloc'd @@ -1126,7 +1126,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, * This moved from below so that rnh->rnh_addaddr() can * examine the ifa and ifa->ifa_ifp if it so desires. */ - IFAREF(ifa); + ifa_ref(ifa); rt->rt_ifa = ifa; rt->rt_ifp = ifa->ifa_ifp; rt->rt_rmx.rmx_weight = 1; @@ -1136,7 +1136,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, if (rn_mpath_capable(rnh) && rt_mpath_conflict(rnh, rt, netmask)) { if (rt->rt_ifa) { - IFAFREE(rt->rt_ifa); + ifa_free(rt->rt_ifa); } Free(rt_key(rt)); RT_LOCK_DESTROY(rt); @@ -1153,7 +1153,7 @@ rtrequest1_fib(int req, struct rt_addrinfo *info, struct rtentry **ret_nrt, */ if (rn == NULL) { if (rt->rt_ifa) - IFAFREE(rt->rt_ifa); + ifa_free(rt->rt_ifa); Free(rt_key(rt)); RT_LOCK_DESTROY(rt); uma_zfree(V_rtzone, rt); @@ -1409,8 +1409,8 @@ rtinit1(struct ifaddr *ifa, int cmd, int flags, int fibnum) */ if (memcmp(rt->rt_ifa->ifa_addr, ifa->ifa_addr, ifa->ifa_addr->sa_len)) { - IFAFREE(rt->rt_ifa); - IFAREF(ifa); + ifa_free(rt->rt_ifa); + ifa_ref(ifa); rt->rt_ifp = ifa->ifa_ifp; rt->rt_ifa = ifa; } diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 56bb3a7..ab38557 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -694,7 +694,7 @@ route_output(struct mbuf *m, struct socket *so) rt->rt_ifa->ifa_rtrequest != NULL) { rt->rt_ifa->ifa_rtrequest(RTM_DELETE, rt, &info); - IFAFREE(rt->rt_ifa); + ifa_free(rt->rt_ifa); } if (info.rti_info[RTAX_GATEWAY] != NULL) { RT_UNLOCK(rt); @@ -712,7 +712,7 @@ route_output(struct mbuf *m, struct socket *so) } if (info.rti_ifa != NULL && info.rti_ifa != rt->rt_ifa) { - IFAREF(info.rti_ifa); + ifa_ref(info.rti_ifa); rt->rt_ifa = info.rti_ifa; rt->rt_ifp = info.rti_ifp; } |