Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145013681
D28136.id89428.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D28136.id89428.diff
View Options
diff --git a/sys/dev/usb/net/if_usie.c b/sys/dev/usb/net/if_usie.c
--- a/sys/dev/usb/net/if_usie.c
+++ b/sys/dev/usb/net/if_usie.c
@@ -483,6 +483,7 @@
usbd_transfer_unsetup(sc->sc_if_xfer, USIE_IF_N_XFER);
bpfdetach(sc->sc_ifp);
if_detach(sc->sc_ifp);
+ if_ioctl_drain(sc->sc_ifp);
if_free(sc->sc_ifp);
sc->sc_ifp = NULL;
}
diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c
--- a/sys/dev/usb/net/uhso.c
+++ b/sys/dev/usb/net/uhso.c
@@ -693,8 +693,9 @@
uhso_if_stop(sc);
bpfdetach(sc->sc_ifp);
if_detach(sc->sc_ifp);
- if_free(sc->sc_ifp);
mtx_unlock(&sc->sc_mtx);
+ if_ioctl_drain(sc->sc_ifp);
+ if_free(sc->sc_ifp);
usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
}
diff --git a/sys/dev/usb/net/usb_ethernet.c b/sys/dev/usb/net/usb_ethernet.c
--- a/sys/dev/usb/net/usb_ethernet.c
+++ b/sys/dev/usb/net/usb_ethernet.c
@@ -292,6 +292,7 @@
/* free unit */
free_unr(ueunit, ue->ue_unit);
if (ue->ue_ifp != NULL) {
+ if_ioctl_drain(ue->ue_ifp);
if_free(ue->ue_ifp);
ue->ue_ifp = NULL;
}
@@ -311,6 +312,9 @@
ifp = ue->ue_ifp;
if (ifp != NULL) {
+ /* drain all IOCTLs */
+ if_ioctl_drain(ifp);
+
/* we are not running any more */
UE_LOCK(ue);
ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -232,6 +232,7 @@
USB_BUS_UNLOCK(ubus);
bpfdetach(ifp);
if_detach(ifp);
+ if_ioctl_drain(ifp);
if_free(ifp);
ifc_free_unit(ifc, unit);
diff --git a/sys/net/if.h b/sys/net/if.h
--- a/sys/net/if.h
+++ b/sys/net/if.h
@@ -163,6 +163,7 @@
#define IFF_DYING 0x200000 /* (n) interface is winding down */
#define IFF_RENAMING 0x400000 /* (n) interface is being renamed */
#define IFF_NOGROUP 0x800000 /* (n) interface is not part of any groups */
+#define IFF_IOCTL_DRAINED 0x1000000 /* (n) control path has been drained */
/*
* Old names for driver flags so that user space tools can continue to use
@@ -177,7 +178,7 @@
#define IFF_CANTCHANGE \
(IFF_BROADCAST|IFF_POINTOPOINT|IFF_DRV_RUNNING|IFF_DRV_OACTIVE|\
IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_PROMISC|\
- IFF_DYING|IFF_CANTCONFIG|IFF_KNOWSEPOCH)
+ IFF_DYING|IFF_CANTCONFIG|IFF_KNOWSEPOCH|IFF_IOCTL_DRAINED)
/*
* Values for if_link_state.
diff --git a/sys/net/if.c b/sys/net/if.c
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -325,6 +325,9 @@
SX_SYSINIT_FLAGS(ifnet_detach, &ifnet_detach_sxlock, "ifnet_detach_sx",
SX_RECURSE);
+static struct sx ifnet_ioctl_sxlock;
+SX_SYSINIT_FLAGS(ifnet_ioctl, &ifnet_ioctl_sxlock, "ifnet_ioctl_sx", SX_RECURSE);
+
/*
* The allocation of network interfaces is a rather non-atomic affair; we
* need to select an index before we are ready to expose the interface for
@@ -652,6 +655,7 @@
ifq_init(&ifp->if_snd, ifp);
refcount_init(&ifp->if_refcount, 1); /* Index reference. */
+
for (int i = 0; i < IFCOUNTERS; i++)
ifp->if_counters[i] = counter_u64_alloc(M_WAITOK);
ifp->if_get_counter = if_get_counter_default;
@@ -769,6 +773,39 @@
NET_EPOCH_CALL(if_destroy, &ifp->if_epoch_ctx);
}
+/*
+ * Keep track of if_ioctl configuration events.
+ * Returns true on success and false on failure.
+ */
+bool
+if_ioctl_ref(struct ifnet *ifp)
+{
+ bool retval;
+
+ if (ifp->if_flags & IFF_IOCTL_DRAINED)
+ return (false);
+
+ sx_slock(&ifnet_ioctl_sxlock);
+ retval = (ifp->if_flags & IFF_IOCTL_DRAINED) == 0;
+ if (!retval)
+ sx_sunlock(&ifnet_ioctl_sxlock);
+ return (retval);
+}
+
+void
+if_ioctl_drain(struct ifnet *ifp)
+{
+ sx_xlock(&ifnet_ioctl_sxlock);
+ ifp->if_flags |= IFF_IOCTL_DRAINED;
+ sx_xunlock(&ifnet_ioctl_sxlock);
+}
+
+void
+if_ioctl_unref(struct ifnet *ifp)
+{
+ sx_sunlock(&ifnet_ioctl_sxlock);
+}
+
void
ifq_init(struct ifaltq *ifq, struct ifnet *ifp)
{
@@ -2458,8 +2495,8 @@
/*
* Hardware specific interface ioctls.
*/
-int
-ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
+static inline int
+ifhwioctl_sub(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
{
struct ifreq *ifr;
int error = 0, do_ifup = 0;
@@ -2883,6 +2920,18 @@
return (error);
}
+int
+ifhwioctl(u_long cmd, struct ifnet *ifp, caddr_t data, struct thread *td)
+{
+ int error;
+
+ if (if_ioctl_ref(ifp) == false)
+ return (ENXIO);
+ error = ifhwioctl_sub(cmd, ifp, data, td);
+ if_ioctl_unref(ifp);
+ return (error);
+}
+
/*
* Interface ioctls.
*/
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -663,6 +663,9 @@
void if_ref(struct ifnet *);
void if_rele(struct ifnet *);
bool __result_use_check if_try_ref(struct ifnet *);
+bool __result_use_check if_ioctl_ref(struct ifnet *);
+void if_ioctl_drain(struct ifnet *);
+void if_ioctl_unref(struct ifnet *);
int if_setlladdr(struct ifnet *, const u_char *, int);
int if_tunnel_check_nesting(struct ifnet *, struct mbuf *, uint32_t, int);
void if_up(struct ifnet *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 16, 1:32 AM (1 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28763045
Default Alt Text
D28136.id89428.diff (4 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