Page MenuHomeFreeBSD

D60751.1793998441.diff
No OneTemporary

Authored By
Unknown
Size
6 KB
Referenced Files
None
Subscribers
None

D60751.1793998441.diff

diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h
--- a/sys/vm/vm_extern.h
+++ b/sys/vm/vm_extern.h
@@ -133,7 +133,7 @@
u_int vm_inactive_count(void);
u_int vm_laundry_count(void);
u_int vm_wait_count(void);
-
+int vm_fault_wire(vm_map_t, vm_map_entry_t, vm_offset_t *);
/*
* Is pa a multiple of alignment, which is a power-of-two?
*/
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -492,6 +492,19 @@
MPASS(vm_page_xbusied(m));
}
+static void
+vm_pager_populate_check_range(vm_object_t obj, vm_pindex_t pager_first,
+ vm_pindex_t pager_last, vm_pindex_t first_pindex)
+{
+ VM_OBJECT_ASSERT_WLOCKED(obj);
+
+ /* Ensure that the driver is obeying the 'vm_pager_populate' interface. */
+ MPASS(pager_first <= pager_last);
+ MPASS(first_pindex <= pager_last);
+ MPASS(first_pindex >= pager_first);
+ MPASS(pager_last < obj->size);
+}
+
static void
vm_fault_populate_cleanup(vm_object_t object, vm_pindex_t first,
vm_pindex_t last)
@@ -561,11 +574,8 @@
if (rv != VM_PAGER_OK)
return (FAULT_FAILURE); /* AKA SIGSEGV */
- /* Ensure that the driver is obeying the interface. */
- MPASS(pager_first <= pager_last);
- MPASS(fs->first_pindex <= pager_last);
- MPASS(fs->first_pindex >= pager_first);
- MPASS(pager_last < fs->first_object->size);
+ vm_pager_populate_check_range(fs->first_object, pager_first, pager_last,
+ fs->first_pindex);
vm_fault_restore_map_lock(fs);
bdry_idx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(fs->entry);
@@ -2513,3 +2523,142 @@
curthread_pflags_restore(save);
}
+
+static enum fault_status
+vm_fault_wire_quick(vm_map_t map, vm_object_t obj, vm_map_entry_t entry,
+ vm_offset_t *faddr)
+{
+ vm_pindex_t pager_first, pager_last, pidx;
+ vm_pindex_t entry_first, entry_last;
+ struct pctrie_iter pages;
+ int npages, i;
+ vm_page_t m;
+ int rv;
+
+ KASSERT(vm_map_locked(map) != 0, ("%s: map is not locked", __func__));
+ KASSERT((obj->flags & OBJ_POPULATE) != 0,
+ ("%s: object cannot use vm_pager_populate", __func__));
+ VM_OBJECT_WLOCK(obj);
+ vm_object_pip_add(obj, 1);
+
+ entry_first = pager_first = OFF_TO_IDX(
+ (*faddr - entry->start) + entry->offset);
+ entry_last = pager_last = pager_first +
+ atop(entry->end - entry->start) - 1;
+#if VM_NRESERVLEVEL > 0
+ vm_object_color(obj, entry_first);
+#endif
+
+ /*
+ * Let the pager populate the entire entry.
+ */
+ rv = vm_pager_populate(obj, entry_first, VM_PROT_NONE,
+ entry->max_protection, &pager_first, &pager_last);
+ if (rv != VM_PAGER_OK) {
+ /*
+ * Fall back to the slow path if the pager requested normal
+ * fault handling through VM_PAGER_BAD.
+ */
+ rv = rv == VM_PAGER_BAD ? FAULT_CONTINUE : FAULT_FAILURE;
+ goto out;
+ }
+ vm_pager_populate_check_range(obj, pager_first, pager_last,
+ entry_first);
+
+ /*
+ * Remove any extraneous pages that the pager might have allocated.
+ */
+ if (entry_first > pager_first) {
+ vm_fault_populate_cleanup(obj, pager_first, entry_first - 1);
+ pager_first = entry_first;
+ }
+ if (entry_last < pager_last) {
+ vm_fault_populate_cleanup(obj, entry_last + 1, pager_last);
+ pager_last = entry_last;
+ }
+
+ vm_page_iter_init(&pages, obj);
+ for (pidx = pager_first; pidx <= pager_last;) {
+ m = vm_radix_iter_lookup(&pages, pidx);
+ KASSERT(m != NULL, ("page not found for pindex 0x%lu", pidx));
+ KASSERT(m->pindex == pidx, ("%s: pindex mismatch", __func__));
+ rv = pmap_enter(map->pmap, *faddr, m, entry->protection,
+ VM_PROT_NONE | PMAP_ENTER_NOSLEEP | PMAP_ENTER_WIRED,
+ m->psind);
+ if (rv != KERN_SUCCESS) {
+ /*
+ * We weren't able to enter the page into the pmap.
+ * Deactivate and unbusy the pages that we were not able to
+ * enter into the pmap and let the slow path cope with whatever
+ * caused the pmap_enter error.
+ */
+ vm_fault_populate_cleanup(obj, pidx, pager_last);
+ return (FAULT_CONTINUE);
+ }
+ npages = pagesizes[m->psind] >> PAGE_SHIFT;
+ for (i = 0; i < npages; i++) {
+ vm_page_wire(&m[i]);
+ vm_page_xunbusy(&m[i]);
+ }
+ *faddr += npages << PAGE_SHIFT;
+ pidx += npages;
+ }
+ rv = FAULT_SUCCESS;
+out:
+ vm_object_pip_wakeup(obj);
+ VM_OBJECT_WUNLOCK(obj);
+
+ return (rv);
+}
+
+int
+vm_fault_wire(vm_map_t map, vm_map_entry_t entry, vm_offset_t *faddr)
+{
+ enum fault_status res;
+ vm_offset_t saved_end;
+ vm_object_t obj;
+ int bidx, incr;
+ int rv;
+
+ KASSERT(vm_map_locked(map) != 0, ("%s: map is not locked", __func__));
+
+ obj = entry->object.vm_object;
+ if (((entry->eflags &
+ (MAP_SPLIT_BOUNDARY_MASK | MAP_ENTRY_NEEDS_COPY)) == 0) &&
+ (obj->flags & OBJ_POPULATE) != 0) {
+ res = vm_fault_wire_quick(map, obj, entry, faddr);
+ switch (res) {
+ case FAULT_SUCCESS:
+ return (KERN_SUCCESS);
+ case FAULT_FAILURE:
+ return (KERN_FAILURE);
+ case FAULT_CONTINUE:
+ /* Fall back to the slow path. */
+ break;
+ default:
+ panic("%s: Unhandled status %d", __func__, res);
+ }
+ }
+
+ bidx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry);
+ incr = pagesizes[bidx];
+ saved_end = entry->end;
+ vm_map_busy(map);
+ vm_map_unlock(map);
+ for (; *faddr < saved_end; *faddr += incr) {
+ /*
+ * Simulate a fault to get the page and enter
+ * it into the physical map.
+ */
+ rv = vm_fault(map, *faddr, VM_PROT_NONE, VM_FAULT_WIRE, NULL);
+ if (rv != KERN_SUCCESS) {
+ vm_map_lock(map);
+ vm_map_unbusy(map);
+ return (rv);
+ }
+ }
+ vm_map_lock(map);
+ vm_map_unbusy(map);
+
+ return (KERN_SUCCESS);
+}
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -3561,8 +3561,8 @@
{
vm_map_entry_t entry, first_entry, next_entry, prev_entry;
vm_offset_t faddr, saved_end, saved_start;
- u_long incr, npages;
- u_int bidx, last_timestamp;
+ u_long npages;
+ u_int last_timestamp;
int rv;
bool holes_ok, need_wakeup, user_wire;
vm_prot_t prot;
@@ -3643,24 +3643,8 @@
saved_start = entry->start;
saved_end = entry->end;
last_timestamp = map->timestamp;
- bidx = MAP_ENTRY_SPLIT_BOUNDARY_INDEX(entry);
- incr = pagesizes[bidx];
- vm_map_busy(map);
- vm_map_unlock(map);
-
- for (faddr = saved_start; faddr < saved_end;
- faddr += incr) {
- /*
- * Simulate a fault to get the page and enter
- * it into the physical map.
- */
- rv = vm_fault(map, faddr, VM_PROT_NONE,
- VM_FAULT_WIRE, NULL);
- if (rv != KERN_SUCCESS)
- break;
- }
- vm_map_lock(map);
- vm_map_unbusy(map);
+ faddr = saved_start;
+ rv = vm_fault_wire(map, entry, &faddr);
if (last_timestamp + 1 != map->timestamp) {
/*
* Look again for the entry because the map was

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 6, 8:54 PM (15 h, 36 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
41532796
Default Alt Text
D60751.1793998441.diff (6 KB)

Event Timeline