From owner-svn-src-stable-7@FreeBSD.ORG Tue Oct 12 16:09:09 2010 Return-Path: Delivered-To: svn-src-stable-7@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 2F3801065675; Tue, 12 Oct 2010 16:09:09 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 1BE528FC08; Tue, 12 Oct 2010 16:09:09 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o9CG997L052845; Tue, 12 Oct 2010 16:09:09 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o9CG99aX052842; Tue, 12 Oct 2010 16:09:09 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <201010121609.o9CG99aX052842@svn.freebsd.org> From: John Baldwin Date: Tue, 12 Oct 2010 16:09:09 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org X-SVN-Group: stable-7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r213727 - stable/7/sys/net X-BeenThere: svn-src-stable-7@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 7-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Oct 2010 16:09:09 -0000 Author: jhb Date: Tue Oct 12 16:09:08 2010 New Revision: 213727 URL: http://svn.freebsd.org/changeset/base/213727 Log: MFC 213028,213328: - Expand scope of tun/tap softc locks to cover more softc fields and driver-maintained ifnet fields (such as if_drv_flags). - Use soft locks as the mutex that protects each interface's knote list rather than using the global knote list lock. Also, use the softc for kn_hook instead of the cdev. - Use mtx_sleep() instead of tsleep() when blocking in the read routines. This fixes a lost wakeup race. - Remove D_NEEDGIANT now that the cdevsw routines use the softc lock where locking is needed. - Lock IFQ when calculating the result for FIONREAD in tap(4). tun(4) already did this. - Remove remaining spl calls. Modified: stable/7/sys/net/if_tap.c stable/7/sys/net/if_tun.c Directory Properties: stable/7/sys/ (props changed) stable/7/sys/cddl/contrib/opensolaris/ (props changed) stable/7/sys/contrib/dev/acpica/ (props changed) stable/7/sys/contrib/pf/ (props changed) Modified: stable/7/sys/net/if_tap.c ============================================================================== --- stable/7/sys/net/if_tap.c Tue Oct 12 16:08:20 2010 (r213726) +++ stable/7/sys/net/if_tap.c Tue Oct 12 16:09:08 2010 (r213727) @@ -132,7 +132,7 @@ static struct filterops tap_write_filter static struct cdevsw tap_cdevsw = { .d_version = D_VERSION, - .d_flags = D_PSEUDO | D_NEEDGIANT, + .d_flags = D_PSEUDO, .d_open = tapopen, .d_close = tapclose, .d_read = tapread, @@ -209,7 +209,6 @@ static void tap_destroy(struct tap_softc *tp) { struct ifnet *ifp = tp->tap_ifp; - int s; /* Unlocked read. */ KASSERT(!(tp->tap_flags & TAP_OPEN), @@ -217,10 +216,8 @@ tap_destroy(struct tap_softc *tp) knlist_destroy(&tp->tap_rsel.si_note); destroy_dev(tp->tap_dev); - s = splimp(); ether_ifdetach(ifp); if_free_type(ifp, IFT_ETHER); - splx(s); mtx_destroy(&tp->tap_mtx); free(tp, M_TAP); @@ -399,7 +396,7 @@ tapcreate(struct cdev *dev) struct tap_softc *tp = NULL; unsigned short macaddr_hi; uint32_t macaddr_mid; - int unit, s; + int unit; char *name = NULL; u_char eaddr[6]; @@ -443,20 +440,18 @@ tapcreate(struct cdev *dev) ifp->if_ioctl = tapifioctl; ifp->if_mtu = ETHERMTU; ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST); - ifp->if_snd.ifq_maxlen = ifqmaxlen; + IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); dev->si_drv1 = tp; tp->tap_dev = dev; - s = splimp(); ether_ifattach(ifp, eaddr); - splx(s); mtx_lock(&tp->tap_mtx); tp->tap_flags |= TAP_INITED; mtx_unlock(&tp->tap_mtx); - knlist_init_mtx(&tp->tap_rsel.si_note, NULL); + knlist_init_mtx(&tp->tap_rsel.si_note, &tp->tap_mtx); TAPDEBUG("interface %s is created. minor = %#x\n", ifp->if_xname, minor(dev)); @@ -473,7 +468,7 @@ tapopen(struct cdev *dev, int flag, int { struct tap_softc *tp = NULL; struct ifnet *ifp = NULL; - int error, s; + int error; if (tapuopen == 0) { error = priv_check(td, PRIV_NET_TAP); @@ -496,14 +491,12 @@ tapopen(struct cdev *dev, int flag, int tp->tap_pid = td->td_proc->p_pid; tp->tap_flags |= TAP_OPEN; ifp = tp->tap_ifp; - mtx_unlock(&tp->tap_mtx); - s = splimp(); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; if (tapuponopen) ifp->if_flags |= IFF_UP; - splx(s); + mtx_unlock(&tp->tap_mtx); TAPDEBUG("%s is open. minor = %#x\n", ifp->if_xname, minor(dev)); @@ -522,9 +515,9 @@ tapclose(struct cdev *dev, int foo, int struct ifaddr *ifa; struct tap_softc *tp = dev->si_drv1; struct ifnet *ifp = tp->tap_ifp; - int s; /* junk all pending output */ + mtx_lock(&tp->tap_mtx); IF_DRAIN(&ifp->if_snd); /* @@ -532,27 +525,25 @@ tapclose(struct cdev *dev, int foo, int * interface, if we are in VMnet mode. just close the device. */ - mtx_lock(&tp->tap_mtx); if (((tp->tap_flags & TAP_VMNET) == 0) && (ifp->if_flags & IFF_UP)) { mtx_unlock(&tp->tap_mtx); - s = splimp(); if_down(ifp); + mtx_lock(&tp->tap_mtx); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + mtx_unlock(&tp->tap_mtx); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { rtinit(ifa, (int)RTM_DELETE, 0); } if_purgeaddrs(ifp); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + mtx_lock(&tp->tap_mtx); } - splx(s); - } else - mtx_unlock(&tp->tap_mtx); + } funsetown(&tp->tap_sigio); selwakeuppri(&tp->tap_rsel, PZERO+1); - KNOTE_UNLOCKED(&tp->tap_rsel.si_note, 0); + KNOTE_LOCKED(&tp->tap_rsel.si_note, 0); - mtx_lock(&tp->tap_mtx); tp->tap_flags &= ~TAP_OPEN; tp->tap_pid = 0; mtx_unlock(&tp->tap_mtx); @@ -577,8 +568,10 @@ tapifinit(void *xtp) TAPDEBUG("initializing %s\n", ifp->if_xname); + mtx_lock(&tp->tap_mtx); ifp->if_drv_flags |= IFF_DRV_RUNNING; ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + mtx_unlock(&tp->tap_mtx); /* attempt to start output */ tapifstart(ifp); @@ -596,7 +589,7 @@ tapifioctl(struct ifnet *ifp, u_long cmd struct tap_softc *tp = ifp->if_softc; struct ifreq *ifr = (struct ifreq *)data; struct ifstat *ifs = NULL; - int s, dummy; + int dummy; switch (cmd) { case SIOCSIFFLAGS: /* XXX -- just like vmnet does */ @@ -609,7 +602,6 @@ tapifioctl(struct ifnet *ifp, u_long cmd break; case SIOCGIFSTATUS: - s = splimp(); ifs = (struct ifstat *)data; dummy = strlen(ifs->ascii); mtx_lock(&tp->tap_mtx); @@ -618,14 +610,10 @@ tapifioctl(struct ifnet *ifp, u_long cmd sizeof(ifs->ascii) - dummy, "\tOpened by PID %d\n", tp->tap_pid); mtx_unlock(&tp->tap_mtx); - splx(s); break; default: - s = splimp(); - dummy = ether_ioctl(ifp, cmd, data); - splx(s); - return (dummy); + return (ether_ioctl(ifp, cmd, data)); /* NOT REACHED */ } @@ -642,7 +630,6 @@ static void tapifstart(struct ifnet *ifp) { struct tap_softc *tp = ifp->if_softc; - int s; TAPDEBUG("%s starting\n", ifp->if_xname); @@ -654,32 +641,28 @@ tapifstart(struct ifnet *ifp) mtx_lock(&tp->tap_mtx); if (((tp->tap_flags & TAP_VMNET) == 0) && ((tp->tap_flags & TAP_READY) != TAP_READY)) { - struct mbuf *m = NULL; - - mtx_unlock(&tp->tap_mtx); + struct mbuf *m; /* Unlocked read. */ TAPDEBUG("%s not ready, tap_flags = 0x%x\n", ifp->if_xname, tp->tap_flags); - s = splimp(); - do { + for (;;) { IF_DEQUEUE(&ifp->if_snd, m); - if (m != NULL) + if (m != NULL) { m_freem(m); - ifp->if_oerrors ++; - } while (m != NULL); - splx(s); + ifp->if_oerrors++; + } else + break; + } + mtx_unlock(&tp->tap_mtx); return; } - mtx_unlock(&tp->tap_mtx); - s = splimp(); ifp->if_drv_flags |= IFF_DRV_OACTIVE; - if (ifp->if_snd.ifq_len != 0) { - mtx_lock(&tp->tap_mtx); + if (!IFQ_IS_EMPTY(&ifp->if_snd)) { if (tp->tap_flags & TAP_RWAIT) { tp->tap_flags &= ~TAP_RWAIT; wakeup(tp); @@ -688,16 +671,16 @@ tapifstart(struct ifnet *ifp) if ((tp->tap_flags & TAP_ASYNC) && (tp->tap_sigio != NULL)) { mtx_unlock(&tp->tap_mtx); pgsigio(&tp->tap_sigio, SIGIO, 0); - } else - mtx_unlock(&tp->tap_mtx); + mtx_lock(&tp->tap_mtx); + } selwakeuppri(&tp->tap_rsel, PZERO+1); - KNOTE_UNLOCKED(&tp->tap_rsel.si_note, 0); + KNOTE_LOCKED(&tp->tap_rsel.si_note, 0); ifp->if_opackets ++; /* obytes are counted in ether_output */ } ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; - splx(s); + mtx_unlock(&tp->tap_mtx); } /* tapifstart */ @@ -712,7 +695,6 @@ tapioctl(struct cdev *dev, u_long cmd, c struct tap_softc *tp = dev->si_drv1; struct ifnet *ifp = tp->tap_ifp; struct tapinfo *tapp = NULL; - int s; int f; #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) @@ -721,19 +703,21 @@ tapioctl(struct cdev *dev, u_long cmd, c switch (cmd) { case TAPSIFINFO: - s = splimp(); tapp = (struct tapinfo *)data; + mtx_lock(&tp->tap_mtx); ifp->if_mtu = tapp->mtu; ifp->if_type = tapp->type; ifp->if_baudrate = tapp->baudrate; - splx(s); + mtx_unlock(&tp->tap_mtx); break; case TAPGIFINFO: tapp = (struct tapinfo *)data; + mtx_lock(&tp->tap_mtx); tapp->mtu = ifp->if_mtu; tapp->type = ifp->if_type; tapp->baudrate = ifp->if_baudrate; + mtx_unlock(&tp->tap_mtx); break; case TAPSDEBUG: @@ -754,26 +738,26 @@ tapioctl(struct cdev *dev, u_long cmd, c break; case FIOASYNC: - s = splimp(); mtx_lock(&tp->tap_mtx); if (*(int *)data) tp->tap_flags |= TAP_ASYNC; else tp->tap_flags &= ~TAP_ASYNC; mtx_unlock(&tp->tap_mtx); - splx(s); break; case FIONREAD: - s = splimp(); - if (ifp->if_snd.ifq_head) { - struct mbuf *mb = ifp->if_snd.ifq_head; + if (!IFQ_IS_EMPTY(&ifp->if_snd)) { + struct mbuf *mb; - for(*(int *)data = 0;mb != NULL;mb = mb->m_next) + IFQ_LOCK(&ifp->if_snd); + IFQ_POLL_NOLOCK(&ifp->if_snd, mb); + for (*(int *)data = 0; mb != NULL; + mb = mb->m_next) *(int *)data += mb->m_len; + IFQ_UNLOCK(&ifp->if_snd); } else *(int *)data = 0; - splx(s); break; case FIOSETOWN: @@ -794,10 +778,6 @@ tapioctl(struct cdev *dev, u_long cmd, c /* VMware/VMnet port ioctl's */ - case SIOCGIFFLAGS: /* get ifnet flags */ - bcopy(&ifp->if_flags, data, sizeof(ifp->if_flags)); - break; - #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ defined(COMPAT_FREEBSD4) case _IO('V', 0): @@ -811,9 +791,9 @@ tapioctl(struct cdev *dev, u_long cmd, c f &= ~IFF_CANTCHANGE; f |= IFF_UP; - s = splimp(); + mtx_lock(&tp->tap_mtx); ifp->if_flags = f | (ifp->if_flags & IFF_CANTCHANGE); - splx(s); + mtx_unlock(&tp->tap_mtx); break; case OSIOCGIFADDR: /* get MAC address of the remote side */ @@ -848,7 +828,7 @@ tapread(struct cdev *dev, struct uio *ui struct tap_softc *tp = dev->si_drv1; struct ifnet *ifp = tp->tap_ifp; struct mbuf *m = NULL; - int error = 0, len, s; + int error = 0, len; TAPDEBUG("%s reading, minor = %#x\n", ifp->if_xname, minor(dev)); @@ -864,26 +844,27 @@ tapread(struct cdev *dev, struct uio *ui } tp->tap_flags &= ~TAP_RWAIT; - mtx_unlock(&tp->tap_mtx); /* sleep until we get a packet */ do { - s = splimp(); IF_DEQUEUE(&ifp->if_snd, m); - splx(s); if (m == NULL) { - if (flag & O_NONBLOCK) + if (flag & O_NONBLOCK) { + mtx_unlock(&tp->tap_mtx); return (EWOULDBLOCK); + } - mtx_lock(&tp->tap_mtx); tp->tap_flags |= TAP_RWAIT; - mtx_unlock(&tp->tap_mtx); - error = tsleep(tp,PCATCH|(PZERO+1),"taprd",0); - if (error) + error = mtx_sleep(tp, &tp->tap_mtx, PCATCH | (PZERO + 1), + "taprd", 0); + if (error) { + mtx_unlock(&tp->tap_mtx); return (error); + } } } while (m == NULL); + mtx_unlock(&tp->tap_mtx); /* feed packet to bpf */ BPF_MTAP(ifp, m); @@ -979,14 +960,14 @@ tappoll(struct cdev *dev, int events, st { struct tap_softc *tp = dev->si_drv1; struct ifnet *ifp = tp->tap_ifp; - int s, revents = 0; + int revents = 0; TAPDEBUG("%s polling, minor = %#x\n", ifp->if_xname, minor(dev)); - s = splimp(); if (events & (POLLIN | POLLRDNORM)) { - if (ifp->if_snd.ifq_len > 0) { + IFQ_LOCK(&ifp->if_snd); + if (!IFQ_IS_EMPTY(&ifp->if_snd)) { TAPDEBUG("%s have data in queue. len = %d, " \ "minor = %#x\n", ifp->if_xname, ifp->if_snd.ifq_len, minor(dev)); @@ -998,12 +979,12 @@ tappoll(struct cdev *dev, int events, st selrecord(td, &tp->tap_rsel); } + IFQ_UNLOCK(&ifp->if_snd); } if (events & (POLLOUT | POLLWRNORM)) revents |= (events & (POLLOUT | POLLWRNORM)); - splx(s); return (revents); } /* tappoll */ @@ -1016,11 +997,9 @@ tappoll(struct cdev *dev, int events, st static int tapkqfilter(struct cdev *dev, struct knote *kn) { - int s; struct tap_softc *tp = dev->si_drv1; struct ifnet *ifp = tp->tap_ifp; - s = splimp(); switch (kn->kn_filter) { case EVFILT_READ: TAPDEBUG("%s kqfilter: EVFILT_READ, minor = %#x\n", @@ -1037,13 +1016,11 @@ tapkqfilter(struct cdev *dev, struct kno default: TAPDEBUG("%s kqfilter: invalid filter, minor = %#x\n", ifp->if_xname, minor(dev)); - splx(s); return (EINVAL); /* NOT REACHED */ } - splx(s); - kn->kn_hook = (caddr_t) dev; + kn->kn_hook = tp; knlist_add(&tp->tap_rsel.si_note, kn, 0); return (0); @@ -1058,12 +1035,11 @@ tapkqfilter(struct cdev *dev, struct kno static int tapkqread(struct knote *kn, long hint) { - int ret, s; - struct cdev *dev = (struct cdev *)(kn->kn_hook); - struct tap_softc *tp = dev->si_drv1; + int ret; + struct tap_softc *tp = kn->kn_hook; + struct cdev *dev = tp->tap_dev; struct ifnet *ifp = tp->tap_ifp; - s = splimp(); if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { TAPDEBUG("%s have data in queue. len = %d, minor = %#x\n", ifp->if_xname, ifp->if_snd.ifq_len, minor(dev)); @@ -1073,7 +1049,6 @@ tapkqread(struct knote *kn, long hint) ifp->if_xname, minor(dev)); ret = 0; } - splx(s); return (ret); } /* tapkqread */ @@ -1087,13 +1062,10 @@ tapkqread(struct knote *kn, long hint) static int tapkqwrite(struct knote *kn, long hint) { - int s; - struct tap_softc *tp = ((struct cdev *) kn->kn_hook)->si_drv1; + struct tap_softc *tp = kn->kn_hook; struct ifnet *ifp = tp->tap_ifp; - s = splimp(); kn->kn_data = ifp->if_mtu; - splx(s); return (1); } /* tapkqwrite */ @@ -1102,7 +1074,7 @@ tapkqwrite(struct knote *kn, long hint) static void tapkqdetach(struct knote *kn) { - struct tap_softc *tp = ((struct cdev *) kn->kn_hook)->si_drv1; + struct tap_softc *tp = kn->kn_hook; knlist_remove(&tp->tap_rsel.si_note, kn, 0); } /* tapkqdetach */ Modified: stable/7/sys/net/if_tun.c ============================================================================== --- stable/7/sys/net/if_tun.c Tue Oct 12 16:08:20 2010 (r213726) +++ stable/7/sys/net/if_tun.c Tue Oct 12 16:09:08 2010 (r213727) @@ -162,7 +162,7 @@ static struct filterops tun_write_filter static struct cdevsw tun_cdevsw = { .d_version = D_VERSION, - .d_flags = D_PSEUDO | D_NEEDGIANT, + .d_flags = D_PSEUDO, .d_open = tunopen, .d_close = tunclose, .d_read = tunread, @@ -333,13 +333,13 @@ tunstart(struct ifnet *ifp) tp->tun_flags &= ~TUN_RWAIT; wakeup(tp); } + selwakeuppri(&tp->tun_rsel, PZERO + 1); + KNOTE_LOCKED(&tp->tun_rsel.si_note, 0); if (tp->tun_flags & TUN_ASYNC && tp->tun_sigio) { mtx_unlock(&tp->tun_mtx); pgsigio(&tp->tun_sigio, SIGIO, 0); } else mtx_unlock(&tp->tun_mtx); - selwakeuppri(&tp->tun_rsel, PZERO + 1); - KNOTE_UNLOCKED(&tp->tun_rsel.si_note, 0); } /* XXX: should return an error code so it can fail. */ @@ -373,7 +373,7 @@ tuncreate(const char *name, struct cdev IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen); ifp->if_snd.ifq_drv_maxlen = 0; IFQ_SET_READY(&ifp->if_snd); - knlist_init_mtx(&sc->tun_rsel.si_note, NULL); + knlist_init_mtx(&sc->tun_rsel.si_note, &sc->tun_mtx); if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(u_int32_t)); @@ -412,9 +412,9 @@ tunopen(struct cdev *dev, int flag, int tp->tun_pid = td->td_proc->p_pid; tp->tun_flags |= TUN_OPEN; - mtx_unlock(&tp->tun_mtx); ifp = TUN2IFP(tp); TUNDEBUG(ifp, "open\n"); + mtx_unlock(&tp->tun_mtx); return (0); } @@ -428,7 +428,6 @@ tunclose(struct cdev *dev, int foo, int { struct tun_softc *tp; struct ifnet *ifp; - int s; tp = dev->si_drv1; ifp = TUN2IFP(tp); @@ -440,22 +439,20 @@ tunclose(struct cdev *dev, int foo, int /* * junk all pending output */ - s = splimp(); IFQ_PURGE(&ifp->if_snd); - splx(s); - mtx_unlock(&tp->tun_mtx); if (ifp->if_flags & IFF_UP) { - s = splimp(); + mtx_unlock(&tp->tun_mtx); if_down(ifp); - splx(s); + mtx_lock(&tp->tun_mtx); } /* Delete all addresses and routes which reference this interface. */ if (ifp->if_drv_flags & IFF_DRV_RUNNING) { struct ifaddr *ifa; - s = splimp(); + ifp->if_drv_flags &= ~IFF_DRV_RUNNING; + mtx_unlock(&tp->tun_mtx); TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { /* deal w/IPv4 PtP destination; unlocked read */ if (ifa->ifa_addr->sa_family == AF_INET) { @@ -466,14 +463,14 @@ tunclose(struct cdev *dev, int foo, int } } if_purgeaddrs(ifp); - ifp->if_drv_flags &= ~IFF_DRV_RUNNING; - splx(s); + mtx_lock(&tp->tun_mtx); } funsetown(&tp->tun_sigio); selwakeuppri(&tp->tun_rsel, PZERO + 1); - KNOTE_UNLOCKED(&tp->tun_rsel.si_note, 0); + KNOTE_LOCKED(&tp->tun_rsel.si_note, 0); TUNDEBUG (ifp, "closed\n"); + mtx_unlock(&tp->tun_mtx); return (0); } @@ -481,11 +478,14 @@ static int tuninit(struct ifnet *ifp) { struct tun_softc *tp = ifp->if_softc; +#ifdef INET struct ifaddr *ifa; +#endif int error = 0; TUNDEBUG(ifp, "tuninit\n"); + mtx_lock(&tp->tun_mtx); ifp->if_flags |= IFF_UP; ifp->if_drv_flags |= IFF_DRV_RUNNING; getmicrotime(&ifp->if_lastchange); @@ -496,17 +496,16 @@ tuninit(struct ifnet *ifp) struct sockaddr_in *si; si = (struct sockaddr_in *)ifa->ifa_addr; - mtx_lock(&tp->tun_mtx); if (si->sin_addr.s_addr) tp->tun_flags |= TUN_IASET; si = (struct sockaddr_in *)ifa->ifa_dstaddr; if (si && si->sin_addr.s_addr) tp->tun_flags |= TUN_DSTADDR; - mtx_unlock(&tp->tun_mtx); } } #endif + mtx_unlock(&tp->tun_mtx); return (error); } @@ -519,9 +518,8 @@ tunifioctl(struct ifnet *ifp, u_long cmd struct ifreq *ifr = (struct ifreq *)data; struct tun_softc *tp = ifp->if_softc; struct ifstat *ifs; - int error = 0, s; + int error = 0; - s = splimp(); switch(cmd) { case SIOCGIFSTATUS: ifs = (struct ifstat *)data; @@ -550,7 +548,6 @@ tunifioctl(struct ifnet *ifp, u_long cmd default: error = EINVAL; } - splx(s); return (error); } @@ -656,7 +653,6 @@ tunoutput( static int tunioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) { - int s; int error; struct tun_softc *tp = dev->si_drv1; struct tuninfo *tunp; @@ -671,15 +667,19 @@ tunioctl(struct cdev *dev, u_long cmd, c if (error) return (error); } + mtx_lock(&tp->tun_mtx); TUN2IFP(tp)->if_mtu = tunp->mtu; TUN2IFP(tp)->if_type = tunp->type; TUN2IFP(tp)->if_baudrate = tunp->baudrate; + mtx_unlock(&tp->tun_mtx); break; case TUNGIFINFO: tunp = (struct tuninfo *)data; + mtx_lock(&tp->tun_mtx); tunp->mtu = TUN2IFP(tp)->if_mtu; tunp->type = TUN2IFP(tp)->if_type; tunp->baudrate = TUN2IFP(tp)->if_baudrate; + mtx_unlock(&tp->tun_mtx); break; case TUNSDEBUG: tundebug = *(int *)data; @@ -706,7 +706,6 @@ tunioctl(struct cdev *dev, u_long cmd, c mtx_unlock(&tp->tun_mtx); break; case TUNGIFHEAD: - /* Could be unlocked read? */ mtx_lock(&tp->tun_mtx); *(int *)data = (tp->tun_flags & TUN_IFHEAD) ? 1 : 0; mtx_unlock(&tp->tun_mtx); @@ -719,9 +718,11 @@ tunioctl(struct cdev *dev, u_long cmd, c switch (*(int *)data & ~IFF_MULTICAST) { case IFF_POINTOPOINT: case IFF_BROADCAST: + mtx_lock(&tp->tun_mtx); TUN2IFP(tp)->if_flags &= ~(IFF_BROADCAST|IFF_POINTOPOINT|IFF_MULTICAST); TUN2IFP(tp)->if_flags |= *(int *)data; + mtx_unlock(&tp->tun_mtx); break; default: return(EINVAL); @@ -743,17 +744,15 @@ tunioctl(struct cdev *dev, u_long cmd, c mtx_unlock(&tp->tun_mtx); break; case FIONREAD: - s = splimp(); if (!IFQ_IS_EMPTY(&TUN2IFP(tp)->if_snd)) { struct mbuf *mb; IFQ_LOCK(&TUN2IFP(tp)->if_snd); IFQ_POLL_NOLOCK(&TUN2IFP(tp)->if_snd, mb); - for( *(int *)data = 0; mb != 0; mb = mb->m_next) + for (*(int *)data = 0; mb != NULL; mb = mb->m_next) *(int *)data += mb->m_len; IFQ_UNLOCK(&TUN2IFP(tp)->if_snd); } else *(int *)data = 0; - splx(s); break; case FIOSETOWN: return (fsetown(*(int *)data, &tp->tun_sigio)); @@ -787,7 +786,7 @@ tunread(struct cdev *dev, struct uio *ui struct tun_softc *tp = dev->si_drv1; struct ifnet *ifp = TUN2IFP(tp); struct mbuf *m; - int error=0, len, s; + int error=0, len; TUNDEBUG (ifp, "read\n"); mtx_lock(&tp->tun_mtx); @@ -798,27 +797,24 @@ tunread(struct cdev *dev, struct uio *ui } tp->tun_flags &= ~TUN_RWAIT; - mtx_unlock(&tp->tun_mtx); - s = splimp(); do { IFQ_DEQUEUE(&ifp->if_snd, m); if (m == NULL) { if (flag & O_NONBLOCK) { - splx(s); + mtx_unlock(&tp->tun_mtx); return (EWOULDBLOCK); } - mtx_lock(&tp->tun_mtx); tp->tun_flags |= TUN_RWAIT; - mtx_unlock(&tp->tun_mtx); - if ((error = tsleep(tp, PCATCH | (PZERO + 1), - "tunread", 0)) != 0) { - splx(s); + error = mtx_sleep(tp, &tp->tun_mtx, PCATCH | (PZERO + 1), + "tunread", 0); + if (error != 0) { + mtx_unlock(&tp->tun_mtx); return (error); } } } while (m == NULL); - splx(s); + mtx_unlock(&tp->tun_mtx); while (m && uio->uio_resid > 0 && error == 0) { len = min(uio->uio_resid, m->m_len); @@ -929,13 +925,11 @@ tunwrite(struct cdev *dev, struct uio *u static int tunpoll(struct cdev *dev, int events, struct thread *td) { - int s; struct tun_softc *tp = dev->si_drv1; struct ifnet *ifp = TUN2IFP(tp); int revents = 0; struct mbuf *m; - s = splimp(); TUNDEBUG(ifp, "tunpoll\n"); if (events & (POLLIN | POLLRDNORM)) { @@ -953,7 +947,6 @@ tunpoll(struct cdev *dev, int events, st if (events & (POLLOUT | POLLWRNORM)) revents |= events & (POLLOUT | POLLWRNORM); - splx(s); return (revents); } @@ -963,11 +956,9 @@ tunpoll(struct cdev *dev, int events, st static int tunkqfilter(struct cdev *dev, struct knote *kn) { - int s; struct tun_softc *tp = dev->si_drv1; struct ifnet *ifp = TUN2IFP(tp); - s = splimp(); switch(kn->kn_filter) { case EVFILT_READ: TUNDEBUG(ifp, "%s kqfilter: EVFILT_READ, minor = %#x\n", @@ -984,12 +975,10 @@ tunkqfilter(struct cdev *dev, struct kno default: TUNDEBUG(ifp, "%s kqfilter: invalid filter, minor = %#x\n", ifp->if_xname, minor(dev)); - splx(s); return(EINVAL); } - splx(s); - kn->kn_hook = (caddr_t) dev; + kn->kn_hook = tp; knlist_add(&tp->tun_rsel.si_note, kn, 0); return (0); @@ -1001,12 +990,11 @@ tunkqfilter(struct cdev *dev, struct kno static int tunkqread(struct knote *kn, long hint) { - int ret, s; - struct cdev *dev = (struct cdev *)(kn->kn_hook); - struct tun_softc *tp = dev->si_drv1; + int ret; + struct tun_softc *tp = kn->kn_hook; + struct cdev *dev = tp->tun_dev; struct ifnet *ifp = TUN2IFP(tp); - s = splimp(); if ((kn->kn_data = ifp->if_snd.ifq_len) > 0) { TUNDEBUG(ifp, "%s have data in the queue. Len = %d, minor = %#x\n", @@ -1018,7 +1006,6 @@ tunkqread(struct knote *kn, long hint) minor(dev)); ret = 0; } - splx(s); return (ret); } @@ -1029,13 +1016,10 @@ tunkqread(struct knote *kn, long hint) static int tunkqwrite(struct knote *kn, long hint) { - int s; - struct tun_softc *tp = ((struct cdev *)kn->kn_hook)->si_drv1; + struct tun_softc *tp = kn->kn_hook; struct ifnet *ifp = TUN2IFP(tp); - s = splimp(); kn->kn_data = ifp->if_mtu; - splx(s); return (1); } @@ -1043,7 +1027,7 @@ tunkqwrite(struct knote *kn, long hint) static void tunkqdetach(struct knote *kn) { - struct tun_softc *tp = ((struct cdev *)kn->kn_hook)->si_drv1; + struct tun_softc *tp = kn->kn_hook; knlist_remove(&tp->tun_rsel.si_note, kn, 0); }