Page MenuHomeFreeBSD

D27279.id79938.diff
No OneTemporary

D27279.id79938.diff

Index: sys/net/if.c
===================================================================
--- sys/net/if.c
+++ sys/net/if.c
@@ -275,6 +275,8 @@
static void if_attach_internal(struct ifnet *, int, struct if_clone *);
static int if_detach_internal(struct ifnet *, int, struct if_clone **);
static void if_siocaddmulti(void *, int);
+static void if_link_ifnet(struct ifnet *);
+static int if_unlink_ifnet(struct ifnet *, int);
#ifdef VIMAGE
static int if_vmove(struct ifnet *, struct vnet *);
#endif
@@ -467,15 +469,75 @@
VNET_SYSUNINIT(vnet_if_uninit, SI_SUB_INIT_IF, SI_ORDER_FIRST,
vnet_if_uninit, NULL);
+static void
+if_link_ifnet(struct ifnet *ifp)
+{
+
+ IFNET_WLOCK();
+ CK_STAILQ_INSERT_TAIL(&V_ifnet, ifp, if_link);
+#ifdef VIMAGE
+ curvnet->vnet_ifcnt++;
+#endif
+ IFNET_WUNLOCK();
+}
+
+static int
+if_unlink_ifnet(struct ifnet *ifp, int vmove)
+{
+ struct ifnet *iter;
+ int found = 0;
+
+ IFNET_WLOCK();
+ CK_STAILQ_FOREACH(iter, &V_ifnet, if_link)
+ if (iter == ifp) {
+ CK_STAILQ_REMOVE(&V_ifnet, ifp, ifnet, if_link);
+ if (!vmove)
+ ifp->if_flags |= IFF_DYING;
+ found = 1;
+ break;
+ }
+#ifdef VIMAGE
+ curvnet->vnet_ifcnt--;
+#endif
+ IFNET_WUNLOCK();
+
+ return (found);
+}
+
static void
vnet_if_return(const void *unused __unused)
{
struct ifnet *ifp, *nifp;
+ struct ifnethead ifnets;
+ int found;
+ CK_STAILQ_INIT(&ifnets);
+
+ /*
+ * We need to protect our access to the V_ifnet tailq. Ordinarily we'd
+ * enter NET_EPOCH, but that's not possible, because if_vmove() calls
+ * if_detach_internal(), which waits for NET_EPOCH callbacks to
+ * complete. We can't do that from within NET_EPOCH.
+ *
+ * However, we can also use the IFNET_xLOCK, which is the V_ifnet
+ * read/write lock. We cannot hold the lock as we call if_vmove()
+ * though, as that presents LOR w.r.t ifnet_sx, in_multi_sx and iflib
+ * ctx lock.
+ */
+ IFNET_WLOCK();
/* Return all inherited interfaces to their parent vnets. */
CK_STAILQ_FOREACH_SAFE(ifp, &V_ifnet, if_link, nifp) {
- if (ifp->if_home_vnet != ifp->if_vnet)
- if_vmove(ifp, ifp->if_home_vnet);
+ if (ifp->if_home_vnet != ifp->if_vnet) {
+ found = if_unlink_ifnet(ifp, 1);
+ MPASS(found);
+
+ CK_STAILQ_INSERT_TAIL(&ifnets, ifp, if_link);
+ }
+ }
+ IFNET_WUNLOCK();
+
+ CK_STAILQ_FOREACH_SAFE(ifp, &ifnets, if_link, nifp) {
+ if_vmove(ifp, ifp->if_home_vnet);
}
}
VNET_SYSUNINIT(vnet_if_return, SI_SUB_VNET_DONE, SI_ORDER_ANY,
@@ -906,12 +968,7 @@
}
#endif
- IFNET_WLOCK();
- CK_STAILQ_INSERT_TAIL(&V_ifnet, ifp, if_link);
-#ifdef VIMAGE
- curvnet->vnet_ifcnt++;
-#endif
- IFNET_WUNLOCK();
+ if_link_ifnet(ifp);
if (domain_init_status >= 2)
if_attachdomain1(ifp);
@@ -1049,9 +1106,12 @@
void
if_detach(struct ifnet *ifp)
{
+ int found;
CURVNET_SET_QUIET(ifp->if_vnet);
- if_detach_internal(ifp, 0, NULL);
+ found = if_unlink_ifnet(ifp, 0);
+ if (found)
+ if_detach_internal(ifp, 0, NULL);
CURVNET_RESTORE();
}
@@ -1071,46 +1131,16 @@
struct ifaddr *ifa;
int i;
struct domain *dp;
- struct ifnet *iter;
- int found = 0;
#ifdef VIMAGE
bool shutdown;
shutdown = VNET_IS_SHUTTING_DOWN(ifp->if_vnet);
#endif
- IFNET_WLOCK();
- CK_STAILQ_FOREACH(iter, &V_ifnet, if_link)
- if (iter == ifp) {
- CK_STAILQ_REMOVE(&V_ifnet, ifp, ifnet, if_link);
- if (!vmove)
- ifp->if_flags |= IFF_DYING;
- found = 1;
- break;
- }
- IFNET_WUNLOCK();
- if (!found) {
- /*
- * While we would want to panic here, we cannot
- * guarantee that the interface is indeed still on
- * the list given we don't hold locks all the way.
- */
- return (ENOENT);
-#if 0
- if (vmove)
- panic("%s: ifp=%p not on the ifnet tailq %p",
- __func__, ifp, &V_ifnet);
- else
- return; /* XXX this should panic as well? */
-#endif
- }
/*
* At this point we know the interface still was on the ifnet list
* and we removed it so we are in a stable state.
*/
-#ifdef VIMAGE
- curvnet->vnet_ifcnt--;
-#endif
epoch_wait_preempt(net_epoch_preempt);
/*
@@ -1334,7 +1364,7 @@
{
struct prison *pr;
struct ifnet *difp;
- int error;
+ int error, found;
bool shutdown;
/* Try to find the prison within our visibility. */
@@ -1371,6 +1401,9 @@
}
CURVNET_RESTORE();
+ found = if_unlink_ifnet(ifp, 1);
+ MPASS(found);
+
/* Move the interface into the child jail/vnet. */
error = if_vmove(ifp, pr->pr_vnet);
@@ -1388,7 +1421,7 @@
struct prison *pr;
struct vnet *vnet_dst;
struct ifnet *ifp;
- int error;
+ int error, found;
bool shutdown;
/* Try to find the prison within our visibility. */
@@ -1426,6 +1459,8 @@
}
/* Get interface back from child jail/vnet. */
+ found = if_unlink_ifnet(ifp, 1);
+ MPASS(found);
error = if_vmove(ifp, vnet_dst);
CURVNET_RESTORE();

File Metadata

Mime Type
text/plain
Expires
Tue, Feb 11, 3:50 AM (4 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16588481
Default Alt Text
D27279.id79938.diff (4 KB)

Event Timeline