Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137435601
D4335.id10708.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D4335.id10708.diff
View Options
Index: head/sys/vm/vm_object.c
===================================================================
--- head/sys/vm/vm_object.c
+++ head/sys/vm/vm_object.c
@@ -1419,12 +1419,11 @@
VM_OBJECT_WLOCK(new_object);
}
-#define OBSC_TEST_ALL_SHADOWED 0x0001
#define OBSC_COLLAPSE_NOWAIT 0x0002
#define OBSC_COLLAPSE_WAIT 0x0004
static vm_page_t
-vm_object_backing_scan_wait(vm_object_t object, vm_page_t p, vm_page_t next,
+vm_object_collapse_scan_wait(vm_object_t object, vm_page_t p, vm_page_t next,
int op)
{
vm_object_t backing_object;
@@ -1452,192 +1451,185 @@
}
static bool
-vm_object_backing_scan(vm_object_t object, int op)
+vm_object_scan_all_shadowed(vm_object_t object)
{
vm_object_t backing_object;
- vm_page_t next, p, pp;
+ vm_page_t p, pp;
vm_pindex_t backing_offset_index, new_pindex;
VM_OBJECT_ASSERT_WLOCKED(object);
VM_OBJECT_ASSERT_WLOCKED(object->backing_object);
backing_object = object->backing_object;
- backing_offset_index = OFF_TO_IDX(object->backing_object_offset);
/*
- * Initial conditions
+ * Initial conditions:
+ *
+ * We do not want to have to test for the existence of cache or swap
+ * pages in the backing object. XXX but with the new swapper this
+ * would be pretty easy to do.
*/
- if (op & OBSC_TEST_ALL_SHADOWED) {
+ if (backing_object->type != OBJT_DEFAULT)
+ return (false);
+
+ backing_offset_index = OFF_TO_IDX(object->backing_object_offset);
+
+ for (p = TAILQ_FIRST(&backing_object->memq); p != NULL;
+ p = TAILQ_NEXT(p, listq)) {
+ new_pindex = p->pindex - backing_offset_index;
+
+ /*
+ * Ignore pages outside the parent object's range and outside
+ * the parent object's mapping of the backing object.
+ */
+ if (p->pindex < backing_offset_index ||
+ new_pindex >= object->size)
+ continue;
+
/*
- * We do not want to have to test for the existence of cache
- * or swap pages in the backing object. XXX but with the
- * new swapper this would be pretty easy to do.
+ * See if the parent has the page or if the parent's object
+ * pager has the page. If the parent has the page but the page
+ * is not valid, the parent's object pager must have the page.
*
- * XXX what about anonymous MAP_SHARED memory that hasn't
- * been ZFOD faulted yet? If we do not test for this, the
- * shadow test may succeed! XXX
+ * If this fails, the parent does not completely shadow the
+ * object and we might as well give up now.
*/
- if (backing_object->type != OBJT_DEFAULT) {
+ pp = vm_page_lookup(object, new_pindex);
+ if ((pp == NULL || pp->valid == 0) &&
+ !vm_pager_has_page(object, new_pindex, NULL, NULL))
return (false);
- }
}
- if (op & OBSC_COLLAPSE_WAIT) {
+ return (true);
+}
+
+static bool
+vm_object_collapse_scan(vm_object_t object, int op)
+{
+ vm_object_t backing_object;
+ vm_page_t next, p, pp;
+ vm_pindex_t backing_offset_index, new_pindex;
+
+ VM_OBJECT_ASSERT_WLOCKED(object);
+ VM_OBJECT_ASSERT_WLOCKED(object->backing_object);
+
+ backing_object = object->backing_object;
+ backing_offset_index = OFF_TO_IDX(object->backing_object_offset);
+
+ /*
+ * Initial conditions
+ */
+ if ((op & OBSC_COLLAPSE_WAIT) != 0)
vm_object_set_flag(backing_object, OBJ_DEAD);
- }
/*
* Our scan
*/
- p = TAILQ_FIRST(&backing_object->memq);
- while (p) {
+ for (p = TAILQ_FIRST(&backing_object->memq); p != NULL; p = next) {
next = TAILQ_NEXT(p, listq);
new_pindex = p->pindex - backing_offset_index;
- if (op & OBSC_TEST_ALL_SHADOWED) {
- /*
- * Ignore pages outside the parent object's range
- * and outside the parent object's mapping of the
- * backing object.
- *
- * Note that we do not busy the backing object's
- * page.
- */
- if (p->pindex < backing_offset_index ||
- new_pindex >= object->size) {
- p = next;
- continue;
- }
-
- /*
- * See if the parent has the page or if the parent's
- * object pager has the page. If the parent has the
- * page but the page is not valid, the parent's
- * object pager must have the page.
- *
- * If this fails, the parent does not completely shadow
- * the object and we might as well give up now.
- */
-
- pp = vm_page_lookup(object, new_pindex);
- if ((pp == NULL || pp->valid == 0) &&
- !vm_pager_has_page(object, new_pindex, NULL, NULL))
- return (false);
- }
/*
* Check for busy page
*/
- if (op & (OBSC_COLLAPSE_WAIT | OBSC_COLLAPSE_NOWAIT)) {
- if (vm_page_busied(p)) {
- p = vm_object_backing_scan_wait(object, p,
- next, op);
- continue;
- }
-
- KASSERT(p->object == backing_object,
- ("vm_object_backing_scan: object mismatch"));
-
- if (p->pindex < backing_offset_index ||
- new_pindex >= object->size) {
- if (backing_object->type == OBJT_SWAP)
- swap_pager_freespace(backing_object,
- p->pindex, 1);
-
- /*
- * Page is out of the parent object's range, we
- * can simply destroy it.
- */
- vm_page_lock(p);
- KASSERT(!pmap_page_is_mapped(p),
- ("freeing mapped page %p", p));
- if (p->wire_count == 0)
- vm_page_free(p);
- else
- vm_page_remove(p);
- vm_page_unlock(p);
- p = next;
- continue;
- }
+ if (vm_page_busied(p)) {
+ next = vm_object_collapse_scan_wait(object, p, next, op);
+ continue;
+ }
- pp = vm_page_lookup(object, new_pindex);
- if (pp != NULL && vm_page_busied(pp)) {
- /*
- * The page in the parent is busy and
- * possibly not (yet) valid. Until
- * its state is finalized by the busy
- * bit owner, we can't tell whether it
- * shadows the original page.
- * Therefore, we must either skip it
- * and the original (backing_object)
- * page or wait for its state to be
- * finalized.
- *
- * This is due to a race with vm_fault()
- * where we must unbusy the original
- * (backing_obj) page before we can
- * (re)lock the parent. Hence we can
- * get here.
- */
- p = vm_object_backing_scan_wait(object, pp,
- next, op);
- continue;
- }
+ KASSERT(p->object == backing_object,
+ ("vm_object_collapse_scan: object mismatch"));
- KASSERT(pp == NULL || pp->valid != 0,
- ("unbusy invalid page %p", pp));
+ if (p->pindex < backing_offset_index ||
+ new_pindex >= object->size) {
+ if (backing_object->type == OBJT_SWAP)
+ swap_pager_freespace(backing_object, p->pindex,
+ 1);
- if (pp != NULL || vm_pager_has_page(object,
- new_pindex, NULL, NULL)) {
- /*
- * The page already exists in the
- * parent OR swap exists for this
- * location in the parent. Leave the
- * parent's page alone. Destroy the
- * original page from the backing
- * object.
- */
- if (backing_object->type == OBJT_SWAP)
- swap_pager_freespace(backing_object,
- p->pindex, 1);
- vm_page_lock(p);
- KASSERT(!pmap_page_is_mapped(p),
- ("freeing mapped page %p", p));
- if (p->wire_count == 0)
- vm_page_free(p);
- else
- vm_page_remove(p);
- vm_page_unlock(p);
- p = next;
- continue;
- }
+ /*
+ * Page is out of the parent object's range, we can
+ * simply destroy it.
+ */
+ vm_page_lock(p);
+ KASSERT(!pmap_page_is_mapped(p),
+ ("freeing mapped page %p", p));
+ if (p->wire_count == 0)
+ vm_page_free(p);
+ else
+ vm_page_remove(p);
+ vm_page_unlock(p);
+ continue;
+ }
+ pp = vm_page_lookup(object, new_pindex);
+ if (pp != NULL && vm_page_busied(pp)) {
/*
- * Page does not exist in parent, rename the
- * page from the backing object to the main object.
+ * The page in the parent is busy and possibly not
+ * (yet) valid. Until its state is finalized by the
+ * busy bit owner, we can't tell whether it shadows the
+ * original page. Therefore, we must either skip it
+ * and the original (backing_object) page or wait for
+ * its state to be finalized.
*
- * If the page was mapped to a process, it can remain
- * mapped through the rename.
- * vm_page_rename() will handle dirty and cache.
+ * This is due to a race with vm_fault() where we must
+ * unbusy the original (backing_obj) page before we can
+ * (re)lock the parent. Hence we can get here.
*/
- if (vm_page_rename(p, object, new_pindex)) {
- p = vm_object_backing_scan_wait(object, NULL,
- next, op);
- continue;
- }
+ next = vm_object_collapse_scan_wait(object, pp, next,
+ op);
+ continue;
+ }
- /* Use the old pindex to free the right page. */
- if (backing_object->type == OBJT_SWAP)
- swap_pager_freespace(backing_object,
- new_pindex + backing_offset_index, 1);
+ KASSERT(pp == NULL || pp->valid != 0,
+ ("unbusy invalid page %p", pp));
-#if VM_NRESERVLEVEL > 0
+ if (pp != NULL || vm_pager_has_page(object, new_pindex, NULL,
+ NULL)) {
/*
- * Rename the reservation.
+ * The page already exists in the parent OR swap exists
+ * for this location in the parent. Leave the parent's
+ * page alone. Destroy the original page from the
+ * backing object.
*/
- vm_reserv_rename(p, object, backing_object,
- backing_offset_index);
-#endif
+ if (backing_object->type == OBJT_SWAP)
+ swap_pager_freespace(backing_object, p->pindex,
+ 1);
+ vm_page_lock(p);
+ KASSERT(!pmap_page_is_mapped(p),
+ ("freeing mapped page %p", p));
+ if (p->wire_count == 0)
+ vm_page_free(p);
+ else
+ vm_page_remove(p);
+ vm_page_unlock(p);
+ continue;
}
- p = next;
+
+ /*
+ * Page does not exist in parent, rename the page from the
+ * backing object to the main object.
+ *
+ * If the page was mapped to a process, it can remain mapped
+ * through the rename. vm_page_rename() will handle dirty and
+ * cache.
+ */
+ if (vm_page_rename(p, object, new_pindex)) {
+ next = vm_object_collapse_scan_wait(object, NULL, next,
+ op);
+ continue;
+ }
+
+ /* Use the old pindex to free the right page. */
+ if (backing_object->type == OBJT_SWAP)
+ swap_pager_freespace(backing_object,
+ new_pindex + backing_offset_index, 1);
+
+#if VM_NRESERVLEVEL > 0
+ /*
+ * Rename the reservation.
+ */
+ vm_reserv_rename(p, object, backing_object,
+ backing_offset_index);
+#endif
}
return (true);
}
@@ -1659,7 +1651,7 @@
if (backing_object->ref_count != 1)
return;
- vm_object_backing_scan(object, OBSC_COLLAPSE_NOWAIT);
+ vm_object_collapse_scan(object, OBSC_COLLAPSE_NOWAIT);
}
/*
@@ -1717,15 +1709,15 @@
* all the resident pages in the entire backing object.
*
* This is ignoring pager-backed pages such as swap pages.
- * vm_object_backing_scan fails the shadowing test in this
+ * vm_object_collapse_scan fails the shadowing test in this
* case.
*/
if (backing_object->ref_count == 1) {
/*
* If there is exactly one reference to the backing
- * object, we can collapse it into the parent.
+ * object, we can collapse it into the parent.
*/
- vm_object_backing_scan(object, OBSC_COLLAPSE_WAIT);
+ vm_object_collapse_scan(object, OBSC_COLLAPSE_WAIT);
#if VM_NRESERVLEVEL > 0
/*
@@ -1806,8 +1798,7 @@
* there is nothing we can do so we give up.
*/
if (object->resident_page_count != object->size &&
- !vm_object_backing_scan(object,
- OBSC_TEST_ALL_SHADOWED)) {
+ !vm_object_scan_all_shadowed(object)) {
VM_OBJECT_WUNLOCK(backing_object);
break;
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 24, 10:50 AM (2 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26057802
Default Alt Text
D4335.id10708.diff (11 KB)
Attached To
Mode
D4335: Pull vm_object_scan_all_shadowed out of vm_object_backing_scan
Attached
Detach File
Event Timeline
Log In to Comment