Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148085336
D22653.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D22653.id.diff
View Options
Index: head/sys/vm/vm_fault.c
===================================================================
--- head/sys/vm/vm_fault.c
+++ head/sys/vm/vm_fault.c
@@ -151,23 +151,42 @@
"the page fault handler");
static inline void
-release_page(struct faultstate *fs)
+fault_page_release(vm_page_t *mp)
{
+ vm_page_t m;
- if (fs->m != NULL) {
+ m = *mp;
+ if (m != NULL) {
/*
- * fs->m's object lock might not be held, so the page must be
- * kept busy until we are done with it.
+ * We are likely to loop around again and attempt to busy
+ * this page. Deactivating it leaves it available for
+ * pageout while optimizing fault restarts.
*/
- vm_page_lock(fs->m);
- vm_page_deactivate(fs->m);
- vm_page_unlock(fs->m);
- vm_page_xunbusy(fs->m);
- fs->m = NULL;
+ vm_page_lock(m);
+ vm_page_deactivate(m);
+ vm_page_unlock(m);
+ vm_page_xunbusy(m);
+ *mp = NULL;
}
}
static inline void
+fault_page_free(vm_page_t *mp)
+{
+ vm_page_t m;
+
+ m = *mp;
+ if (m != NULL) {
+ VM_OBJECT_ASSERT_WLOCKED(m->object);
+ if (!vm_page_wired(m))
+ vm_page_free(m);
+ else
+ vm_page_xunbusy(m);
+ *mp = NULL;
+ }
+}
+
+static inline void
unlock_map(struct faultstate *fs)
{
@@ -191,13 +210,13 @@
fault_deallocate(struct faultstate *fs)
{
+ fault_page_release(&fs->m);
vm_object_pip_wakeup(fs->object);
if (fs->object != fs->first_object) {
VM_OBJECT_WLOCK(fs->first_object);
- vm_page_free(fs->first_m);
- vm_object_pip_wakeup(fs->first_object);
+ fault_page_free(&fs->first_m);
VM_OBJECT_WUNLOCK(fs->first_object);
- fs->first_m = NULL;
+ vm_object_pip_wakeup(fs->first_object);
}
vm_object_deallocate(fs->first_object);
unlock_map(fs);
@@ -657,7 +676,6 @@
}
vhold(vp);
- release_page(fs);
unlock_and_deallocate(fs);
error = vget(vp, locked | LK_RETRY | LK_CANRECURSE, curthread);
vdrop(vp);
@@ -774,7 +792,7 @@
fs.lookup_still_valid = true;
- fs.first_m = NULL;
+ fs.m = fs.first_m = NULL;
/*
* Search for the page at object/offset.
@@ -782,6 +800,8 @@
fs.object = fs.first_object;
fs.pindex = fs.first_pindex;
while (TRUE) {
+ KASSERT(fs.m == NULL,
+ ("page still set %p at loop start", fs.m));
/*
* If the object is marked for imminent termination,
* we retry here, since the collapse pass has raced
@@ -826,23 +846,15 @@
*/
vm_page_aflag_set(fs.m, PGA_REFERENCED);
if (fs.object != fs.first_object) {
- if (!VM_OBJECT_TRYWLOCK(
- fs.first_object)) {
- VM_OBJECT_WUNLOCK(fs.object);
- VM_OBJECT_WLOCK(fs.first_object);
- VM_OBJECT_WLOCK(fs.object);
- }
- vm_page_free(fs.first_m);
+ fault_page_release(&fs.first_m);
vm_object_pip_wakeup(fs.first_object);
- VM_OBJECT_WUNLOCK(fs.first_object);
- fs.first_m = NULL;
}
unlock_map(&fs);
+ vm_object_pip_wakeup(fs.object);
if (fs.m == vm_page_lookup(fs.object,
fs.pindex)) {
vm_page_sleep_if_busy(fs.m, "vmpfw");
}
- vm_object_pip_wakeup(fs.object);
VM_OBJECT_WUNLOCK(fs.object);
VM_CNT_INC(v_intrans);
vm_object_deallocate(fs.first_object);
@@ -1091,40 +1103,28 @@
* an error.
*/
if (rv == VM_PAGER_ERROR || rv == VM_PAGER_BAD) {
- if (!vm_page_wired(fs.m))
- vm_page_free(fs.m);
- else
- vm_page_xunbusy(fs.m);
- fs.m = NULL;
+ fault_page_free(&fs.m);
unlock_and_deallocate(&fs);
return (KERN_OUT_OF_BOUNDS);
}
- /*
- * The requested page does not exist at this object/
- * offset. Remove the invalid page from the object,
- * waking up anyone waiting for it, and continue on to
- * the next object. However, if this is the top-level
- * object, we must leave the busy page in place to
- * prevent another process from rushing past us, and
- * inserting the page in that object at the same time
- * that we are.
- */
- if (fs.object != fs.first_object) {
- if (!vm_page_wired(fs.m))
- vm_page_free(fs.m);
- else
- vm_page_xunbusy(fs.m);
- fs.m = NULL;
- }
}
/*
- * We get here if the object has default pager (or unwiring)
- * or the pager doesn't have the page.
+ * The requested page does not exist at this object/
+ * offset. Remove the invalid page from the object,
+ * waking up anyone waiting for it, and continue on to
+ * the next object. However, if this is the top-level
+ * object, we must leave the busy page in place to
+ * prevent another process from rushing past us, and
+ * inserting the page in that object at the same time
+ * that we are.
*/
- if (fs.object == fs.first_object)
+ if (fs.object == fs.first_object) {
fs.first_m = fs.m;
+ fs.m = NULL;
+ } else
+ fault_page_free(&fs.m);
/*
* Move on to the next object. Lock the next object before
@@ -1142,9 +1142,11 @@
fs.object = fs.first_object;
fs.pindex = fs.first_pindex;
- fs.m = fs.first_m;
VM_OBJECT_WLOCK(fs.object);
}
+ MPASS(fs.first_m != NULL);
+ MPASS(fs.m == NULL);
+ fs.m = fs.first_m;
fs.first_m = NULL;
/*
@@ -1161,6 +1163,7 @@
faultcount = 1;
break; /* break to PAGE HAS BEEN FOUND */
} else {
+ MPASS(fs.first_m != NULL);
KASSERT(fs.object != next_object,
("object loop %p", next_object));
VM_OBJECT_WLOCK(next_object);
@@ -1257,7 +1260,7 @@
/*
* We no longer need the old page or object.
*/
- release_page(&fs);
+ fault_page_release(&fs.m);
}
/*
* fs.object != fs.first_object due to above
@@ -1295,7 +1298,6 @@
*/
if (!fs.lookup_still_valid) {
if (!vm_map_trylock_read(fs.map)) {
- release_page(&fs);
unlock_and_deallocate(&fs);
goto RetryFault;
}
@@ -1310,7 +1312,6 @@
* pageout will grab it eventually.
*/
if (result != KERN_SUCCESS) {
- release_page(&fs);
unlock_and_deallocate(&fs);
/*
@@ -1323,7 +1324,6 @@
}
if ((retry_object != fs.first_object) ||
(retry_pindex != fs.first_pindex)) {
- release_page(&fs);
unlock_and_deallocate(&fs);
goto RetryFault;
}
@@ -1339,7 +1339,6 @@
prot &= retry_prot;
fault_type &= retry_prot;
if (prot == 0) {
- release_page(&fs);
unlock_and_deallocate(&fs);
goto RetryFault;
}
@@ -1400,6 +1399,7 @@
vm_page_wire(fs.m);
}
vm_page_xunbusy(fs.m);
+ fs.m = NULL;
/*
* Unlock everything, and return
Index: head/sys/vm/vm_object.c
===================================================================
--- head/sys/vm/vm_object.c
+++ head/sys/vm/vm_object.c
@@ -1477,6 +1477,18 @@
goto retry;
}
+ /*
+ * The page was left invalid. Likely placed there by
+ * an incomplete fault. Just remove and ignore.
+ */
+ if (vm_page_none_valid(m)) {
+ if (vm_page_remove(m))
+ vm_page_free(m);
+ else
+ vm_page_xunbusy(m);
+ continue;
+ }
+
/* vm_page_rename() will dirty the page. */
if (vm_page_rename(m, new_object, idx)) {
vm_page_xunbusy(m);
@@ -1688,8 +1700,18 @@
continue;
}
- KASSERT(pp == NULL || !vm_page_none_valid(pp),
- ("unbusy invalid page %p", pp));
+ if (pp != NULL && vm_page_none_valid(pp)) {
+ /*
+ * The page was invalid in the parent. Likely placed
+ * there by an incomplete fault. Just remove and
+ * ignore. p can replace it.
+ */
+ if (vm_page_remove(pp))
+ vm_page_free(pp);
+ else
+ vm_page_xunbusy(pp);
+ pp = NULL;
+ }
if (pp != NULL || vm_pager_has_page(object, new_pindex, NULL,
NULL)) {
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 16, 4:13 PM (7 h, 37 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29752364
Default Alt Text
D22653.id.diff (7 KB)
Attached To
Mode
D22653: Allow default objects to have invalid pages so that fault restarts don't reallocate continuously.
Attached
Detach File
Event Timeline
Log In to Comment