Author: rwatson
Date: Sun Jun 21 19:30:33 2009
New Revision: 194602
URL: http://svn.freebsd.org/changeset/base/194602

Log:
  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

Modified:
  head/sys/net/if.c
  head/sys/net/if_var.h
  head/sys/net/route.c
  head/sys/net/rtsock.c
  head/sys/netatalk/at_control.c
  head/sys/netinet/in.c
  head/sys/netinet6/in6.c
  head/sys/netinet6/in6_ifattach.c
  head/sys/netinet6/nd6_nbr.c
  head/sys/netipx/ipx.c

Modified: head/sys/net/if.c
==============================================================================
--- head/sys/net/if.c   Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/net/if.c   Sun Jun 21 19:30:33 2009        (r194602)
@@ -758,7 +758,7 @@ if_attach_internal(struct ifnet *ifp, in
                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, in
                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, in
                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 *ar
 }
 
 /*
+ * 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 *
                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);
        }

Modified: head/sys/net/if_var.h
==============================================================================
--- head/sys/net/if_var.h       Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/net/if_var.h       Sun Jun 21 19:30:33 2009        (r194602)
@@ -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() \

Modified: head/sys/net/route.c
==============================================================================
--- head/sys/net/route.c        Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/net/route.c        Sun Jun 21 19:30:33 2009        (r194602)
@@ -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_addrin
                 * 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_addrin
                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_addrin
                 */
                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
                         */
                        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;
                        }

Modified: head/sys/net/rtsock.c
==============================================================================
--- head/sys/net/rtsock.c       Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/net/rtsock.c       Sun Jun 21 19:30:33 2009        (r194602)
@@ -694,7 +694,7 @@ route_output(struct mbuf *m, struct sock
                            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 sock
                        }
                        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;
                        }

Modified: head/sys/netatalk/at_control.c
==============================================================================
--- head/sys/netatalk/at_control.c      Sun Jun 21 19:21:01 2009        
(r194601)
+++ head/sys/netatalk/at_control.c      Sun Jun 21 19:30:33 2009        
(r194602)
@@ -189,8 +189,7 @@ at_control(struct socket *so, u_long cmd
                         * and link our new one on the end 
                         */
                        ifa = (struct ifaddr *)aa;
-                       IFA_LOCK_INIT(ifa);
-                       ifa->ifa_refcnt = 1;
+                       ifa_init(ifa);
 
                        /*
                         * As the at_ifaddr contains the actual sockaddrs,
@@ -325,7 +324,7 @@ at_control(struct socket *so, u_long cmd
                /*
                 * Now reclaim the reference.
                 */
-               IFAFREE(ifa0);
+               ifa_free(ifa0);
                break;
 
        default:

Modified: head/sys/netinet/in.c
==============================================================================
--- head/sys/netinet/in.c       Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/netinet/in.c       Sun Jun 21 19:30:33 2009        (r194602)
@@ -377,11 +377,10 @@ in_control(struct socket *so, u_long cmd
                        }
 
                        ifa = &ia->ia_ifa;
-                       IFA_LOCK_INIT(ifa);
+                       ifa_init(ifa);
                        ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
                        ifa->ifa_dstaddr = (struct sockaddr *)&ia->ia_dstaddr;
                        ifa->ifa_netmask = (struct sockaddr *)&ia->ia_sockmask;
-                       ifa->ifa_refcnt = 1;
 
                        ia->ia_sockmask.sin_len = 8;
                        ia->ia_sockmask.sin_family = AF_INET;
@@ -617,7 +616,7 @@ in_control(struct socket *so, u_long cmd
                        IN_MULTI_UNLOCK();
                }
        }
-       IFAFREE(&ia->ia_ifa);
+       ifa_free(&ia->ia_ifa);
        splx(s);
 
        return (error);

