On Thu, Dec 23, 2021 at 11:49:08PM +0800, G.R. wrote: > On Wed, Dec 22, 2021 at 3:13 AM Roger Pau Monné <[email protected]> wrote: > > > Could you build a debug kernel with the following patch applied and > > give me the trace when it explodes? > > Please find the trace and the kernel CL below. > Note, the domU get stuck into a bootloop with this assertion as the > situation will come back after domU restart and only dom0 reboot can > get the situation back to normal. > The trace I captured below is within the boot loop. I suspect the > initial trigger may look different. Will give it another try soon. > > FreeBSD 12.2-RELEASE-p11 #0 c8625d629c3(truenas/12.0-stable)-dirty: > Wed Dec 22 20:26:46 UTC 2021 > The repo is here: https://github.com/freenas/os.git > > db:0:kdb.enter.default> bt > Tracing pid 0 tid 101637 td 0xfffff80069cc4000 > kdb_enter() at kdb_enter+0x37/frame 0xfffffe009f121460 > vpanic() at vpanic+0x197/frame 0xfffffe009f1214b0 > panic() at panic+0x43/frame 0xfffffe009f121510 > xn_txq_mq_start_locked() at xn_txq_mq_start_locked+0x4c6/frame > 0xfffffe009f121580 > xn_txq_mq_start() at xn_txq_mq_start+0x84/frame 0xfffffe009f1215b0 > ether_output_frame() at ether_output_frame+0xb4/frame 0xfffffe009f1215e0 > ether_output() at ether_output+0x6a5/frame 0xfffffe009f121680 > ip_output() at ip_output+0x1319/frame 0xfffffe009f1217e0 > tcp_output() at tcp_output+0x1dbf/frame 0xfffffe009f121980 > tcp_usr_send() at tcp_usr_send+0x3c9/frame 0xfffffe009f121a40 > sosend_generic() at sosend_generic+0x440/frame 0xfffffe009f121af0 > sosend() at sosend+0x66/frame 0xfffffe009f121b20 > icl_send_thread() at icl_send_thread+0x44e/frame 0xfffffe009f121bb0 > fork_exit() at fork_exit+0x80/frame 0xfffffe009f121bf0 > fork_trampoline() at fork_trampoline+0xe/frame 0xfffffe009f121bf0
Thanks. I've raised this on freensd-net for advice [0]. IMO netfront shouldn't receive an mbuf that crosses a page boundary, but if that's indeed a legit mbuf I will figure out the best way to handle it. I have a clumsy patch (below) that might solve this, if you want to give it a try. Regards, Roger. [0] https://lists.freebsd.org/archives/freebsd-net/2021-December/001179.html --- diff --git a/sys/dev/xen/netfront/netfront.c b/sys/dev/xen/netfront/netfront.c index 87bc3ecfc4dd..c8f807778b75 100644 --- a/sys/dev/xen/netfront/netfront.c +++ b/sys/dev/xen/netfront/netfront.c @@ -1529,6 +1529,35 @@ xn_count_frags(struct mbuf *m) return (nfrags); } +static inline int fragment(struct mbuf *m) +{ + while (m != NULL) { + vm_offset_t offset = mtod(m, vm_offset_t) & PAGE_MASK; + + if (offset + m->m_len > PAGE_SIZE) { + /* Split mbuf because it crosses a page boundary. */ + struct mbuf *m_new = m_getcl(M_NOWAIT, MT_DATA, 0); + + if (m_new == NULL) + return (ENOMEM); + + m_copydata(m, 0, m->m_len - (PAGE_SIZE - offset), + mtod(m_new, caddr_t)); + + /* Set adjusted mbuf sizes. */ + m_new->m_len = m->m_len - (PAGE_SIZE - offset); + m->m_len = PAGE_SIZE - offset; + + /* Insert new mbuf into chain. */ + m_new->m_next = m->m_next; + m->m_next = m_new; + } + m = m->m_next; + } + + return (0); +} + /** * Given an mbuf chain, make sure we have enough room and then push * it onto the transmit ring. @@ -1541,6 +1570,12 @@ xn_assemble_tx_request(struct netfront_txq *txq, struct mbuf *m_head) struct ifnet *ifp = np->xn_ifp; u_int nfrags; int otherend_id; + int rc; + + /* Fragment if mbuf crosses a page boundary. */ + rc = fragment(m_head); + if (rc != 0) + return (rc); /** * Defragment the mbuf if necessary.
