Changeset View
Changeset View
Standalone View
Standalone View
head/sys/dev/md/md.c
Show First 20 Lines • Show All 1,051 Lines • ▼ Show 20 Lines | mdstart_swap(struct md_s *sc, struct bio *bp) | ||||
* position within that last page (ie, PAGE_SIZE if | * position within that last page (ie, PAGE_SIZE if | ||||
* we're operating on complete aligned pages). | * we're operating on complete aligned pages). | ||||
*/ | */ | ||||
offs = bp->bio_offset % PAGE_SIZE; | offs = bp->bio_offset % PAGE_SIZE; | ||||
lastp = (bp->bio_offset + bp->bio_length - 1) / PAGE_SIZE; | lastp = (bp->bio_offset + bp->bio_length - 1) / PAGE_SIZE; | ||||
lastend = (bp->bio_offset + bp->bio_length - 1) % PAGE_SIZE + 1; | lastend = (bp->bio_offset + bp->bio_length - 1) % PAGE_SIZE + 1; | ||||
rv = VM_PAGER_OK; | rv = VM_PAGER_OK; | ||||
VM_OBJECT_WLOCK(sc->object); | |||||
vm_object_pip_add(sc->object, 1); | vm_object_pip_add(sc->object, 1); | ||||
for (i = bp->bio_offset / PAGE_SIZE; i <= lastp; i++) { | for (i = bp->bio_offset / PAGE_SIZE; i <= lastp; i++) { | ||||
len = ((i == lastp) ? lastend : PAGE_SIZE) - offs; | len = ((i == lastp) ? lastend : PAGE_SIZE) - offs; | ||||
VM_OBJECT_WLOCK(sc->object); | |||||
m = vm_page_grab(sc->object, i, VM_ALLOC_SYSTEM); | m = vm_page_grab(sc->object, i, VM_ALLOC_SYSTEM); | ||||
VM_OBJECT_WUNLOCK(sc->object); | |||||
if (bp->bio_cmd == BIO_READ) { | if (bp->bio_cmd == BIO_READ) { | ||||
if (vm_page_all_valid(m)) | if (vm_page_all_valid(m)) | ||||
rv = VM_PAGER_OK; | rv = VM_PAGER_OK; | ||||
else | else | ||||
rv = vm_pager_get_pages(sc->object, &m, 1, | rv = vm_pager_get_pages(sc->object, &m, 1, | ||||
NULL, NULL); | NULL, NULL); | ||||
if (rv == VM_PAGER_ERROR) { | if (rv == VM_PAGER_ERROR) { | ||||
VM_OBJECT_WLOCK(sc->object); | |||||
vm_page_free(m); | vm_page_free(m); | ||||
VM_OBJECT_WUNLOCK(sc->object); | |||||
break; | break; | ||||
} else if (rv == VM_PAGER_FAIL) { | } else if (rv == VM_PAGER_FAIL) { | ||||
/* | /* | ||||
* Pager does not have the page. Zero | * Pager does not have the page. Zero | ||||
* the allocated page, and mark it as | * the allocated page, and mark it as | ||||
* valid. Do not set dirty, the page | * valid. Do not set dirty, the page | ||||
* can be recreated if thrown out. | * can be recreated if thrown out. | ||||
*/ | */ | ||||
Show All 13 Lines | if (bp->bio_cmd == BIO_READ) { | ||||
} | } | ||||
} else if (bp->bio_cmd == BIO_WRITE) { | } else if (bp->bio_cmd == BIO_WRITE) { | ||||
if (len == PAGE_SIZE || vm_page_all_valid(m)) | if (len == PAGE_SIZE || vm_page_all_valid(m)) | ||||
rv = VM_PAGER_OK; | rv = VM_PAGER_OK; | ||||
else | else | ||||
rv = vm_pager_get_pages(sc->object, &m, 1, | rv = vm_pager_get_pages(sc->object, &m, 1, | ||||
NULL, NULL); | NULL, NULL); | ||||
if (rv == VM_PAGER_ERROR) { | if (rv == VM_PAGER_ERROR) { | ||||
VM_OBJECT_WLOCK(sc->object); | |||||
vm_page_free(m); | vm_page_free(m); | ||||
VM_OBJECT_WUNLOCK(sc->object); | |||||
break; | break; | ||||
} else if (rv == VM_PAGER_FAIL) | } else if (rv == VM_PAGER_FAIL) | ||||
pmap_zero_page(m); | pmap_zero_page(m); | ||||
if ((bp->bio_flags & BIO_UNMAPPED) != 0) { | if ((bp->bio_flags & BIO_UNMAPPED) != 0) { | ||||
pmap_copy_pages(bp->bio_ma, ma_offs, &m, | pmap_copy_pages(bp->bio_ma, ma_offs, &m, | ||||
offs, len); | offs, len); | ||||
} else if ((bp->bio_flags & BIO_VLIST) != 0) { | } else if ((bp->bio_flags & BIO_VLIST) != 0) { | ||||
physcopyin_vlist(vlist, ma_offs, | physcopyin_vlist(vlist, ma_offs, | ||||
VM_PAGE_TO_PHYS(m) + offs, len); | VM_PAGE_TO_PHYS(m) + offs, len); | ||||
} else { | } else { | ||||
physcopyin(p, VM_PAGE_TO_PHYS(m) + offs, len); | physcopyin(p, VM_PAGE_TO_PHYS(m) + offs, len); | ||||
} | } | ||||
vm_page_valid(m); | vm_page_valid(m); | ||||
vm_page_set_dirty(m); | vm_page_set_dirty(m); | ||||
} else if (bp->bio_cmd == BIO_DELETE) { | } else if (bp->bio_cmd == BIO_DELETE) { | ||||
if (len == PAGE_SIZE || vm_page_all_valid(m)) | if (len == PAGE_SIZE || vm_page_all_valid(m)) | ||||
rv = VM_PAGER_OK; | rv = VM_PAGER_OK; | ||||
else | else | ||||
rv = vm_pager_get_pages(sc->object, &m, 1, | rv = vm_pager_get_pages(sc->object, &m, 1, | ||||
NULL, NULL); | NULL, NULL); | ||||
VM_OBJECT_WLOCK(sc->object); | |||||
if (rv == VM_PAGER_ERROR) { | if (rv == VM_PAGER_ERROR) { | ||||
vm_page_free(m); | vm_page_free(m); | ||||
VM_OBJECT_WUNLOCK(sc->object); | |||||
break; | break; | ||||
} else if (rv == VM_PAGER_FAIL) { | } else if (rv == VM_PAGER_FAIL) { | ||||
vm_page_free(m); | vm_page_free(m); | ||||
m = NULL; | m = NULL; | ||||
} else { | } else { | ||||
/* Page is valid. */ | /* Page is valid. */ | ||||
if (len != PAGE_SIZE) { | if (len != PAGE_SIZE) { | ||||
pmap_zero_page_area(m, offs, len); | pmap_zero_page_area(m, offs, len); | ||||
vm_page_set_dirty(m); | vm_page_set_dirty(m); | ||||
} else { | } else { | ||||
vm_pager_page_unswapped(m); | vm_pager_page_unswapped(m); | ||||
vm_page_free(m); | vm_page_free(m); | ||||
m = NULL; | m = NULL; | ||||
} | } | ||||
} | } | ||||
VM_OBJECT_WUNLOCK(sc->object); | |||||
} | } | ||||
if (m != NULL) { | if (m != NULL) { | ||||
vm_page_xunbusy(m); | vm_page_xunbusy(m); | ||||
/* | /* | ||||
* The page may be deactivated prior to setting | * The page may be deactivated prior to setting | ||||
* PGA_REFERENCED, but in this case it will be | * PGA_REFERENCED, but in this case it will be | ||||
* reactivated by the page daemon. | * reactivated by the page daemon. | ||||
*/ | */ | ||||
if (vm_page_active(m)) | if (vm_page_active(m)) | ||||
vm_page_reference(m); | vm_page_reference(m); | ||||
else | else | ||||
vm_page_activate(m); | vm_page_activate(m); | ||||
} | } | ||||
/* Actions on further pages start at offset 0 */ | /* Actions on further pages start at offset 0 */ | ||||
p += PAGE_SIZE - offs; | p += PAGE_SIZE - offs; | ||||
offs = 0; | offs = 0; | ||||
ma_offs += len; | ma_offs += len; | ||||
} | } | ||||
vm_object_pip_wakeup(sc->object); | vm_object_pip_wakeup(sc->object); | ||||
VM_OBJECT_WUNLOCK(sc->object); | |||||
return (rv != VM_PAGER_ERROR ? 0 : ENOSPC); | return (rv != VM_PAGER_ERROR ? 0 : ENOSPC); | ||||
} | } | ||||
static int | static int | ||||
mdstart_null(struct md_s *sc, struct bio *bp) | mdstart_null(struct md_s *sc, struct bio *bp) | ||||
{ | { | ||||
switch (bp->bio_cmd) { | switch (bp->bio_cmd) { | ||||
▲ Show 20 Lines • Show All 998 Lines • Show Last 20 Lines |