Author: alc
Date: Sun Dec 31 04:01:47 2017
New Revision: 327410
URL: https://svnweb.freebsd.org/changeset/base/327410

Log:
  Previously, swap_pager_copy() freed swap blocks one at at time, via
  swp_pager_meta_ctl(), with no opportunity to recognize freeing of
  consecutive blocks and free fewer block ranges.  To open that opportunity,
  this change removes the SWM_FREE option from swp_pager_meta_ctl(), and
  compels the caller to do the freeing when a valid block address is returned.
  In swap_pager_copy(), these frees are aggregated, so that a sequence of them
  can be done at one time.
  
  The only other caller to swp_pager_meta_ctl() that passed SWM_FREE,
  swp_pager_unswapped(), is also modified to handle its single free
  explicitly.
  
  Submitted by: Doug Moore <do...@rice.edu>
  Reviewed by:  kib (an earlier version)
  MFC after:    1 week
  Differential Revision:        https://reviews.freebsd.org/D13290

Modified:
  head/sys/vm/swap_pager.c

Modified: head/sys/vm/swap_pager.c
==============================================================================
--- head/sys/vm/swap_pager.c    Sun Dec 31 03:35:34 2017        (r327409)
+++ head/sys/vm/swap_pager.c    Sun Dec 31 04:01:47 2017        (r327410)
@@ -311,8 +311,7 @@ swap_release_by_cred(vm_ooffset_t decr, struct ucred *
        racct_sub_cred(cred, RACCT_SWAP, decr);
 }
 
