Diff below rewrites uvm_fault() using a loop.
I added a KERNEL_LOCK/UNLOCK() dance around the part that won't be
unlocked soon to illustrate where this is going.
ok?
Index: uvm/uvm_fault.c
===================================================================
RCS file: /cvs/src/sys/uvm/uvm_fault.c,v
retrieving revision 1.108
diff -u -p -r1.108 uvm_fault.c
--- uvm/uvm_fault.c 19 Nov 2020 17:06:40 -0000 1.108
+++ uvm/uvm_fault.c 7 Dec 2020 18:20:16 -0000
@@ -907,7 +907,7 @@ uvm_fault(vm_map_t orig_map, vaddr_t vad
boolean_t shadowed;
struct vm_anon *anons_store[UVM_MAXRANGE], **anons;
struct vm_page *pages[UVM_MAXRANGE];
- int error;
+ int error = ERESTART;
uvmexp.faults++; /* XXX: locking? */
TRACEPOINT(uvm, fault, vaddr, fault_type, access_type, NULL);
@@ -923,43 +923,32 @@ uvm_fault(vm_map_t orig_map, vaddr_t vad
flt.narrow = FALSE; /* normal fault */
- /* "goto ReFault" means restart the page fault from ground zero. */
-ReFault:
- anons = anons_store;
-
- error = uvm_fault_check(&ufi, &flt, &anons, access_type);
- switch (error) {
- case 0:
- break;
- case ERESTART:
- goto ReFault;
- default:
- return error;
- }
-
- /* (shadowed == TRUE) if there is an anon at the faulting address */
- shadowed = uvm_fault_upper_lookup(&ufi, &flt, anons, pages);
-
- /* handle case 1: fault on an anon in our amap */
- if (shadowed == TRUE) {
- error = uvm_fault_upper(&ufi, &flt, anons, fault_type,
- access_type);
- switch (error) {
- case ERESTART:
- goto ReFault;
- default:
- return error;
+ /*
+ * ReFault
+ */
+ while (error == ERESTART) {
+ anons = anons_store;
+
+ error = uvm_fault_check(&ufi, &flt, &anons, access_type);
+ if (error != 0)
+ continue;
+
+ /* True if there is an anon at the faulting address */
+ shadowed = uvm_fault_upper_lookup(&ufi, &flt, anons, pages);
+ if (shadowed == TRUE) {
+ /* case 1: fault on an anon in our amap */
+ error = uvm_fault_upper(&ufi, &flt, anons, fault_type,
+ access_type);
+ } else {
+ /* case 2: fault on backing object or zero fill */
+ KERNEL_LOCK();
+ error = uvm_fault_lower(&ufi, &flt, pages, fault_type,
+ access_type);
+ KERNEL_UNLOCK();
}
}
- /* handle case 2: faulting on backing object or zero fill */
- error = uvm_fault_lower(&ufi, &flt, pages, fault_type, access_type);
- switch (error) {
- case ERESTART:
- goto ReFault;
- default:
- return error;
- }
+ return error;
}
int