Annotation of sys/uvm/uvm_loan.c, Revision 1.1.1.1
1.1 nbrk 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:
CVSweb