Page MenuHomeFreeBSD

D34704.diff
No OneTemporary

D34704.diff

diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -513,7 +513,9 @@
IFNET_WUNLOCK();
for (int j = 0; j < i; j++) {
+ sx_xlock(&ifnet_detach_sxlock);
if_vmove(pending[j], pending[j]->if_home_vnet);
+ sx_xunlock(&ifnet_detach_sxlock);
}
free(pending, M_IFNET);
@@ -1312,6 +1314,8 @@
bool found __diagused;
bool shutdown;
+ MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp);
+
/* Try to find the prison within our visibility. */
sx_slock(&allprison_lock);
pr = prison_find_child(td->td_ucred->cr_prison, jid);
@@ -1336,10 +1340,12 @@
prison_free(pr);
return (EEXIST);
}
+ sx_xlock(&ifnet_detach_sxlock);
/* Make sure the VNET is stable. */
shutdown = VNET_IS_SHUTTING_DOWN(ifp->if_vnet);
if (shutdown) {
+ sx_xunlock(&ifnet_detach_sxlock);
CURVNET_RESTORE();
prison_free(pr);
return (EBUSY);
@@ -1347,7 +1353,12 @@
CURVNET_RESTORE();
found = if_unlink_ifnet(ifp, true);
- MPASS(found);
+ if (! found) {
+ sx_xunlock(&ifnet_detach_sxlock);
+ CURVNET_RESTORE();
+ prison_free(pr);
+ return (ENODEV);
+ }
/* Move the interface into the child jail/vnet. */
error = if_vmove(ifp, pr->pr_vnet);
@@ -1356,6 +1367,8 @@
if (error == 0)
sprintf(ifname, "%s", ifp->if_xname);
+ sx_xunlock(&ifnet_detach_sxlock);
+
prison_free(pr);
return (error);
}
@@ -1406,7 +1419,9 @@
/* Get interface back from child jail/vnet. */
found = if_unlink_ifnet(ifp, true);
MPASS(found);
+ sx_xlock(&ifnet_detach_sxlock);
error = if_vmove(ifp, vnet_dst);
+ sx_xunlock(&ifnet_detach_sxlock);
CURVNET_RESTORE();
/* Report the new if_xname back to the userland on success. */
@@ -2283,8 +2298,11 @@
!(ifp->if_flags & IFF_DYING))
break;
}
- if (ifp != NULL)
+ if (ifp != NULL) {
if_ref(ifp);
+ MPASS(ifindex_table[ifp->if_index].ife_ifnet == ifp);
+ }
+
NET_EPOCH_EXIT(et);
return (ifp);
}
diff --git a/tests/sys/net/if_clone_test.sh b/tests/sys/net/if_clone_test.sh
--- a/tests/sys/net/if_clone_test.sh
+++ b/tests/sys/net/if_clone_test.sh
@@ -69,6 +69,34 @@
cleanup_ifaces
}
+atf_test_case epair_destroy_race cleanup
+epair_destroy_race_head()
+{
+ atf_set "descr" "Race if_detach() and if_vmove()"
+ atf_set "require.user" "root"
+}
+epair_destroy_race_body()
+{
+ for i in `seq 1 10`
+ do
+ epair_a=$(ifconfig epair create)
+ echo $epair_a >> devices_to_cleanup
+ epair_b=${epair_a%a}b
+
+ jail -c vnet name="epair_destroy" nopersist path=/ \
+ host.hostname="epair_destroy" vnet.interface="$epair_b" \
+ command=sh -c "ifconfig $epair_b 192.0.2.1/24; sleep 0.1"&
+ pid=$!
+ ifconfig "$epair_a" destroy
+ wait $pid
+ done
+ true
+}
+epair_destroy_race_cleanup()
+{
+ cleanup_ifaces
+}
+
atf_test_case epair_ipv6_up_stress cleanup
epair_ipv6_up_stress_head()
{
@@ -405,6 +433,7 @@
atf_add_test_case epair_ipv6_up_stress
atf_add_test_case epair_stress
atf_add_test_case epair_up_stress
+ atf_add_test_case epair_destroy_race
atf_add_test_case faith_ipv6_up_stress
atf_add_test_case faith_stress
atf_add_test_case faith_up_stress

File Metadata

Mime Type
text/plain
Expires
Tue, Jan 28, 4:41 AM (9 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16248992
Default Alt Text
D34704.diff (3 KB)

Event Timeline