* Create a writable copy of the mbuf chain. While doing this * we compact the chain with a goal of producing a chain with * at most two mbufs. The second mbuf in this chain is likely * to be a cluster. The primary purpose of this work is to create * a writable packet for encryption, compression, etc. The * secondary goal is to linearize the data so the data can be * passed to crypto hard
| 1916 | * passed to crypto hardware in the most efficient manner possible. |
| 1917 | */ |
| 1918 | struct mbuf * |
| 1919 | m_unshare(struct mbuf *m0, int how) |
| 1920 | { |
| 1921 | struct mbuf *m, *mprev; |
| 1922 | struct mbuf *n, *mfirst, *mlast; |
| 1923 | int len, off; |
| 1924 | |
| 1925 | mprev = NULL; |
| 1926 | for (m = m0; m != NULL; m = mprev->m_next) { |
| 1927 | /* |
| 1928 | * Regular mbufs are ignored unless there's a cluster |
| 1929 | * in front of it that we can use to coalesce. We do |
| 1930 | * the latter mainly so later clusters can be coalesced |
| 1931 | * also w/o having to handle them specially (i.e. convert |
| 1932 | * mbuf+cluster -> cluster). This optimization is heavily |
| 1933 | * influenced by the assumption that we're running over |
| 1934 | * Ethernet where MCLBYTES is large enough that the max |
| 1935 | * packet size will permit lots of coalescing into a |
| 1936 | * single cluster. This in turn permits efficient |
| 1937 | * crypto operations, especially when using hardware. |
| 1938 | */ |
| 1939 | if ((m->m_flags & M_EXT) == 0) { |
| 1940 | if (mprev && (mprev->m_flags & M_EXT) && |
| 1941 | m->m_len <= M_TRAILINGSPACE(mprev)) { |
| 1942 | /* XXX: this ignores mbuf types */ |
| 1943 | memcpy(mtod(mprev, caddr_t) + mprev->m_len, |
| 1944 | mtod(m, caddr_t), m->m_len); |
| 1945 | mprev->m_len += m->m_len; |
| 1946 | mprev->m_next = m->m_next; /* unlink from chain */ |
| 1947 | m_free(m); /* reclaim mbuf */ |
| 1948 | } else { |
| 1949 | mprev = m; |
| 1950 | } |
| 1951 | continue; |
| 1952 | } |
| 1953 | /* |
| 1954 | * Writable mbufs are left alone (for now). |
| 1955 | */ |
| 1956 | if (M_WRITABLE(m)) { |
| 1957 | mprev = m; |
| 1958 | continue; |
| 1959 | } |
| 1960 | |
| 1961 | /* |
| 1962 | * Not writable, replace with a copy or coalesce with |
| 1963 | * the previous mbuf if possible (since we have to copy |
| 1964 | * it anyway, we try to reduce the number of mbufs and |
| 1965 | * clusters so that future work is easier). |
| 1966 | */ |
| 1967 | KASSERT(m->m_flags & M_EXT, ("m_flags 0x%x", m->m_flags)); |
| 1968 | /* NB: we only coalesce into a cluster or larger */ |
| 1969 | if (mprev != NULL && (mprev->m_flags & M_EXT) && |
| 1970 | m->m_len <= M_TRAILINGSPACE(mprev)) { |
| 1971 | /* XXX: this ignores mbuf types */ |
| 1972 | memcpy(mtod(mprev, caddr_t) + mprev->m_len, |
| 1973 | mtod(m, caddr_t), m->m_len); |
| 1974 | mprev->m_len += m->m_len; |
| 1975 | mprev->m_next = m->m_next; /* unlink from chain */ |
no test coverage detected