summaryrefslogtreecommitdiffstats
path: root/sys/vm/vnode_pager.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm/vnode_pager.c')
-rw-r--r--sys/vm/vnode_pager.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index a6d78f4..1e3f4b4 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -373,6 +373,7 @@ vnode_pager_setsize(vp, nsize)
vm_ooffset_t nsize;
{
vm_object_t object;
+ struct vnode *drop;
vm_page_t m;
vm_pindex_t nobjsize;
@@ -398,16 +399,41 @@ vnode_pager_setsize(vp, nsize)
/*
* this gets rid of garbage at the end of a page that is now
* only partially backed by the vnode.
- *
- * XXX for some reason (I don't know yet), if we take a
- * completely invalid page and mark it partially valid
- * it can screw up NFS reads, so we don't allow the case.
*/
if ((nsize & PAGE_MASK) &&
- (m = vm_page_lookup(object, OFF_TO_IDX(nsize))) != NULL &&
- m->valid != 0) {
- int base = (int)nsize & PAGE_MASK;
- int size = PAGE_SIZE - base;
+ (m = vm_radix_lookup(&object->rtree, OFF_TO_IDX(nsize),
+ VM_RADIX_ANY)) != NULL) {
+ int base;
+ int size;
+
+ /*
+ * Eliminate any cached page as we would have to
+ * do too much work to save it.
+ */
+ if (m->flags & PG_CACHED) {
+ drop = NULL;
+ mtx_lock(&vm_page_queue_free_mtx);
+ if (m->object == object) {
+ vm_page_cache_free(m);
+ if (object->cached_page_count == 0)
+ drop = vp;
+ }
+ mtx_unlock(&vm_page_queue_free_mtx);
+ if (drop)
+ vdrop(drop);
+ goto out;
+ }
+ /*
+ * XXX for some reason (I don't know yet), if we take a
+ * completely invalid page and mark it partially valid
+ * it can screw up NFS reads, so we don't allow the
+ * case.
+ */
+ if (m->valid != 0 || m->object != object)
+ goto out;
+
+ base = (int)nsize & PAGE_MASK;
+ size = PAGE_SIZE - base;
/*
* Clear out partial-page garbage in case
@@ -437,12 +463,9 @@ vnode_pager_setsize(vp, nsize)
* replacement from working properly.
*/
vm_page_clear_dirty(m, base, PAGE_SIZE - base);
- } else if ((nsize & PAGE_MASK) &&
- vm_page_is_cached(object, OFF_TO_IDX(nsize))) {
- vm_page_cache_free(object, OFF_TO_IDX(nsize),
- nobjsize);
}
}
+out:
object->un_pager.vnp.vnp_size = nsize;
object->size = nobjsize;
VM_OBJECT_UNLOCK(object);
OpenPOWER on IntegriCloud