diff options
author | kib <kib@FreeBSD.org> | 2013-09-14 10:11:38 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2013-09-14 10:11:38 +0000 |
commit | 889b9d0e0bc82fd4927dd02d64c973c36fa661a3 (patch) | |
tree | f37a78f4d81e6169576aba18f93a523010b92d84 /sys | |
parent | 8e2ea476ab8229a8a75ced9a6a6256ef9e102363 (diff) | |
download | FreeBSD-src-889b9d0e0bc82fd4927dd02d64c973c36fa661a3.zip FreeBSD-src-889b9d0e0bc82fd4927dd02d64c973c36fa661a3.tar.gz |
If the last page of the file is partially full and whole valid
portion is invalidated, invalidate the whole page. Otherwise,
partially valid page appears on a page queue, which is wrong. This
could only happen for the last page, because only then buffer which
triggered invalidation could not cover the whole page.
Reported and tested by: pho (previous version)
Reviewed by: alc
Sponsored by: The FreeBSD Foundation
Approved by: re (delphij)
MFC after: 2 weeks
Diffstat (limited to 'sys')
-rw-r--r-- | sys/vm/vm_page.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 53ffc72..3a2c7f0 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -2980,12 +2980,19 @@ void vm_page_set_invalid(vm_page_t m, int base, int size) { vm_page_bits_t bits; + vm_object_t object; - VM_OBJECT_ASSERT_WLOCKED(m->object); - bits = vm_page_bits(base, size); + object = m->object; + VM_OBJECT_ASSERT_WLOCKED(object); + if (object->type == OBJT_VNODE && base == 0 && IDX_TO_OFF(m->pindex) + + size >= object->un_pager.vnp.vnp_size) + bits = VM_PAGE_BITS_ALL; + else + bits = vm_page_bits(base, size); if (m->valid == VM_PAGE_BITS_ALL && bits != 0) pmap_remove_all(m); - KASSERT(!pmap_page_is_mapped(m), + KASSERT((bits == 0 && m->valid == VM_PAGE_BITS_ALL) || + !pmap_page_is_mapped(m), ("vm_page_set_invalid: page %p is mapped", m)); m->valid &= ~bits; m->dirty &= ~bits; |