128993443SEd Schouten /*- 228993443SEd Schouten * Copyright (c) 1982, 1986, 1991, 1993 328993443SEd Schouten * The Regents of the University of California. All rights reserved. 428993443SEd Schouten * (c) UNIX System Laboratories, Inc. 528993443SEd Schouten * All or some portions of this file are derived from material licensed 628993443SEd Schouten * to the University of California by American Telephone and Telegraph 728993443SEd Schouten * Co. or Unix System Laboratories, Inc. and are reproduced herein with 828993443SEd Schouten * the permission of UNIX System Laboratories, Inc. 928993443SEd Schouten * 1028993443SEd Schouten * Redistribution and use in source and binary forms, with or without 1128993443SEd Schouten * modification, are permitted provided that the following conditions 1228993443SEd Schouten * are met: 1328993443SEd Schouten * 1. Redistributions of source code must retain the above copyright 1428993443SEd Schouten * notice, this list of conditions and the following disclaimer. 1528993443SEd Schouten * 2. Redistributions in binary form must reproduce the above copyright 1628993443SEd Schouten * notice, this list of conditions and the following disclaimer in the 1728993443SEd Schouten * documentation and/or other materials provided with the distribution. 1828993443SEd Schouten * 4. Neither the name of the University nor the names of its contributors 1928993443SEd Schouten * may be used to endorse or promote products derived from this software 2028993443SEd Schouten * without specific prior written permission. 2128993443SEd Schouten * 2228993443SEd Schouten * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2328993443SEd Schouten * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2428993443SEd Schouten * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2528993443SEd Schouten * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2628993443SEd Schouten * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2728993443SEd Schouten * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2828993443SEd Schouten * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2928993443SEd Schouten * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3028993443SEd Schouten * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3128993443SEd Schouten * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3228993443SEd Schouten * SUCH DAMAGE. 3328993443SEd Schouten * 3428993443SEd Schouten * @(#)kern_subr.c 8.3 (Berkeley) 1/21/94 3528993443SEd Schouten */ 3628993443SEd Schouten 3728993443SEd Schouten #include <sys/cdefs.h> 3828993443SEd Schouten __FBSDID("$FreeBSD$"); 3928993443SEd Schouten 4028993443SEd Schouten #include "opt_zero.h" 4128993443SEd Schouten 4228993443SEd Schouten #include <sys/param.h> 4328993443SEd Schouten #include <sys/systm.h> 4428993443SEd Schouten #include <sys/kernel.h> 4528993443SEd Schouten #include <sys/limits.h> 4628993443SEd Schouten #include <sys/lock.h> 4728993443SEd Schouten #include <sys/mutex.h> 4828993443SEd Schouten #include <sys/proc.h> 4928993443SEd Schouten #include <sys/sched.h> 5028993443SEd Schouten #include <sys/sysctl.h> 5128993443SEd Schouten #include <sys/vnode.h> 5228993443SEd Schouten 5328993443SEd Schouten #include <vm/vm.h> 5428993443SEd Schouten #include <vm/vm_page.h> 5528993443SEd Schouten #include <vm/vm_map.h> 5628993443SEd Schouten #ifdef ZERO_COPY_SOCKETS 5728993443SEd Schouten #include <vm/vm_param.h> 5828993443SEd Schouten #include <vm/vm_object.h> 5928993443SEd Schouten #endif 6028993443SEd Schouten 6128993443SEd Schouten SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, NULL, UIO_MAXIOV, 6228993443SEd Schouten "Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)"); 6328993443SEd Schouten 6428993443SEd Schouten #ifdef ZERO_COPY_SOCKETS 6528993443SEd Schouten /* Declared in uipc_socket.c */ 6628993443SEd Schouten extern int so_zero_copy_receive; 6728993443SEd Schouten 6828993443SEd Schouten /* 6928993443SEd Schouten * Identify the physical page mapped at the given kernel virtual 7028993443SEd Schouten * address. Insert this physical page into the given address space at 7128993443SEd Schouten * the given virtual address, replacing the physical page, if any, 7228993443SEd Schouten * that already exists there. 7328993443SEd Schouten */ 7428993443SEd Schouten static int 7528993443SEd Schouten vm_pgmoveco(vm_map_t mapa, vm_offset_t kaddr, vm_offset_t uaddr) 7628993443SEd Schouten { 7728993443SEd Schouten vm_map_t map = mapa; 7828993443SEd Schouten vm_page_t kern_pg, user_pg; 7928993443SEd Schouten vm_object_t uobject; 8028993443SEd Schouten vm_map_entry_t entry; 8128993443SEd Schouten vm_pindex_t upindex; 8228993443SEd Schouten vm_prot_t prot; 8328993443SEd Schouten boolean_t wired; 8428993443SEd Schouten 8528993443SEd Schouten KASSERT((uaddr & PAGE_MASK) == 0, 8628993443SEd Schouten ("vm_pgmoveco: uaddr is not page aligned")); 8728993443SEd Schouten 8828993443SEd Schouten /* 8928993443SEd Schouten * Herein the physical page is validated and dirtied. It is 9028993443SEd Schouten * unwired in sf_buf_mext(). 9128993443SEd Schouten */ 9228993443SEd Schouten kern_pg = PHYS_TO_VM_PAGE(vtophys(kaddr)); 9328993443SEd Schouten kern_pg->valid = VM_PAGE_BITS_ALL; 9428993443SEd Schouten KASSERT(kern_pg->queue == PQ_NONE && kern_pg->wire_count == 1, 9528993443SEd Schouten ("vm_pgmoveco: kern_pg is not correctly wired")); 9628993443SEd Schouten 9728993443SEd Schouten if ((vm_map_lookup(&map, uaddr, 9828993443SEd Schouten VM_PROT_WRITE, &entry, &uobject, 9928993443SEd Schouten &upindex, &prot, &wired)) != KERN_SUCCESS) { 10028993443SEd Schouten return(EFAULT); 10128993443SEd Schouten } 10228993443SEd Schouten VM_OBJECT_LOCK(uobject); 10328993443SEd Schouten retry: 10428993443SEd Schouten if ((user_pg = vm_page_lookup(uobject, upindex)) != NULL) { 10528993443SEd Schouten if (vm_page_sleep_if_busy(user_pg, TRUE, "vm_pgmoveco")) 10628993443SEd Schouten goto retry; 1075ac59343SAlan Cox vm_page_lock(user_pg); 10828993443SEd Schouten pmap_remove_all(user_pg); 10928993443SEd Schouten vm_page_free(user_pg); 1105ac59343SAlan Cox vm_page_unlock(user_pg); 11128993443SEd Schouten } else { 11228993443SEd Schouten /* 11328993443SEd Schouten * Even if a physical page does not exist in the 11428993443SEd Schouten * object chain's first object, a physical page from a 11528993443SEd Schouten * backing object may be mapped read only. 11628993443SEd Schouten */ 11728993443SEd Schouten if (uobject->backing_object != NULL) 11828993443SEd Schouten pmap_remove(map->pmap, uaddr, uaddr + PAGE_SIZE); 11928993443SEd Schouten } 12028993443SEd Schouten vm_page_insert(kern_pg, uobject, upindex); 12128993443SEd Schouten vm_page_dirty(kern_pg); 12228993443SEd Schouten VM_OBJECT_UNLOCK(uobject); 12328993443SEd Schouten vm_map_lookup_done(map, entry); 12428993443SEd Schouten return(KERN_SUCCESS); 12528993443SEd Schouten } 12628993443SEd Schouten #endif /* ZERO_COPY_SOCKETS */ 12728993443SEd Schouten 12828993443SEd Schouten int 12928993443SEd Schouten uiomove(void *cp, int n, struct uio *uio) 13028993443SEd Schouten { 13128993443SEd Schouten struct thread *td = curthread; 13228993443SEd Schouten struct iovec *iov; 13328993443SEd Schouten u_int cnt; 13428993443SEd Schouten int error = 0; 13528993443SEd Schouten int save = 0; 13628993443SEd Schouten 13728993443SEd Schouten KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 13828993443SEd Schouten ("uiomove: mode")); 13928993443SEd Schouten KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 14028993443SEd Schouten ("uiomove proc")); 14128993443SEd Schouten WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 14228993443SEd Schouten "Calling uiomove()"); 14328993443SEd Schouten 14428993443SEd Schouten save = td->td_pflags & TDP_DEADLKTREAT; 14528993443SEd Schouten td->td_pflags |= TDP_DEADLKTREAT; 14628993443SEd Schouten 14728993443SEd Schouten while (n > 0 && uio->uio_resid) { 14828993443SEd Schouten iov = uio->uio_iov; 14928993443SEd Schouten cnt = iov->iov_len; 15028993443SEd Schouten if (cnt == 0) { 15128993443SEd Schouten uio->uio_iov++; 15228993443SEd Schouten uio->uio_iovcnt--; 15328993443SEd Schouten continue; 15428993443SEd Schouten } 15528993443SEd Schouten if (cnt > n) 15628993443SEd Schouten cnt = n; 15728993443SEd Schouten 15828993443SEd Schouten switch (uio->uio_segflg) { 15928993443SEd Schouten 16028993443SEd Schouten case UIO_USERSPACE: 161*08b163faSMatthew D Fleming maybe_yield(); 16228993443SEd Schouten if (uio->uio_rw == UIO_READ) 16328993443SEd Schouten error = copyout(cp, iov->iov_base, cnt); 16428993443SEd Schouten else 16528993443SEd Schouten error = copyin(iov->iov_base, cp, cnt); 16628993443SEd Schouten if (error) 16728993443SEd Schouten goto out; 16828993443SEd Schouten break; 16928993443SEd Schouten 17028993443SEd Schouten case UIO_SYSSPACE: 17128993443SEd Schouten if (uio->uio_rw == UIO_READ) 17228993443SEd Schouten bcopy(cp, iov->iov_base, cnt); 17328993443SEd Schouten else 17428993443SEd Schouten bcopy(iov->iov_base, cp, cnt); 17528993443SEd Schouten break; 17628993443SEd Schouten case UIO_NOCOPY: 17728993443SEd Schouten break; 17828993443SEd Schouten } 17928993443SEd Schouten iov->iov_base = (char *)iov->iov_base + cnt; 18028993443SEd Schouten iov->iov_len -= cnt; 18128993443SEd Schouten uio->uio_resid -= cnt; 18228993443SEd Schouten uio->uio_offset += cnt; 18328993443SEd Schouten cp = (char *)cp + cnt; 18428993443SEd Schouten n -= cnt; 18528993443SEd Schouten } 18628993443SEd Schouten out: 18728993443SEd Schouten if (save == 0) 18828993443SEd Schouten td->td_pflags &= ~TDP_DEADLKTREAT; 18928993443SEd Schouten return (error); 19028993443SEd Schouten } 19128993443SEd Schouten 19228993443SEd Schouten /* 19328993443SEd Schouten * Wrapper for uiomove() that validates the arguments against a known-good 19428993443SEd Schouten * kernel buffer. Currently, uiomove accepts a signed (n) argument, which 19528993443SEd Schouten * is almost definitely a bad thing, so we catch that here as well. We 19628993443SEd Schouten * return a runtime failure, but it might be desirable to generate a runtime 19728993443SEd Schouten * assertion failure instead. 19828993443SEd Schouten */ 19928993443SEd Schouten int 20028993443SEd Schouten uiomove_frombuf(void *buf, int buflen, struct uio *uio) 20128993443SEd Schouten { 20228993443SEd Schouten unsigned int offset, n; 20328993443SEd Schouten 20428993443SEd Schouten if (uio->uio_offset < 0 || uio->uio_resid < 0 || 20528993443SEd Schouten (offset = uio->uio_offset) != uio->uio_offset) 20628993443SEd Schouten return (EINVAL); 20728993443SEd Schouten if (buflen <= 0 || offset >= buflen) 20828993443SEd Schouten return (0); 20928993443SEd Schouten if ((n = buflen - offset) > INT_MAX) 21028993443SEd Schouten return (EINVAL); 21128993443SEd Schouten return (uiomove((char *)buf + offset, n, uio)); 21228993443SEd Schouten } 21328993443SEd Schouten 21428993443SEd Schouten #ifdef ZERO_COPY_SOCKETS 21528993443SEd Schouten /* 21628993443SEd Schouten * Experimental support for zero-copy I/O 21728993443SEd Schouten */ 21828993443SEd Schouten static int 21928993443SEd Schouten userspaceco(void *cp, u_int cnt, struct uio *uio, int disposable) 22028993443SEd Schouten { 22128993443SEd Schouten struct iovec *iov; 22228993443SEd Schouten int error; 22328993443SEd Schouten 22428993443SEd Schouten iov = uio->uio_iov; 22528993443SEd Schouten if (uio->uio_rw == UIO_READ) { 22628993443SEd Schouten if ((so_zero_copy_receive != 0) 22728993443SEd Schouten && ((cnt & PAGE_MASK) == 0) 22828993443SEd Schouten && ((((intptr_t) iov->iov_base) & PAGE_MASK) == 0) 22928993443SEd Schouten && ((uio->uio_offset & PAGE_MASK) == 0) 23028993443SEd Schouten && ((((intptr_t) cp) & PAGE_MASK) == 0) 23128993443SEd Schouten && (disposable != 0)) { 23228993443SEd Schouten /* SOCKET: use page-trading */ 23328993443SEd Schouten /* 23428993443SEd Schouten * We only want to call vm_pgmoveco() on 23528993443SEd Schouten * disposeable pages, since it gives the 23628993443SEd Schouten * kernel page to the userland process. 23728993443SEd Schouten */ 23828993443SEd Schouten error = vm_pgmoveco(&curproc->p_vmspace->vm_map, 23928993443SEd Schouten (vm_offset_t)cp, (vm_offset_t)iov->iov_base); 24028993443SEd Schouten 24128993443SEd Schouten /* 24228993443SEd Schouten * If we get an error back, attempt 24328993443SEd Schouten * to use copyout() instead. The 24428993443SEd Schouten * disposable page should be freed 24528993443SEd Schouten * automatically if we weren't able to move 24628993443SEd Schouten * it into userland. 24728993443SEd Schouten */ 24828993443SEd Schouten if (error != 0) 24928993443SEd Schouten error = copyout(cp, iov->iov_base, cnt); 25028993443SEd Schouten } else { 25128993443SEd Schouten error = copyout(cp, iov->iov_base, cnt); 25228993443SEd Schouten } 25328993443SEd Schouten } else { 25428993443SEd Schouten error = copyin(iov->iov_base, cp, cnt); 25528993443SEd Schouten } 25628993443SEd Schouten return (error); 25728993443SEd Schouten } 25828993443SEd Schouten 25928993443SEd Schouten int 26028993443SEd Schouten uiomoveco(void *cp, int n, struct uio *uio, int disposable) 26128993443SEd Schouten { 26228993443SEd Schouten struct iovec *iov; 26328993443SEd Schouten u_int cnt; 26428993443SEd Schouten int error; 26528993443SEd Schouten 26628993443SEd Schouten KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, 26728993443SEd Schouten ("uiomoveco: mode")); 26828993443SEd Schouten KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, 26928993443SEd Schouten ("uiomoveco proc")); 27028993443SEd Schouten 27128993443SEd Schouten while (n > 0 && uio->uio_resid) { 27228993443SEd Schouten iov = uio->uio_iov; 27328993443SEd Schouten cnt = iov->iov_len; 27428993443SEd Schouten if (cnt == 0) { 27528993443SEd Schouten uio->uio_iov++; 27628993443SEd Schouten uio->uio_iovcnt--; 27728993443SEd Schouten continue; 27828993443SEd Schouten } 27928993443SEd Schouten if (cnt > n) 28028993443SEd Schouten cnt = n; 28128993443SEd Schouten 28228993443SEd Schouten switch (uio->uio_segflg) { 28328993443SEd Schouten 28428993443SEd Schouten case UIO_USERSPACE: 285*08b163faSMatthew D Fleming maybe_yield(); 28628993443SEd Schouten error = userspaceco(cp, cnt, uio, disposable); 28728993443SEd Schouten if (error) 28828993443SEd Schouten return (error); 28928993443SEd Schouten break; 29028993443SEd Schouten 29128993443SEd Schouten case UIO_SYSSPACE: 29228993443SEd Schouten if (uio->uio_rw == UIO_READ) 29328993443SEd Schouten bcopy(cp, iov->iov_base, cnt); 29428993443SEd Schouten else 29528993443SEd Schouten bcopy(iov->iov_base, cp, cnt); 29628993443SEd Schouten break; 29728993443SEd Schouten case UIO_NOCOPY: 29828993443SEd Schouten break; 29928993443SEd Schouten } 30028993443SEd Schouten iov->iov_base = (char *)iov->iov_base + cnt; 30128993443SEd Schouten iov->iov_len -= cnt; 30228993443SEd Schouten uio->uio_resid -= cnt; 30328993443SEd Schouten uio->uio_offset += cnt; 30428993443SEd Schouten cp = (char *)cp + cnt; 30528993443SEd Schouten n -= cnt; 30628993443SEd Schouten } 30728993443SEd Schouten return (0); 30828993443SEd Schouten } 30928993443SEd Schouten #endif /* ZERO_COPY_SOCKETS */ 31028993443SEd Schouten 31128993443SEd Schouten /* 31228993443SEd Schouten * Give next character to user as result of read. 31328993443SEd Schouten */ 31428993443SEd Schouten int 31528993443SEd Schouten ureadc(int c, struct uio *uio) 31628993443SEd Schouten { 31728993443SEd Schouten struct iovec *iov; 31828993443SEd Schouten char *iov_base; 31928993443SEd Schouten 32028993443SEd Schouten WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, 32128993443SEd Schouten "Calling ureadc()"); 32228993443SEd Schouten 32328993443SEd Schouten again: 32428993443SEd Schouten if (uio->uio_iovcnt == 0 || uio->uio_resid == 0) 32528993443SEd Schouten panic("ureadc"); 32628993443SEd Schouten iov = uio->uio_iov; 32728993443SEd Schouten if (iov->iov_len == 0) { 32828993443SEd Schouten uio->uio_iovcnt--; 32928993443SEd Schouten uio->uio_iov++; 33028993443SEd Schouten goto again; 33128993443SEd Schouten } 33228993443SEd Schouten switch (uio->uio_segflg) { 33328993443SEd Schouten 33428993443SEd Schouten case UIO_USERSPACE: 33528993443SEd Schouten if (subyte(iov->iov_base, c) < 0) 33628993443SEd Schouten return (EFAULT); 33728993443SEd Schouten break; 33828993443SEd Schouten 33928993443SEd Schouten case UIO_SYSSPACE: 34028993443SEd Schouten iov_base = iov->iov_base; 34128993443SEd Schouten *iov_base = c; 34228993443SEd Schouten iov->iov_base = iov_base; 34328993443SEd Schouten break; 34428993443SEd Schouten 34528993443SEd Schouten case UIO_NOCOPY: 34628993443SEd Schouten break; 34728993443SEd Schouten } 34828993443SEd Schouten iov->iov_base = (char *)iov->iov_base + 1; 34928993443SEd Schouten iov->iov_len--; 35028993443SEd Schouten uio->uio_resid--; 35128993443SEd Schouten uio->uio_offset++; 35228993443SEd Schouten return (0); 35328993443SEd Schouten } 35428993443SEd Schouten 355*08b163faSMatthew D Fleming int 356*08b163faSMatthew D Fleming should_yield(void) 357*08b163faSMatthew D Fleming { 358*08b163faSMatthew D Fleming 359*08b163faSMatthew D Fleming return (ticks - PCPU_GET(switchticks) >= hogticks); 360*08b163faSMatthew D Fleming } 361*08b163faSMatthew D Fleming 362*08b163faSMatthew D Fleming void 363*08b163faSMatthew D Fleming maybe_yield(void) 364*08b163faSMatthew D Fleming { 365*08b163faSMatthew D Fleming 366*08b163faSMatthew D Fleming if (should_yield()) 367*08b163faSMatthew D Fleming uio_yield(); 368*08b163faSMatthew D Fleming } 369*08b163faSMatthew D Fleming 37028993443SEd Schouten void 37128993443SEd Schouten uio_yield(void) 37228993443SEd Schouten { 37328993443SEd Schouten struct thread *td; 37428993443SEd Schouten 37528993443SEd Schouten td = curthread; 37628993443SEd Schouten DROP_GIANT(); 37728993443SEd Schouten thread_lock(td); 37828993443SEd Schouten sched_prio(td, td->td_user_pri); 37928993443SEd Schouten mi_switch(SW_INVOL | SWT_RELINQUISH, NULL); 38028993443SEd Schouten thread_unlock(td); 38128993443SEd Schouten PICKUP_GIANT(); 38228993443SEd Schouten } 38328993443SEd Schouten 38428993443SEd Schouten int 38528993443SEd Schouten copyinfrom(const void * __restrict src, void * __restrict dst, size_t len, 38628993443SEd Schouten int seg) 38728993443SEd Schouten { 38828993443SEd Schouten int error = 0; 38928993443SEd Schouten 39028993443SEd Schouten switch (seg) { 39128993443SEd Schouten case UIO_USERSPACE: 39228993443SEd Schouten error = copyin(src, dst, len); 39328993443SEd Schouten break; 39428993443SEd Schouten case UIO_SYSSPACE: 39528993443SEd Schouten bcopy(src, dst, len); 39628993443SEd Schouten break; 39728993443SEd Schouten default: 39828993443SEd Schouten panic("copyinfrom: bad seg %d\n", seg); 39928993443SEd Schouten } 40028993443SEd Schouten return (error); 40128993443SEd Schouten } 40228993443SEd Schouten 40328993443SEd Schouten int 40428993443SEd Schouten copyinstrfrom(const void * __restrict src, void * __restrict dst, size_t len, 40528993443SEd Schouten size_t * __restrict copied, int seg) 40628993443SEd Schouten { 40728993443SEd Schouten int error = 0; 40828993443SEd Schouten 40928993443SEd Schouten switch (seg) { 41028993443SEd Schouten case UIO_USERSPACE: 41128993443SEd Schouten error = copyinstr(src, dst, len, copied); 41228993443SEd Schouten break; 41328993443SEd Schouten case UIO_SYSSPACE: 41428993443SEd Schouten error = copystr(src, dst, len, copied); 41528993443SEd Schouten break; 41628993443SEd Schouten default: 41728993443SEd Schouten panic("copyinstrfrom: bad seg %d\n", seg); 41828993443SEd Schouten } 41928993443SEd Schouten return (error); 42028993443SEd Schouten } 42128993443SEd Schouten 42228993443SEd Schouten int 42328993443SEd Schouten copyiniov(struct iovec *iovp, u_int iovcnt, struct iovec **iov, int error) 42428993443SEd Schouten { 42528993443SEd Schouten u_int iovlen; 42628993443SEd Schouten 42728993443SEd Schouten *iov = NULL; 42828993443SEd Schouten if (iovcnt > UIO_MAXIOV) 42928993443SEd Schouten return (error); 43028993443SEd Schouten iovlen = iovcnt * sizeof (struct iovec); 43128993443SEd Schouten *iov = malloc(iovlen, M_IOV, M_WAITOK); 43228993443SEd Schouten error = copyin(iovp, *iov, iovlen); 43328993443SEd Schouten if (error) { 43428993443SEd Schouten free(*iov, M_IOV); 43528993443SEd Schouten *iov = NULL; 43628993443SEd Schouten } 43728993443SEd Schouten return (error); 43828993443SEd Schouten } 43928993443SEd Schouten 44028993443SEd Schouten int 44128993443SEd Schouten copyinuio(struct iovec *iovp, u_int iovcnt, struct uio **uiop) 44228993443SEd Schouten { 44328993443SEd Schouten struct iovec *iov; 44428993443SEd Schouten struct uio *uio; 44528993443SEd Schouten u_int iovlen; 44628993443SEd Schouten int error, i; 44728993443SEd Schouten 44828993443SEd Schouten *uiop = NULL; 44928993443SEd Schouten if (iovcnt > UIO_MAXIOV) 45028993443SEd Schouten return (EINVAL); 45128993443SEd Schouten iovlen = iovcnt * sizeof (struct iovec); 45228993443SEd Schouten uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 45328993443SEd Schouten iov = (struct iovec *)(uio + 1); 45428993443SEd Schouten error = copyin(iovp, iov, iovlen); 45528993443SEd Schouten if (error) { 45628993443SEd Schouten free(uio, M_IOV); 45728993443SEd Schouten return (error); 45828993443SEd Schouten } 45928993443SEd Schouten uio->uio_iov = iov; 46028993443SEd Schouten uio->uio_iovcnt = iovcnt; 46128993443SEd Schouten uio->uio_segflg = UIO_USERSPACE; 46228993443SEd Schouten uio->uio_offset = -1; 46328993443SEd Schouten uio->uio_resid = 0; 46428993443SEd Schouten for (i = 0; i < iovcnt; i++) { 46528993443SEd Schouten if (iov->iov_len > INT_MAX - uio->uio_resid) { 46628993443SEd Schouten free(uio, M_IOV); 46728993443SEd Schouten return (EINVAL); 46828993443SEd Schouten } 46928993443SEd Schouten uio->uio_resid += iov->iov_len; 47028993443SEd Schouten iov++; 47128993443SEd Schouten } 47228993443SEd Schouten *uiop = uio; 47328993443SEd Schouten return (0); 47428993443SEd Schouten } 47528993443SEd Schouten 47628993443SEd Schouten struct uio * 47728993443SEd Schouten cloneuio(struct uio *uiop) 47828993443SEd Schouten { 47928993443SEd Schouten struct uio *uio; 48028993443SEd Schouten int iovlen; 48128993443SEd Schouten 48228993443SEd Schouten iovlen = uiop->uio_iovcnt * sizeof (struct iovec); 48328993443SEd Schouten uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); 48428993443SEd Schouten *uio = *uiop; 48528993443SEd Schouten uio->uio_iov = (struct iovec *)(uio + 1); 48628993443SEd Schouten bcopy(uiop->uio_iov, uio->uio_iov, iovlen); 48728993443SEd Schouten return (uio); 48828993443SEd Schouten } 489