diff options
author | Bret Lambert <blambert@cvs.openbsd.org> | 2010-07-02 02:40:18 +0000 |
---|---|---|
committer | Bret Lambert <blambert@cvs.openbsd.org> | 2010-07-02 02:40:18 +0000 |
commit | bfc9493d9280a5a8ab43b8df30cd772c910140ba (patch) | |
tree | 32334a91bf10c89a8551f90fe6749d45476d9ad8 /sys/kern | |
parent | 364840df3893a5f720df05ee307b996c62195a07 (diff) |
m_copyback can fail to allocate memory, but is a void fucntion so gymnastics
are required to detect that.
Change the function to take a wait argument (used in nfs server, but
M_NOWAIT everywhere else for now) and to return an error
ok claudio@ henning@ krw@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/uipc_mbuf.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index dcf977c50a4..9940151a3e0 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_mbuf.c,v 1.139 2010/07/01 19:23:51 beck Exp $ */ +/* $OpenBSD: uipc_mbuf.c,v 1.140 2010/07/02 02:40:16 blambert Exp $ */ /* $NetBSD: uipc_mbuf.c,v 1.15.4.1 1996/06/13 17:11:44 cgd Exp $ */ /* @@ -726,26 +726,30 @@ m_copydata(struct mbuf *m, int off, int len, caddr_t cp) * chain if necessary. The mbuf needs to be properly initialized * including the setting of m_len. */ -void -m_copyback(struct mbuf *m0, int off, int len, const void *_cp) +int +m_copyback(struct mbuf *m0, int off, int len, const void *_cp, int wait) { int mlen, totlen = 0; struct mbuf *m = m0, *n; caddr_t cp = (caddr_t)_cp; + int error = 0; if (m0 == NULL) - return; + return (0); while (off > (mlen = m->m_len)) { off -= mlen; totlen += mlen; if (m->m_next == NULL) { - if ((n = m_get(M_DONTWAIT, m->m_type)) == NULL) + if ((n = m_get(wait, m->m_type)) == NULL) { + error = ENOBUFS; goto out; + } if (off + len > MLEN) { - MCLGETI(n, M_DONTWAIT, NULL, off + len); + MCLGETI(n, wait, NULL, off + len); if (!(n->m_flags & M_EXT)) { m_free(n); + error = ENOBUFS; goto out; } } @@ -770,13 +774,16 @@ m_copyback(struct mbuf *m0, int off, int len, const void *_cp) off = 0; if (m->m_next == NULL) { - if ((n = m_get(M_DONTWAIT, m->m_type)) == NULL) + if ((n = m_get(wait, m->m_type)) == NULL) { + error = ENOBUFS; goto out; + } if (len > MLEN) { - MCLGETI(n, M_DONTWAIT, NULL, len); + MCLGETI(n, wait, NULL, len); if (!(n->m_flags & M_EXT)) { m_free(n); + error = ENOBUFS; goto out; } } @@ -788,6 +795,8 @@ m_copyback(struct mbuf *m0, int off, int len, const void *_cp) out: if (((m = m0)->m_flags & M_PKTHDR) && (m->m_pkthdr.len < totlen)) m->m_pkthdr.len = totlen; + + return (error); } /* |