Deleted Added
full compact
vm_pageout.c (50477) vm_pageout.c (51337)
1/*
2 * Copyright (c) 1991 Regents of the University of California.
3 * All rights reserved.
4 * Copyright (c) 1994 John S. Dyson
5 * All rights reserved.
6 * Copyright (c) 1994 David Greenman
7 * All rights reserved.
8 *

--- 51 unchanged lines hidden (view full) ---

60 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
61 * School of Computer Science
62 * Carnegie Mellon University
63 * Pittsburgh PA 15213-3890
64 *
65 * any improvements or extensions that they make and grant Carnegie the
66 * rights to redistribute these changes.
67 *
1/*
2 * Copyright (c) 1991 Regents of the University of California.
3 * All rights reserved.
4 * Copyright (c) 1994 John S. Dyson
5 * All rights reserved.
6 * Copyright (c) 1994 David Greenman
7 * All rights reserved.
8 *

--- 51 unchanged lines hidden (view full) ---

60 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
61 * School of Computer Science
62 * Carnegie Mellon University
63 * Pittsburgh PA 15213-3890
64 *
65 * any improvements or extensions that they make and grant Carnegie the
66 * rights to redistribute these changes.
67 *
68 * $FreeBSD: head/sys/vm/vm_pageout.c 50477 1999-08-28 01:08:13Z peter $
68 * $FreeBSD: head/sys/vm/vm_pageout.c 51337 1999-09-17 04:56:40Z dillon $
69 */
70
71/*
72 * The proverbial page-out daemon.
73 */
74
75#include "opt_vm.h"
76#include <sys/param.h>

--- 137 unchanged lines hidden (view full) ---