-#define SWM_FREE       0x02    /* free, period                 */
-#define SWM_POP                0x04    /* pop out                      */
+#define SWM_POP                0x01    /* pop out                      */
 
 static int swap_pager_full = 2;        /* swap space exhaustion (task killing) 
*/
 static int swap_pager_almost_full = 1; /* swap space exhaustion 
(w/hysteresis)*/
@@ -911,6 +910,7 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dst
     vm_pindex_t offset, int destroysource)
 {
        vm_pindex_t i;
+       daddr_t dstaddr, first_free, num_free, srcaddr;
 
        VM_OBJECT_ASSERT_WLOCKED(srcobject);
        VM_OBJECT_ASSERT_WLOCKED(dstobject);
@@ -935,53 +935,44 @@ swap_pager_copy(vm_object_t srcobject, vm_object_t dst
        }
 
        /*
-        * transfer source to destination.
+        * Transfer source to destination.
         */
+       first_free = SWAPBLK_NONE;
+       num_free = 0;
        for (i = 0; i < dstobject->size; ++i) {
-               daddr_t dstaddr;
-
-               /*
-                * Locate (without changing) the swapblk on the destination,
-                * unless it is invalid in which case free it silently, or
-                * if the destination is a resident page, in which case the
-                * source is thrown away.
-                */
+               srcaddr = swp_pager_meta_ctl(srcobject, i + offset, SWM_POP);
+               if (srcaddr == SWAPBLK_NONE)
+                       continue;
                dstaddr = swp_pager_meta_ctl(dstobject, i, 0);
-
                if (dstaddr == SWAPBLK_NONE) {
                        /*
                         * Destination has no swapblk and is not resident,
                         * copy source.
+                        *
+                        * swp_pager_meta_build() can sleep.
                         */
-                       daddr_t srcaddr;
-
-                       srcaddr = swp_pager_meta_ctl(
-                           srcobject,
-                           i + offset,
-                           SWM_POP
-                       );
-
-                       if (srcaddr != SWAPBLK_NONE) {
-                               /*
-                                * swp_pager_meta_build() can sleep.
-                                */
-                               vm_object_pip_add(srcobject, 1);
-                               VM_OBJECT_WUNLOCK(srcobject);
-                               vm_object_pip_add(dstobject, 1);
-                               swp_pager_meta_build(dstobject, i, srcaddr);
-                               vm_object_pip_wakeup(dstobject);
-                               VM_OBJECT_WLOCK(srcobject);
-                               vm_object_pip_wakeup(srcobject);
-                       }
+                       vm_object_pip_add(srcobject, 1);
+                       VM_OBJECT_WUNLOCK(srcobject);
+                       vm_object_pip_add(dstobject, 1);
+                       swp_pager_meta_build(dstobject, i, srcaddr);
+                       vm_object_pip_wakeup(dstobject);
+                       VM_OBJECT_WLOCK(srcobject);
+                       vm_object_pip_wakeup(srcobject);
                } else {
                        /*
                         * Destination has valid swapblk or it is represented
                         * by a resident page.  We destroy the sourceblock.
                         */
-
-                       swp_pager_meta_ctl(srcobject, i + offset, SWM_FREE);
+                       if (first_free + num_free == srcaddr)
+                               num_free++;
+                       else {
+                               swp_pager_freeswapspace(first_free, num_free);
+                               first_free = srcaddr;
+                               num_free = 1;
+                       }
                }
        }
+       swp_pager_freeswapspace(first_free, num_free);
 
        /*
         * Free left over swap blocks in source.
@@ -1082,8 +1073,11 @@ swap_pager_haspage(vm_object_t object, vm_pindex_t pin
 static void
 swap_pager_unswapped(vm_page_t m)
 {
+       daddr_t srcaddr;
 
-       swp_pager_meta_ctl(m->object, m->pindex, SWM_FREE);
+       srcaddr = swp_pager_meta_ctl(m->object, m->pindex, SWM_POP);
+       if (srcaddr != SWAPBLK_NONE)
+               swp_pager_freeswapspace(srcaddr, 1);
 }
 
 /*
@@ -1999,21 +1993,17 @@ swp_pager_meta_free_all(vm_object_t object)
 }
 
 /*
- * SWP_PAGER_METACTL() -  misc control of swap and vm_page_t meta data.
+ * SWP_PAGER_METACTL() -  misc control of swap meta data.
  *
- *     This routine is capable of looking up, popping, or freeing
- *     swapblk assignments in the swap meta data or in the vm_page_t.
- *     The routine typically returns the swapblk being looked-up, or popped,
- *     or SWAPBLK_NONE if the block was freed, or SWAPBLK_NONE if the block
- *     was invalid.  This routine will automatically free any invalid
- *     meta-data swapblks.
+ *     This routine is capable of looking up, or removing swapblk
+ *     assignments in the swap meta data.  It returns the swapblk being
+ *     looked-up, popped, or SWAPBLK_NONE if the block was invalid.
  *
  *     When acting on a busy resident page and paging is in progress, we
  *     have to wait until paging is complete but otherwise can act on the
  *     busy page.
  *
- *     SWM_FREE        remove and free swap block from metadata
- *     SWM_POP         remove from meta data but do not free.. pop it out
+ *     SWM_POP         remove from meta data but do not free it
  */
 static daddr_t
 swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pindex, int flags)
@@ -2021,7 +2011,7 @@ swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pin
        struct swblk *sb;
        daddr_t r1;
 
-       if ((flags & (SWM_FREE | SWM_POP)) != 0)
+       if ((flags & SWM_POP) != 0)
                VM_OBJECT_ASSERT_WLOCKED(object);
        else
                VM_OBJECT_ASSERT_LOCKED(object);
@@ -2040,17 +2030,13 @@ swp_pager_meta_ctl(vm_object_t object, vm_pindex_t pin
        r1 = sb->d[pindex % SWAP_META_PAGES];
        if (r1 == SWAPBLK_NONE)
                return (SWAPBLK_NONE);
-       if ((flags & (SWM_FREE | SWM_POP)) != 0) {
+       if ((flags & SWM_POP) != 0) {
                sb->d[pindex % SWAP_META_PAGES] = SWAPBLK_NONE;
                if (swp_pager_swblk_empty(sb, 0, SWAP_META_PAGES)) {
                        SWAP_PCTRIE_REMOVE(&object->un_pager.swp.swp_blks,
                            rounddown(pindex, SWAP_META_PAGES));
                        uma_zfree(swblk_zone, sb);
                }
-       }
-       if ((flags & SWM_FREE) != 0) {
-               swp_pager_freeswapspace(r1, 1);
-               r1 = SWAPBLK_NONE;
        }
        return (r1);
 }
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to