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_object.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_object.c   8.5 (Berkeley) 3/22/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$
   65  */
   66 
   67 /*
   68  *      Virtual memory object module.
   69  */
   70 
   71 #include <sys/param.h>
   72 #include <sys/systm.h>
   73 #include <sys/proc.h>           /* for curproc, pageproc */
   74 #include <sys/vnode.h>
   75 #include <sys/vmmeter.h>
   76 #include <sys/mman.h>
   77 #include <sys/mount.h>
   78 
   79 #include <vm/vm.h>
   80 #include <vm/vm_param.h>
   81 #include <vm/vm_prot.h>
   82 #include <vm/pmap.h>
   83 #include <vm/vm_map.h>
   84 #include <vm/vm_object.h>
   85 #include <vm/vm_page.h>
   86 #include <vm/vm_pageout.h>
   87 #include <vm/vm_pager.h>
   88 #include <vm/swap_pager.h>
   89 #include <vm/vm_kern.h>
   90 #include <vm/vm_extern.h>
   91 #include <vm/vm_zone.h>
   92 
   93 static void     vm_object_qcollapse __P((vm_object_t object));
   94 
   95 /*
   96  *      Virtual memory objects maintain the actual data
   97  *      associated with allocated virtual memory.  A given
   98  *      page of memory exists within exactly one object.
   99  *
  100  *      An object is only deallocated when all "references"
  101  *      are given up.  Only one "reference" to a given
  102  *      region of an object should be writeable.
  103  *
  104  *      Associated with each object is a list of all resident
  105  *      memory pages belonging to that object; this list is
  106  *      maintained by the "vm_page" module, and locked by the object's
  107  *      lock.
  108  *
  109  *      Each object also records a "pager" routine which is
  110  *      used to retrieve (and store) pages to the proper backing
  111  *      storage.  In addition, objects may be backed by other
  112  *      objects from which they were virtual-copied.
  113  *
  114  *      The only items within the object structure which are
  115  *      modified after time of creation are:
  116  *              reference count         locked by object's lock
  117  *              pager routine           locked by object's lock
  118  *
  119  */
  120 
  121 struct object_q vm_object_list;
  122 #ifndef NULL_SIMPLELOCKS
  123 static struct simplelock vm_object_list_lock;
  124 #endif
  125 static long vm_object_count;            /* count of all objects */
  126 vm_object_t kernel_object;
  127 vm_object_t kmem_object;
  128 static struct vm_object kernel_object_store;
  129 static struct vm_object kmem_object_store;
  130 extern int vm_pageout_page_count;
  131 
  132 static long object_collapses;
  133 static long object_bypasses;
  134 static int next_index;
  135 static vm_zone_t obj_zone;
  136 static struct vm_zone obj_zone_store;
  137 #define VM_OBJECTS_INIT 256
  138 static struct vm_object vm_objects_init[VM_OBJECTS_INIT];
  139 static int objidnumber;
  140 
  141 void
  142 _vm_object_allocate(type, size, object)
  143         objtype_t type;
  144         vm_size_t size;
  145         register vm_object_t object;
  146 {
  147         int incr;
  148         TAILQ_INIT(&object->memq);
  149         TAILQ_INIT(&object->shadow_head);
  150 
  151         object->type = type;
  152         object->size = size;
  153         object->ref_count = 1;
  154         object->flags = 0;
  155         object->id = ++objidnumber;
  156         if ((object->type == OBJT_DEFAULT) || (object->type == OBJT_SWAP))
  157                 vm_object_set_flag(object, OBJ_ONEMAPPING);
  158         object->behavior = OBJ_NORMAL;
  159         object->paging_in_progress = 0;
  160         object->resident_page_count = 0;
  161         object->shadow_count = 0;
  162         object->pg_color = next_index;
  163         if ( size > (PQ_L2_SIZE / 3 + PQ_PRIME1))
  164                 incr = PQ_L2_SIZE / 3 + PQ_PRIME1;
  165         else
  166                 incr = size;
  167         next_index = (next_index + incr) & PQ_L2_MASK;
  168         object->handle = NULL;
  169         object->paging_offset = (vm_ooffset_t) 0;
  170         object->backing_object = NULL;
  171         object->backing_object_offset = (vm_ooffset_t) 0;
  172         object->page_hint = NULL;
  173 
  174         object->last_read = 0;
  175         object->generation++;
  176 
  177         TAILQ_INSERT_TAIL(&vm_object_list, object, object_list);
  178         vm_object_count++;
  179 }
  180 
  181 /*
  182  *      vm_object_init:
  183  *
  184  *      Initialize the VM objects module.
  185  */
  186 void
  187 vm_object_init()
  188 {
  189         TAILQ_INIT(&vm_object_list);
  190         simple_lock_init(&vm_object_list_lock);
  191         vm_object_count = 0;
  192         
  193         kernel_object = &kernel_object_store;
  194         _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS),
  195             kernel_object);
  196 
  197         kmem_object = &kmem_object_store;
  198         _vm_object_allocate(OBJT_DEFAULT, OFF_TO_IDX(VM_MAX_KERNEL_ADDRESS - VM_MIN_KERNEL_ADDRESS),
  199             kmem_object);
  200 
  201         obj_zone = &obj_zone_store;
  202         zbootinit(obj_zone, "VM OBJECT", sizeof (struct vm_object),
  203                 vm_objects_init, VM_OBJECTS_INIT);
  204 }
  205 
  206 void
  207 vm_object_init2() {
  208         zinitna(obj_zone, NULL, NULL, 0, 0, 0, 1);
  209 }
  210 
  211 /*
  212  *      vm_object_allocate:
  213  *
  214  *      Returns a new object with the given size.
  215  */
  216 
  217 vm_object_t
  218 vm_object_allocate(type, size)
  219         objtype_t type;
  220         vm_size_t size;
  221 {
  222         register vm_object_t result;
  223         result = (vm_object_t) zalloc(obj_zone);
  224 
  225         _vm_object_allocate(type, size, result);
  226 
  227         return (result);
  228 }
  229 
  230 
  231 /*
  232  *      vm_object_reference:
  233  *
  234  *      Gets another reference to the given object.
  235  */
  236 void
  237 vm_object_reference(object)
  238         register vm_object_t object;
  239 {
  240         if (object == NULL)
  241                 return;
  242 
  243         KASSERT(!(object->flags & OBJ_DEAD),
  244             ("vm_object_reference: attempting to reference dead obj"));
  245 
  246         object->ref_count++;
  247         if (object->type == OBJT_VNODE) {
  248                 while (vget((struct vnode *) object->handle, LK_RETRY|LK_NOOBJ, curproc)) {
  249 #if !defined(MAX_PERF)
  250                         printf("vm_object_reference: delay in getting object\n");
  251 #endif
  252                 }
  253         }
  254 }
  255 
  256 void
  257 vm_object_vndeallocate(object)
  258         vm_object_t object;
  259 {
  260         struct vnode *vp = (struct vnode *) object->handle;
  261 
  262         KASSERT(object->type == OBJT_VNODE,
  263             ("vm_object_vndeallocate: not a vnode object"));
  264         KASSERT(vp != NULL, ("vm_object_vndeallocate: missing vp"));
  265 #ifdef INVARIANTS
  266         if (object->ref_count == 0) {
  267                 vprint("vm_object_vndeallocate", vp);
  268                 panic("vm_object_vndeallocate: bad object reference count");
  269         }
  270 #endif
  271 
  272         object->ref_count--;
  273         if (object->ref_count == 0) {
  274                 vp->v_flag &= ~VTEXT;
  275                 vm_object_clear_flag(object, OBJ_OPT);
  276         }
  277         vrele(vp);
  278 }
  279 
  280 /*
  281  *      vm_object_deallocate:
  282  *
  283  *      Release a reference to the specified object,
  284  *      gained either through a vm_object_allocate
  285  *      or a vm_object_reference call.  When all references
  286  *      are gone, storage associated with this object
  287  *      may be relinquished.
  288  *
  289  *      No object may be locked.
  290  */
  291 void
  292 vm_object_deallocate(object)
  293         vm_object_t object;
  294 {
  295         vm_object_t temp;
  296 
  297         while (object != NULL) {
  298 
  299                 if (object->type == OBJT_VNODE) {
  300                         vm_object_vndeallocate(object);
  301                         return;
  302                 }
  303 
  304                 if (object->ref_count == 0) {
  305                         panic("vm_object_deallocate: object deallocated too many times: %d", object->type);
  306                 } else if (object->ref_count > 2) {
  307                         object->ref_count--;
  308                         return;
  309                 }
  310 
  311                 /*
  312                  * Here on ref_count of one or two, which are special cases for
  313                  * objects.
  314                  */
  315                 if ((object->ref_count == 2) && (object->shadow_count == 0)) {
  316                         vm_object_set_flag(object, OBJ_ONEMAPPING);
  317                         object->ref_count--;
  318                         return;
  319                 } else if ((object->ref_count == 2) && (object->shadow_count == 1)) {
  320                         object->ref_count--;
  321                         if ((object->handle == NULL) &&
  322                             (object->type == OBJT_DEFAULT ||
  323                              object->type == OBJT_SWAP)) {
  324                                 vm_object_t robject;
  325 
  326                                 robject = TAILQ_FIRST(&object->shadow_head);
  327                                 KASSERT(robject != NULL,
  328                                     ("vm_object_deallocate: ref_count: %d, shadow_count: %d",
  329                                          object->ref_count,
  330                                          object->shadow_count));
  331                                 if ((robject->handle == NULL) &&
  332                                     (robject->type == OBJT_DEFAULT ||
  333                                      robject->type == OBJT_SWAP)) {
  334 
  335                                         robject->ref_count++;
  336 
  337                         retry:
  338                                         if (robject->paging_in_progress ||
  339                                                         object->paging_in_progress) {
  340                                                 vm_object_pip_sleep(robject, "objde1");
  341                                                 if (robject->paging_in_progress &&
  342                                                         robject->type == OBJT_SWAP) {
  343                                                         swap_pager_sync();
  344                                                         goto retry;
  345                                                 }
  346 
  347                                                 vm_object_pip_sleep(object, "objde2");
  348                                                 if (object->paging_in_progress &&
  349                                                         object->type == OBJT_SWAP) {
  350                                                         swap_pager_sync();
  351                                                 }
  352                                                 goto retry;
  353                                         }
  354 
  355                                         if( robject->ref_count == 1) {
  356                                                 robject->ref_count--;
  357                                                 object = robject;
  358                                                 goto doterm;
  359                                         }
  360 
  361                                         object = robject;
  362                                         vm_object_collapse(object);
  363                                         continue;
  364                                 }
  365                         }
  366 
  367                         return;
  368 
  369                 } else {
  370                         object->ref_count--;
  371                         if (object->ref_count != 0)
  372                                 return;
  373                 }
  374 
  375 doterm:
  376 
  377                 temp = object->backing_object;
  378                 if (temp) {
  379                         TAILQ_REMOVE(&temp->shadow_head, object, shadow_list);
  380                         temp->shadow_count--;
  381                         if (temp->ref_count == 0)
  382                                 vm_object_clear_flag(temp, OBJ_OPT);
  383                         temp->generation++;
  384                         object->backing_object = NULL;
  385                 }
  386                 vm_object_terminate(object);
  387                 /* unlocks and deallocates object */
  388                 object = temp;
  389         }
  390 }
  391 
  392 /*
  393  *      vm_object_terminate actually destroys the specified object, freeing
  394  *      up all previously used resources.
  395  *
  396  *      The object must be locked.
  397  */
  398 void
  399 vm_object_terminate(object)
  400         register vm_object_t object;
  401 {
  402         register vm_page_t p;
  403         int s;
  404 
  405         /*
  406          * Make sure no one uses us.
  407          */
  408         vm_object_set_flag(object, OBJ_DEAD);
  409 
  410         /*
  411          * wait for the pageout daemon to be done with the object
  412          */
  413         vm_object_pip_wait(object, "objtrm");
  414 
  415         KASSERT(!object->paging_in_progress,
  416                 ("vm_object_terminate: pageout in progress"));
  417 
  418         /*
  419          * Clean and free the pages, as appropriate. All references to the
  420          * object are gone, so we don't need to lock it.
  421          */
  422         if (object->type == OBJT_VNODE) {
  423                 struct vnode *vp;
  424 
  425                 /*
  426                  * Freeze optimized copies.
  427                  */
  428                 vm_freeze_copyopts(object, 0, object->size);
  429 
  430                 /*
  431                  * Clean pages and flush buffers.
  432                  */
  433                 vm_object_page_clean(object, 0, 0, OBJPC_SYNC);
  434 
  435                 vp = (struct vnode *) object->handle;
  436                 vinvalbuf(vp, V_SAVE, NOCRED, NULL, 0, 0);
  437         }
  438 
  439         if (object->ref_count != 0)
  440                 panic("vm_object_terminate: object with references, ref_count=%d", object->ref_count);
  441 
  442         /*
  443          * Now free any remaining pages. For internal objects, this also
  444          * removes them from paging queues. Don't free wired pages, just
  445          * remove them from the object.
  446          */
  447         s = splvm();
  448         while ((p = TAILQ_FIRST(&object->memq)) != NULL) {
  449 #if !defined(MAX_PERF)
  450                 if (p->busy || (p->flags & PG_BUSY))
  451                         printf("vm_object_terminate: freeing busy page\n");
  452 #endif
  453                 if (p->wire_count == 0) {
  454                         vm_page_busy(p);
  455                         vm_page_free(p);
  456                         cnt.v_pfree++;
  457                 } else {
  458                         vm_page_busy(p);
  459                         vm_page_remove(p);
  460                 }
  461         }
  462         splx(s);
  463 
  464         /*
  465          * Let the pager know object is dead.
  466          */
  467         vm_pager_deallocate(object);
  468 
  469         /*
  470          * Remove the object from the global object list.
  471          */
  472         simple_lock(&vm_object_list_lock);
  473         TAILQ_REMOVE(&vm_object_list, object, object_list);
  474         simple_unlock(&vm_object_list_lock);
  475 
  476         wakeup(object);
  477 
  478         /*
  479          * Free the space for the object.
  480          */
  481         zfree(obj_zone, object);
  482 }
  483 
  484 /*
  485  *      vm_object_page_clean
  486  *
  487  *      Clean all dirty pages in the specified range of object.
  488  *      Leaves page on whatever queue it is currently on.
  489  *
  490  *      Odd semantics: if start == end, we clean everything.
  491  *
  492  *      The object must be locked.
  493  */
  494 
  495 void
  496 vm_object_page_clean(object, start, end, flags)
  497         vm_object_t object;
  498         vm_pindex_t start;
  499         vm_pindex_t end;
  500         int flags;
  501 {
  502         register vm_page_t p, np, tp;
  503         register vm_offset_t tstart, tend;
  504         vm_pindex_t pi;
  505         int s;
  506         struct vnode *vp;
  507         int runlen;
  508         int maxf;
  509         int chkb;
  510         int maxb;
  511         int i;
  512         int pagerflags;
  513         vm_page_t maf[vm_pageout_page_count];
  514         vm_page_t mab[vm_pageout_page_count];
  515         vm_page_t ma[vm_pageout_page_count];
  516         int curgeneration;
  517 
  518         if (object->type != OBJT_VNODE ||
  519                 (object->flags & OBJ_MIGHTBEDIRTY) == 0)
  520                 return;
  521 
  522         pagerflags = (flags & (OBJPC_SYNC | OBJPC_INVAL)) ? VM_PAGER_PUT_SYNC : 0;
  523         pagerflags |= (flags & OBJPC_INVAL) ? VM_PAGER_PUT_INVAL : 0;
  524 
  525         vp = object->handle;
  526 
  527         vm_object_set_flag(object, OBJ_CLEANING);
  528 
  529         tstart = start;
  530         if (end == 0) {
  531                 tend = object->size;
  532         } else {
  533                 tend = end;
  534         }
  535 
  536         for(p = TAILQ_FIRST(&object->memq); p; p = TAILQ_NEXT(p, listq)) {
  537                 vm_page_flag_set(p, PG_CLEANCHK);
  538                 vm_page_protect(p, VM_PROT_READ);
  539         }
  540 
  541         if ((tstart == 0) && (tend == object->size)) {
  542                 vm_object_clear_flag(object, OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY);
  543         }
  544 
  545 rescan:
  546         curgeneration = object->generation;
  547 
  548         for(p = TAILQ_FIRST(&object->memq); p; p = np) {
  549                 np = TAILQ_NEXT(p, listq);
  550 
  551                 pi = p->pindex;
  552                 if (((p->flags & PG_CLEANCHK) == 0) ||
  553                         (pi < tstart) || (pi >= tend) ||
  554                         (p->valid == 0) ||
  555                         ((p->queue - p->pc) == PQ_CACHE)) {
  556                         vm_page_flag_clear(p, PG_CLEANCHK);
  557                         continue;
  558                 }
  559 
  560                 vm_page_test_dirty(p);
  561                 if ((p->dirty & p->valid) == 0) {
  562                         vm_page_flag_clear(p, PG_CLEANCHK);
  563                         continue;
  564                 }
  565 
  566                 s = splvm();
  567                 while ((p->flags & PG_BUSY) || p->busy) {
  568                         vm_page_flag_set(p, PG_WANTED | PG_REFERENCED);
  569                         tsleep(p, PVM, "vpcwai", 0);
  570                         if (object->generation != curgeneration) {
  571                                 splx(s);
  572                                 goto rescan;
  573                         }
  574                 }
  575 
  576                 maxf = 0;
  577                 for(i=1;i<vm_pageout_page_count;i++) {
  578                         if (tp = vm_page_lookup(object, pi + i)) {
  579                                 if ((tp->flags & PG_BUSY) ||
  580                                         (tp->flags & PG_CLEANCHK) == 0 ||
  581                                         (tp->busy != 0))
  582                                         break;
  583                                 if((tp->queue - tp->pc) == PQ_CACHE) {
  584                                         vm_page_flag_clear(tp, PG_CLEANCHK);
  585                                         break;
  586                                 }
  587                                 vm_page_test_dirty(tp);
  588                                 if ((tp->dirty & tp->valid) == 0) {
  589                                         vm_page_flag_clear(tp, PG_CLEANCHK);
  590                                         break;
  591                                 }
  592                                 maf[ i - 1 ] = tp;
  593                                 maxf++;
  594                                 continue;
  595                         }
  596                         break;
  597                 }
  598 
  599                 maxb = 0;
  600                 chkb = vm_pageout_page_count -  maxf;
  601                 if (chkb) {
  602                         for(i = 1; i < chkb;i++) {
  603                                 if (tp = vm_page_lookup(object, pi - i)) {
  604                                         if ((tp->flags & PG_BUSY) ||
  605                                                 (tp->flags & PG_CLEANCHK) == 0 ||
  606                                                 (tp->busy != 0))
  607                                                 break;
  608                                         if((tp->queue - tp->pc) == PQ_CACHE) {
  609                                                 vm_page_flag_clear(tp, PG_CLEANCHK);
  610                                                 break;
  611                                         }
  612                                         vm_page_test_dirty(tp);
  613                                         if ((tp->dirty & tp->valid) == 0) {
  614                                                 vm_page_flag_clear(tp, PG_CLEANCHK);
  615                                                 break;
  616                                         }
  617                                         mab[ i - 1 ] = tp;
  618                                         maxb++;
  619                                         continue;
  620                                 }
  621                                 break;
  622                         }
  623                 }
  624 
  625                 for(i=0;i<maxb;i++) {
  626                         int index = (maxb - i) - 1;
  627                         ma[index] = mab[i];
  628                         vm_page_flag_clear(ma[index], PG_CLEANCHK);
  629                 }
  630                 vm_page_flag_clear(p, PG_CLEANCHK);
  631                 ma[maxb] = p;
  632                 for(i=0;i<maxf;i++) {
  633                         int index = (maxb + i) + 1;
  634                         ma[index] = maf[i];
  635                         vm_page_flag_clear(ma[index], PG_CLEANCHK);
  636                 }
  637                 runlen = maxb + maxf + 1;
  638 
  639                 splx(s);
  640                 vm_pageout_flush(ma, runlen, pagerflags);
  641                 for (i = 0; i<runlen; i++) {
  642                         if (ma[i]->valid & ma[i]->dirty) {
  643                                 vm_page_protect(ma[i], VM_PROT_READ);
  644                                 vm_page_flag_set(ma[i], PG_CLEANCHK);
  645                         }
  646                 }
  647                 if (object->generation != curgeneration)
  648                         goto rescan;
  649         }
  650 
  651         VOP_FSYNC(vp, NULL, (pagerflags & VM_PAGER_PUT_SYNC)?MNT_WAIT:0, curproc);
  652 
  653         vm_object_clear_flag(object, OBJ_CLEANING);
  654         return;
  655 }
  656 
  657 #ifdef not_used
  658 /* XXX I cannot tell if this should be an exported symbol */
  659 /*
  660  *      vm_object_deactivate_pages
  661  *
  662  *      Deactivate all pages in the specified object.  (Keep its pages
  663  *      in memory even though it is no longer referenced.)
  664  *
  665  *      The object must be locked.
  666  */
  667 static void
  668 vm_object_deactivate_pages(object)
  669         register vm_object_t object;
  670 {
  671         register vm_page_t p, next;
  672 
  673         for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) {
  674                 next = TAILQ_NEXT(p, listq);
  675                 vm_page_deactivate(p);
  676         }
  677 }
  678 #endif
  679 
  680 /*
  681  *      vm_object_pmap_copy:
  682  *
  683  *      Makes all physical pages in the specified
  684  *      object range copy-on-write.  No writeable
  685  *      references to these pages should remain.
  686  *
  687  *      The object must *not* be locked.
  688  */
  689 void
  690 vm_object_pmap_copy(object, start, end)
  691         register vm_object_t object;
  692         register vm_pindex_t start;
  693         register vm_pindex_t end;
  694 {
  695         register vm_page_t p;
  696 
  697         if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0)
  698                 return;
  699 
  700         for (p = TAILQ_FIRST(&object->memq);
  701                 p != NULL;
  702                 p = TAILQ_NEXT(p, listq)) {
  703                 vm_page_protect(p, VM_PROT_READ);
  704         }
  705 
  706         vm_object_clear_flag(object, OBJ_WRITEABLE);
  707 }
  708 
  709 /*
  710  * Same as vm_object_pmap_copy_1, except range checking really
  711  * works, and is meant for small sections of an object.
  712  */
  713 void
  714 vm_object_pmap_copy_1(object, start, end)
  715         register vm_object_t object;
  716         register vm_pindex_t start;
  717         register vm_pindex_t end;
  718 {
  719         vm_pindex_t idx;
  720         register vm_page_t p;
  721 
  722         if (object == NULL || (object->flags & OBJ_WRITEABLE) == 0)
  723                 return;
  724 
  725         for (idx = start; idx < end; idx++) {
  726                 p = vm_page_lookup(object, idx);
  727                 if (p == NULL)
  728                         continue;
  729                 vm_page_protect(p, VM_PROT_READ);
  730         }
  731 }
  732 
  733 /*
  734  *      vm_object_pmap_remove:
  735  *
  736  *      Removes all physical pages in the specified
  737  *      object range from all physical maps.
  738  *
  739  *      The object must *not* be locked.
  740  */
  741 void
  742 vm_object_pmap_remove(object, start, end)
  743         register vm_object_t object;
  744         register vm_pindex_t start;
  745         register vm_pindex_t end;
  746 {
  747         register vm_page_t p;
  748         if (object == NULL)
  749                 return;
  750         for (p = TAILQ_FIRST(&object->memq);
  751                 p != NULL;
  752                 p = TAILQ_NEXT(p, listq)) {
  753                 if (p->pindex >= start && p->pindex < end)
  754                         vm_page_protect(p, VM_PROT_NONE);
  755         }
  756         if ((start == 0) && (object->size == end))
  757                 vm_object_clear_flag(object, OBJ_WRITEABLE);
  758 }
  759 
  760 /*
  761  *      vm_object_madvise:
  762  *
  763  *      Implements the madvise function at the object/page level.
  764  */
  765 void
  766 vm_object_madvise(object, pindex, count, advise)
  767         vm_object_t object;
  768         vm_pindex_t pindex;
  769         int count;
  770         int advise;
  771 {
  772         vm_pindex_t end, tpindex;
  773         vm_object_t tobject;
  774         vm_page_t m;
  775 
  776         if (object == NULL)
  777                 return;
  778 
  779         end = pindex + count;
  780 
  781         for (; pindex < end; pindex += 1) {
  782 
  783 relookup:
  784                 tobject = object;
  785                 tpindex = pindex;
  786 shadowlookup:
  787                 if (tobject->type != OBJT_DEFAULT &&
  788                     tobject->type != OBJT_SWAP
  789                 ) {
  790                         continue;
  791                 }
  792 
  793                 if ((tobject->flags & OBJ_ONEMAPPING) == 0)
  794                         continue;
  795 
  796                 m = vm_page_lookup(tobject, tpindex);
  797 
  798                 if (m == NULL) {
  799                         tobject = tobject->backing_object;
  800                         if (tobject == NULL)
  801                                 continue;
  802 
  803                         tpindex += OFF_TO_IDX(tobject->backing_object_offset);
  804                         goto shadowlookup;
  805                 }
  806 
  807                 /*
  808                  * If the page is busy or not in a normal active state,
  809                  * we skip it.  Things can break if we mess with pages
  810                  * in any of the below states.
  811                  */
  812                 if (
  813                     m->hold_count || 
  814                     m->wire_count ||
  815                     m->valid != VM_PAGE_BITS_ALL
  816                 ) {
  817                         continue;
  818                 }
  819 
  820                 if (vm_page_sleep(m, "madvpo", &m->busy))
  821                         goto relookup;
  822 
  823                 if (advise == MADV_WILLNEED) {
  824                         vm_page_activate(m);
  825                 } else if (advise == MADV_DONTNEED) {
  826                         vm_page_deactivate(m);
  827                 } else if (advise == MADV_FREE) {
  828                         pmap_clear_modify(VM_PAGE_TO_PHYS(m));
  829                         m->dirty = 0;
  830                         /*
  831                          * Force a demand zero if attempt to read from swap.
  832                          * We currently don't handle vnode files correctly,
  833                          * and will reread stale contents unnecessarily.
  834                          */
  835                         if (object->type == OBJT_SWAP)
  836                                 swap_pager_dmzspace(tobject, m->pindex, 1);
  837                 }
  838         }       
  839 }
  840 
  841 /*
  842  *      vm_object_shadow:
  843  *
  844  *      Create a new object which is backed by the
  845  *      specified existing object range.  The source
  846  *      object reference is deallocated.
  847  *
  848  *      The new object and offset into that object
  849  *      are returned in the source parameters.
  850  */
  851 
  852 void
  853 vm_object_shadow(object, offset, length)
  854         vm_object_t *object;    /* IN/OUT */
  855         vm_ooffset_t *offset;   /* IN/OUT */
  856         vm_size_t length;
  857 {
  858         register vm_object_t source;
  859         register vm_object_t result;
  860 
  861         source = *object;
  862 
  863         /*
  864          * Allocate a new object with the given length
  865          */
  866 
  867         if ((result = vm_object_allocate(OBJT_DEFAULT, length)) == NULL)
  868                 panic("vm_object_shadow: no object for shadowing");
  869 
  870         /*
  871          * The new object shadows the source object, adding a reference to it.
  872          * Our caller changes his reference to point to the new object,
  873          * removing a reference to the source object.  Net result: no change
  874          * of reference count.
  875          *
  876          * Try to optimize the result object's page color when shadowing
  877          * in order to maintain page coloring consistancy in the combined 
  878          * shadowed object.
  879          */
  880         result->backing_object = source;
  881         if (source) {
  882                 TAILQ_INSERT_TAIL(&source->shadow_head, result, shadow_list);
  883                 vm_object_clear_flag(source, OBJ_ONEMAPPING);
  884                 source->shadow_count++;
  885                 source->generation++;
  886                 result->pg_color = (source->pg_color + OFF_TO_IDX(*offset)) & PQ_L2_MASK;
  887         }
  888 
  889         /*
  890          * Store the offset into the source object, and fix up the offset into
  891          * the new object.
  892          */
  893 
  894         result->backing_object_offset = *offset;
  895 
  896         /*
  897          * Return the new things
  898          */
  899 
  900         *offset = 0;
  901         *object = result;
  902 }
  903 
  904 
  905 /*
  906  * this version of collapse allows the operation to occur earlier and
  907  * when paging_in_progress is true for an object...  This is not a complete
  908  * operation, but should plug 99.9% of the rest of the leaks.
  909  */
  910 static void
  911 vm_object_qcollapse(object)
  912         register vm_object_t object;
  913 {
  914         register vm_object_t backing_object;
  915         register vm_pindex_t backing_offset_index, paging_offset_index;
  916         vm_pindex_t backing_object_paging_offset_index;
  917         vm_pindex_t new_pindex;
  918         register vm_page_t p, pp;
  919         register vm_size_t size;
  920 
  921         backing_object = object->backing_object;
  922         if (backing_object->ref_count != 1)
  923                 return;
  924 
  925         backing_object->ref_count += 2;
  926 
  927         backing_offset_index = OFF_TO_IDX(object->backing_object_offset);
  928         backing_object_paging_offset_index = OFF_TO_IDX(backing_object->paging_offset);
  929         paging_offset_index = OFF_TO_IDX(object->paging_offset);
  930         size = object->size;
  931         p = TAILQ_FIRST(&backing_object->memq);
  932         while (p) {
  933                 vm_page_t next;
  934 
  935                 next = TAILQ_NEXT(p, listq);
  936                 if ((p->flags & (PG_BUSY | PG_FICTITIOUS)) ||
  937                     !p->valid || p->hold_count || p->wire_count || p->busy) {
  938                         p = next;
  939                         continue;
  940                 }
  941                 vm_page_busy(p);
  942 
  943                 new_pindex = p->pindex - backing_offset_index;
  944                 if (p->pindex < backing_offset_index ||
  945                     new_pindex >= size) {
  946                         if (backing_object->type == OBJT_SWAP)
  947                                 swap_pager_freespace(backing_object,
  948                                     backing_object_paging_offset_index+p->pindex,
  949                                     1);
  950                         vm_page_protect(p, VM_PROT_NONE);
  951                         vm_page_free(p);
  952                 } else {
  953                         pp = vm_page_lookup(object, new_pindex);
  954                         if (pp != NULL ||
  955                                 (object->type == OBJT_SWAP && vm_pager_has_page(object,
  956                                     paging_offset_index + new_pindex, NULL, NULL))) {
  957                                 if (backing_object->type == OBJT_SWAP)
  958                                         swap_pager_freespace(backing_object,
  959                                             backing_object_paging_offset_index + p->pindex, 1);
  960                                 vm_page_protect(p, VM_PROT_NONE);
  961                                 vm_page_free(p);
  962                         } else {
  963                                 if (backing_object->type == OBJT_SWAP)
  964                                         swap_pager_freespace(backing_object,
  965                                             backing_object_paging_offset_index + p->pindex, 1);
  966 
  967                                 if ((p->queue - p->pc) == PQ_CACHE)
  968                                         vm_page_deactivate(p);
  969                                 else
  970                                         vm_page_protect(p, VM_PROT_NONE);
  971 
  972                                 vm_page_rename(p, object, new_pindex);
  973                                 p->dirty = VM_PAGE_BITS_ALL;
  974                         }
  975                 }
  976                 p = next;
  977         }
  978         backing_object->ref_count -= 2;
  979 }
  980 
  981 /*
  982  *      vm_object_collapse:
  983  *
  984  *      Collapse an object with the object backing it.
  985  *      Pages in the backing object are moved into the
  986  *      parent, and the backing object is deallocated.
  987  */
  988 void
  989 vm_object_collapse(object)
  990         vm_object_t object;
  991 
  992 {
  993         vm_object_t backing_object;
  994         vm_ooffset_t backing_offset;
  995         vm_size_t size;
  996         vm_pindex_t new_pindex, backing_offset_index;
  997         vm_page_t p, pp;
  998 
  999         while (TRUE) {
 1000                 /*
 1001                  * Verify that the conditions are right for collapse:
 1002                  *
 1003                  * The object exists and no pages in it are currently being paged
 1004                  * out.
 1005                  */
 1006                 if (object == NULL)
 1007                         return;
 1008 
 1009                 /*
 1010                  * Make sure there is a backing object.
 1011                  */
 1012                 if ((backing_object = object->backing_object) == NULL)
 1013                         return;
 1014 
 1015                 /*
 1016                  * we check the backing object first, because it is most likely
 1017                  * not collapsable.
 1018                  */
 1019                 if (backing_object->handle != NULL ||
 1020                     (backing_object->type != OBJT_DEFAULT &&
 1021                      backing_object->type != OBJT_SWAP) ||
 1022                     (backing_object->flags & OBJ_DEAD) ||
 1023                     object->handle != NULL ||
 1024                     (object->type != OBJT_DEFAULT &&
 1025                      object->type != OBJT_SWAP) ||
 1026                     (object->flags & OBJ_DEAD)) {
 1027                         return;
 1028                 }
 1029 
 1030                 if (object->paging_in_progress != 0 ||
 1031                     backing_object->paging_in_progress != 0) {
 1032                         vm_object_qcollapse(object);
 1033                         return;
 1034                 }
 1035 
 1036                 /*
 1037                  * We know that we can either collapse the backing object (if
 1038                  * the parent is the only reference to it) or (perhaps) remove
 1039                  * the parent's reference to it.
 1040                  */
 1041 
 1042                 backing_offset = object->backing_object_offset;
 1043                 backing_offset_index = OFF_TO_IDX(backing_offset);
 1044                 size = object->size;
 1045 
 1046                 /*
 1047                  * If there is exactly one reference to the backing object, we
 1048                  * can collapse it into the parent.
 1049                  */
 1050 
 1051                 if (backing_object->ref_count == 1) {
 1052 
 1053                         vm_object_set_flag(backing_object, OBJ_DEAD);
 1054                         /*
 1055                          * We can collapse the backing object.
 1056                          *
 1057                          * Move all in-memory pages from backing_object to the
 1058                          * parent.  Pages that have been paged out will be
 1059                          * overwritten by any of the parent's pages that
 1060                          * shadow them.
 1061                          */
 1062 
 1063                         while ((p = TAILQ_FIRST(&backing_object->memq)) != 0) {
 1064                                 if (vm_page_sleep(p, "vmocol", &p->busy))
 1065                                         continue;
 1066                                 vm_page_busy(p);
 1067                                 new_pindex = p->pindex - backing_offset_index;
 1068 
 1069                                 /*
 1070                                  * If the parent has a page here, or if this
 1071                                  * page falls outside the parent, dispose of
 1072                                  * it.
 1073                                  *
 1074                                  * Otherwise, move it as planned.
 1075                                  */
 1076 
 1077                                 if (p->pindex < backing_offset_index ||
 1078                                     new_pindex >= size) {
 1079                                         vm_page_protect(p, VM_PROT_NONE);
 1080                                         vm_page_free(p);
 1081                                 } else {
 1082                                         pp = vm_page_lookup(object, new_pindex);
 1083                                         if (pp != NULL || (object->type == OBJT_SWAP && vm_pager_has_page(object,
 1084                                             OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL))) {
 1085                                                 vm_page_protect(p, VM_PROT_NONE);
 1086                                                 vm_page_free(p);
 1087                                         } else {
 1088                                                 if ((p->queue - p->pc) == PQ_CACHE)
 1089                                                         vm_page_deactivate(p);
 1090                                                 else
 1091                                                         vm_page_protect(p, VM_PROT_NONE);
 1092                                                 vm_page_rename(p, object, new_pindex);
 1093                                                 p->dirty = VM_PAGE_BITS_ALL;
 1094                                         }
 1095                                 }
 1096                         }
 1097 
 1098                         /*
 1099                          * Move the pager from backing_object to object.
 1100                          */
 1101 
 1102                         if (backing_object->type == OBJT_SWAP) {
 1103                                 vm_object_pip_add(backing_object, 1);
 1104                                 if (object->type == OBJT_SWAP) {
 1105                                         vm_object_pip_add(object, 1);
 1106                                         /*
 1107                                          * copy shadow object pages into ours
 1108                                          * and destroy unneeded pages in
 1109                                          * shadow object.
 1110                                          */
 1111                                         swap_pager_copy(
 1112                                             backing_object,
 1113                                             OFF_TO_IDX(backing_object->paging_offset),
 1114                                             object,
 1115                                             OFF_TO_IDX(object->paging_offset),
 1116                                             OFF_TO_IDX(object->backing_object_offset), TRUE);
 1117                                         vm_object_pip_wakeup(object);
 1118                                 } else {
 1119                                         vm_object_pip_add(object, 1);
 1120                                         /*
 1121                                          * move the shadow backing_object's pager data to
 1122                                          * "object" and convert "object" type to OBJT_SWAP.
 1123                                          */
 1124                                         object->type = OBJT_SWAP;
 1125                                         object->un_pager.swp.swp_nblocks =
 1126                                             backing_object->un_pager.swp.swp_nblocks;
 1127                                         object->un_pager.swp.swp_allocsize =
 1128                                             backing_object->un_pager.swp.swp_allocsize;
 1129                                         object->un_pager.swp.swp_blocks =
 1130                                             backing_object->un_pager.swp.swp_blocks;
 1131                                         object->un_pager.swp.swp_poip =         /* XXX */
 1132                                             backing_object->un_pager.swp.swp_poip;
 1133                                         object->paging_offset = backing_object->paging_offset + backing_offset;
 1134                                         TAILQ_INSERT_TAIL(&swap_pager_un_object_list, object, pager_object_list);
 1135 
 1136                                         /*
 1137                                          * Convert backing object from OBJT_SWAP to
 1138                                          * OBJT_DEFAULT. XXX - only the TAILQ_REMOVE is
 1139                                          * actually necessary.
 1140                                          */
 1141                                         backing_object->type = OBJT_DEFAULT;
 1142                                         TAILQ_REMOVE(&swap_pager_un_object_list, backing_object, pager_object_list);
 1143                                         /*
 1144                                          * free unnecessary blocks
 1145                                          */
 1146                                         swap_pager_freespace(object, 0,
 1147                                                 OFF_TO_IDX(object->paging_offset));
 1148                                         vm_object_pip_wakeup(object);
 1149                                 }
 1150 
 1151                                 vm_object_pip_wakeup(backing_object);
 1152                         }
 1153                         /*
 1154                          * Object now shadows whatever backing_object did.
 1155                          * Note that the reference to backing_object->backing_object
 1156                          * moves from within backing_object to within object.
 1157                          */
 1158 
 1159                         TAILQ_REMOVE(&object->backing_object->shadow_head, object,
 1160                             shadow_list);
 1161                         object->backing_object->shadow_count--;
 1162                         object->backing_object->generation++;
 1163                         if (backing_object->backing_object) {
 1164                                 TAILQ_REMOVE(&backing_object->backing_object->shadow_head,
 1165                                     backing_object, shadow_list);
 1166                                 backing_object->backing_object->shadow_count--;
 1167                                 backing_object->backing_object->generation++;
 1168                         }
 1169                         object->backing_object = backing_object->backing_object;
 1170                         if (object->backing_object) {
 1171                                 TAILQ_INSERT_TAIL(&object->backing_object->shadow_head,
 1172                                     object, shadow_list);
 1173                                 object->backing_object->shadow_count++;
 1174                                 object->backing_object->generation++;
 1175                         }
 1176 
 1177                         object->backing_object_offset += backing_object->backing_object_offset;
 1178                         /*
 1179                          * Discard backing_object.
 1180                          *
 1181                          * Since the backing object has no pages, no pager left,
 1182                          * and no object references within it, all that is
 1183                          * necessary is to dispose of it.
 1184                          */
 1185 
 1186                         TAILQ_REMOVE(&vm_object_list, backing_object,
 1187                             object_list);
 1188                         vm_object_count--;
 1189 
 1190                         zfree(obj_zone, backing_object);
 1191 
 1192                         object_collapses++;
 1193                 } else {
 1194                         vm_object_t new_backing_object;
 1195                         /*
 1196                          * If all of the pages in the backing object are
 1197                          * shadowed by the parent object, the parent object no
 1198                          * longer has to shadow the backing object; it can
 1199                          * shadow the next one in the chain.
 1200                          *
 1201                          * The backing object must not be paged out - we'd have
 1202                          * to check all of the paged-out pages, as well.
 1203                          */
 1204 
 1205                         if (backing_object->type != OBJT_DEFAULT) {
 1206                                 return;
 1207                         }
 1208                         /*
 1209                          * Should have a check for a 'small' number of pages
 1210                          * here.
 1211                          */
 1212 
 1213                         for (p = TAILQ_FIRST(&backing_object->memq); p;
 1214                                         p = TAILQ_NEXT(p, listq)) {
 1215 
 1216                                 new_pindex = p->pindex - backing_offset_index;
 1217                                 vm_page_busy(p);
 1218 
 1219                                 /*
 1220                                  * If the parent has a page here, or if this
 1221                                  * page falls outside the parent, keep going.
 1222                                  *
 1223                                  * Otherwise, the backing_object must be left in
 1224                                  * the chain.
 1225                                  */
 1226 
 1227                                 if (p->pindex >= backing_offset_index &&
 1228                                         new_pindex <= size) {
 1229 
 1230                                         pp = vm_page_lookup(object, new_pindex);
 1231 
 1232                                         if ((pp == NULL) || (pp->flags & PG_BUSY) || pp->busy) {
 1233                                                 vm_page_wakeup(p);
 1234                                                 return;
 1235                                         }
 1236 
 1237                                         vm_page_busy(pp);
 1238                                         if ((pp->valid == 0) &&
 1239                                             !vm_pager_has_page(object, OFF_TO_IDX(object->paging_offset) + new_pindex, NULL, NULL)) {
 1240                                                 /*
 1241                                                  * Page still needed. Can't go any
 1242                                                  * further.
 1243                                                  */
 1244                                                 vm_page_wakeup(pp);
 1245                                                 vm_page_wakeup(p);
 1246                                                 return;
 1247                                         }
 1248                                         vm_page_wakeup(pp);
 1249                                 }
 1250                                 vm_page_wakeup(p);
 1251                         }
 1252 
 1253                         /*
 1254                          * Make the parent shadow the next object in the
 1255                          * chain.  Deallocating backing_object will not remove
 1256                          * it, since its reference count is at least 2.
 1257                          */
 1258 
 1259                         TAILQ_REMOVE(&backing_object->shadow_head,
 1260                             object, shadow_list);
 1261                         backing_object->shadow_count--;
 1262                         backing_object->generation++;
 1263 
 1264                         new_backing_object = backing_object->backing_object;
 1265                         if (object->backing_object = new_backing_object) {
 1266                                 vm_object_reference(new_backing_object);
 1267                                 TAILQ_INSERT_TAIL(&new_backing_object->shadow_head,
 1268                                     object, shadow_list);
 1269                                 new_backing_object->shadow_count++;
 1270                                 new_backing_object->generation++;
 1271                                 object->backing_object_offset +=
 1272                                         backing_object->backing_object_offset;
 1273                         }
 1274 
 1275                         /*
 1276                          * Drop the reference count on backing_object. Since
 1277                          * its ref_count was at least 2, it will not vanish;
 1278                          * so we don't need to call vm_object_deallocate, but
 1279                          * we do anyway.
 1280                          */
 1281                         vm_object_deallocate(backing_object);
 1282                         object_bypasses++;
 1283                 }
 1284 
 1285                 /*
 1286                  * Try again with this object's new backing object.
 1287                  */
 1288         }
 1289 }
 1290 
 1291 /*
 1292  *      vm_object_page_remove: [internal]
 1293  *
 1294  *      Removes all physical pages in the specified
 1295  *      object range from the object's list of pages.
 1296  *
 1297  *      The object must be locked.
 1298  */
 1299 void
 1300 vm_object_page_remove(object, start, end, clean_only)
 1301         register vm_object_t object;
 1302         register vm_pindex_t start;
 1303         register vm_pindex_t end;
 1304         boolean_t clean_only;
 1305 {
 1306         register vm_page_t p, next;
 1307         unsigned int size;
 1308         int all;
 1309 
 1310         if (object == NULL ||
 1311             object->resident_page_count == 0)
 1312                 return;
 1313 
 1314         all = ((end == 0) && (start == 0));
 1315 
 1316         vm_object_pip_add(object, 1);
 1317 again:
 1318         size = end - start;
 1319         if (all || size > object->resident_page_count / 4) {
 1320                 for (p = TAILQ_FIRST(&object->memq); p != NULL; p = next) {
 1321                         next = TAILQ_NEXT(p, listq);
 1322                         if (all || ((start <= p->pindex) && (p->pindex < end))) {
 1323                                 if (p->wire_count != 0) {
 1324                                         vm_page_protect(p, VM_PROT_NONE);
 1325                                         if (!clean_only)
 1326                                                 p->valid = 0;
 1327                                         continue;
 1328                                 }
 1329 
 1330                                 /*
 1331                                  * The busy flags are only cleared at
 1332                                  * interrupt -- minimize the spl transitions
 1333                                  */
 1334 
 1335                                 if (vm_page_sleep(p, "vmopar", &p->busy))
 1336                                         goto again;
 1337 
 1338                                 if (clean_only && p->valid) {
 1339                                         vm_page_test_dirty(p);
 1340                                         if (p->valid & p->dirty)
 1341                                                 continue;
 1342                                 }
 1343 
 1344                                 vm_page_busy(p);
 1345                                 vm_page_protect(p, VM_PROT_NONE);
 1346                                 vm_page_free(p);
 1347                         }
 1348                 }
 1349         } else {
 1350                 while (size > 0) {
 1351                         if ((p = vm_page_lookup(object, start)) != 0) {
 1352 
 1353                                 if (p->wire_count != 0) {
 1354                                         vm_page_protect(p, VM_PROT_NONE);
 1355                                         if (!clean_only)
 1356                                                 p->valid = 0;
 1357                                         start += 1;
 1358                                         size -= 1;
 1359                                         continue;
 1360                                 }
 1361 
 1362                                 /*
 1363                                  * The busy flags are only cleared at
 1364                                  * interrupt -- minimize the spl transitions
 1365                                  */
 1366                                 if (vm_page_sleep(p, "vmopar", &p->busy))
 1367                                         goto again;
 1368 
 1369                                 if (clean_only && p->valid) {
 1370                                         vm_page_test_dirty(p);
 1371                                         if (p->valid & p->dirty) {
 1372                                                 start += 1;
 1373                                                 size -= 1;
 1374                                                 continue;
 1375                                         }
 1376                                 }
 1377 
 1378                                 vm_page_busy(p);
 1379                                 vm_page_protect(p, VM_PROT_NONE);
 1380                                 vm_page_free(p);
 1381                         }
 1382                         start += 1;
 1383                         size -= 1;
 1384                 }
 1385         }
 1386         vm_object_pip_wakeup(object);
 1387 }
 1388 
 1389 /*
 1390  *      Routine:        vm_object_coalesce
 1391  *      Function:       Coalesces two objects backing up adjoining
 1392  *                      regions of memory into a single object.
 1393  *
 1394  *      returns TRUE if objects were combined.
 1395  *
 1396  *      NOTE:   Only works at the moment if the second object is NULL -
 1397  *              if it's not, which object do we lock first?
 1398  *
 1399  *      Parameters:
 1400  *              prev_object     First object to coalesce
 1401  *              prev_offset     Offset into prev_object
 1402  *              next_object     Second object into coalesce
 1403  *              next_offset     Offset into next_object
 1404  *
 1405  *              prev_size       Size of reference to prev_object
 1406  *              next_size       Size of reference to next_object
 1407  *
 1408  *      Conditions:
 1409  *      The object must *not* be locked.
 1410  */
 1411 boolean_t
 1412 vm_object_coalesce(prev_object, prev_pindex, prev_size, next_size)
 1413         register vm_object_t prev_object;
 1414         vm_pindex_t prev_pindex;
 1415         vm_size_t prev_size, next_size;
 1416 {
 1417         vm_size_t newsize;
 1418 
 1419         if (prev_object == NULL) {
 1420                 return (TRUE);
 1421         }
 1422 
 1423         if (prev_object->type != OBJT_DEFAULT) {
 1424                 return (FALSE);
 1425         }
 1426 
 1427         /*
 1428          * Try to collapse the object first
 1429          */
 1430         vm_object_collapse(prev_object);
 1431 
 1432         /*
 1433          * Can't coalesce if: . more than one reference . paged out . shadows
 1434          * another object . has a copy elsewhere (any of which mean that the
 1435          * pages not mapped to prev_entry may be in use anyway)
 1436          */
 1437 
 1438         if (prev_object->backing_object != NULL) {
 1439                 return (FALSE);
 1440         }
 1441 
 1442         prev_size >>= PAGE_SHIFT;
 1443         next_size >>= PAGE_SHIFT;
 1444 
 1445         if ((prev_object->ref_count > 1) &&
 1446             (prev_object->size != prev_pindex + prev_size)) {
 1447                 return (FALSE);
 1448         }
 1449 
 1450         /*
 1451          * Remove any pages that may still be in the object from a previous
 1452          * deallocation.
 1453          */
 1454 
 1455         vm_object_page_remove(prev_object,
 1456             prev_pindex + prev_size,
 1457             prev_pindex + prev_size + next_size, FALSE);
 1458 
 1459         /*
 1460          * Extend the object if necessary.
 1461          */
 1462         newsize = prev_pindex + prev_size + next_size;
 1463         if (newsize > prev_object->size)
 1464                 prev_object->size = newsize;
 1465 
 1466         return (TRUE);
 1467 }
 1468 
 1469 #include "opt_ddb.h"
 1470 #ifdef DDB
 1471 #include <sys/kernel.h>
 1472 
 1473 #include <machine/cons.h>
 1474 
 1475 #include <ddb/ddb.h>
 1476 
 1477 static int      _vm_object_in_map __P((vm_map_t map, vm_object_t object,
 1478                                        vm_map_entry_t entry));
 1479 static int      vm_object_in_map __P((vm_object_t object));
 1480 
 1481 static int
 1482 _vm_object_in_map(map, object, entry)
 1483         vm_map_t map;
 1484         vm_object_t object;
 1485         vm_map_entry_t entry;
 1486 {
 1487         vm_map_t tmpm;
 1488         vm_map_entry_t tmpe;
 1489         vm_object_t obj;
 1490         int entcount;
 1491 
 1492         if (map == 0)
 1493                 return 0;
 1494 
 1495         if (entry == 0) {
 1496                 tmpe = map->header.next;
 1497                 entcount = map->nentries;
 1498                 while (entcount-- && (tmpe != &map->header)) {
 1499                         if( _vm_object_in_map(map, object, tmpe)) {
 1500                                 return 1;
 1501                         }
 1502                         tmpe = tmpe->next;
 1503                 }
 1504         } else if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP)) {
 1505                 tmpm = entry->object.share_map;
 1506                 tmpe = tmpm->header.next;
 1507                 entcount = tmpm->nentries;
 1508                 while (entcount-- && tmpe != &tmpm->header) {
 1509                         if( _vm_object_in_map(tmpm, object, tmpe)) {
 1510                                 return 1;
 1511                         }
 1512                         tmpe = tmpe->next;
 1513                 }
 1514         } else if (obj = entry->object.vm_object) {
 1515                 for(; obj; obj=obj->backing_object)
 1516                         if( obj == object) {
 1517                                 return 1;
 1518                         }
 1519         }
 1520         return 0;
 1521 }
 1522 
 1523 static int
 1524 vm_object_in_map( object)
 1525         vm_object_t object;
 1526 {
 1527         struct proc *p;
 1528         for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
 1529                 if( !p->p_vmspace /* || (p->p_flag & (P_SYSTEM|P_WEXIT)) */)
 1530                         continue;
 1531                 if( _vm_object_in_map(&p->p_vmspace->vm_map, object, 0))
 1532                         return 1;
 1533         }
 1534         if( _vm_object_in_map( kernel_map, object, 0))
 1535                 return 1;
 1536         if( _vm_object_in_map( kmem_map, object, 0))
 1537                 return 1;
 1538         if( _vm_object_in_map( pager_map, object, 0))
 1539                 return 1;
 1540         if( _vm_object_in_map( buffer_map, object, 0))
 1541                 return 1;
 1542         if( _vm_object_in_map( io_map, object, 0))
 1543                 return 1;
 1544         if( _vm_object_in_map( phys_map, object, 0))
 1545                 return 1;
 1546         if( _vm_object_in_map( mb_map, object, 0))
 1547                 return 1;
 1548         if( _vm_object_in_map( u_map, object, 0))
 1549                 return 1;
 1550         return 0;
 1551 }
 1552 
 1553 DB_SHOW_COMMAND(vmochk, vm_object_check)
 1554 {
 1555         vm_object_t object;
 1556 
 1557         /*
 1558          * make sure that internal objs are in a map somewhere
 1559          * and none have zero ref counts.
 1560          */
 1561         for (object = TAILQ_FIRST(&vm_object_list);
 1562                         object != NULL;
 1563                         object = TAILQ_NEXT(object, object_list)) {
 1564                 if (object->handle == NULL &&
 1565                     (object->type == OBJT_DEFAULT || object->type == OBJT_SWAP)) {
 1566                         if (object->ref_count == 0) {
 1567                                 db_printf("vmochk: internal obj has zero ref count: %d\n",
 1568                                         object->size);
 1569                         }
 1570                         if (!vm_object_in_map(object)) {
 1571                                 db_printf(
 1572                         "vmochk: internal obj is not in a map: "
 1573                         "ref: %d, size: %lu: 0x%lx, backing_object: %p\n",
 1574                                     object->ref_count, (u_long)object->size, 
 1575                                     (u_long)object->size,
 1576                                     (void *)object->backing_object);
 1577                         }
 1578                 }
 1579         }
 1580 }
 1581 
 1582 /*
 1583  *      vm_object_print:        [ debug ]
 1584  */
 1585 DB_SHOW_COMMAND(object, vm_object_print_static)
 1586 {
 1587         /* XXX convert args. */
 1588         vm_object_t object = (vm_object_t)addr;
 1589         boolean_t full = have_addr;
 1590 
 1591         register vm_page_t p;
 1592 
 1593         /* XXX count is an (unused) arg.  Avoid shadowing it. */
 1594 #define count   was_count
 1595 
 1596         register int count;
 1597 
 1598         if (object == NULL)
 1599                 return;
 1600 
 1601         db_iprintf(
 1602             "Object %p: type=%d, size=0x%lx, res=%d, ref=%d, flags=0x%x\n",
 1603             object, (int)object->type, (u_long)object->size,
 1604             object->resident_page_count, object->ref_count, object->flags);
 1605         /*
 1606          * XXX no %qd in kernel.  Truncate object->paging_offset and
 1607          * object->backing_object_offset.
 1608          */
 1609         db_iprintf(" sref=%d, offset=0x%lx, backing_object(%d)=(%p)+0x%lx\n",
 1610             object->shadow_count, (long)object->paging_offset,
 1611             object->backing_object ? object->backing_object->ref_count : 0,
 1612             object->backing_object, (long)object->backing_object_offset);
 1613 
 1614         if (!full)
 1615                 return;
 1616 
 1617         db_indent += 2;
 1618         count = 0;
 1619         for (p = TAILQ_FIRST(&object->memq); p != NULL; p = TAILQ_NEXT(p, listq)) {
 1620                 if (count == 0)
 1621                         db_iprintf("memory:=");
 1622                 else if (count == 6) {
 1623                         db_printf("\n");
 1624                         db_iprintf(" ...");
 1625                         count = 0;
 1626                 } else
 1627                         db_printf(",");
 1628                 count++;
 1629 
 1630                 db_printf("(off=0x%lx,page=0x%lx)",
 1631                     (u_long) p->pindex, (u_long) VM_PAGE_TO_PHYS(p));
 1632         }
 1633         if (count != 0)
 1634                 db_printf("\n");
 1635         db_indent -= 2;
 1636 }
 1637 
 1638 /* XXX. */
 1639 #undef count
 1640 
 1641 /* XXX need this non-static entry for calling from vm_map_print. */
 1642 void
 1643 vm_object_print(addr, have_addr, count, modif)
 1644         /* db_expr_t */ long addr;
 1645         boolean_t have_addr;
 1646         /* db_expr_t */ long count;
 1647         char *modif;
 1648 {
 1649         vm_object_print_static(addr, have_addr, count, modif);
 1650 }
 1651 
 1652 DB_SHOW_COMMAND(vmopag, vm_object_print_pages)
 1653 {
 1654         vm_object_t object;
 1655         int nl = 0;
 1656         int c;
 1657         for (object = TAILQ_FIRST(&vm_object_list);
 1658                         object != NULL;
 1659                         object = TAILQ_NEXT(object, object_list)) {
 1660                 vm_pindex_t idx, fidx;
 1661                 vm_pindex_t osize;
 1662                 vm_offset_t pa = -1, padiff;
 1663                 int rcount;
 1664                 vm_page_t m;
 1665 
 1666                 db_printf("new object: %p\n", (void *)object);
 1667                 if ( nl > 18) {
 1668                         c = cngetc();
 1669                         if (c != ' ')
 1670                                 return;
 1671                         nl = 0;
 1672                 }
 1673                 nl++;
 1674                 rcount = 0;
 1675                 fidx = 0;
 1676                 osize = object->size;
 1677                 if (osize > 128)
 1678                         osize = 128;
 1679                 for(idx=0;idx<osize;idx++) {
 1680                         m = vm_page_lookup(object, idx);
 1681                         if (m == NULL) {
 1682                                 if (rcount) {
 1683                                         db_printf(" index(%d)run(%d)pa(0x%x)\n",
 1684                                                 fidx, rcount, pa);
 1685                                         if ( nl > 18) {
 1686                                                 c = cngetc();
 1687                                                 if (c != ' ')
 1688                                                         return;
 1689                                                 nl = 0;
 1690                                         }
 1691                                         nl++;
 1692                                         rcount = 0;
 1693                                 }
 1694                                 continue;
 1695                         }
 1696 
 1697                                 
 1698                         if (rcount &&
 1699                                 (VM_PAGE_TO_PHYS(m) == pa + rcount * PAGE_SIZE)) {
 1700                                 ++rcount;
 1701                                 continue;
 1702                         }
 1703                         if (rcount) {
 1704                                 padiff = pa + rcount * PAGE_SIZE - VM_PAGE_TO_PHYS(m);
 1705                                 padiff >>= PAGE_SHIFT;
 1706                                 padiff &= PQ_L2_MASK;
 1707                                 if (padiff == 0) {
 1708                                         pa = VM_PAGE_TO_PHYS(m) - rcount * PAGE_SIZE;
 1709                                         ++rcount;
 1710                                         continue;
 1711                                 }
 1712                                 db_printf(" index(%d)run(%d)pa(0x%x)", fidx, rcount, pa);
 1713                                 db_printf("pd(%d)\n", padiff);
 1714                                 if ( nl > 18) {
 1715                                         c = cngetc();
 1716                                         if (c != ' ')
 1717                                                 return;
 1718                                         nl = 0;
 1719                                 }
 1720                                 nl++;
 1721                         }
 1722                         fidx = idx;
 1723                         pa = VM_PAGE_TO_PHYS(m);
 1724                         rcount = 1;
 1725                 }
 1726                 if (rcount) {
 1727                         db_printf(" index(%d)run(%d)pa(0x%x)\n", fidx, rcount, pa);
 1728                         if ( nl > 18) {
 1729                                 c = cngetc();
 1730                                 if (c != ' ')
 1731                                         return;
 1732                                 nl = 0;
 1733                         }
 1734                         nl++;
 1735                 }
 1736         }
 1737 }
 1738 #endif /* DDB */

Cache object: b8eff5e7ed48a654ab56124b1f05e082


[ 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.