Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 12 Jun 2018 22:18:15 +0000 (UTC)
From:      Matt Macy <mmacy@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r335015 - head/sys/netinet
Message-ID:  <201806122218.w5CMIFRS067684@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mmacy
Date: Tue Jun 12 22:18:15 2018
New Revision: 335015
URL: https://svnweb.freebsd.org/changeset/base/335015

Log:
  Defer inpcb deletion until after a grace period has elapsed
  
  Deferring the actual free of the inpcb until after a grace
  period has elapsed will allow us to convert the inpcbinfo
  info and hash read locks to epoch.
  
  Reviewed by: gallatin, jtl
  Sponsored by: Limelight Networks
  Differential Revision: https://reviews.freebsd.org/D15510

Modified:
  head/sys/netinet/in_pcb.c
  head/sys/netinet/in_pcb.h

Modified: head/sys/netinet/in_pcb.c
==============================================================================
--- head/sys/netinet/in_pcb.c	Tue Jun 12 20:03:00 2018	(r335014)
+++ head/sys/netinet/in_pcb.c	Tue Jun 12 22:18:15 2018	(r335015)
@@ -1569,6 +1569,45 @@ in_pcblist_rele_rlocked(epoch_context_t ctx)
 	free(il, M_TEMP);
 }
 
+static void
+in_pcbfree_deferred(epoch_context_t ctx)
+{
+	struct inpcb *inp;
+	struct inpcbinfo *pcbinfo;
+	int released __unused;
+
+	inp = __containerof(ctx, struct inpcb, inp_epoch_ctx);
+	pcbinfo = inp->inp_pcbinfo;
+
+	INP_WLOCK(inp);
+#ifdef INET
+	inp_freemoptions(inp->inp_moptions);
+	inp->inp_moptions = NULL;
+#endif
+	/* XXXRW: Do as much as possible here. */
+#if defined(IPSEC) || defined(IPSEC_SUPPORT)
+	if (inp->inp_sp != NULL)
+		ipsec_delete_pcbpolicy(inp);
+#endif
+#ifdef INET6
+	if (inp->inp_vflag & INP_IPV6PROTO) {
+		ip6_freepcbopts(inp->in6p_outputopts);
+		ip6_freemoptions(inp->in6p_moptions);
+		inp->in6p_moptions = NULL;
+	}
+#endif
+	if (inp->inp_options)
+		(void)m_free(inp->inp_options);
+
+	inp->inp_vflag = 0;
+	crfree(inp->inp_cred);
+#ifdef MAC
+	mac_inpcb_destroy(inp);
+#endif
+	released = in_pcbrele_wlocked(inp);
+	MPASS(released);
+}
+
 /*
  * Unconditionally schedule an inpcb to be freed by decrementing its
  * reference count, which should occur only after the inpcb has been detached
@@ -1583,14 +1622,7 @@ in_pcbfree(struct inpcb *inp)
 {
 	struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
 
-#ifdef INET6
-	struct ip6_moptions *im6o = NULL;
-#endif
-#ifdef INET
-	struct ip_moptions *imo = NULL;
-#endif
 	KASSERT(inp->inp_socket == NULL, ("%s: inp_socket != NULL", __func__));
-
 	KASSERT((inp->inp_flags2 & INP_FREED) == 0,
 	    ("%s: called twice for pcb %p", __func__, inp));
 	if (inp->inp_flags2 & INP_FREED) {
@@ -1606,45 +1638,14 @@ in_pcbfree(struct inpcb *inp)
 	}
 #endif
 	INP_WLOCK_ASSERT(inp);
-
-#ifdef INET
-	imo = inp->inp_moptions;
-	inp->inp_moptions = NULL;
-#endif
-	/* XXXRW: Do as much as possible here. */
-#if defined(IPSEC) || defined(IPSEC_SUPPORT)
-	if (inp->inp_sp != NULL)
-		ipsec_delete_pcbpolicy(inp);
-#endif
 	INP_LIST_WLOCK(pcbinfo);
-	inp->inp_gencnt = ++pcbinfo->ipi_gencnt;
 	in_pcbremlists(inp);
 	INP_LIST_WUNLOCK(pcbinfo);
-#ifdef INET6
-	if (inp->inp_vflag & INP_IPV6PROTO) {
-		ip6_freepcbopts(inp->in6p_outputopts);
-		im6o = inp->in6p_moptions;
-		inp->in6p_moptions = NULL;
-	}
-#endif
-	if (inp->inp_options)
-		(void)m_free(inp->inp_options);
 	RO_INVALIDATE_CACHE(&inp->inp_route);
-
-	inp->inp_vflag = 0;
+	/* mark as destruction in progress */
 	inp->inp_flags2 |= INP_FREED;
-	crfree(inp->inp_cred);
-#ifdef MAC
-	mac_inpcb_destroy(inp);
-#endif
-#ifdef INET6
-	ip6_freemoptions(im6o);
-#endif
-#ifdef INET
-	inp_freemoptions(imo);
-#endif
-	if (!in_pcbrele_wlocked(inp))
-		INP_WUNLOCK(inp);
+	INP_WUNLOCK(inp);
+	epoch_call(net_epoch_preempt, &inp->inp_epoch_ctx, in_pcbfree_deferred);
 }
 
 /*

Modified: head/sys/netinet/in_pcb.h
==============================================================================
--- head/sys/netinet/in_pcb.h	Tue Jun 12 20:03:00 2018	(r335014)
+++ head/sys/netinet/in_pcb.h	Tue Jun 12 22:18:15 2018	(r335015)
@@ -325,6 +325,7 @@ struct inpcb {
 	LIST_ENTRY(inpcb) inp_list;	/* (p/l) list for all PCBs for proto */
 	                                /* (p[w]) for list iteration */
 	                                /* (p[r]/l) for addition/removal */
+	struct epoch_context inp_epoch_ctx;
 };
 #endif	/* _KERNEL */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201806122218.w5CMIFRS067684>