No regression so far. //mxb
> On 15 dec. 2015, at 14:18, Mike Belopuhov <[email protected]> wrote: > > Hi, > > This has been in my tree for a while and I believe Yasuoka-san has > tested it in the scenario where it was crashing. > > m_pulldown is done here with a zero offset which means that if > there's been no space reserved for the Ethernet header in the mbuf > or the cluster it will allocate a new chunk of memory and return a > new pointer that the vmx code ignores. This can realistically > happen only during the bpf injection. > > The diff below makes sure to keep the modified chain pointer around > and passes it back to the calling code so that it will get properly > accounted for. m_pulldown with a zero offset is equivalent to a > m_pullup. > > OK? > > > diff --git sys/dev/pci/if_vmx.c sys/dev/pci/if_vmx.c > index 055cfe1..50edb0b 100644 > --- sys/dev/pci/if_vmx.c > +++ sys/dev/pci/if_vmx.c > @@ -164,11 +164,11 @@ void vmxnet3_stop(struct ifnet *); > void vmxnet3_reset(struct vmxnet3_softc *); > int vmxnet3_init(struct vmxnet3_softc *); > int vmxnet3_ioctl(struct ifnet *, u_long, caddr_t); > void vmxnet3_start(struct ifnet *); > int vmxnet3_load_mbuf(struct vmxnet3_softc *, struct vmxnet3_txring *, > - struct mbuf *); > + struct mbuf **); > void vmxnet3_watchdog(struct ifnet *); > void vmxnet3_media_status(struct ifnet *, struct ifmediareq *); > int vmxnet3_media_change(struct ifnet *); > void *vmxnet3_dma_allocmem(struct vmxnet3_softc *, u_int, u_int, bus_addr_t > *); > > @@ -1063,11 +1063,11 @@ vmxnet3_start(struct ifnet *ifp) > > IFQ_DEQUEUE(&ifp->if_snd, m); > if (m == NULL) > break; > > - n = vmxnet3_load_mbuf(sc, ring, m); > + n = vmxnet3_load_mbuf(sc, ring, &m); > if (n == -1) { > ifp->if_oerrors++; > continue; > } > > @@ -1087,13 +1087,14 @@ vmxnet3_start(struct ifnet *ifp) > } > } > > int > vmxnet3_load_mbuf(struct vmxnet3_softc *sc, struct vmxnet3_txring *ring, > - struct mbuf *m) > + struct mbuf **mp) > { > struct vmxnet3_txdesc *txd, *sop; > + struct mbuf *n, *m = *mp; > bus_dmamap_t map; > u_int hlen = ETHER_HDR_LEN, csum_off; > u_int prod; > int gen, i; > > @@ -1105,29 +1106,29 @@ vmxnet3_load_mbuf(struct vmxnet3_softc *sc, struct > vmxnet3_txring *ring, > sc->sc_dev.dv_xname); > return -1; > } > #endif > if (m->m_pkthdr.csum_flags & (M_TCP_CSUM_OUT|M_UDP_CSUM_OUT)) { > - struct mbuf *mp; > struct ip *ip; > int offp; > > if (m->m_pkthdr.csum_flags & M_TCP_CSUM_OUT) > csum_off = offsetof(struct tcphdr, th_sum); > else > csum_off = offsetof(struct udphdr, uh_sum); > > - mp = m_pulldown(m, hlen, sizeof(*ip), &offp); > - if (mp == NULL) > + n = m_pulldown(m, hlen, sizeof(*ip), &offp); > + if (n == NULL) > return (-1); > > - ip = (struct ip *)(mp->m_data + offp); > + ip = (struct ip *)(n->m_data + offp); > hlen += ip->ip_hl << 2; > > - mp = m_pulldown(m, 0, hlen + csum_off + 2, &offp); > - if (mp == NULL) > + *mp = m_pullup(m, hlen + csum_off + 2); > + if (*mp == NULL) > return (-1); > + m = *mp; > } > > switch (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, BUS_DMA_NOWAIT)) { > case 0: > break; >
