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

Reply via email to