From 796d4eb89e2c6e95be4d3cdb5b01fd3a09218039 Mon Sep 17 00:00:00 2001 From: Andrew Gallatin Date: Mon, 31 Aug 2020 13:53:14 +0000 Subject: [PATCH] make m_getm2() resilient to zone_jumbop exhaustion When the zone_jumbop is exhausted, most things using using sosend* (like sshd) will eventually fail or hang if allocations are limited to the depleted jumbop zone. This makes it imossible to communicate with a box which is under an attach which exhausts the jumbop zone. Rather than depending on the page size zone, also try cluster allocations to satisfy larger requests. This allows me to ssh to, and serve 100Gb/s of traffic from a server which under attack and has had its page-sized zone exhausted. Reviewed by: glebius, markj, rmacklem Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D26150 --- sys/kern/kern_mbuf.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index 5fa614e7348..dfd626f0de7 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -1423,21 +1423,28 @@ m_getm2(struct mbuf *m, int len, int how, short type, int flags) /* Loop and append maximum sized mbufs to the chain tail. */ while (len > 0) { - if (len > MCLBYTES) - mb = m_getjcl(how, type, (flags & M_PKTHDR), + mb = NULL; + if (len > MCLBYTES) { + mb = m_getjcl(M_NOWAIT, type, (flags & M_PKTHDR), MJUMPAGESIZE); - else if (len >= MINCLSIZE) - mb = m_getcl(how, type, (flags & M_PKTHDR)); - else if (flags & M_PKTHDR) - mb = m_gethdr(how, type); - else - mb = m_get(how, type); - /* Fail the whole operation if one mbuf can't be allocated. */ + } if (mb == NULL) { - if (nm != NULL) + if (len >= MINCLSIZE) + mb = m_getcl(how, type, (flags & M_PKTHDR)); + else if (flags & M_PKTHDR) + mb = m_gethdr(how, type); + else + mb = m_get(how, type); + + /* + * Fail the whole operation if one mbuf can't be + * allocated. + */ + if (mb == NULL) { m_freem(nm); - return (NULL); + return (NULL); + } } /* Book keeping. */