Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F81969297
D6085.id15571.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D6085.id15571.diff
View Options
Index: sys/vm/vm_fault.c
===================================================================
--- sys/vm/vm_fault.c
+++ sys/vm/vm_fault.c
@@ -137,7 +137,12 @@
vm_page_xunbusy(fs->m);
vm_page_lock(fs->m);
- vm_page_deactivate(fs->m);
+ if (fs->m->valid == 0) {
+ if (fs->m->wire_count == 0)
+ vm_page_free(fs->m);
+ } else {
+ vm_page_deactivate(fs->m);
+ }
vm_page_unlock(fs->m);
fs->m = NULL;
}
@@ -292,7 +297,8 @@
struct faultstate fs;
struct vnode *vp;
vm_page_t m;
- int ahead, behind, cluster_offset, error, locked;
+ int ahead, behind, cluster_offset, dead, error, locked, rv;
+ u_char behavior;
hardfault = 0;
growstack = TRUE;
@@ -412,7 +418,7 @@
fs.lookup_still_valid = TRUE;
- fs.first_m = NULL;
+ fs.m = fs.first_m = NULL;
/*
* Search for the page at object/offset.
@@ -421,11 +427,20 @@
fs.pindex = fs.first_pindex;
while (TRUE) {
/*
- * If the object is dead, we stop here
+ * If the object is marked for imminent termination,
+ * we retry here, since the collapse pass has raced
+ * with us. Otherwise, if we see terminally dead
+ * object, return fail.
*/
- if (fs.object->flags & OBJ_DEAD) {
+ if ((fs.object->flags & OBJ_DEAD) != 0) {
+ dead = fs.object->type == OBJT_DEAD;
+ if (fs.m != NULL && fs.m != fs.first_m)
+ release_page(&fs);
unlock_and_deallocate(&fs);
- return (KERN_PROTECTION_FAILURE);
+ if (dead)
+ return (KERN_PROTECTION_FAILURE);
+ pause("vmf_de", 1);
+ goto RetryFault;
}
/*
@@ -551,9 +566,18 @@
* zero-filled pages.
*/
if (fs.object->type != OBJT_DEFAULT) {
- int rv;
- u_char behavior = vm_map_entry_behavior(fs.entry);
-
+ if (!fs.lookup_still_valid) {
+ locked = vm_map_trylock_read(fs.map);
+ if (locked)
+ fs.lookup_still_valid = TRUE;
+ if (!locked || fs.map->timestamp !=
+ map_generation) {
+ release_page(&fs);
+ unlock_and_deallocate(&fs);
+ goto RetryFault;
+ }
+ }
+ behavior = vm_map_entry_behavior(fs.entry);
era = fs.entry->read_ahead;
if (behavior == MAP_ENTRY_BEHAV_RANDOM ||
P_KILLED(curproc)) {
@@ -604,6 +628,7 @@
}
ahead = ulmin(ahead, atop(fs.entry->end - vaddr) - 1);
if (era != nera)
+ /* XXX only read-lock on map */
fs.entry->read_ahead = nera;
/*
@@ -821,6 +846,7 @@
if (vm_page_rename(fs.m, fs.first_object,
fs.first_pindex)) {
VM_OBJECT_WUNLOCK(fs.first_object);
+ release_page(&fs);
unlock_and_deallocate(&fs);
goto RetryFault;
}
Index: sys/vm/vm_object.c
===================================================================
--- sys/vm/vm_object.c
+++ sys/vm/vm_object.c
@@ -1584,7 +1584,7 @@
continue;
}
- KASSERT(pp == NULL || pp->valid != 0,
+ KASSERT(pp == NULL || pp->wire_count > 0 || pp->valid != 0,
("unbusy invalid page %p", pp));
if (pp != NULL || vm_pager_has_page(object, new_pindex, NULL,
@@ -1669,11 +1669,14 @@
void
vm_object_collapse(vm_object_t object)
{
+ vm_object_t backing_object, new_backing_object;
+
VM_OBJECT_ASSERT_WLOCKED(object);
-
- while (TRUE) {
- vm_object_t backing_object;
+ if ((object->flags & OBJ_DEAD) != 0)
+ return;
+ vm_object_pip_add(object, 1);
+ while (TRUE) {
/*
* Verify that the conditions are right for collapse:
*
@@ -1699,14 +1702,14 @@
break;
}
- if (
- object->paging_in_progress != 0 ||
- backing_object->paging_in_progress != 0
- ) {
+ if (object->paging_in_progress > 1 /* one ref is from us */ ||
+ backing_object->paging_in_progress != 0) {
vm_object_qcollapse(object);
VM_OBJECT_WUNLOCK(backing_object);
break;
}
+ vm_object_pip_add(backing_object, 1);
+
/*
* We know that we can either collapse the backing object (if
* the parent is the only reference to it) or (perhaps) have
@@ -1789,6 +1792,7 @@
KASSERT(backing_object->ref_count == 1, (
"backing_object %p was somehow re-referenced during collapse!",
backing_object));
+ vm_object_pip_wakeup(backing_object);
backing_object->type = OBJT_DEAD;
backing_object->ref_count = 0;
VM_OBJECT_WUNLOCK(backing_object);
@@ -1796,14 +1800,13 @@
object_collapses++;
} else {
- vm_object_t new_backing_object;
-
/*
* If we do not entirely shadow the backing object,
* there is nothing we can do so we give up.
*/
if (object->resident_page_count != object->size &&
!vm_object_scan_all_shadowed(object)) {
+ vm_object_pip_wakeup(backing_object);
VM_OBJECT_WUNLOCK(backing_object);
break;
}
@@ -1836,6 +1839,7 @@
* its ref_count was at least 2, it will not vanish.
*/
backing_object->ref_count--;
+ vm_object_pip_wakeup(backing_object);
VM_OBJECT_WUNLOCK(backing_object);
object_bypasses++;
}
@@ -1844,6 +1848,7 @@
* Try again with this object's new backing object.
*/
}
+ vm_object_pip_wakeup(object);
}
/*
Index: sys/vm/vm_page.c
===================================================================
--- sys/vm/vm_page.c
+++ sys/vm/vm_page.c
@@ -1944,8 +1944,10 @@
m < &m_ret[npages]; m++) {
if ((req & VM_ALLOC_WIRED) != 0)
m->wire_count = 0;
- if (m >= m_tmp)
+ if (m >= m_tmp) {
m->object = NULL;
+ m->oflags |= VPO_UNMANAGED;
+ }
vm_page_free(m);
}
return (NULL);
@@ -3288,7 +3290,8 @@
cache_was_empty = vm_radix_is_empty(&object->cache);
if (vm_radix_insert(&object->cache, m)) {
mtx_unlock(&vm_page_queue_free_mtx);
- if (object->resident_page_count == 0)
+ if (object->type == OBJT_VNODE &&
+ object->resident_page_count == 0)
vdrop(object->handle);
m->object = NULL;
vm_page_free(m);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Dec 15, 4:48 AM (12 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
9091418
Default Alt Text
D6085.id15571.diff (5 KB)
Attached To
Mode
D6085: Collapse/vm_fault races and small fixes for radix insertion failures
Attached
Detach File
Event Timeline
Log In to Comment