@@ -1938,65 +1938,103 @@ m_uiotombuf_nomap(struct uio *uio, int how, int len, int maxseg, int flags)
1938
1938
1939
1939
/*
1940
1940
* Copy the contents of uio into a properly sized mbuf chain.
1941
+ * A compat KPI. Users are recommended to use direct calls to backing
1942
+ * functions.
1941
1943
*/
1942
1944
struct mbuf *
1943
- m_uiotombuf (struct uio * uio , int how , int len , int align , int flags )
1945
+ m_uiotombuf (struct uio * uio , int how , int len , int lspace , int flags )
1944
1946
{
1945
- struct mbuf * m , * mb ;
1946
- int error , length ;
1947
- ssize_t total ;
1948
- int progress = 0 ;
1949
1947
1950
- if (flags & M_EXTPG )
1951
- return (m_uiotombuf_nomap (uio , how , len , align , flags ));
1948
+ if (flags & M_EXTPG ) {
1949
+ /* XXX: 'lspace' magically becomes maxseg! */
1950
+ return (m_uiotombuf_nomap (uio , how , len , lspace , flags ));
1951
+ } else if (__predict_false (uio -> uio_resid + len == 0 )) {
1952
+ struct mbuf * m ;
1952
1953
1953
- /*
1954
- * len can be zero or an arbitrary large value bound by
1955
- * the total data supplied by the uio.
1956
- */
1957
- if (len > 0 )
1958
- total = (uio -> uio_resid < len ) ? uio -> uio_resid : len ;
1954
+ /*
1955
+ * m_uiotombuf() is known to return zero length buffer, keep
1956
+ * this compatibility. mc_uiotomc() won't do that.
1957
+ */
1958
+ if (flags & M_PKTHDR ) {
1959
+ m = m_gethdr (how , MT_DATA );
1960
+ m -> m_pkthdr .memlen = MSIZE ;
1961
+ } else
1962
+ m = m_get (how , MT_DATA );
1963
+ if (m != NULL )
1964
+ m -> m_data += lspace ;
1965
+ return (m );
1966
+ } else {
1967
+ struct mchain mc ;
1968
+ int error ;
1969
+
1970
+ error = mc_uiotomc (& mc , uio , len , lspace , how , flags );
1971
+ if (__predict_true (error == 0 )) {
1972
+ if (flags & M_PKTHDR ) {
1973
+ mc_first (& mc )-> m_pkthdr .len = mc .mc_len ;
1974
+ mc_first (& mc )-> m_pkthdr .memlen = mc .mc_mlen ;
1975
+ }
1976
+ return (mc_first (& mc ));
1977
+ } else
1978
+ return (NULL );
1979
+ }
1980
+ }
1981
+
1982
+ /*
1983
+ * Copy the contents of uio into a properly sized mbuf chain.
1984
+ * In case of failure state of mchain is inconsistent.
1985
+ * @param length Limit copyout length. If 0 entire uio_resid is copied.
1986
+ * @param lspace Provide leading space in the first mbuf in the chain.
1987
+ */
1988
+ int
1989
+ mc_uiotomc (struct mchain * mc , struct uio * uio , u_int length , u_int lspace ,
1990
+ int how , int flags )
1991
+ {
1992
+ struct mbuf * mb ;
1993
+ u_int total ;
1994
+ int error ;
1995
+
1996
+ MPASS (lspace < MHLEN );
1997
+ MPASS (UINT_MAX - lspace >= length );
1998
+ MPASS (uio -> uio_rw == UIO_WRITE );
1999
+ MPASS (uio -> uio_resid >= 0 );
2000
+
2001
+ if (length > 0 ) {
2002
+ if (uio -> uio_resid > length ) {
2003
+ total = length ;
2004
+ flags &= ~M_EOR ;
2005
+ } else
2006
+ total = uio -> uio_resid ;
2007
+ } else if (__predict_false (uio -> uio_resid + lspace > UINT_MAX ))
2008
+ return (EOVERFLOW );
1959
2009
else
1960
2010
total = uio -> uio_resid ;
1961
2011
1962
- /*
1963
- * The smallest unit returned by m_getm2() is a single mbuf
1964
- * with pkthdr. We can't align past it.
1965
- */
1966
- if (align >= MHLEN )
1967
- return (NULL );
2012
+ if (__predict_false (total + lspace == 0 )) {
2013
+ * mc = MCHAIN_INITIALIZER (mc );
2014
+ return (0 );
2015
+ }
1968
2016
1969
- /*
1970
- * Give us the full allocation or nothing.
1971
- * If len is zero return the smallest empty mbuf.
1972
- */
1973
- m = m_getm2 (NULL , max (total + align , 1 ), how , MT_DATA , flags );
1974
- if (m == NULL )
1975
- return (NULL );
1976
- m -> m_data += align ;
2017
+ error = mc_get (mc , total + lspace , how , MT_DATA , flags );
2018
+ if (__predict_false (error ))
2019
+ return (error );
2020
+ mc_first (mc )-> m_data += lspace ;
1977
2021
1978
2022
/* Fill all mbufs with uio data and update header information. */
1979
- for (mb = m ; mb != NULL ; mb = mb -> m_next ) {
1980
- length = min (M_TRAILINGSPACE (mb ), total - progress );
1981
-
1982
- error = uiomove (mtod (mb , void * ), length , uio );
1983
- if (error ) {
1984
- m_freem (m );
1985
- return (NULL );
1986
- }
2023
+ STAILQ_FOREACH (mb , & mc -> mc_q , m_stailq ) {
2024
+ u_int mlen ;
1987
2025
1988
- mb -> m_len = length ;
1989
- progress += length ;
1990
- if (flags & M_PKTHDR ) {
1991
- m -> m_pkthdr .len += length ;
1992
- m -> m_pkthdr .memlen += MSIZE ;
1993
- if (mb -> m_flags & M_EXT )
1994
- m -> m_pkthdr .memlen += mb -> m_ext .ext_size ;
2026
+ mlen = min (M_TRAILINGSPACE (mb ), total - mc -> mc_len );
2027
+ error = uiomove (mtod (mb , void * ), mlen , uio );
2028
+ if (__predict_false (error )) {
2029
+ mc_freem (mc );
2030
+ return (error );
1995
2031
}
2032
+ mb -> m_len = mlen ;
2033
+ mc -> mc_len += mlen ;
1996
2034
}
1997
- KASSERT ( progress == total , ( "%s: progress != total" , __func__ ) );
2035
+ MPASS ( mc -> mc_len == total );
1998
2036
1999
- return (m );
2037
+ return (0 );
2000
2038
}
2001
2039
2002
2040
/*
0 commit comments