diff options
author | rwatson <rwatson@FreeBSD.org> | 2009-08-23 20:40:19 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2009-08-23 20:40:19 +0000 |
commit | ef8d755d4df716bf13f8a1833f7dd1db0b78c569 (patch) | |
tree | 83b839696bd918acacee8b38993abd3c6857a5fb /sys/compat/linux/linux_ioctl.c | |
parent | 3d8e6186e2a82569f4f5214f8c8af700e5e36c13 (diff) | |
download | FreeBSD-src-ef8d755d4df716bf13f8a1833f7dd1db0b78c569.zip FreeBSD-src-ef8d755d4df716bf13f8a1833f7dd1db0b78c569.tar.gz |
Rework global locks for interface list and index management, correcting
several critical bugs, including race conditions and lock order issues:
Replace the single rwlock, ifnet_lock, with two locks, an rwlock and an
sxlock. Either can be held to stablize the lists and indexes, but both
are required to write. This allows the list to be held stable in both
network interrupt contexts and sleepable user threads across sleeping
memory allocations or device driver interactions. As before, writes to
the interface list must occur from sleepable contexts.
Reviewed by: bz, julian
MFC after: 3 days
Diffstat (limited to 'sys/compat/linux/linux_ioctl.c')
-rw-r--r-- | sys/compat/linux/linux_ioctl.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c index 11dc6d5..03ac334 100644 --- a/sys/compat/linux/linux_ioctl.c +++ b/sys/compat/linux/linux_ioctl.c @@ -2061,22 +2061,20 @@ linux_ifname(struct ifnet *ifp, char *buffer, size_t buflen) struct ifnet *ifscan; int ethno; + IFNET_RLOCK_ASSERT(); + /* Short-circuit non ethernet interfaces */ if (!IFP_IS_ETH(ifp)) return (strlcpy(buffer, ifp->if_xname, buflen)); /* Determine the (relative) unit number for ethernet interfaces */ ethno = 0; - IFNET_RLOCK(); TAILQ_FOREACH(ifscan, &V_ifnet, if_link) { - if (ifscan == ifp) { - IFNET_RUNLOCK(); + if (ifscan == ifp) return (snprintf(buffer, buflen, "eth%d", ethno)); - } if (IFP_IS_ETH(ifscan)) ethno++; } - IFNET_RUNLOCK(); return (0); } @@ -2177,7 +2175,7 @@ again: valid_len = 0; /* Return all AF_INET addresses of all interfaces */ - IFNET_RLOCK(); /* could sleep XXX */ + IFNET_RLOCK(); TAILQ_FOREACH(ifp, &V_ifnet, if_link) { int addrs = 0; |