os161-1.99
 All Data Structures
uio.c
00001 /*
00002  * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
00003  *      The President and Fellows of Harvard College.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 #include <types.h>
00031 #include <lib.h>
00032 #include <uio.h>
00033 #include <proc.h>
00034 #include <current.h>
00035 #include <copyinout.h>
00036 
00037 /*
00038  * See uio.h for a description.
00039  */
00040 
00041 int
00042 uiomove(void *ptr, size_t n, struct uio *uio)
00043 {
00044         struct iovec *iov;
00045         size_t size;
00046         int result;
00047 
00048         if (uio->uio_rw != UIO_READ && uio->uio_rw != UIO_WRITE) {
00049                 panic("uiomove: Invalid uio_rw %d\n", (int) uio->uio_rw);
00050         }
00051         if (uio->uio_segflg==UIO_SYSSPACE) {
00052                 KASSERT(uio->uio_space == NULL);
00053         }
00054         else {
00055                 KASSERT(uio->uio_space == curproc_getas());
00056         }
00057 
00058         while (n > 0 && uio->uio_resid > 0) {
00059                 /* get the first iovec */
00060                 iov = uio->uio_iov;
00061                 size = iov->iov_len;
00062 
00063                 if (size > n) {
00064                         size = n;
00065                 }
00066 
00067                 if (size == 0) {
00068                         /* move to the next iovec and try again */
00069                         uio->uio_iov++;
00070                         uio->uio_iovcnt--;
00071                         if (uio->uio_iovcnt == 0) {
00072                                 /* 
00073                                  * This should only happen if you set
00074                                  * uio_resid incorrectly (to more than
00075                                  * the total length of buffers the uio
00076                                  * points to).
00077                                  */
00078                                 panic("uiomove: ran out of buffers\n");
00079                         }
00080                         continue;
00081                 }
00082 
00083                 switch (uio->uio_segflg) {
00084                     case UIO_SYSSPACE:
00085                             result = 0;
00086                             if (uio->uio_rw == UIO_READ) {
00087                                     memmove(iov->iov_kbase, ptr, size);
00088                             }
00089                             else {
00090                                     memmove(ptr, iov->iov_kbase, size);
00091                             }
00092                             iov->iov_kbase = ((char *)iov->iov_kbase+size);
00093                             break;
00094                     case UIO_USERSPACE:
00095                     case UIO_USERISPACE:
00096                             if (uio->uio_rw == UIO_READ) {
00097                                     result = copyout(ptr, iov->iov_ubase,size);
00098                             }
00099                             else {
00100                                     result = copyin(iov->iov_ubase, ptr, size);
00101                             }
00102                             if (result) {
00103                                     return result;
00104                             }
00105                             iov->iov_ubase += size;
00106                             break;
00107                     default:
00108                             panic("uiomove: Invalid uio_segflg %d\n",
00109                                   (int)uio->uio_segflg);
00110                 }
00111 
00112                 iov->iov_len -= size;
00113                 uio->uio_resid -= size;
00114                 uio->uio_offset += size;
00115                 ptr = ((char *)ptr + size);
00116                 n -= size;
00117         }
00118 
00119         return 0;
00120 }
00121 
00122 int
00123 uiomovezeros(size_t n, struct uio *uio)
00124 {
00125         /* static, so initialized as zero */
00126         static char zeros[16];
00127         size_t amt;
00128         int result;
00129 
00130         /* This only makes sense when reading */
00131         KASSERT(uio->uio_rw == UIO_READ);
00132 
00133         while (n > 0) {
00134                 amt = sizeof(zeros);
00135                 if (amt > n) {
00136                         amt = n;
00137                 }
00138                 result = uiomove(zeros, amt, uio);
00139                 if (result) {
00140                         return result;
00141                 }
00142                 n -= amt;
00143         }
00144 
00145         return 0;
00146 }
00147 
00148 /*
00149  * Convenience function to initialize an iovec and uio for kernel I/O.
00150  */
00151 
00152 void
00153 uio_kinit(struct iovec *iov, struct uio *u,
00154           void *kbuf, size_t len, off_t pos, enum uio_rw rw)
00155 {
00156         iov->iov_kbase = kbuf;
00157         iov->iov_len = len;
00158         u->uio_iov = iov;
00159         u->uio_iovcnt = 1;
00160         u->uio_offset = pos;
00161         u->uio_resid = len;
00162         u->uio_segflg = UIO_SYSSPACE;
00163         u->uio_rw = rw;
00164         u->uio_space = NULL;
00165 }
 All Data Structures