[BACK]Return to uvm_io.c CVS log [TXT][DIR] Up to [local] / sys / uvm

Annotation of sys/uvm/uvm_io.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: uvm_io.c,v 1.16 2005/11/04 21:48:07 miod Exp $        */
                      2: /*     $NetBSD: uvm_io.c,v 1.12 2000/06/27 17:29:23 mrg Exp $  */
                      3:
                      4: /*
                      5:  *
                      6:  * Copyright (c) 1997 Charles D. Cranor and Washington University.
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed by Charles D. Cranor and
                     20:  *      Washington University.
                     21:  * 4. The name of the author may not be used to endorse or promote products
                     22:  *    derived from this software without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     26:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     27:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     28:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     29:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     30:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     31:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     32:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     33:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     34:  *
                     35:  * from: Id: uvm_io.c,v 1.1.2.2 1997/12/30 12:02:00 mrg Exp
                     36:  */
                     37:
                     38: /*
                     39:  * uvm_io.c: uvm i/o ops
                     40:  */
                     41:
                     42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/mman.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/malloc.h>
                     47: #include <sys/uio.h>
                     48:
                     49: #include <uvm/uvm.h>
                     50:
                     51: /*
                     52:  * functions
                     53:  */
                     54:
                     55: /*
                     56:  * uvm_io: perform I/O on a map
                     57:  *
                     58:  * => caller must have a reference to "map" so that it doesn't go away
                     59:  *    while we are working.
                     60:  */
                     61:
                     62: int
                     63: uvm_io(vm_map_t map, struct uio *uio, int flags)
                     64: {
                     65:        vaddr_t baseva, endva, pageoffset, kva;
                     66:        vsize_t chunksz, togo, sz;
                     67:        vm_map_entry_t dead_entries;
                     68:        int error, extractflags;
                     69:
                     70:        /*
                     71:         * step 0: sanity checks and set up for copy loop.  start with a
                     72:         * large chunk size.  if we have trouble finding vm space we will
                     73:         * reduce it.
                     74:         */
                     75:
                     76:        if (uio->uio_resid == 0)
                     77:                return(0);
                     78:        togo = uio->uio_resid;
                     79:
                     80:        baseva = (vaddr_t) uio->uio_offset;
                     81:        endva = baseva + (togo - 1);
                     82:
                     83:        if (endva < baseva)   /* wrap around? */
                     84:                return(EIO);
                     85:
                     86:        if (baseva >= VM_MAXUSER_ADDRESS)
                     87:                return(0);
                     88:        if (endva >= VM_MAXUSER_ADDRESS)
                     89:                /* EOF truncate */
                     90:                togo = togo - (endva - VM_MAXUSER_ADDRESS + 1);
                     91:        pageoffset = baseva & PAGE_MASK;
                     92:        baseva = trunc_page(baseva);
                     93:        chunksz = min(round_page(togo + pageoffset), MAXBSIZE);
                     94:        error = 0;
                     95:
                     96:        extractflags = UVM_EXTRACT_QREF | UVM_EXTRACT_CONTIG;
                     97:        if (flags & UVM_IO_FIXPROT)
                     98:                extractflags |= UVM_EXTRACT_FIXPROT;
                     99:
                    100:        /*
                    101:         * step 1: main loop...  while we've got data to move
                    102:         */
                    103:
                    104:        for (/*null*/; togo > 0 ; pageoffset = 0) {
                    105:
                    106:                /*
                    107:                 * step 2: extract mappings from the map into kernel_map
                    108:                 */
                    109:
                    110:                error = uvm_map_extract(map, baseva, chunksz, kernel_map, &kva,
                    111:                    extractflags);
                    112:                if (error) {
                    113:
                    114:                        /* retry with a smaller chunk... */
                    115:                        if (error == ENOMEM && chunksz > PAGE_SIZE) {
                    116:                                chunksz = trunc_page(chunksz / 2);
                    117:                                if (chunksz < PAGE_SIZE)
                    118:                                        chunksz = PAGE_SIZE;
                    119:                                continue;
                    120:                        }
                    121:
                    122:                        break;
                    123:                }
                    124:
                    125:                /*
                    126:                 * step 3: move a chunk of data
                    127:                 */
                    128:
                    129:                sz = chunksz - pageoffset;
                    130:                if (sz > togo)
                    131:                        sz = togo;
                    132:                error = uiomove((caddr_t) (kva + pageoffset), sz, uio);
                    133:                togo -= sz;
                    134:                baseva += chunksz;
                    135:
                    136:
                    137:                /*
                    138:                 * step 4: unmap the area of kernel memory
                    139:                 */
                    140:
                    141:                vm_map_lock(kernel_map);
                    142:                uvm_unmap_remove(kernel_map, kva, kva+chunksz,
                    143:                    &dead_entries, NULL);
                    144:                vm_map_unlock(kernel_map);
                    145:
                    146:                if (dead_entries != NULL)
                    147:                        uvm_unmap_detach(dead_entries, AMAP_REFALL);
                    148:
                    149:                /*
                    150:                 * We defer checking the error return from uiomove until
                    151:                 * here so that we won't leak memory.
                    152:                 */
                    153:                if (error)
                    154:                        break;
                    155:        }
                    156:
                    157:        /*
                    158:         * done
                    159:         */
                    160:
                    161:        return (error);
                    162: }

CVSweb