summaryrefslogtreecommitdiffstats
path: root/sys/kern/subr_mchain.c
diff options
context:
space:
mode:
authorbp <bp@FreeBSD.org>2002-02-21 16:23:38 +0000
committerbp <bp@FreeBSD.org>2002-02-21 16:23:38 +0000
commit72144faea40b15509e9cde60b156358ec3104a2a (patch)
treef6d158f4a15bedc85476c6d3c9d52cdeb5943e28 /sys/kern/subr_mchain.c
parent5829508a14d782a246c4c7bf4c1afbc6c26e2da1 (diff)
downloadFreeBSD-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/kern/subr_mchain.c')
-rw-r--r--sys/kern/subr_mchain.c30
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;
OpenPOWER on IntegriCloud