Author: jeff
Date: Thu Jan 23 05:11:01 2020
New Revision: 357023
URL: https://svnweb.freebsd.org/changeset/base/357023

Log:
  (fault 4/9) Move copy-on-write into a dedicated function.
  
  Reviewed by:  kib, markj
  Differential Revision:        https://reviews.freebsd.org/D23304

Modified:
  head/sys/vm/vm_fault.c

Modified: head/sys/vm/vm_fault.c
==============================================================================
--- head/sys/vm/vm_fault.c      Thu Jan 23 05:07:01 2020        (r357022)
+++ head/sys/vm/vm_fault.c      Thu Jan 23 05:11:01 2020        (r357023)
@@ -846,6 +846,92 @@ vm_fault_relookup(struct faultstate *fs)
        return (KERN_SUCCESS);
 }
 
+static void
+vm_fault_cow(struct faultstate *fs)
+{
+       bool is_first_object_locked;
+
+       /*
+        * This allows pages to be virtually copied from a backing_object
+        * into the first_object, where the backing object has no other
+        * refs to it, and cannot gain any more refs.  Instead of a bcopy,
+        * we just move the page from the backing object to the first
+        * object.  Note that we must mark the page dirty in the first
+        * object so that it will go out to swap when needed.
+        */
+       is_first_object_locked = false;
+       if (
+           /*
+            * Only one shadow object and no other refs.
+            */
+           fs->object->shadow_count == 1 && fs->object->ref_count == 1 &&
+           /*
+            * No other ways to look the object up
+            */
+           fs->object->handle == NULL && (fs->object->flags & OBJ_ANON) != 0 &&
+           /*
+            * We don't chase down the shadow chain and we can acquire locks.
+            */
+           (is_first_object_locked = VM_OBJECT_TRYWLOCK(fs->first_object)) &&
+           fs->object == fs->first_object->backing_object &&
+           VM_OBJECT_TRYWLOCK(fs->object)) {
+
+               /*
+                * Remove but keep xbusy for replace.  fs->m is moved into
+                * fs->first_object and left busy while fs->first_m is
+                * conditionally freed.
+                */
+               vm_page_remove_xbusy(fs->m);
+               vm_page_replace(fs->m, fs->first_object, fs->first_pindex,
+                   fs->first_m);
+               vm_page_dirty(fs->m);
+#if VM_NRESERVLEVEL > 0
+               /*
+                * Rename the reservation.
+                */
+               vm_reserv_rename(fs->m, fs->first_object, fs->object,
+                   OFF_TO_IDX(fs->first_object->backing_object_offset));
+#endif
+               VM_OBJECT_WUNLOCK(fs->object);
+               VM_OBJECT_WUNLOCK(fs->first_object);
+               fs->first_m = fs->m;
+               fs->m = NULL;
+               VM_CNT_INC(v_cow_optim);
+       } else {
+               if (is_first_object_locked)
+                       VM_OBJECT_WUNLOCK(fs->first_object);
+               /*
+                * Oh, well, lets copy it.
+                */
+               pmap_copy_page(fs->m, fs->first_m);
+               vm_page_valid(fs->first_m);
+               if (fs->wired && (fs->fault_flags & VM_FAULT_WIRE) == 0) {
+                       vm_page_wire(fs->first_m);
+                       vm_page_unwire(fs->m, PQ_INACTIVE);
+               }
+               /*
+                * Save the cow page to be released after
+                * pmap_enter is complete.
+                */
+               fs->m_cow = fs->m;
+               fs->m = NULL;
+       }
+       /*
+        * fs->object != fs->first_object due to above 
+        * conditional
+        */
+       vm_object_pip_wakeup(fs->object);
+
+       /*
+        * Only use the new page below...
+        */
+       fs->object = fs->first_object;
+       fs->pindex = fs->first_pindex;
+       fs->m = fs->first_m;
+       VM_CNT_INC(v_cow_faults);
+       curthread->td_cow++;
+}
+
 /*
  * Wait/Retry if the page is busy.  We have to do this if the page is
  * either exclusive or shared busy because the vm_pager may be using
@@ -893,7 +979,7 @@ vm_fault(vm_map_t map, vm_offset_t vaddr, vm_prot_t fa
        int ahead, alloc_req, behind, cluster_offset, faultcount;
        int nera, oom, result, rv;
        u_char behavior;
-       bool dead, hardfault, is_first_object_locked;
+       bool dead, hardfault;
 
        VM_CNT_INC(v_vm_faults);
 
@@ -1302,90 +1388,8 @@ next:
                 * We only really need to copy if we want to write it.
                 */
                if ((fs.fault_type & (VM_PROT_COPY | VM_PROT_WRITE)) != 0) {
+                       vm_fault_cow(&fs);
                        /*
-                        * This allows pages to be virtually copied from a 
-                        * backing_object into the first_object, where the 
-                        * backing object has no other refs to it, and cannot
-                        * gain any more refs.  Instead of a bcopy, we just 
-                        * move the page from the backing object to the 
-                        * first object.  Note that we must mark the page 
-                        * dirty in the first object so that it will go out 
-                        * to swap when needed.
-                        */
-                       is_first_object_locked = false;
-                       if (
-                           /*
-                            * Only one shadow object
-                            */
-                           fs.object->shadow_count == 1 &&
-                           /*
-                            * No COW refs, except us
-                            */
-                           fs.object->ref_count == 1 &&
-                           /*
-                            * No one else can look this object up
-                            */
-                           fs.object->handle == NULL &&
-                           /*
-                            * No other ways to look the object up
-                            */
-                           (fs.object->flags & OBJ_ANON) != 0 &&
-                           (is_first_object_locked = 
VM_OBJECT_TRYWLOCK(fs.first_object)) &&
-                           /*
-                            * We don't chase down the shadow chain
-                            */
-                           fs.object == fs.first_object->backing_object &&
-                           VM_OBJECT_TRYWLOCK(fs.object)) {
-
-                               /*
-                                * Remove but keep xbusy for replace.  fs.m is
-                                * moved into fs.first_object and left busy
-                                * while fs.first_m is conditionally freed.
-                                */
-                               vm_page_remove_xbusy(fs.m);
-                               vm_page_replace(fs.m, fs.first_object,
-                                   fs.first_pindex, fs.first_m);
-                               vm_page_dirty(fs.m);
-#if VM_NRESERVLEVEL > 0
-                               /*
-                                * Rename the reservation.
-                                */
-                               vm_reserv_rename(fs.m, fs.first_object,
-                                   fs.object, OFF_TO_IDX(
-                                   fs.first_object->backing_object_offset));
-#endif
-                               VM_OBJECT_WUNLOCK(fs.object);
-                               VM_OBJECT_WUNLOCK(fs.first_object);
-                               fs.first_m = fs.m;
-                               fs.m = NULL;
-                               VM_CNT_INC(v_cow_optim);
-                       } else {
-                               if (is_first_object_locked)
-                                       VM_OBJECT_WUNLOCK(fs.first_object);
-                               /*
-                                * Oh, well, lets copy it.
-                                */
-                               pmap_copy_page(fs.m, fs.first_m);
-                               vm_page_valid(fs.first_m);
-                               if (fs.wired && (fs.fault_flags &
-                                   VM_FAULT_WIRE) == 0) {
-                                       vm_page_wire(fs.first_m);
-                                       vm_page_unwire(fs.m, PQ_INACTIVE);
-                               }
-                               /*
-                                * Save the cow page to be released after
-                                * pmap_enter is complete.
-                                */
-                               fs.m_cow = fs.m;
-                               fs.m = NULL;
-                       }
-                       /*
-                        * fs.object != fs.first_object due to above 
-                        * conditional
-                        */
-                       vm_object_pip_wakeup(fs.object);
-
-                       /*
                         * We only try to prefault read-only mappings to the
                         * neighboring pages when this copy-on-write fault is
                         * a hard fault.  In other cases, trying to prefault
@@ -1394,14 +1398,6 @@ next:
                        if (faultcount == 0)
                                faultcount = 1;
 
-                       /*
-                        * Only use the new page below...
-                        */
-                       fs.object = fs.first_object;
-                       fs.pindex = fs.first_pindex;
-                       fs.m = fs.first_m;
-                       VM_CNT_INC(v_cow_faults);
-                       curthread->td_cow++;
                } else {
                        fs.prot &= ~VM_PROT_WRITE;
                }
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to