Page MenuHomeFreeBSD

D28136.id89585.diff
No OneTemporary

D28136.id89585.diff

diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -110,6 +110,8 @@
offsetof(struct ifreq, ifr_ifru), "gap between ifr_name and ifr_ifru");
__read_mostly epoch_t net_epoch_preempt;
+__read_mostly epoch_t net_epoch_sleepable;
+
#ifdef COMPAT_FREEBSD32
#include <sys/mount.h>
#include <compat/freebsd32/freebsd32.h>
@@ -283,6 +285,7 @@
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 void if_wait_sleepable(void);
static bool if_unlink_ifnet(struct ifnet *, bool);
#ifdef VIMAGE
static int if_vmove(struct ifnet *, struct vnet *);
@@ -494,6 +497,13 @@
IFNET_WUNLOCK();
}
+static void
+if_wait_sleepable(void)
+{
+ /* Wait for pending user-space calls to complete. */
+ epoch_wait_sleepable(net_epoch_sleepable);
+}
+
static bool
if_unlink_ifnet(struct ifnet *ifp, bool vmove)
{
@@ -554,6 +564,8 @@
}
IFNET_WUNLOCK();
+ if_wait_sleepable();
+
for (int j = 0; j < i; j++) {
if_vmove(pending[j], pending[j]->if_home_vnet);
}
@@ -1015,6 +1027,7 @@
{
net_epoch_preempt = epoch_alloc("Net preemptible", EPOCH_PREEMPT);
+ net_epoch_sleepable = epoch_alloc("Net sleepable", EPOCH_SLEEPABLE);
}
SYSINIT(ifepochalloc, SI_SUB_EPOCH, SI_ORDER_ANY, if_epochalloc, NULL);
@@ -1140,6 +1153,8 @@
CURVNET_SET_QUIET(ifp->if_vnet);
found = if_unlink_ifnet(ifp, false);
if (found) {
+ if_wait_sleepable();
+
sx_xlock(&ifnet_detach_sxlock);
if_detach_internal(ifp, 0, NULL);
sx_xunlock(&ifnet_detach_sxlock);
@@ -1437,6 +1452,8 @@
found = if_unlink_ifnet(ifp, true);
MPASS(found);
+ if_wait_sleepable();
+
/* Move the interface into the child jail/vnet. */
error = if_vmove(ifp, pr->pr_vnet);
@@ -1494,6 +1511,9 @@
/* Get interface back from child jail/vnet. */
found = if_unlink_ifnet(ifp, true);
MPASS(found);
+
+ if_wait_sleepable();
+
error = if_vmove(ifp, vnet_dst);
CURVNET_RESTORE();
@@ -2886,8 +2906,8 @@
/*
* Interface ioctls.
*/
-int
-ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
+static inline int
+ifioctl_locked(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
{
#ifdef COMPAT_FREEBSD32
union {
@@ -3111,6 +3131,19 @@
return (error);
}
+int
+ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
+{
+ struct epoch_tracker et;
+ int retval;
+
+ epoch_enter_sleepable(net_epoch_sleepable, &et);
+ retval = ifioctl_locked(so, cmd, data, td);
+ epoch_exit_sleepable(net_epoch_sleepable, &et);
+
+ return (retval);
+}
+
/*
* The code common to handling reference counted flags,
* e.g., in ifpromisc() and if_allmulti().
diff --git a/sys/sys/epoch.h b/sys/sys/epoch.h
--- a/sys/sys/epoch.h
+++ b/sys/sys/epoch.h
@@ -115,8 +115,10 @@
/*
* Globally recognized epochs in the FreeBSD kernel.
*/
-/* Network preemptible epoch, declared in sys/net/if.c. */
+
+/* Network epochs, declared in sys/net/if.c. */
extern epoch_t net_epoch_preempt;
+extern epoch_t net_epoch_sleepable;
#define NET_EPOCH_ENTER(et) epoch_enter_preempt(net_epoch_preempt, &(et))
#define NET_EPOCH_EXIT(et) epoch_exit_preempt(net_epoch_preempt, &(et))
#define NET_EPOCH_WAIT() epoch_wait_preempt(net_epoch_preempt)

File Metadata

Mime Type
text/plain
Expires
Tue, Mar 24, 8:06 PM (20 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
30269154
Default Alt Text
D28136.id89585.diff (3 KB)

Event Timeline