summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/vm_fault.c3
-rw-r--r--sys/vm/vm_object.c41
-rw-r--r--sys/vm/vm_object.h1
-rw-r--r--sys/vm/vm_page.c2
4 files changed, 42 insertions, 5 deletions
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index 3507353..8814ae5 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -806,8 +806,7 @@ readrest:
if (prot & VM_PROT_WRITE) {
vm_page_flag_set(fs.m, PG_WRITEABLE);
- vm_object_set_flag(fs.m->object,
- OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY);
+ vm_object_set_writeable_dirty(fs.m->object);
/*
* If the fault is a write, we know that this page is being
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 1d5a989..b7613eb 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -321,8 +321,11 @@ vm_object_reference(vm_object_t object)
if (object == NULL)
return;
+#if 0
+ /* object can be re-referenced during final cleaning */
KASSERT(!(object->flags & OBJ_DEAD),
("vm_object_reference: attempting to reference dead obj"));
+#endif
object->ref_count++;
if (object->type == OBJT_VNODE) {
@@ -454,8 +457,13 @@ doterm:
temp->generation++;
object->backing_object = NULL;
}
- vm_object_terminate(object);
- /* unlocks and deallocates object */
+ /*
+ * Don't double-terminate, we could be in a termination
+ * recursion due to the terminate having to sync data
+ * to disk.
+ */
+ if ((object->flags & OBJ_DEAD) == 0)
+ vm_object_terminate(object);
object = temp;
}
}
@@ -627,7 +635,17 @@ vm_object_page_clean(vm_object_t object, vm_pindex_t start, vm_pindex_t end, int
}
if (clearobjflags && (tstart == 0) && (tend == object->size)) {
+ struct vnode *vp;
+
vm_object_clear_flag(object, OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY);
+ if (object->type == OBJT_VNODE &&
+ (vp = (struct vnode *)object->handle) != NULL) {
+ if (vp->v_flag & VOBJDIRTY) {
+ mtx_lock(&vp->v_interlock);
+ vp->v_flag &= ~VOBJDIRTY;
+ mtx_unlock(&vp->v_interlock);
+ }
+ }
}
rescan:
@@ -1357,6 +1375,8 @@ vm_object_collapse(vm_object_t object)
* and no object references within it, all that is
* necessary is to dispose of it.
*/
+ KASSERT(backing_object->ref_count == 1, ("backing_object %p was somehow re-referenced during collapse!", backing_object));
+ KASSERT(TAILQ_FIRST(&backing_object->memq) == NULL, ("backing_object %p somehow has left over pages during collapse!", backing_object));
TAILQ_REMOVE(
&vm_object_list,
@@ -1684,6 +1704,23 @@ vm_object_in_map(vm_object_t object)
return 0;
}
+void
+vm_object_set_writeable_dirty(vm_object_t object)
+{
+ struct vnode *vp;
+
+ vm_object_set_flag(object, OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY);
+ if (object->type == OBJT_VNODE &&
+ (vp = (struct vnode *)object->handle) != NULL) {
+ if ((vp->v_flag & VOBJDIRTY) == 0) {
+ mtx_lock(&vp->v_interlock);
+ vp->v_flag |= VOBJDIRTY;
+ mtx_unlock(&vp->v_interlock);
+ }
+ }
+}
+
+
DB_SHOW_COMMAND(vmochk, vm_object_check)
{
vm_object_t object;
diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h
index c126cb6..1256e85 100644
--- a/sys/vm/vm_object.h
+++ b/sys/vm/vm_object.h
@@ -184,6 +184,7 @@ void vm_object_collapse (vm_object_t);
void vm_object_deallocate (vm_object_t);
void vm_object_terminate (vm_object_t);
void vm_object_vndeallocate (vm_object_t);
+void vm_object_set_writeable_dirty (vm_object_t);
void vm_object_init (void);
void vm_object_page_clean (vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t);
void vm_object_page_remove (vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t);
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
index 61d821f..0eb06fc 100644
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -609,7 +609,7 @@ vm_page_insert(vm_page_t m, vm_object_t object, vm_pindex_t pindex)
* update the object's OBJ_WRITEABLE and OBJ_MIGHTBEDIRTY flags.
*/
if (m->flags & PG_WRITEABLE)
- vm_object_set_flag(object, OBJ_WRITEABLE|OBJ_MIGHTBEDIRTY);
+ vm_object_set_writeable_dirty(object);
}
/*
OpenPOWER on IntegriCloud