MCPcopy Create free account
hub / github.com/F-Stack/f-stack / m_collapse

Function m_collapse

freebsd/kern/uipc_mbuf.c:1474–1553  ·  view source on GitHub ↗

* Defragment an mbuf chain, returning at most maxfrags separate * mbufs+clusters. If this is not possible NULL is returned and * the original mbuf chain is left in its present (potentially * modified) state. We use two techniques: collapsing consecutive * mbufs and replacing consecutive mbufs by a cluster. * * NB: this should really be named m_defrag but that name is taken */

Source from the content-addressed store, hash-verified

1472 * NB: this should really be named m_defrag but that name is taken
1473 */
1474struct mbuf *
1475m_collapse(struct mbuf *m0, int how, int maxfrags)
1476{
1477 struct mbuf *m, *n, *n2, **prev;
1478 u_int curfrags;
1479
1480 /*
1481 * Calculate the current number of frags.
1482 */
1483 curfrags = 0;
1484 for (m = m0; m != NULL; m = m->m_next)
1485 curfrags += frags_per_mbuf(m);
1486 /*
1487 * First, try to collapse mbufs. Note that we always collapse
1488 * towards the front so we don't need to deal with moving the
1489 * pkthdr. This may be suboptimal if the first mbuf has much
1490 * less data than the following.
1491 */
1492 m = m0;
1493again:
1494 for (;;) {
1495 n = m->m_next;
1496 if (n == NULL)
1497 break;
1498 if (M_WRITABLE(m) &&
1499 n->m_len < M_TRAILINGSPACE(m)) {
1500 m_copydata(n, 0, n->m_len,
1501 mtod(m, char *) + m->m_len);
1502 m->m_len += n->m_len;
1503 m->m_next = n->m_next;
1504 curfrags -= frags_per_mbuf(n);
1505 m_free(n);
1506 if (curfrags <= maxfrags)
1507 return m0;
1508 } else
1509 m = n;
1510 }
1511 KASSERT(maxfrags > 1,
1512 ("maxfrags %u, but normal collapse failed", maxfrags));
1513 /*
1514 * Collapse consecutive mbufs to a cluster.
1515 */
1516 prev = &m0->m_next; /* NB: not the first mbuf */
1517 while ((n = *prev) != NULL) {
1518 if ((n2 = n->m_next) != NULL &&
1519 n->m_len + n2->m_len < MCLBYTES) {
1520 m = m_getcl(how, MT_DATA, 0);
1521 if (m == NULL)
1522 goto bad;
1523 m_copydata(n, 0, n->m_len, mtod(m, char *));
1524 m_copydata(n2, 0, n2->m_len,
1525 mtod(m, char *) + n->m_len);
1526 m->m_len = n->m_len + n2->m_len;
1527 m->m_next = n2->m_next;
1528 *prev = m;
1529 curfrags += 1; /* For the new cluster */
1530 curfrags -= frags_per_mbuf(n);
1531 curfrags -= frags_per_mbuf(n2);

Callers 3

gen_encapFunction · 0.85
awg_encapFunction · 0.85
iflib_encapFunction · 0.85

Calls 4

frags_per_mbufFunction · 0.85
m_copydataFunction · 0.85
m_freeFunction · 0.50
m_getclFunction · 0.50

Tested by

no test coverage detected