Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F116025599
D28136.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D28136.diff
View Options
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -126,6 +126,7 @@
#include <sys/kernel.h>
#include <sys/khelp.h>
#include <sys/ktls.h>
+#include <sys/epoch.h>
#include <sys/event.h>
#include <sys/eventhandler.h>
#include <sys/poll.h>
@@ -2983,8 +2984,8 @@
return (sosetopt(so, &sopt));
}
-int
-sosetopt(struct socket *so, struct sockopt *sopt)
+static inline int
+sosetopt_locked(struct socket *so, struct sockopt *sopt)
{
int error, optval;
struct linger l;
@@ -2995,7 +2996,6 @@
struct mac extmac;
#endif
- CURVNET_SET(so->so_vnet);
error = 0;
if (sopt->sopt_level != SOL_SOCKET) {
if (so->so_proto->pr_ctloutput != NULL)
@@ -3182,10 +3182,24 @@
(void)(*so->so_proto->pr_ctloutput)(so, sopt);
}
bad:
- CURVNET_RESTORE();
return (error);
}
+int
+sosetopt(struct socket *so, struct sockopt *sopt)
+{
+ struct epoch_tracker et;
+ int retval;
+
+ epoch_enter_sleepable(net_epoch_sleepable, &et);
+ CURVNET_SET(so->so_vnet);
+ retval = sosetopt_locked(so, sopt);
+ CURVNET_RESTORE();
+ epoch_exit_sleepable(net_epoch_sleepable, &et);
+
+ return (retval);
+}
+
/*
* Helper routine for getsockopt.
*/
@@ -3216,8 +3230,8 @@
return (error);
}
-int
-sogetopt(struct socket *so, struct sockopt *sopt)
+static inline int
+sogetopt_locked(struct socket *so, struct sockopt *sopt)
{
int error, optval;
struct linger l;
@@ -3226,14 +3240,12 @@
struct mac extmac;
#endif
- CURVNET_SET(so->so_vnet);
error = 0;
if (sopt->sopt_level != SOL_SOCKET) {
if (so->so_proto->pr_ctloutput != NULL)
error = (*so->so_proto->pr_ctloutput)(so, sopt);
else
error = ENOPROTOOPT;
- CURVNET_RESTORE();
return (error);
} else {
switch (sopt->sopt_name) {
@@ -3388,10 +3400,24 @@
#ifdef MAC
bad:
#endif
- CURVNET_RESTORE();
return (error);
}
+int
+sogetopt(struct socket *so, struct sockopt *sopt)
+{
+ struct epoch_tracker et;
+ int retval;
+
+ epoch_enter_sleepable(net_epoch_sleepable, &et);
+ CURVNET_SET(so->so_vnet);
+ retval = sogetopt_locked(so, sopt);
+ CURVNET_RESTORE();
+ epoch_exit_sleepable(net_epoch_sleepable, &et);
+
+ return (retval);
+}
+
int
soopt_getm(struct sockopt *sopt, struct mbuf **mp)
{
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();
@@ -2891,8 +2911,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 {
@@ -3116,6 +3136,30 @@
return (error);
}
+int
+ifioctl(struct socket *so, u_long cmd, caddr_t data, struct thread *td)
+{
+ struct epoch_tracker et;
+ int retval;
+
+ switch (cmd) {
+#ifdef VIMAGE
+ case SIOCSIFRVNET:
+#endif
+ case SIOCIFCREATE:
+ case SIOCIFCREATE2:
+ case SIOCIFDESTROY:
+ retval = ifioctl_locked(so, cmd, data, td);
+ break;
+ default:
+ epoch_enter_sleepable(net_epoch_sleepable, &et);
+ retval = ifioctl_locked(so, cmd, data, td);
+ epoch_exit_sleepable(net_epoch_sleepable, &et);
+ break;
+ }
+ 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
Details
Attached
Mime Type
text/plain
Expires
Fri, May 2, 6:40 PM (13 h, 42 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17910170
Default Alt Text
D28136.diff (5 KB)
Attached To
Mode
D28136: Make sure user-space calls are drained when detaching network interfaces.
Attached
Detach File
Event Timeline
Log In to Comment