diff options
author | bp <bp@FreeBSD.org> | 2002-02-21 16:23:38 +0000 |
---|---|---|
committer | bp <bp@FreeBSD.org> | 2002-02-21 16:23:38 +0000 |
commit | 72144faea40b15509e9cde60b156358ec3104a2a (patch) | |
tree | f6d158f4a15bedc85476c6d3c9d52cdeb5943e28 /sys | |
parent | 5829508a14d782a246c4c7bf4c1afbc6c26e2da1 (diff) | |
download | FreeBSD-src-72144faea40b15509e9cde60b156358ec3104a2a.zip FreeBSD-src-72144faea40b15509e9cde60b156358ec3104a2a.tar.gz |
Add support for iovcnt greater than 1. This should resolve problems
with some applications.
Obtained from: Darwin project
MFC after: 2 weeks
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/subr_mchain.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/sys/kern/subr_mchain.c b/sys/kern/subr_mchain.c index d78b37f..21fddac 100644 --- a/sys/kern/subr_mchain.c +++ b/sys/kern/subr_mchain.c @@ -266,7 +266,6 @@ mb_put_mbuf(struct mbchain *mbp, struct mbuf *m) /* * copies a uio scatter/gather list to an mbuf chain. - * NOTE: can ony handle iovcnt == 1 */ int mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) @@ -274,14 +273,17 @@ mb_put_uio(struct mbchain *mbp, struct uio *uiop, int size) long left; int mtype, error; -#ifdef DIAGNOSTIC - if (uiop->uio_iovcnt != 1) - MBPANIC("iovcnt != 1"); -#endif mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; - while (size > 0) { + while (size > 0 && uiop->uio_resid) { + if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) + return EFBIG; left = uiop->uio_iov->iov_len; + if (left == 0) { + uiop->uio_iov++; + uiop->uio_iovcnt--; + continue; + } if (left > size) left = size; error = mb_put_mem(mbp, uiop->uio_iov->iov_base, left, mtype); @@ -522,10 +524,15 @@ md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) int mtype, error; mtype = (uiop->uio_segflg == UIO_SYSSPACE) ? MB_MSYSTEM : MB_MUSER; - while (size > 0) { + while (size > 0 && uiop->uio_resid) { if (uiop->uio_iovcnt <= 0 || uiop->uio_iov == NULL) return EFBIG; left = uiop->uio_iov->iov_len; + if (left == 0) { + uiop->uio_iov++; + uiop->uio_iovcnt--; + continue; + } uiocp = uiop->uio_iov->iov_base; if (left > size) left = size; @@ -534,13 +541,8 @@ md_get_uio(struct mdchain *mdp, struct uio *uiop, int size) return error; uiop->uio_offset += left; uiop->uio_resid -= left; - if (uiop->uio_iov->iov_len <= size) { - uiop->uio_iovcnt--; - uiop->uio_iov++; - } else { - uiop->uio_iov->iov_base += left; - uiop->uio_iov->iov_len -= left; - } + uiop->uio_iov->iov_base += left; + uiop->uio_iov->iov_len -= left; size -= left; } return 0; |