On Wed, Nov 16, 2016 at 12:18:48PM +0100, Martin Pieuchot wrote: > Here's another extracted diff: Use goto in read & write and always > increment the reference count in write. > > ok?
OK bluhm@ > > Index: net/bpf.c > =================================================================== > RCS file: /cvs/src/sys/net/bpf.c,v > retrieving revision 1.151 > diff -u -p -r1.151 bpf.c > --- net/bpf.c 16 Nov 2016 09:00:01 -0000 1.151 > +++ net/bpf.c 16 Nov 2016 11:08:25 -0000 > @@ -406,16 +406,17 @@ bpfread(dev_t dev, struct uio *uio, int > if (d->bd_bif == NULL) > return (ENXIO); > > + s = splnet(); > + bpf_get(d); > + > /* > * Restrict application to use a buffer the same size as > * as kernel buffers. > */ > - if (uio->uio_resid != d->bd_bufsize) > - return (EINVAL); > - > - s = splnet(); > - > - bpf_get(d); > + if (uio->uio_resid != d->bd_bufsize) { > + error = EINVAL; > + goto out; > + } > > /* > * If there's a timeout, bd_rdStart is tagged when we start the read. > @@ -431,13 +432,12 @@ bpfread(dev_t dev, struct uio *uio, int > * ends when the timeout expires or when enough packets > * have arrived to fill the store buffer. > */ > - while (d->bd_hbuf == 0) { > + while (d->bd_hbuf == NULL) { > if (d->bd_bif == NULL) { > /* interface is gone */ > if (d->bd_slen == 0) { > - bpf_put(d); > - splx(s); > - return (EIO); > + error = EIO; > + goto out; > } > ROTATE_BUFFERS(d); > break; > @@ -461,18 +461,15 @@ bpfread(dev_t dev, struct uio *uio, int > } else > error = EWOULDBLOCK; > } > - if (error == EINTR || error == ERESTART) { > - bpf_put(d); > - splx(s); > - return (error); > - } > + if (error == EINTR || error == ERESTART) > + goto out; > if (error == EWOULDBLOCK) { > /* > * On a timeout, return what's in the buffer, > * which may be nothing. If there is something > * in the store buffer, we can rotate the buffers. > */ > - if (d->bd_hbuf) > + if (d->bd_hbuf != NULL) > /* > * We filled up the buffer in between > * getting the timeout and arriving > @@ -481,9 +478,8 @@ bpfread(dev_t dev, struct uio *uio, int > break; > > if (d->bd_slen == 0) { > - bpf_put(d); > - splx(s); > - return (0); > + error = 0; > + goto out; > } > ROTATE_BUFFERS(d); > break; > @@ -505,7 +501,7 @@ bpfread(dev_t dev, struct uio *uio, int > d->bd_fbuf = d->bd_hbuf; > d->bd_hbuf = NULL; > d->bd_hlen = 0; > - > +out: > bpf_put(d); > splx(s); > > @@ -554,32 +550,40 @@ bpfwrite(dev_t dev, struct uio *uio, int > struct bpf_insn *fcode = NULL; > int error, s; > struct sockaddr_storage dst; > + u_int dlt; > > d = bpfilter_lookup(minor(dev)); > if (d->bd_bif == NULL) > return (ENXIO); > > + bpf_get(d); > ifp = d->bd_bif->bif_ifp; > > - if ((ifp->if_flags & IFF_UP) == 0) > - return (ENETDOWN); > + if ((ifp->if_flags & IFF_UP) == 0) { > + error = ENETDOWN; > + goto out; > + } > > - if (uio->uio_resid == 0) > - return (0); > + if (uio->uio_resid == 0) { > + error = 0; > + goto out; > + } > > KERNEL_ASSERT_LOCKED(); /* for accessing bd_wfilter */ > bf = srp_get_locked(&d->bd_wfilter); > if (bf != NULL) > fcode = bf->bf_insns; > > - error = bpf_movein(uio, d->bd_bif->bif_dlt, &m, > - (struct sockaddr *)&dst, fcode); > + dlt = d->bd_bif->bif_dlt; > + > + error = bpf_movein(uio, dlt, &m, (struct sockaddr *)&dst, fcode); > if (error) > - return (error); > + goto out; > > if (m->m_pkthdr.len > ifp->if_mtu) { > m_freem(m); > - return (EMSGSIZE); > + error = EMSGSIZE; > + goto out; > } > > m->m_pkthdr.ph_rtableid = ifp->if_rdomain; > @@ -591,9 +595,9 @@ bpfwrite(dev_t dev, struct uio *uio, int > s = splsoftnet(); > error = ifp->if_output(ifp, m, (struct sockaddr *)&dst, NULL); > splx(s); > - /* > - * The driver frees the mbuf. > - */ > + > +out: > + bpf_put(d); > return (error); > } >