Changeset View
Standalone View
sys/kern/kern_mbuf.c
Show First 20 Lines • Show All 702 Lines • ▼ Show 20 Lines | mb_dtor_pack(void *mem, int size, void *arg) | ||||
KASSERT(m->m_ext.ext_arg2 == NULL, ("%s: ext_arg2 != NULL", __func__)); | KASSERT(m->m_ext.ext_arg2 == NULL, ("%s: ext_arg2 != NULL", __func__)); | ||||
KASSERT(m->m_ext.ext_size == MCLBYTES, ("%s: ext_size != MCLBYTES", __func__)); | KASSERT(m->m_ext.ext_size == MCLBYTES, ("%s: ext_size != MCLBYTES", __func__)); | ||||
KASSERT(m->m_ext.ext_type == EXT_PACKET, ("%s: ext_type != EXT_PACKET", __func__)); | KASSERT(m->m_ext.ext_type == EXT_PACKET, ("%s: ext_type != EXT_PACKET", __func__)); | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
trash_dtor(m->m_ext.ext_buf, MCLBYTES, arg); | trash_dtor(m->m_ext.ext_buf, MCLBYTES, arg); | ||||
#endif | #endif | ||||
/* | /* | ||||
* If there are processes blocked on zone_clust, waiting for pages | * If there are processes blocked on zone_clust, waiting for pages | ||||
* to be freed up, * cause them to be woken up by draining the | * to be freed up, cause them to be woken up by draining the | ||||
* packet zone. We are exposed to a race here * (in the check for | * packet zone. We are exposed to a race here (in the check for | ||||
* the UMA_ZFLAG_FULL) where we might miss the flag set, but that | * the UMA_ZFLAG_FULL) where we might miss the flag set, but that | ||||
* is deliberate. We don't want to acquire the zone lock for every | * is deliberate. We don't want to acquire the zone lock for every | ||||
* mbuf free. | * mbuf free. | ||||
*/ | */ | ||||
if (uma_zone_exhausted_nolock(zone_clust)) | if (uma_zone_exhausted_nolock(zone_clust)) | ||||
zone_drain(zone_pack); | uma_zreclaim(zone_pack, UMA_RECLAIM_DRAIN); | ||||
jeff: Shouldn't this be trim, not drain? We need to free some memory but not all. Possibly we need… | |||||
Not Done Inline ActionsIsn't mbuf cluster zone exhaustion a fairly exceptional situation? They usually indicate an mbuf leak in my experience. In that case mbuf packet allocations will likely be failing too, and even a trim will require the cluster zone lock so it's an expensive operation regardless. Will fix the comment. markj: Isn't mbuf cluster zone exhaustion a fairly exceptional situation? They usually indicate an… | |||||
Not Done Inline ActionsThe boot defaults for clusters are relatively low and sometimes if you have a lot of interfaces it will trip more often because so much is sitting in receive queues. At isilon the zone sizes were tuned up substantially from the defaults so the only time it happened there was with a leak. It's not a regression to leave it this way but I would possibly appreciate a comment about it. jeff: The boot defaults for clusters are relatively low and sometimes if you have a lot of interfaces… | |||||
Not Done Inline ActionsIsilon just removed the limits entirely. OneFS also has patches to allow sockbuf limits to be overridden. markj: Isilon just removed the limits entirely. OneFS also has patches to allow sockbuf limits to be… | |||||
} | } | ||||
/* | /* | ||||
* The Cluster and Jumbo[PAGESIZE|9|16] zone constructor. | * The Cluster and Jumbo[PAGESIZE|9|16] zone constructor. | ||||
* | * | ||||
* Here the 'arg' pointer points to the Mbuf which we | * Here the 'arg' pointer points to the Mbuf which we | ||||
* are configuring cluster storage for. If 'arg' is | * are configuring cluster storage for. If 'arg' is | ||||
* empty we allocate just the cluster without setting | * empty we allocate just the cluster without setting | ||||
▲ Show 20 Lines • Show All 613 Lines • ▼ Show 20 Lines | KASSERT((m->m_flags & M_EXT) == 0, ("%s: mbuf %p has M_EXT", | ||||
__func__, m)); | __func__, m)); | ||||
m->m_ext.ext_buf = (char *)NULL; | m->m_ext.ext_buf = (char *)NULL; | ||||
uma_zalloc_arg(zone_clust, m, how); | uma_zalloc_arg(zone_clust, m, how); | ||||
/* | /* | ||||
* On a cluster allocation failure, drain the packet zone and retry, | * On a cluster allocation failure, drain the packet zone and retry, | ||||
* we might be able to loosen a few clusters up on the drain. | * we might be able to loosen a few clusters up on the drain. | ||||
*/ | */ | ||||
if ((how & M_NOWAIT) && (m->m_ext.ext_buf == NULL)) { | if ((how & M_NOWAIT) && (m->m_ext.ext_buf == NULL)) { | ||||
zone_drain(zone_pack); | uma_zreclaim(zone_pack, UMA_RECLAIM_DRAIN); | ||||
Not Done Inline ActionsHere again, do we need to drain the whole thing or just free some memory? jeff: Here again, do we need to drain the whole thing or just free some memory? | |||||
uma_zalloc_arg(zone_clust, m, how); | uma_zalloc_arg(zone_clust, m, how); | ||||
} | } | ||||
MBUF_PROBE2(m__clget, m, how); | MBUF_PROBE2(m__clget, m, how); | ||||
return (m->m_flags & M_EXT); | return (m->m_flags & M_EXT); | ||||
} | } | ||||
/* | /* | ||||
* m_cljget() is different from m_clget() as it can allocate clusters without | * m_cljget() is different from m_clget() as it can allocate clusters without | ||||
▲ Show 20 Lines • Show All 226 Lines • Show Last 20 Lines |
Shouldn't this be trim, not drain? We need to free some memory but not all. Possibly we need to guarantee that trim does something even if wss is reached but otherwise this is more expensive than it needs to be.
There is also a stray * in the comment above that you could remove while you're here.