214
215static int
216vm_pageout_clean(m)
217 vm_page_t m;
218{
219 register vm_object_t object;
220 vm_page_t mc[2*vm_pageout_page_count];
221 int pageout_count;
69 */
70
71/*
72 * The proverbial page-out daemon.
73 */
74
75#include "opt_vm.h"
76#include <sys/param.h>

--- 137 unchanged lines hidden (view full) ---

214
215static int
216vm_pageout_clean(m)
217 vm_page_t m;
218{
219 register vm_object_t object;
220 vm_page_t mc[2*vm_pageout_page_count];
221 int pageout_count;
222 int i, forward_okay, backward_okay, page_base;
222 int ib, is, page_base;
223 vm_pindex_t pindex = m->pindex;
224
225 object = m->object;
226
227 /*
228 * It doesn't cost us anything to pageout OBJT_DEFAULT or OBJT_SWAP
229 * with the new swapper, but we could have serious problems paging
230 * out other object types if there is insufficient memory.

--- 7 unchanged lines hidden (view full) ---

238 */
239 if ((m->hold_count != 0) ||
240 ((m->busy != 0) || (m->flags & PG_BUSY)))
241 return 0;
242
243 mc[vm_pageout_page_count] = m;
244 pageout_count = 1;
245 page_base = vm_pageout_page_count;
223 vm_pindex_t pindex = m->pindex;
224
225 object = m->object;
226
227 /*
228 * It doesn't cost us anything to pageout OBJT_DEFAULT or OBJT_SWAP
229 * with the new swapper, but we could have serious problems paging
230 * out other object types if there is insufficient memory.

--- 7 unchanged lines hidden (view full) ---

238 */
239 if ((m->hold_count != 0) ||
240 ((m->busy != 0) || (m->flags & PG_BUSY)))
241 return 0;
242
243 mc[vm_pageout_page_count] = m;
244 pageout_count = 1;
245 page_base = vm_pageout_page_count;
246 forward_okay = TRUE;
247 if (pindex != 0)
248 backward_okay = TRUE;
249 else
250 backward_okay = FALSE;
246 ib = 1;
247 is = 1;
248
251 /*
252 * Scan object for clusterable pages.
253 *
254 * We can cluster ONLY if: ->> the page is NOT
255 * clean, wired, busy, held, or mapped into a
256 * buffer, and one of the following:
257 * 1) The page is inactive, or a seldom used
258 * active page.
259 * -or-
260 * 2) we force the issue.
249 /*
250 * Scan object for clusterable pages.
251 *
252 * We can cluster ONLY if: ->> the page is NOT
253 * clean, wired, busy, held, or mapped into a
254 * buffer, and one of the following:
255 * 1) The page is inactive, or a seldom used
256 * active page.
257 * -or-
258 * 2) we force the issue.
259 *
260 * During heavy mmap/modification loads the pageout
261 * daemon can really fragment the underlying file
262 * due to flushing pages out of order and not trying
263 * align the clusters (which leave sporatic out-of-order
264 * holes). To solve this problem we do the reverse scan
265 * first and attempt to align our cluster, then do a
266 * forward scan if room remains.
261 */
267 */
262 for (i = 1; (i < vm_pageout_page_count) && (forward_okay || backward_okay); i++) {
268
269more:
270 while (ib && pageout_count < vm_pageout_page_count) {
263 vm_page_t p;
264
271 vm_page_t p;
272
265 /*
266 * See if forward page is clusterable.
267 */
268 if (forward_okay) {
269 /*
270 * Stop forward scan at end of object.
271 */
272 if ((pindex + i) > object->size) {
273 forward_okay = FALSE;
274 goto do_backward;
275 }
276 p = vm_page_lookup(object, pindex + i);
277 if (p) {
278 if (((p->queue - p->pc) == PQ_CACHE) ||
279 (p->flags & PG_BUSY) || p->busy) {
280 forward_okay = FALSE;
281 goto do_backward;
282 }
283 vm_page_test_dirty(p);
284 if ((p->dirty & p->valid) != 0 &&
285 (p->queue == PQ_INACTIVE) &&
286 (p->wire_count == 0) &&
287 (p->hold_count == 0)) {
288 mc[vm_pageout_page_count + i] = p;
289 pageout_count++;
290 if (pageout_count == vm_pageout_page_count)
291 break;
292 } else {
293 forward_okay = FALSE;
294 }
295 } else {
296 forward_okay = FALSE;
297 }
273 if (ib > pindex) {
274 ib = 0;
275 break;
298 }
276 }
299do_backward:
277
278 if ((p = vm_page_lookup(object, pindex - ib)) == NULL) {
279 ib = 0;
280 break;
281 }
282 if (((p->queue - p->pc) == PQ_CACHE) ||
283 (p->flags & PG_BUSY) || p->busy) {
284 ib = 0;
285 break;
286 }
287 vm_page_test_dirty(p);
288 if ((p->dirty & p->valid) == 0 ||
289 p->queue != PQ_INACTIVE ||
290 p->wire_count != 0 ||
291 p->hold_count != 0) {
292 ib = 0;
293 break;
294 }
295 mc[--page_base] = p;
296 ++pageout_count;
297 ++ib;
300 /*
298 /*
301 * See if backward page is clusterable.
299 * alignment boundry, stop here and switch directions. Do
300 * not clear ib.
302 */
301 */
303 if (backward_okay) {
304 /*
305 * Stop backward scan at beginning of object.
306 */
307 if ((pindex - i) == 0) {
308 backward_okay = FALSE;
309 }
310 p = vm_page_lookup(object, pindex - i);
311 if (p) {
312 if (((p->queue - p->pc) == PQ_CACHE) ||
313 (p->flags & PG_BUSY) || p->busy) {
314 backward_okay = FALSE;
315 continue;
316 }
317 vm_page_test_dirty(p);
318 if ((p->dirty & p->valid) != 0 &&
319 (p->queue == PQ_INACTIVE) &&
320 (p->wire_count == 0) &&
321 (p->hold_count == 0)) {
322 mc[vm_pageout_page_count - i] = p;
323 pageout_count++;
324 page_base--;
325 if (pageout_count == vm_pageout_page_count)
326 break;
327 } else {
328 backward_okay = FALSE;
329 }
330 } else {
331 backward_okay = FALSE;
332 }
302 if ((pindex - (ib - 1)) % vm_pageout_page_count == 0)
303 break;
304 }
305
306 while (pageout_count < vm_pageout_page_count &&
307 pindex + is < object->size) {
308 vm_page_t p;
309
310 if ((p = vm_page_lookup(object, pindex + is)) == NULL)
311 break;
312 if (((p->queue - p->pc) == PQ_CACHE) ||
313 (p->flags & PG_BUSY) || p->busy) {
314 break;
333 }
315 }
316 vm_page_test_dirty(p);
317 if ((p->dirty & p->valid) == 0 ||
318 p->queue != PQ_INACTIVE ||
319 p->wire_count != 0 ||
320 p->hold_count != 0) {
321 break;
322 }
323 mc[page_base + pageout_count] = p;
324 ++pageout_count;
325 ++is;
334 }
335
336 /*
326 }
327
328 /*
329 * If we exhausted our forward scan, continue with the reverse scan
330 * when possible, even past a page boundry. This catches boundry
331 * conditions.
332 */
333 if (ib && pageout_count < vm_pageout_page_count)
334 goto more;
335
336 /*
337 * we allow reads during pageouts...
338 */
339 return vm_pageout_flush(&mc[page_base], pageout_count, 0);
340}
341
342/*
343 * vm_pageout_flush() - launder the given pages
344 *

--- 47 unchanged lines hidden (view full) ---

392 break;
393 case VM_PAGER_BAD:
394 /*
395 * Page outside of range of object. Right now we
396 * essentially lose the changes by pretending it
397 * worked.
398 */
399 pmap_clear_modify(VM_PAGE_TO_PHYS(mt));
337 * we allow reads during pageouts...
338 */
339 return vm_pageout_flush(&mc[page_base], pageout_count, 0);
340}
341
342/*
343 * vm_pageout_flush() - launder the given pages
344 *

--- 47 unchanged lines hidden (view full) ---

392 break;
393 case VM_PAGER_BAD:
394 /*
395 * Page outside of range of object. Right now we
396 * essentially lose the changes by pretending it
397 * worked.
398 */
399 pmap_clear_modify(VM_PAGE_TO_PHYS(mt));
400 mt->dirty = 0;
400 vm_page_undirty(mt);
401 break;
402 case VM_PAGER_ERROR:
403 case VM_PAGER_FAIL:
404 /*
405 * If page couldn't be paged out, then reactivate the
406 * page so it doesn't clog the inactive list. (We
407 * will try paging out it again later).
408 */

--- 232 unchanged lines hidden (view full) ---

641 if (max_page_launder == 0)
642 max_page_launder = 1;
643
644 /*
645 * Calculate the number of pages we want to either free or move
646 * to the cache.
647 */
648
401 break;
402 case VM_PAGER_ERROR:
403 case VM_PAGER_FAIL:
404 /*
405 * If page couldn't be paged out, then reactivate the
406 * page so it doesn't clog the inactive list. (We
407 * will try paging out it again later).
408 */

--- 232 unchanged lines hidden (view full) ---

641 if (max_page_launder == 0)
642 max_page_launder = 1;
643
644 /*
645 * Calculate the number of pages we want to either free or move
646 * to the cache.
647 */
648
649 page_shortage = (cnt.v_free_target + cnt.v_cache_min) -
650 (cnt.v_free_count + cnt.v_cache_count);
651 page_shortage += addl_page_shortage_init;
649 page_shortage = vm_paging_target() + addl_page_shortage_init;
652
653 /*
654 * Figure out what to do with dirty pages when they are encountered.
655 * Assume that 1/3 of the pages on the inactive list are clean. If
656 * we think we can reach our target, disable laundering (do not
657 * clean any dirty pages). If we miss the target we will loop back
658 * up and do a laundering run.
659 */

--- 122 unchanged lines hidden (view full) ---

782
783 object = m->object;
784
785 if ((object->type != OBJT_SWAP) && (object->type != OBJT_DEFAULT)) {
786 swap_pageouts_ok = 1;
787 } else {
788 swap_pageouts_ok = !(defer_swap_pageouts || disable_swap_pageouts);
789 swap_pageouts_ok |= (!disable_swap_pageouts && defer_swap_pageouts &&
650
651 /*
652 * Figure out what to do with dirty pages when they are encountered.
653 * Assume that 1/3 of the pages on the inactive list are clean. If
654 * we think we can reach our target, disable laundering (do not
655 * clean any dirty pages). If we miss the target we will loop back
656 * up and do a laundering run.
657 */

--- 122 unchanged lines hidden (view full) ---

780
781 object = m->object;
782
783 if ((object->type != OBJT_SWAP) && (object->type != OBJT_DEFAULT)) {
784 swap_pageouts_ok = 1;
785 } else {
786 swap_pageouts_ok = !(defer_swap_pageouts || disable_swap_pageouts);
787 swap_pageouts_ok |= (!disable_swap_pageouts && defer_swap_pageouts &&
790 (cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min);
788 vm_page_count_min());
791
792 }
793
794 /*
795 * We don't bother paging objects that are "dead".
796 * Those objects are in a "rundown" state.
797 */
798 if (!swap_pageouts_ok || (object->flags & OBJ_DEAD)) {

--- 278 unchanged lines hidden (view full) ---

1077 }
1078#endif
1079
1080 /*
1081 * If we didn't get enough free pages, and we have skipped a vnode
1082 * in a writeable object, wakeup the sync daemon. And kick swapout
1083 * if we did not get enough free pages.
1084 */
789
790 }
791
792 /*
793 * We don't bother paging objects that are "dead".
794 * Those objects are in a "rundown" state.
795 */
796 if (!swap_pageouts_ok || (object->flags & OBJ_DEAD)) {

--- 278 unchanged lines hidden (view full) ---

1075 }
1076#endif
1077
1078 /*
1079 * If we didn't get enough free pages, and we have skipped a vnode
1080 * in a writeable object, wakeup the sync daemon. And kick swapout
1081 * if we did not get enough free pages.
1082 */
1085 if ((cnt.v_cache_count + cnt.v_free_count) <
1086 (cnt.v_free_target + cnt.v_cache_min) ) {
1087 if (vnodes_skipped &&
1088 (cnt.v_cache_count + cnt.v_free_count) < cnt.v_free_min) {
1083 if (vm_paging_target() > 0) {
1084 if (vnodes_skipped && vm_page_count_min())
1089 (void) speedup_syncer();
1085 (void) speedup_syncer();
1090 }
1091#if !defined(NO_SWAPPING)
1086#if !defined(NO_SWAPPING)
1092 if (vm_swap_enabled &&
1093 (cnt.v_free_count + cnt.v_cache_count < cnt.v_free_target)) {
1087 if (vm_swap_enabled && vm_page_count_target()) {
1094 vm_req_vmdaemon();
1095 vm_pageout_req_swapout |= VM_SWAP_NORMAL;
1096 }
1097#endif
1098 }
1099
1100 /*
1101 * make sure that we have swap space -- if we are low on memory and
1102 * swap -- then kill the biggest process.
1103 */
1088 vm_req_vmdaemon();
1089 vm_pageout_req_swapout |= VM_SWAP_NORMAL;
1090 }
1091#endif
1092 }
1093
1094 /*
1095 * make sure that we have swap space -- if we are low on memory and
1096 * swap -- then kill the biggest process.
1097 */
1104 if ((vm_swap_size == 0 || swap_pager_full) &&
1105 ((cnt.v_free_count + cnt.v_cache_count) < cnt.v_free_min)) {
1098 if ((vm_swap_size == 0 || swap_pager_full) && vm_page_count_min()) {
1106 bigproc = NULL;
1107 bigsize = 0;
1108 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
1109 /*
1110 * if this is a system process, skip it
1111 */
1112 if ((p->p_flag & P_SYSTEM) || (p->p_lock > 0) ||
1113 (p->p_pid == 1) ||

--- 41 unchanged lines hidden (view full) ---

1155vm_pageout_page_stats()
1156{
1157 int s;
1158 vm_page_t m,next;
1159 int pcount,tpcount; /* Number of pages to check */
1160 static int fullintervalcount = 0;
1161 int page_shortage;
1162
1099 bigproc = NULL;
1100 bigsize = 0;
1101 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
1102 /*
1103 * if this is a system process, skip it
1104 */
1105 if ((p->p_flag & P_SYSTEM) || (p->p_lock > 0) ||
1106 (p->p_pid == 1) ||

--- 41 unchanged lines hidden (view full) ---

1148vm_pageout_page_stats()
1149{
1150 int s;
1151 vm_page_t m,next;
1152 int pcount,tpcount; /* Number of pages to check */
1153 static int fullintervalcount = 0;
1154 int page_shortage;
1155
1163 page_shortage = (cnt.v_inactive_target + cnt.v_cache_max + cnt.v_free_min) -
1156 page_shortage =
1157 (cnt.v_inactive_target + cnt.v_cache_max + cnt.v_free_min) -
1164 (cnt.v_free_count + cnt.v_inactive_count + cnt.v_cache_count);
1158 (cnt.v_free_count + cnt.v_inactive_count + cnt.v_cache_count);
1159
1165 if (page_shortage <= 0)
1166 return;
1167
1168 pcount = cnt.v_active_count;
1169 fullintervalcount += vm_pageout_stats_interval;
1170 if (fullintervalcount < vm_pageout_full_stats_interval) {
1171 tpcount = (vm_pageout_stats_max * cnt.v_active_count) / cnt.v_page_count;
1172 if (pcount > tpcount)

--- 75 unchanged lines hidden (view full) ---

1248 if (cnt.v_page_count > 1024)
1249 cnt.v_free_min = 4 + (cnt.v_page_count - 1024) / 200;
1250 else
1251 cnt.v_free_min = 4;
1252 cnt.v_pageout_free_min = (2*MAXBSIZE)/PAGE_SIZE +
1253 cnt.v_interrupt_free_min;
1254 cnt.v_free_reserved = vm_pageout_page_count +
1255 cnt.v_pageout_free_min + (count / 768) + PQ_L2_SIZE;
1160 if (page_shortage <= 0)
1161 return;
1162
1163 pcount = cnt.v_active_count;
1164 fullintervalcount += vm_pageout_stats_interval;
1165 if (fullintervalcount < vm_pageout_full_stats_interval) {
1166 tpcount = (vm_pageout_stats_max * cnt.v_active_count) / cnt.v_page_count;
1167 if (pcount > tpcount)

--- 75 unchanged lines hidden (view full) ---

1243 if (cnt.v_page_count > 1024)
1244 cnt.v_free_min = 4 + (cnt.v_page_count - 1024) / 200;
1245 else
1246 cnt.v_free_min = 4;
1247 cnt.v_pageout_free_min = (2*MAXBSIZE)/PAGE_SIZE +
1248 cnt.v_interrupt_free_min;
1249 cnt.v_free_reserved = vm_pageout_page_count +
1250 cnt.v_pageout_free_min + (count / 768) + PQ_L2_SIZE;
1251 cnt.v_free_severe = cnt.v_free_min / 2;
1256 cnt.v_free_min += cnt.v_free_reserved;
1252 cnt.v_free_min += cnt.v_free_reserved;
1253 cnt.v_free_severe += cnt.v_free_reserved;
1257 return 1;
1258}
1259
1260
1261/*
1262 * vm_pageout is the high level pageout daemon.
1263 */
1264static void

--- 56 unchanged lines hidden (view full) ---

1321 curproc->p_flag |= P_BUFEXHAUST;
1322 swap_pager_swap_init();
1323 /*
1324 * The pageout daemon is never done, so loop forever.
1325 */
1326 while (TRUE) {
1327 int error;
1328 int s = splvm();
1254 return 1;
1255}
1256
1257
1258/*
1259 * vm_pageout is the high level pageout daemon.
1260 */
1261static void

--- 56 unchanged lines hidden (view full) ---

1318 curproc->p_flag |= P_BUFEXHAUST;
1319 swap_pager_swap_init();
1320 /*
1321 * The pageout daemon is never done, so loop forever.
1322 */
1323 while (TRUE) {
1324 int error;
1325 int s = splvm();
1329 if (!vm_pages_needed ||
1330 ((cnt.v_free_count + cnt.v_cache_count) > cnt.v_free_min)) {
1326
1327 if (vm_pages_needed && vm_page_count_min()) {
1328 /*
1329 * Still not done, sleep a bit and go again
1330 */
1331 vm_pages_needed = 0;
1331 vm_pages_needed = 0;
1332 tsleep(&vm_pages_needed, PVM, "psleep", hz/2);
1333 } else {
1334 /*
1335 * Good enough, sleep & handle stats
1336 */
1337 vm_pages_needed = 0;
1332 error = tsleep(&vm_pages_needed,
1333 PVM, "psleep", vm_pageout_stats_interval * hz);
1334 if (error && !vm_pages_needed) {
1335 splx(s);
1336 vm_pageout_page_stats();
1337 continue;
1338 }
1338 error = tsleep(&vm_pages_needed,
1339 PVM, "psleep", vm_pageout_stats_interval * hz);
1340 if (error && !vm_pages_needed) {
1341 splx(s);
1342 vm_pageout_page_stats();
1343 continue;
1344 }
1339 } else if (vm_pages_needed) {
1340 vm_pages_needed = 0;
1341 tsleep(&vm_pages_needed, PVM, "psleep", hz/2);
1342 }
1343
1344 if (vm_pages_needed)
1345 cnt.v_pdwakeups++;
1346 vm_pages_needed = 0;
1347 splx(s);
1348 vm_pageout_scan();
1349 vm_pageout_deficit = 0;

--- 82 unchanged lines hidden ---
1345 }
1346
1347 if (vm_pages_needed)
1348 cnt.v_pdwakeups++;
1349 vm_pages_needed = 0;
1350 splx(s);
1351 vm_pageout_scan();
1352 vm_pageout_deficit = 0;

--- 82 unchanged lines hidden ---