* vm_pageout_flush() - launder the given pages * * The given pages are laundered. Note that we setup for the start of * I/O ( i.e. busy the page ), mark it read-only, and bump the object * reference count all in here rather then in the parent. If we want * the parent to do more sophisticated things we may have to change * the ordering. * * Returned runlen is the count of pages between mr
| 467 | * for any page in runlen set. |
| 468 | */ |
| 469 | int |
| 470 | vm_pageout_flush(vm_page_t *mc, int count, int flags, int mreq, int *prunlen, |
| 471 | boolean_t *eio) |
| 472 | { |
| 473 | vm_object_t object = mc[0]->object; |
| 474 | int pageout_status[count]; |
| 475 | int numpagedout = 0; |
| 476 | int i, runlen; |
| 477 | |
| 478 | VM_OBJECT_ASSERT_WLOCKED(object); |
| 479 | |
| 480 | /* |
| 481 | * Initiate I/O. Mark the pages shared busy and verify that they're |
| 482 | * valid and read-only. |
| 483 | * |
| 484 | * We do not have to fixup the clean/dirty bits here... we can |
| 485 | * allow the pager to do it after the I/O completes. |
| 486 | * |
| 487 | * NOTE! mc[i]->dirty may be partial or fragmented due to an |
| 488 | * edge case with file fragments. |
| 489 | */ |
| 490 | for (i = 0; i < count; i++) { |
| 491 | KASSERT(vm_page_all_valid(mc[i]), |
| 492 | ("vm_pageout_flush: partially invalid page %p index %d/%d", |
| 493 | mc[i], i, count)); |
| 494 | KASSERT((mc[i]->a.flags & PGA_WRITEABLE) == 0, |
| 495 | ("vm_pageout_flush: writeable page %p", mc[i])); |
| 496 | vm_page_busy_downgrade(mc[i]); |
| 497 | } |
| 498 | vm_object_pip_add(object, count); |
| 499 | |
| 500 | vm_pager_put_pages(object, mc, count, flags, pageout_status); |
| 501 | |
| 502 | runlen = count - mreq; |
| 503 | if (eio != NULL) |
| 504 | *eio = FALSE; |
| 505 | for (i = 0; i < count; i++) { |
| 506 | vm_page_t mt = mc[i]; |
| 507 | |
| 508 | KASSERT(pageout_status[i] == VM_PAGER_PEND || |
| 509 | !pmap_page_is_write_mapped(mt), |
| 510 | ("vm_pageout_flush: page %p is not write protected", mt)); |
| 511 | switch (pageout_status[i]) { |
| 512 | case VM_PAGER_OK: |
| 513 | /* |
| 514 | * The page may have moved since laundering started, in |
| 515 | * which case it should be left alone. |
| 516 | */ |
| 517 | if (vm_page_in_laundry(mt)) |
| 518 | vm_page_deactivate_noreuse(mt); |
| 519 | /* FALLTHROUGH */ |
| 520 | case VM_PAGER_PEND: |
| 521 | numpagedout++; |
| 522 | break; |
| 523 | case VM_PAGER_BAD: |
| 524 | /* |
| 525 | * The page is outside the object's range. We pretend |
| 526 | * that the page out worked and clean the page, so the |
no test coverage detected