svn commit: r191025 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb net

Max Laier mlaier at FreeBSD.org
Mon Apr 13 22:17:04 UTC 2009


Author: mlaier
Date: Mon Apr 13 22:17:03 2009
New Revision: 191025
URL: http://svn.freebsd.org/changeset/base/191025

Log:
  MFH r190903 & r190895:
    Remove interfaces from interface groups on detach.
  
  Reported by:	various
  Submitted by:	Mikolaj Golub (r190895)
  PR:		kern/130977, kern/131310
  Approved by:	re (gnn)

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/net/if.c

Modified: stable/7/sys/net/if.c
==============================================================================
--- stable/7/sys/net/if.c	Mon Apr 13 21:04:53 2009	(r191024)
+++ stable/7/sys/net/if.c	Mon Apr 13 22:17:03 2009	(r191025)
@@ -128,6 +128,7 @@ static void	if_start_deferred(void *cont
 static void	do_link_state_change(void *, int);
 static int	if_getgroup(struct ifgroupreq *, struct ifnet *);
 static int	if_getgroupmembers(struct ifgroupreq *);
+static void	if_delgroups(struct ifnet *);
 #ifdef INET6
 /*
  * XXX: declare here to avoid to include many inet6 related files..
@@ -828,6 +829,7 @@ if_detach(struct ifnet *ifp)
 	rt_ifannouncemsg(ifp, IFAN_DEPARTURE);
 	EVENTHANDLER_INVOKE(ifnet_departure_event, ifp);
 	devctl_notify("IFNET", ifp->if_xname, "DETACH", NULL);
+	if_delgroups(ifp);
 
 	IF_AFDATA_LOCK(ifp);
 	for (dp = domains; dp; dp = dp->dom_next) {
@@ -963,6 +965,53 @@ if_delgroup(struct ifnet *ifp, const cha
 }
 
 /*
+ * Remove an interface from all groups
+ */
+static void
+if_delgroups(struct ifnet *ifp)
+{
+	struct ifg_list		*ifgl;
+	struct ifg_member	*ifgm;
+	char groupname[IFNAMSIZ];
+
+	IFNET_WLOCK();
+	while (!TAILQ_EMPTY(&ifp->if_groups)) {
+		ifgl = TAILQ_FIRST(&ifp->if_groups);
+
+		strlcpy(groupname, ifgl->ifgl_group->ifg_group, IFNAMSIZ);
+
+		IF_ADDR_LOCK(ifp);
+		TAILQ_REMOVE(&ifp->if_groups, ifgl, ifgl_next);
+		IF_ADDR_UNLOCK(ifp);
+
+		TAILQ_FOREACH(ifgm, &ifgl->ifgl_group->ifg_members, ifgm_next)
+			if (ifgm->ifgm_ifp == ifp)
+				break;
+
+		if (ifgm != NULL) {
+			TAILQ_REMOVE(&ifgl->ifgl_group->ifg_members, ifgm,
+			    ifgm_next);
+			free(ifgm, M_TEMP);
+		}
+
+		if (--ifgl->ifgl_group->ifg_refcnt == 0) {
+			TAILQ_REMOVE(&ifg_head, ifgl->ifgl_group, ifg_next);
+			EVENTHANDLER_INVOKE(group_detach_event,
+			    ifgl->ifgl_group);
+			free(ifgl->ifgl_group, M_TEMP);
+		}
+		IFNET_WUNLOCK();
+
+		free(ifgl, M_TEMP);
+
+		EVENTHANDLER_INVOKE(group_change_event, groupname);
+
+		IFNET_WLOCK();
+	}
+	IFNET_WUNLOCK();
+}
+
+/*
  * Stores all groups from an interface in memory pointed
  * to by data
  */


More information about the svn-src-all mailing list