The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/vm/vm_pager.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 1991, 1993
    3  *      The Regents of the University of California.  All rights reserved.
    4  *
    5  * This code is derived from software contributed to Berkeley by
    6  * The Mach Operating System project at Carnegie-Mellon University.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the following acknowledgement:
   18  *      This product includes software developed by the University of
   19  *      California, Berkeley and its contributors.
   20  * 4. Neither the name of the University nor the names of its contributors
   21  *    may be used to endorse or promote products derived from this software
   22  *    without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   34  * SUCH DAMAGE.
   35  *
   36  *      from: @(#)vm_pager.c    8.6 (Berkeley) 1/12/94
   37  *
   38  *
   39  * Copyright (c) 1987, 1990 Carnegie-Mellon University.
   40  * All rights reserved.
   41  *
   42  * Authors: Avadis Tevanian, Jr., Michael Wayne Young
   43  *
   44  * Permission to use, copy, modify and distribute this software and
   45  * its documentation is hereby granted, provided that both the copyright
   46  * notice and this permission notice appear in all copies of the
   47  * software, derivative works or modified versions, and any portions
   48  * thereof, and that both notices appear in supporting documentation.
   49  *
   50  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
   51  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
   52  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   53  *
   54  * Carnegie Mellon requests users of this software to return to
   55  *
   56  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   57  *  School of Computer Science
   58  *  Carnegie Mellon University
   59  *  Pittsburgh PA 15213-3890
   60  *
   61  * any improvements or extensions that they make and grant Carnegie the
   62  * rights to redistribute these changes.
   63  *
   64  * $FreeBSD: src/sys/vm/vm_pager.c,v 1.24.2.2 1999/09/05 08:24:38 peter Exp $
   65  */
   66 
   67 /*
   68  *      Paging space routine stubs.  Emulates a matchmaker-like interface
   69  *      for builtin pagers.
   70  */
   71 
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/proc.h>
   75 #include <sys/malloc.h>
   76 #include <sys/buf.h>
   77 #include <sys/ucred.h>
   78 
   79 #include <vm/vm.h>
   80 #include <vm/vm_param.h>
   81 #include <vm/vm_prot.h>
   82 #include <vm/vm_object.h>
   83 #include <vm/vm_page.h>
   84 #include <vm/vm_kern.h>
   85 #include <vm/vm_pager.h>
   86 #include <vm/vm_extern.h>
   87 
   88 extern struct pagerops defaultpagerops;
   89 extern struct pagerops swappagerops;
   90 extern struct pagerops vnodepagerops;
   91 extern struct pagerops devicepagerops;
   92 
   93 static struct pagerops *pagertab[] = {
   94         &defaultpagerops,       /* OBJT_DEFAULT */
   95         &swappagerops,          /* OBJT_SWAP */
   96         &vnodepagerops,         /* OBJT_VNODE */
   97         &devicepagerops,        /* OBJT_DEVICE */
   98 };
   99 static int npagers = sizeof(pagertab) / sizeof(pagertab[0]);
  100 
  101 /*
  102  * Kernel address space for mapping pages.
  103  * Used by pagers where KVAs are needed for IO.
  104  *
  105  * XXX needs to be large enough to support the number of pending async
  106  * cleaning requests (NPENDINGIO == 64) * the maximum swap cluster size
  107  * (MAXPHYS == 64k) if you want to get the most efficiency.
  108  */
  109 #define PAGER_MAP_SIZE  (8 * 1024 * 1024)
  110 
  111 int pager_map_size = PAGER_MAP_SIZE;
  112 vm_map_t pager_map;
  113 static int bswneeded;
  114 static vm_offset_t swapbkva;            /* swap buffers kva */
  115 
  116 void
  117 vm_pager_init()
  118 {
  119         struct pagerops **pgops;
  120 
  121         /*
  122          * Initialize known pagers
  123          */
  124         for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
  125                 if (pgops && ((*pgops)->pgo_init != NULL))
  126                         (*(*pgops)->pgo_init) ();
  127 }
  128 
  129 void
  130 vm_pager_bufferinit()
  131 {
  132         struct buf *bp;
  133         int i;
  134 
  135         bp = swbuf;
  136         /*
  137          * Now set up swap and physical I/O buffer headers.
  138          */
  139         for (i = 0; i < nswbuf - 1; i++, bp++) {
  140                 TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist);
  141                 bp->b_rcred = bp->b_wcred = NOCRED;
  142                 bp->b_vnbufs.le_next = NOLIST;
  143         }
  144         bp->b_rcred = bp->b_wcred = NOCRED;
  145         bp->b_vnbufs.le_next = NOLIST;
  146 
  147         swapbkva = kmem_alloc_pageable(pager_map, nswbuf * MAXPHYS);
  148         if (!swapbkva)
  149                 panic("Not enough pager_map VM space for physical buffers");
  150 }
  151 
  152 /*
  153  * Allocate an instance of a pager of the given type.
  154  * Size, protection and offset parameters are passed in for pagers that
  155  * need to perform page-level validation (e.g. the device pager).
  156  */
  157 vm_object_t
  158 vm_pager_allocate(type, handle, size, prot, off)
  159         objtype_t type;
  160         void *handle;
  161         vm_size_t size;
  162         vm_prot_t prot;
  163         vm_ooffset_t off;
  164 {
  165         struct pagerops *ops;
  166 
  167         ops = pagertab[type];
  168         if (ops)
  169                 return ((*ops->pgo_alloc) (handle, size, prot, off));
  170         return (NULL);
  171 }
  172 
  173 void
  174 vm_pager_deallocate(object)
  175         vm_object_t object;
  176 {
  177         (*pagertab[object->type]->pgo_dealloc) (object);
  178 }
  179 
  180 
  181 int
  182 vm_pager_get_pages(object, m, count, reqpage)
  183         vm_object_t object;
  184         vm_page_t *m;
  185         int count;
  186         int reqpage;
  187 {
  188         return ((*pagertab[object->type]->pgo_getpages)(object, m, count, reqpage));
  189 }
  190 
  191 int
  192 vm_pager_put_pages(object, m, count, sync, rtvals)
  193         vm_object_t object;
  194         vm_page_t *m;
  195         int count;
  196         boolean_t sync;
  197         int *rtvals;
  198 {
  199         return ((*pagertab[object->type]->pgo_putpages)(object, m, count, sync, rtvals));
  200 }
  201 
  202 boolean_t
  203 vm_pager_has_page(object, offset, before, after)
  204         vm_object_t object;
  205         vm_pindex_t offset;
  206         int *before;
  207         int *after;
  208 {
  209         return ((*pagertab[object->type]->pgo_haspage) (object, offset, before, after));
  210 }
  211 
  212 /*
  213  * Called by pageout daemon before going back to sleep.
  214  * Gives pagers a chance to clean up any completed async pageing operations.
  215  */
  216 void
  217 vm_pager_sync()
  218 {
  219         struct pagerops **pgops;
  220 
  221         for (pgops = pagertab; pgops < &pagertab[npagers]; pgops++)
  222                 if (pgops && ((*pgops)->pgo_sync != NULL))
  223                         (*(*pgops)->pgo_sync) ();
  224 }
  225 
  226 vm_offset_t
  227 vm_pager_map_page(m)
  228         vm_page_t m;
  229 {
  230         vm_offset_t kva;
  231 
  232         kva = kmem_alloc_wait(pager_map, PAGE_SIZE);
  233         pmap_kenter(kva, VM_PAGE_TO_PHYS(m));
  234         return (kva);
  235 }
  236 
  237 void
  238 vm_pager_unmap_page(kva)
  239         vm_offset_t kva;
  240 {
  241         pmap_kremove(kva);
  242         kmem_free_wakeup(pager_map, kva, PAGE_SIZE);
  243 }
  244 
  245 vm_object_t
  246 vm_pager_object_lookup(pg_list, handle)
  247         register struct pagerlst *pg_list;
  248         void *handle;
  249 {
  250         register vm_object_t object;
  251 
  252         for (object = TAILQ_FIRST(pg_list); object != NULL; object = TAILQ_NEXT(object,pager_object_list))
  253                 if (object->handle == handle)
  254                         return (object);
  255         return (NULL);
  256 }
  257 
  258 /*
  259  * This routine loses a reference to the object -
  260  * thus a reference must be gained before calling.
  261  */
  262 int
  263 pager_cache(object, should_cache)
  264         vm_object_t object;
  265         boolean_t should_cache;
  266 {
  267         if (object == NULL)
  268                 return (KERN_INVALID_ARGUMENT);
  269 
  270         if (should_cache)
  271                 object->flags |= OBJ_CANPERSIST;
  272         else
  273                 object->flags &= ~OBJ_CANPERSIST;
  274 
  275         vm_object_deallocate(object);
  276 
  277         return (KERN_SUCCESS);
  278 }
  279 
  280 /*
  281  * initialize a physical buffer
  282  */
  283 
  284 static void
  285 initpbuf(struct buf *bp) {
  286         bzero(bp, sizeof *bp);
  287         bp->b_rcred = NOCRED;
  288         bp->b_wcred = NOCRED;
  289         bp->b_qindex = QUEUE_NONE;
  290         bp->b_data = (caddr_t) (MAXPHYS * (bp - swbuf)) + swapbkva;
  291         bp->b_kvabase = bp->b_data;
  292         bp->b_kvasize = MAXPHYS;
  293         bp->b_vnbufs.le_next = NOLIST;
  294 }
  295 
  296 /*
  297  * allocate a physical buffer
  298  */
  299 struct buf *
  300 getpbuf()
  301 {
  302         int s;
  303         struct buf *bp;
  304 
  305         s = splbio();
  306         /* get a bp from the swap buffer header pool */
  307         while ((bp = TAILQ_FIRST(&bswlist)) == NULL) {
  308                 bswneeded = 1;
  309                 tsleep(&bswneeded, PVM, "wswbuf", 0);
  310         }
  311         TAILQ_REMOVE(&bswlist, bp, b_freelist);
  312         splx(s);
  313 
  314         initpbuf(bp);
  315         return bp;
  316 }
  317 
  318 /*
  319  * allocate a physical buffer, if one is available
  320  */
  321 struct buf *
  322 trypbuf()
  323 {
  324         int s;
  325         struct buf *bp;
  326 
  327         s = splbio();
  328         if ((bp = TAILQ_FIRST(&bswlist)) == NULL) {
  329                 splx(s);
  330                 return NULL;
  331         }
  332         TAILQ_REMOVE(&bswlist, bp, b_freelist);
  333         splx(s);
  334 
  335         initpbuf(bp);
  336 
  337         return bp;
  338 }
  339 
  340 /*
  341  * release a physical buffer
  342  */
  343 void
  344 relpbuf(bp)
  345         struct buf *bp;
  346 {
  347         int s;
  348 
  349         s = splbio();
  350 
  351         if (bp->b_rcred != NOCRED) {
  352                 crfree(bp->b_rcred);
  353                 bp->b_rcred = NOCRED;
  354         }
  355         if (bp->b_wcred != NOCRED) {
  356                 crfree(bp->b_wcred);
  357                 bp->b_wcred = NOCRED;
  358         }
  359         if (bp->b_vp)
  360                 pbrelvp(bp);
  361 
  362         if (bp->b_flags & B_WANTED)
  363                 wakeup(bp);
  364 
  365         TAILQ_INSERT_HEAD(&bswlist, bp, b_freelist);
  366 
  367         if (bswneeded) {
  368                 bswneeded = 0;
  369                 wakeup(&bswneeded);
  370         }
  371         splx(s);
  372 }

Cache object: bb1afb12cc0476bd3a496f2624ae06ec


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.