summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-09-14 10:11:38 +0000
committerkib <kib@FreeBSD.org>2013-09-14 10:11:38 +0000
commit889b9d0e0bc82fd4927dd02d64c973c36fa661a3 (patch)
treef37a78f4d81e6169576aba18f93a523010b92d84
parent8e2ea476ab8229a8a75ced9a6a6256ef9e102363 (diff)
downloadFreeBSD-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
-rw-r--r--sys/vm/vm_page.c13
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;
OpenPOWER on IntegriCloud