svn commit: r228969 - head/sys/netinet

John Baldwin jhb at FreeBSD.org
Thu Dec 29 20:41:16 UTC 2011


Author: jhb
Date: Thu Dec 29 20:41:16 2011
New Revision: 228969
URL: http://svn.freebsd.org/changeset/base/228969

Log:
  Defer the work of freeing IPv4 multicast options from a socket to an
  asychronous task.  This avoids tearing down multicast state including
  sending IGMP leave messages and reprogramming MAC filters while holding
  the per-protocol global pcbinfo lock that is used in the receive path of
  packet processing.
  
  Reviewed by:	rwatson
  MFC after:	1 month

Modified:
  head/sys/netinet/in_mcast.c
  head/sys/netinet/ip_var.h

Modified: head/sys/netinet/in_mcast.c
==============================================================================
--- head/sys/netinet/in_mcast.c	Thu Dec 29 19:01:29 2011	(r228968)
+++ head/sys/netinet/in_mcast.c	Thu Dec 29 20:41:16 2011	(r228969)
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/protosw.h>
 #include <sys/sysctl.h>
 #include <sys/ktr.h>
+#include <sys/taskqueue.h>
 #include <sys/tree.h>
 
 #include <net/if.h>
@@ -144,6 +145,8 @@ static void	inm_purge(struct in_multi *)
 static void	inm_reap(struct in_multi *);
 static struct ip_moptions *
 		inp_findmoptions(struct inpcb *);
+static void	inp_freemoptions_internal(struct ip_moptions *);
+static void	inp_gcmoptions(void *, int);
 static int	inp_get_source_filters(struct inpcb *, struct sockopt *);
 static int	inp_join_group(struct inpcb *, struct sockopt *);
 static int	inp_leave_group(struct inpcb *, struct sockopt *);
@@ -179,6 +182,10 @@ static SYSCTL_NODE(_net_inet_ip_mcast, O
     CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_ip_mcast_filters,
     "Per-interface stack-wide source filters");
 
+static STAILQ_HEAD(, ip_moptions) imo_gc_list =
+    STAILQ_HEAD_INITIALIZER(imo_gc_list);
+static struct task imo_gc_task = TASK_INITIALIZER(0, inp_gcmoptions, NULL);
+
 /*
  * Inline function which wraps assertions for a valid ifp.
  * The ifnet layer will set the ifma's ifp pointer to NULL if the ifp
@@ -1518,17 +1525,29 @@ inp_findmoptions(struct inpcb *inp)
 }
 
 /*
- * Discard the IP multicast options (and source filters).
+ * Discard the IP multicast options (and source filters).  To minimize
+ * the amount of work done while holding locks such as the INP's
+ * pcbinfo lock (which is used in the receive path), the free
+ * operation is performed asynchronously in a separate task.
  *
  * SMPng: NOTE: assumes INP write lock is held.
  */
 void
 inp_freemoptions(struct ip_moptions *imo)
 {
-	struct in_mfilter	*imf;
-	size_t			 idx, nmships;
 
 	KASSERT(imo != NULL, ("%s: ip_moptions is NULL", __func__));
+	IN_MULTI_LOCK();
+	STAILQ_INSERT_TAIL(&imo_gc_list, imo, imo_link);
+	IN_MULTI_UNLOCK();
+	taskqueue_enqueue(taskqueue_thread, &imo_gc_task);
+}
+
+static void
+inp_freemoptions_internal(struct ip_moptions *imo)
+{
+	struct in_mfilter	*imf;
+	size_t			 idx, nmships;
 
 	nmships = imo->imo_num_memberships;
 	for (idx = 0; idx < nmships; ++idx) {
@@ -1546,6 +1565,22 @@ inp_freemoptions(struct ip_moptions *imo
 	free(imo, M_IPMOPTS);
 }
 
+static void
+inp_gcmoptions(void *context, int pending)
+{
+	struct ip_moptions *imo;
+
+	IN_MULTI_LOCK();
+	while (!STAILQ_EMPTY(&imo_gc_list)) {
+		imo = STAILQ_FIRST(&imo_gc_list);
+		STAILQ_REMOVE_HEAD(&imo_gc_list, imo_link);
+		IN_MULTI_UNLOCK();
+		inp_freemoptions_internal(imo);
+		IN_MULTI_LOCK();
+	}
+	IN_MULTI_UNLOCK();
+}
+
 /*
  * Atomically get source filters on a socket for an IPv4 multicast group.
  * Called with INP lock held; returns with lock released.

Modified: head/sys/netinet/ip_var.h
==============================================================================
--- head/sys/netinet/ip_var.h	Thu Dec 29 19:01:29 2011	(r228968)
+++ head/sys/netinet/ip_var.h	Thu Dec 29 20:41:16 2011	(r228969)
@@ -93,6 +93,7 @@ struct ip_moptions {
 	u_short	imo_max_memberships;	/* max memberships this socket */
 	struct	in_multi **imo_membership;	/* group memberships */
 	struct	in_mfilter *imo_mfilters;	/* source filters */
+	STAILQ_ENTRY(ip_moptions) imo_link;
 };
 
 struct	ipstat {


More information about the svn-src-all mailing list