Modified: head/sys/netinet6/in6.c
==============================================================================
--- head/sys/netinet6/in6.c     Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/netinet6/in6.c     Sun Jun 21 19:30:33 2009        (r194602)
@@ -784,9 +784,9 @@ in6_update_ifa(struct ifnet *ifp, struct
                if (ia == NULL)
                        return (ENOBUFS);
                bzero((caddr_t)ia, sizeof(*ia));
+               ifa_init(&ia->ia_ifa);
                LIST_INIT(&ia->ia6_memberships);
                /* Initialize the address and masks, and put time stamp */
-               IFA_LOCK_INIT(&ia->ia_ifa);
                ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
                ia->ia_addr.sin6_family = AF_INET6;
                ia->ia_addr.sin6_len = sizeof(ia->ia_addr);
@@ -811,7 +811,6 @@ in6_update_ifa(struct ifnet *ifp, struct
                } else
                        V_in6_ifaddr = ia;
 
-               ia->ia_ifa.ifa_refcnt = 1;
                IF_ADDR_LOCK(ifp);
                TAILQ_INSERT_TAIL(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
                IF_ADDR_UNLOCK(ifp);
@@ -1387,7 +1386,7 @@ in6_unlink_ifa(struct in6_ifaddr *ia, st
         * release another refcnt for the link from in6_ifaddr.
         * Note that we should decrement the refcnt at least once for all *BSD.
         */
-       IFAFREE(&oia->ia_ifa);
+       ifa_free(&oia->ia_ifa);
 
        splx(s);
 }

Modified: head/sys/netinet6/in6_ifattach.c
==============================================================================
--- head/sys/netinet6/in6_ifattach.c    Sun Jun 21 19:21:01 2009        
(r194601)
+++ head/sys/netinet6/in6_ifattach.c    Sun Jun 21 19:30:33 2009        
(r194602)
@@ -827,7 +827,7 @@ in6_ifdetach(struct ifnet *ifp)
                IF_ADDR_LOCK(ifp);
                TAILQ_REMOVE(&ifp->if_addrhead, (struct ifaddr *)ia, ifa_link);
                IF_ADDR_UNLOCK(ifp);
-               IFAFREE(&ia->ia_ifa);
+               ifa_free(&ia->ia_ifa);
 
                /* also remove from the IPv6 address chain(itojun&jinmei) */
                oia = ia;
@@ -845,7 +845,7 @@ in6_ifdetach(struct ifnet *ifp)
                        }
                }
 
-               IFAFREE(&oia->ia_ifa);
+               ifa_free(&oia->ia_ifa);
        }
 
        in6_pcbpurgeif0(&V_udbinfo, ifp);

Modified: head/sys/netinet6/nd6_nbr.c
==============================================================================
--- head/sys/netinet6/nd6_nbr.c Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/netinet6/nd6_nbr.c Sun Jun 21 19:30:33 2009        (r194602)
@@ -1223,7 +1223,7 @@ nd6_dad_start(struct ifaddr *ifa, int de
         * (re)initialization.
         */
        dp->dad_ifa = ifa;
-       IFAREF(ifa);    /* just for safety */
+       ifa_ref(ifa);   /* just for safety */
        dp->dad_count = V_ip6_dad_count;
        dp->dad_ns_icount = dp->dad_na_icount = 0;
        dp->dad_ns_ocount = dp->dad_ns_tcount = 0;
@@ -1258,7 +1258,7 @@ nd6_dad_stop(struct ifaddr *ifa)
        TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
        free(dp, M_IP6NDP);
        dp = NULL;
-       IFAFREE(ifa);
+       ifa_free(ifa);
 }
 
 static void
@@ -1301,7 +1301,7 @@ nd6_dad_timer(struct dadq *dp)
                TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
                free(dp, M_IP6NDP);
                dp = NULL;
-               IFAFREE(ifa);
+               ifa_free(ifa);
                goto done;
        }
 
@@ -1354,7 +1354,7 @@ nd6_dad_timer(struct dadq *dp)
                        TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
                        free(dp, M_IP6NDP);
                        dp = NULL;
-                       IFAFREE(ifa);
+                       ifa_free(ifa);
                }
        }
 
@@ -1432,7 +1432,7 @@ nd6_dad_duplicated(struct ifaddr *ifa)
        TAILQ_REMOVE(&V_dadq, (struct dadq *)dp, dad_list);
        free(dp, M_IP6NDP);
        dp = NULL;
-       IFAFREE(ifa);
+       ifa_free(ifa);
 }
 
 static void

Modified: head/sys/netipx/ipx.c
==============================================================================
--- head/sys/netipx/ipx.c       Sun Jun 21 19:21:01 2009        (r194601)
+++ head/sys/netipx/ipx.c       Sun Jun 21 19:30:33 2009        (r194602)
@@ -170,8 +170,7 @@ ipx_control(struct socket *so, u_long cm
                                ipx_ifaddr = oia;
                        ia = oia;
                        ifa = (struct ifaddr *)ia;
-                       IFA_LOCK_INIT(ifa);
-                       ifa->ifa_refcnt = 1;
+                       ifa_init(ifa);
                        TAILQ_INSERT_TAIL(&ifp->if_addrhead, ifa, ifa_link);
                        ia->ia_ifp = ifp;
                        ifa->ifa_addr = (struct sockaddr *)&ia->ia_addr;
@@ -231,7 +230,7 @@ ipx_control(struct socket *so, u_long cm
                        else
                                printf("Didn't unlink ipxifadr from list\n");
                }
-               IFAFREE((&oia->ia_ifa));
+               ifa_free(&oia->ia_ifa);
                return (0);
 
        case SIOCAIFADDR:
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to