root/uvm/uvm_loan.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. uvm_loanentry
  2. uvm_loan
  3. uvm_loananon
  4. uvm_loanuobj
  5. uvm_loanzero
  6. uvm_unloananon
  7. uvm_unloanpage

    1 /*      $OpenBSD: uvm_loan.c,v 1.28 2007/06/18 21:51:15 pedro Exp $     */
    2 /*      $NetBSD: uvm_loan.c,v 1.22 2000/06/27 17:29:25 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_loan.c,v 1.1.6.4 1998/02/06 05:08:43 chs Exp
   36  */
   37 
   38 /*
   39  * uvm_loan.c: page loanout handler
   40  */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/proc.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mman.h>
   48 
   49 #include <uvm/uvm.h>
   50 
   51 /*
   52  * "loaned" pages are pages which are (read-only, copy-on-write) loaned 
   53  * from the VM system to other parts of the kernel.   this allows page
   54  * copying to be avoided (e.g. you can loan pages from objs/anons to
   55  * the mbuf system).
   56  *
   57  * there are 3 types of loans possible:
   58  *  O->K  uvm_object page to wired kernel page (e.g. mbuf data area)
   59  *  A->K  anon page to wired kernel page (e.g. mbuf data area)
   60  *  O->A  uvm_object to anon loan (e.g. vnode page to an anon)
   61  * note that it possible to have an O page loaned to both an A and K
   62  * at the same time.
   63  *
   64  * loans are tracked by pg->loan_count.  an O->A page will have both
   65  * a uvm_object and a vm_anon, but PQ_ANON will not be set.   this sort
   66  * of page is considered "owned" by the uvm_object (not the anon).
   67  *
   68  * each loan of a page to the kernel bumps the pg->wire_count.  the
   69  * kernel mappings for these pages will be read-only and wired.  since
   70  * the page will also be wired, it will not be a candidate for pageout,
   71  * and thus will never be pmap_page_protect()'d with VM_PROT_NONE.  a
   72  * write fault in the kernel to one of these pages will not cause
   73  * copy-on-write.  instead, the page fault is considered fatal.  this
   74  * is because the kernel mapping will have no way to look up the
   75  * object/anon which the page is owned by.  this is a good side-effect,
   76  * since a kernel write to a loaned page is an error.
   77  *
   78  * owners that want to free their pages and discover that they are 
   79  * loaned out simply "disown" them (the page becomes an orphan).  these
   80  * pages should be freed when the last loan is dropped.   in some cases
   81  * an anon may "adopt" an orphaned page.
   82  *
   83  * locking: to read pg->loan_count either the owner or the page queues
   84  * must be locked.   to modify pg->loan_count, both the owner of the page
   85  * and the PQs must be locked.   pg->flags is (as always) locked by
   86  * the owner of the page.
   87  *
   88  * note that locking from the "loaned" side is tricky since the object
   89  * getting the loaned page has no reference to the page's owner and thus
   90  * the owner could "die" at any time.   in order to prevent the owner
   91  * from dying the page queues should be locked.   this forces us to sometimes
   92  * use "try" locking.
   93  *
   94  * loans are typically broken by the following events:
   95  *  1. write fault to a loaned page 
   96  *  2. pageout of clean+inactive O->A loaned page
   97  *  3. owner frees page (e.g. pager flush)
   98  *
   99  * note that loaning a page causes all mappings of the page to become
  100  * read-only (via pmap_page_protect).   this could have an unexpected
  101  * effect on normal "wired" pages if one is not careful (XXX).
  102  */
  103 
  104 /*
  105  * local prototypes
  106  */
  107 
  108 static int      uvm_loananon(struct uvm_faultinfo *, void ***, 
  109                                 int, struct vm_anon *);
  110 static int      uvm_loanentry(struct uvm_faultinfo *, void ***, int);
  111 static int      uvm_loanuobj(struct uvm_faultinfo *, void ***, 
  112                                 int, vaddr_t);
  113 static int      uvm_loanzero(struct uvm_faultinfo *, void ***, int);
  114 
  115 /*
  116  * inlines
  117  */
  118 
  119 /*
  120  * uvm_loanentry: loan out pages in a map entry (helper fn for uvm_loan())
  121  *
  122  * => "ufi" is the result of a successful map lookup (meaning that
  123  *      the maps are locked by the caller)
  124  * => we may unlock the maps if needed (for I/O)
  125  * => we put our output result in "output"
  126  * => we return the number of pages we loaned, or -1 if we had an error
  127  */
  128 
  129 static __inline int
  130 uvm_loanentry(ufi, output, flags)
  131         struct uvm_faultinfo *ufi;
  132         void ***output;
  133         int flags;
  134 {
  135         vaddr_t curaddr = ufi->orig_rvaddr;
  136         vsize_t togo = ufi->size;
  137         struct vm_aref *aref = &ufi->entry->aref;
  138         struct uvm_object *uobj = ufi->entry->object.uvm_obj;
  139         struct vm_anon *anon;
  140         int rv, result = 0;
  141 
  142         /*
  143          * lock us the rest of the way down
  144          */
  145         if (uobj)
  146                 simple_lock(&uobj->vmobjlock);
  147 
  148         /*
  149          * loop until done
  150          */
  151         while (togo) {
  152 
  153                 /*
  154                  * find the page we want.   check the anon layer first.
  155                  */
  156 
  157                 if (aref->ar_amap) {
  158                         anon = amap_lookup(aref, curaddr - ufi->entry->start);
  159                 } else {
  160                         anon = NULL;
  161                 }
  162 
  163                 if (anon) {
  164                         rv = uvm_loananon(ufi, output, flags, anon);
  165                 } else if (uobj) {
  166                         rv = uvm_loanuobj(ufi, output, flags, curaddr);
  167                 } else if (UVM_ET_ISCOPYONWRITE(ufi->entry)) {
  168                         rv = uvm_loanzero(ufi, output, flags);
  169                 } else {
  170                         rv = -1;                /* null map entry... fail now */
  171                 }
  172 
  173                 /* total failure */
  174                 if (rv < 0)
  175                         return(-1);
  176 
  177                 /* relock failed, need to do another lookup */
  178                 if (rv == 0)
  179                         return(result);
  180 
  181                 /*
  182                  * got it... advance to next page
  183                  */
  184                 result++;
  185                 togo -= PAGE_SIZE;
  186                 curaddr += PAGE_SIZE;
  187         }
  188 
  189         /*
  190          * unlock everything and return
  191          */
  192         uvmfault_unlockall(ufi, aref->ar_amap, uobj, NULL);
  193         return(result);
  194 }
  195 
  196 /*
  197  * normal functions
  198  */
  199 
  200 /*
  201  * uvm_loan: loan pages out to anons or to the kernel
  202  * 
  203  * => map should be unlocked
  204  * => start and len should be multiples of PAGE_SIZE
  205  * => result is either an array of anon's or vm_pages (depending on flags)
  206  * => flag values: UVM_LOAN_TOANON - loan to anons
  207  *                 UVM_LOAN_TOPAGE - loan to wired kernel page
  208  *    one and only one of these flags must be set!
  209  */
  210 
  211 int
  212 uvm_loan(map, start, len, result, flags)
  213         struct vm_map *map;
  214         vaddr_t start;
  215         vsize_t len;
  216         void **result;
  217         int flags;
  218 {
  219         struct uvm_faultinfo ufi;
  220         void **output;
  221         int rv;
  222 
  223 #ifdef DIAGNOSTIC
  224         if (map->flags & VM_MAP_INTRSAFE)
  225                 panic("uvm_loan: intrsafe map");
  226 #endif
  227 
  228         /*
  229          * ensure that one and only one of the flags is set
  230          */
  231 
  232         if ((flags & (UVM_LOAN_TOANON|UVM_LOAN_TOPAGE)) == 
  233             (UVM_LOAN_TOANON|UVM_LOAN_TOPAGE) ||
  234             (flags & (UVM_LOAN_TOANON|UVM_LOAN_TOPAGE)) == 0)
  235                 return (EFAULT);
  236 
  237         /*
  238          * "output" is a pointer to the current place to put the loaned
  239          * page...
  240          */
  241 
  242         output = &result[0];    /* start at the beginning ... */
  243 
  244         /*
  245          * while we've got pages to do
  246          */
  247 
  248         while (len > 0) {
  249 
  250                 /*
  251                  * fill in params for a call to uvmfault_lookup
  252                  */
  253 
  254                 ufi.orig_map = map;
  255                 ufi.orig_rvaddr = start;
  256                 ufi.orig_size = len;
  257                 
  258                 /*
  259                  * do the lookup, the only time this will fail is if we hit on
  260                  * an unmapped region (an error)
  261                  */
  262 
  263                 if (!uvmfault_lookup(&ufi, FALSE)) 
  264                         goto fail;
  265 
  266                 /*
  267                  * map now locked.  now do the loanout...
  268                  */
  269                 rv = uvm_loanentry(&ufi, &output, flags);
  270                 if (rv < 0) 
  271                         goto fail;
  272 
  273                 /*
  274                  * done!  the map is unlocked.  advance, if possible.
  275                  *
  276                  * XXXCDC: could be recoded to hold the map lock with   
  277                  *         smarter code (but it only happens on map entry
  278                  *         boundaries, so it isn't that bad).
  279                  */
  280                 if (rv) {
  281                         rv <<= PAGE_SHIFT;
  282                         len -= rv;
  283                         start += rv;
  284                 }
  285         }
  286         
  287         /*
  288          * got it!   return success.
  289          */
  290 
  291         return (0);
  292 
  293 fail:
  294         /*
  295          * fail: failed to do it.   drop our loans and return failure code.
  296          */
  297         if (output - result) {
  298                 if (flags & UVM_LOAN_TOANON)
  299                         uvm_unloananon((struct vm_anon **)result,
  300                             output - result);
  301                 else
  302                         uvm_unloanpage((struct vm_page **)result,
  303                             output - result);
  304         }
  305         return (EFAULT);
  306 }
  307 
  308 /*
  309  * uvm_loananon: loan a page from an anon out
  310  * 
  311  * => return value:
  312  *      -1 = fatal error, everything is unlocked, abort.
  313  *       0 = lookup in ufi went stale, everything unlocked, relookup and
  314  *              try again
  315  *       1 = got it, everything still locked
  316  */
  317 
  318 int
  319 uvm_loananon(ufi, output, flags, anon)
  320         struct uvm_faultinfo *ufi;
  321         void ***output;
  322         int flags;
  323         struct vm_anon *anon;
  324 {
  325         struct vm_page *pg;
  326         int result;
  327 
  328         /*
  329          * if we are loaning to another anon then it is easy, we just
  330          * bump the reference count on the current anon and return a
  331          * pointer to it.
  332          */
  333         if (flags & UVM_LOAN_TOANON) {
  334                 simple_lock(&anon->an_lock);
  335                 pg = anon->an_page;
  336                 if (pg && (pg->pg_flags & PQ_ANON) != 0 && anon->an_ref == 1)
  337                         /* read protect it */
  338                         pmap_page_protect(pg, VM_PROT_READ);
  339                 anon->an_ref++;
  340                 **output = anon;
  341                 *output = (*output) + 1;
  342                 simple_unlock(&anon->an_lock);
  343                 return(1);
  344         }
  345 
  346         /*
  347          * we are loaning to a kernel-page.   we need to get the page
  348          * resident so we can wire it.   uvmfault_anonget will handle
  349          * this for us.
  350          */
  351 
  352         simple_lock(&anon->an_lock);
  353         result = uvmfault_anonget(ufi, ufi->entry->aref.ar_amap, anon);
  354 
  355         /*
  356          * if we were unable to get the anon, then uvmfault_anonget has
  357          * unlocked everything and returned an error code.
  358          */
  359 
  360         if (result != VM_PAGER_OK) {
  361 
  362                 /* need to refault (i.e. refresh our lookup) ? */
  363                 if (result == VM_PAGER_REFAULT)
  364                         return(0);
  365 
  366                 /* "try again"?   sleep a bit and retry ... */
  367                 if (result == VM_PAGER_AGAIN) {
  368                         tsleep((caddr_t)&lbolt, PVM, "loanagain", 0);
  369                         return(0);
  370                 }
  371 
  372                 /* otherwise flag it as an error */
  373                 return(-1);
  374         }
  375 
  376         /*
  377          * we have the page and its owner locked: do the loan now.
  378          */
  379 
  380         pg = anon->an_page;
  381         uvm_lock_pageq();
  382         if (pg->loan_count == 0)
  383                 pmap_page_protect(pg, VM_PROT_READ);
  384         pg->loan_count++;
  385         uvm_pagewire(pg);       /* always wire it */
  386         uvm_unlock_pageq();
  387         **output = pg;
  388         *output = (*output) + 1;
  389 
  390         /* unlock anon and return success */
  391         if (pg->uobject)
  392                 simple_unlock(&pg->uobject->vmobjlock);
  393         simple_unlock(&anon->an_lock);
  394         return(1);
  395 }
  396 
  397 /*
  398  * uvm_loanuobj: loan a page from a uobj out
  399  *
  400  * => return value:
  401  *      -1 = fatal error, everything is unlocked, abort.
  402  *       0 = lookup in ufi went stale, everything unlocked, relookup and
  403  *              try again
  404  *       1 = got it, everything still locked
  405  */
  406 
  407 int
  408 uvm_loanuobj(ufi, output, flags, va)
  409         struct uvm_faultinfo *ufi;
  410         void ***output;
  411         int flags;
  412         vaddr_t va;
  413 {
  414         struct vm_amap *amap = ufi->entry->aref.ar_amap;
  415         struct uvm_object *uobj = ufi->entry->object.uvm_obj;
  416         struct vm_page *pg;
  417         struct vm_anon *anon;
  418         int result, npages;
  419         boolean_t locked;
  420 
  421         /*
  422          * first we must make sure the page is resident.
  423          *
  424          * XXXCDC: duplicate code with uvm_fault().
  425          */
  426 
  427         if (uobj->pgops->pgo_get) {
  428                 npages = 1;
  429                 pg = NULL;
  430                 result = uobj->pgops->pgo_get(uobj, va - ufi->entry->start,
  431                     &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, PGO_LOCKED);
  432         } else {
  433                 result = VM_PAGER_ERROR;
  434         }
  435 
  436         /*
  437          * check the result of the locked pgo_get.  if there is a problem,
  438          * then we fail the loan.
  439          */
  440 
  441         if (result != VM_PAGER_OK && result != VM_PAGER_UNLOCK) {
  442                 uvmfault_unlockall(ufi, amap, uobj, NULL);
  443                 return(-1);
  444         }
  445 
  446         /*
  447          * if we need to unlock for I/O, do so now.
  448          */
  449 
  450         if (result == VM_PAGER_UNLOCK) {
  451                 uvmfault_unlockall(ufi, amap, NULL, NULL);
  452                 
  453                 npages = 1;
  454                 /* locked: uobj */
  455                 result = uobj->pgops->pgo_get(uobj, va - ufi->entry->start,
  456                     &pg, &npages, 0, VM_PROT_READ, MADV_NORMAL, 0);
  457                 /* locked: <nothing> */
  458                 
  459                 /*
  460                  * check for errors
  461                  */
  462 
  463                 if (result != VM_PAGER_OK) {
  464                          if (result == VM_PAGER_AGAIN) {
  465                                 tsleep((caddr_t)&lbolt, PVM, "fltagain2", 0);
  466                                 return(0); /* redo the lookup and try again */
  467                         } 
  468                         return(-1);     /* total failure */
  469                 }
  470 
  471                 /*
  472                  * pgo_get was a success.   attempt to relock everything.
  473                  */
  474 
  475                 locked = uvmfault_relock(ufi);
  476                 simple_lock(&uobj->vmobjlock);
  477 
  478                 /*
  479                  * verify that the page has not be released and re-verify
  480                  * that amap slot is still free.   if there is a problem we
  481                  * drop our lock (thus force a lookup refresh/retry).
  482                  */
  483                         
  484                 if ((pg->pg_flags & PG_RELEASED) != 0 ||
  485                     (locked && amap && amap_lookup(&ufi->entry->aref,
  486                     ufi->orig_rvaddr - ufi->entry->start))) {
  487                         
  488                         if (locked)
  489                                 uvmfault_unlockall(ufi, amap, NULL, NULL);
  490                         locked = FALSE;
  491                 } 
  492 
  493                 /*
  494                  * didn't get the lock?   release the page and retry.
  495                  */
  496 
  497                 if (locked == FALSE) {
  498 
  499                         if (pg->pg_flags & PG_WANTED)
  500                                 /* still holding object lock */
  501                                 wakeup(pg);
  502 
  503                         if (pg->pg_flags & PG_RELEASED) {
  504 #ifdef DIAGNOSTIC
  505                                 if (uobj->pgops->pgo_releasepg == NULL)
  506                         panic("uvm_loanuobj: object has no releasepg function");
  507 #endif
  508                                 /* frees page */
  509                                 if (uobj->pgops->pgo_releasepg(pg, NULL))
  510                                         simple_unlock(&uobj->vmobjlock);
  511                                 return (0);
  512                         }
  513 
  514                         uvm_lock_pageq();
  515                         uvm_pageactivate(pg); /* make sure it is in queues */
  516                         uvm_unlock_pageq();
  517                         atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_WANTED);
  518                         UVM_PAGE_OWN(pg, NULL);
  519                         simple_unlock(&uobj->vmobjlock);
  520                         return (0);
  521                 }
  522         }
  523 
  524         /*
  525          * at this point we have the page we want ("pg") marked PG_BUSY for us
  526          * and we have all data structures locked.   do the loanout.   page can
  527          * not be PG_RELEASED (we caught this above).
  528          */
  529 
  530         if ((flags & UVM_LOAN_TOANON) == 0) {   /* loan to wired-kernel page? */
  531                 uvm_lock_pageq();
  532                 if (pg->loan_count == 0)
  533                         pmap_page_protect(pg, VM_PROT_READ);
  534                 pg->loan_count++;
  535                 uvm_pagewire(pg);
  536                 uvm_unlock_pageq();
  537                 **output = pg;
  538                 *output = (*output) + 1;
  539                 if (pg->pg_flags & PG_WANTED)
  540                         wakeup(pg);
  541                 atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
  542                 UVM_PAGE_OWN(pg, NULL);
  543                 return(1);              /* got it! */
  544         }
  545 
  546         /*
  547          * must be a loan to an anon.   check to see if there is already
  548          * an anon associated with this page.  if so, then just return
  549          * a reference to this object.   the page should already be 
  550          * mapped read-only because it is already on loan.
  551          */
  552 
  553         if (pg->uanon) {
  554                 anon = pg->uanon;
  555                 simple_lock(&anon->an_lock);
  556                 anon->an_ref++;
  557                 simple_unlock(&anon->an_lock);
  558                 **output = anon;
  559                 *output = (*output) + 1;
  560                 uvm_lock_pageq();
  561                 uvm_pageactivate(pg);   /* reactivate */
  562                 uvm_unlock_pageq();
  563                 if (pg->pg_flags & PG_WANTED)
  564                         wakeup(pg);
  565                 atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
  566                 UVM_PAGE_OWN(pg, NULL);
  567                 return(1);
  568         }
  569         
  570         /*
  571          * need to allocate a new anon
  572          */
  573 
  574         anon = uvm_analloc();
  575         if (anon == NULL) {             /* out of VM! */
  576                 if (pg->pg_flags & PG_WANTED)
  577                         wakeup(pg);
  578                 atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
  579                 UVM_PAGE_OWN(pg, NULL);
  580                 uvmfault_unlockall(ufi, amap, uobj, NULL);
  581                 return(-1);
  582         }
  583         anon->an_page = pg;
  584         pg->uanon = anon;
  585         uvm_lock_pageq();
  586         if (pg->loan_count == 0)
  587                 pmap_page_protect(pg, VM_PROT_READ);
  588         pg->loan_count++;
  589         uvm_pageactivate(pg);
  590         uvm_unlock_pageq();
  591         **output = anon;
  592         *output = (*output) + 1;
  593         if (pg->pg_flags & PG_WANTED)
  594                 wakeup(pg);
  595         atomic_clearbits_int(&pg->pg_flags, PG_WANTED|PG_BUSY);
  596         UVM_PAGE_OWN(pg, NULL);
  597         return(1);
  598 }
  599 
  600 /*
  601  * uvm_loanzero: "loan" a zero-fill page out
  602  *
  603  * => return value:
  604  *      -1 = fatal error, everything is unlocked, abort.
  605  *       0 = lookup in ufi went stale, everything unlocked, relookup and
  606  *              try again
  607  *       1 = got it, everything still locked
  608  */
  609 
  610 int
  611 uvm_loanzero(ufi, output, flags)
  612         struct uvm_faultinfo *ufi;
  613         void ***output;
  614         int flags;
  615 {
  616         struct vm_anon *anon;
  617         struct vm_page *pg;
  618 
  619         if ((flags & UVM_LOAN_TOANON) == 0) {   /* loaning to kernel-page */
  620 
  621                 while ((pg = uvm_pagealloc(NULL, 0, NULL,
  622                     UVM_PGA_ZERO)) == NULL) {
  623                         uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap, 
  624                             ufi->entry->object.uvm_obj, NULL);
  625                         uvm_wait("loanzero1");
  626                         if (!uvmfault_relock(ufi))
  627                                 return(0);
  628                         if (ufi->entry->object.uvm_obj)
  629                                 simple_lock(
  630                                     &ufi->entry->object.uvm_obj->vmobjlock);
  631                         /* ... and try again */
  632                 }
  633                 
  634                 /* got a zero'd page; return */
  635                 atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE);
  636                 UVM_PAGE_OWN(pg, NULL);
  637                 **output = pg;
  638                 *output = (*output) + 1;
  639                 uvm_lock_pageq();
  640                 /* wire it as we are loaning to kernel-page */
  641                 uvm_pagewire(pg);
  642                 pg->loan_count = 1;
  643                 uvm_unlock_pageq();
  644                 return(1);
  645         }
  646 
  647         /* loaning to an anon */
  648         while ((anon = uvm_analloc()) == NULL || 
  649             (pg = uvm_pagealloc(NULL, 0, anon, UVM_PGA_ZERO)) == NULL) {
  650 
  651                 /* unlock everything */
  652                 uvmfault_unlockall(ufi, ufi->entry->aref.ar_amap,
  653                        ufi->entry->object.uvm_obj, NULL);
  654 
  655                 /* out of swap causes us to fail */
  656                 if (anon == NULL)
  657                         return(-1);
  658 
  659                 uvm_anfree(anon);
  660                 uvm_wait("loanzero2");          /* wait for pagedaemon */
  661 
  662                 if (!uvmfault_relock(ufi))
  663                         /* map changed while unlocked, need relookup */
  664                         return (0);
  665 
  666                 /* relock everything else */
  667                 if (ufi->entry->object.uvm_obj)
  668                         simple_lock(&ufi->entry->object.uvm_obj->vmobjlock);
  669                 /* ... and try again */
  670         }
  671 
  672         /* got a zero'd page; return */
  673         atomic_clearbits_int(&pg->pg_flags, PG_BUSY|PG_FAKE);
  674         UVM_PAGE_OWN(pg, NULL);
  675         uvm_lock_pageq();
  676         uvm_pageactivate(pg);
  677         uvm_unlock_pageq();
  678         **output = anon;
  679         *output = (*output) + 1;
  680         return(1);
  681 }
  682 
  683 
  684 /*
  685  * uvm_unloananon: kill loans on anons (basically a normal ref drop)
  686  *
  687  * => we expect all our resources to be unlocked
  688  */
  689 
  690 void
  691 uvm_unloananon(aloans, nanons)
  692         struct vm_anon **aloans;
  693         int nanons;
  694 {
  695         struct vm_anon *anon;
  696 
  697         while (nanons-- > 0) {
  698                 int refs;
  699 
  700                 anon = *aloans++;
  701                 simple_lock(&anon->an_lock);
  702                 refs = --anon->an_ref;
  703                 simple_unlock(&anon->an_lock);
  704 
  705                 if (refs == 0) {
  706                         uvm_anfree(anon);       /* last reference: kill anon */
  707                 }
  708         }
  709 }
  710 
  711 /*
  712  * uvm_unloanpage: kill loans on pages loaned out to the kernel
  713  *
  714  * => we expect all our resources to be unlocked
  715  */
  716 
  717 void
  718 uvm_unloanpage(ploans, npages)
  719         struct vm_page **ploans;
  720         int npages;
  721 {
  722         struct vm_page *pg;
  723 
  724         uvm_lock_pageq();
  725 
  726         while (npages-- > 0) {
  727                 pg = *ploans++;
  728 
  729                 if (pg->loan_count < 1)
  730                         panic("uvm_unloanpage: page %p isn't loaned", pg);
  731 
  732                 pg->loan_count--;               /* drop loan */
  733                 uvm_pageunwire(pg);             /* and wire */
  734 
  735                 /*
  736                  * if page is unowned and we killed last loan, then we can
  737                  * free it
  738                  */
  739                 if (pg->loan_count == 0 && pg->uobject == NULL &&
  740                     pg->uanon == NULL) {
  741 
  742                         if (pg->pg_flags & PG_BUSY)
  743         panic("uvm_unloanpage: page %p unowned but PG_BUSY!", pg);
  744 
  745                         /* be safe */
  746                         pmap_page_protect(pg, VM_PROT_NONE);
  747                         uvm_pagefree(pg);       /* pageq locked above */
  748 
  749                 }
  750         }
  751 
  752         uvm_unlock_pageq();
  753 }
  754 

/* [<][>][^][v][top][bottom][index][help] */