diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c --- a/sys/kern/subr_uio.c +++ b/sys/kern/subr_uio.c @@ -287,6 +287,37 @@ return (error); } +/* + * Advance the pointer in the uio by offset. + */ +void +uioadvance(struct uio *uio, size_t offset) +{ + + MPASS(uio->uio_resid >= offset); + + while (offset > 0) { + struct iovec *iov; + size_t cnt; + + KASSERT(uio->uio_iovcnt > 0, + ("%s: uio %p iovcnt underflow", __func__, uio)); + iov = uio->uio_iov; + if ((cnt = iov->iov_len) == 0) { + uio->uio_iov++; + uio->uio_iovcnt--; + continue; + } + if (cnt > offset) + cnt = offset; + iov->iov_base = (char *)iov->iov_base + cnt; + iov->iov_len -= cnt; + uio->uio_resid -= cnt; + uio->uio_offset += cnt; + offset -= cnt; + } +} + /* * Wrapper for uiomove() that validates the arguments against a known-good * kernel buffer. Currently, uiomove accepts a signed (n) argument, which diff --git a/sys/sys/uio.h b/sys/sys/uio.h --- a/sys/sys/uio.h +++ b/sys/sys/uio.h @@ -90,6 +90,7 @@ vm_paddr_t dst, size_t len); int physcopyout_vlist(vm_paddr_t src, struct bus_dma_segment *dst, off_t offset, size_t len); +void uioadvance(struct uio *, size_t); int uiomove(void *cp, int n, struct uio *uio); int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n,