]> xenbits.xensource.com Git - people/liuw/freebsd.git/commitdiff
Ensure that deactivated pages that are not expected to be reused are
authormarkj <markj@FreeBSD.org>
Sun, 8 Nov 2015 01:36:18 +0000 (01:36 +0000)
committermarkj <markj@FreeBSD.org>
Sun, 8 Nov 2015 01:36:18 +0000 (01:36 +0000)
reclaimed in FIFO order by the pagedaemon.  Previously we would enqueue
such pages at the head of the inactive queue, yielding a LIFO reclaim order.

Reviewed by: alc
MFC after: 2 weeks
Sponsored by: EMC / Isilon Storage Division

sys/vm/vm_page.c
sys/vm/vm_page.h
sys/vm/vm_pageout.c

index 8492f2ebd75eb613ed26ffdb022848420c25e3da..de67e4e2677e810760b4f094873e5e25a1d44301 100644 (file)
@@ -2536,14 +2536,16 @@ vm_page_unwire(vm_page_t m, uint8_t queue)
  * processes.  This optimization causes one-time-use metadata to be
  * reused more quickly.
  *
- * Normally athead is 0 resulting in LRU operation.  athead is set
- * to 1 if we want this page to be 'as if it were placed in the cache',
- * except without unmapping it from the process address space.
+ * Normally noreuse is FALSE, resulting in LRU operation.  noreuse is set
+ * to TRUE if we want this page to be 'as if it were placed in the cache',
+ * except without unmapping it from the process address space.  In
+ * practice this is implemented by inserting the page at the head of the
+ * queue, using a marker page to guide FIFO insertion ordering.
  *
  * The page must be locked.
  */
 static inline void
-_vm_page_deactivate(vm_page_t m, int athead)
+_vm_page_deactivate(vm_page_t m, boolean_t noreuse)
 {
        struct vm_pagequeue *pq;
        int queue;
@@ -2554,7 +2556,7 @@ _vm_page_deactivate(vm_page_t m, int athead)
         * Ignore if the page is already inactive, unless it is unlikely to be
         * reactivated.
         */
-       if ((queue = m->queue) == PQ_INACTIVE && !athead)
+       if ((queue = m->queue) == PQ_INACTIVE && !noreuse)
                return;
        if (m->wire_count == 0 && (m->oflags & VPO_UNMANAGED) == 0) {
                pq = &vm_phys_domain(m)->vmd_pagequeues[PQ_INACTIVE];
@@ -2569,8 +2571,9 @@ _vm_page_deactivate(vm_page_t m, int athead)
                        vm_pagequeue_lock(pq);
                }
                m->queue = PQ_INACTIVE;
-               if (athead)
-                       TAILQ_INSERT_HEAD(&pq->pq_pl, m, plinks.q);
+               if (noreuse)
+                       TAILQ_INSERT_BEFORE(&vm_phys_domain(m)->vmd_inacthead,
+                           m, plinks.q);
                else
                        TAILQ_INSERT_TAIL(&pq->pq_pl, m, plinks.q);
                vm_pagequeue_cnt_inc(pq);
@@ -2587,7 +2590,7 @@ void
 vm_page_deactivate(vm_page_t m)
 {
 
-       _vm_page_deactivate(m, 0);
+       _vm_page_deactivate(m, FALSE);
 }
 
 /*
@@ -2600,7 +2603,7 @@ void
 vm_page_deactivate_noreuse(vm_page_t m)
 {
 
-       _vm_page_deactivate(m, 1);
+       _vm_page_deactivate(m, TRUE);
 }
 
 /*
index a23f746f0dae9c75611f470d48f7db547d0f2efc..a87f682d4fe59c9bcdb03c8040daa9624308da34 100644 (file)
@@ -229,6 +229,7 @@ struct vm_domain {
        int vmd_pass;   /* local pagedaemon pass */
        int vmd_last_active_scan;
        struct vm_page vmd_marker; /* marker for pagedaemon private use */
+       struct vm_page vmd_inacthead; /* marker for LRU-defeating insertions */
 };
 
 extern struct vm_domain vm_dom[MAXMEMDOM];
index 188866efbec4ac63140ed8fd2a617efa95c44476..f564fb591905fad44bb31b4449fcb7c39c2c168d 100644 (file)
@@ -1630,6 +1630,9 @@ vm_pageout_worker(void *arg)
        KASSERT(domain->vmd_segs != 0, ("domain without segments"));
        domain->vmd_last_active_scan = ticks;
        vm_pageout_init_marker(&domain->vmd_marker, PQ_INACTIVE);
+       vm_pageout_init_marker(&domain->vmd_inacthead, PQ_INACTIVE);
+       TAILQ_INSERT_HEAD(&domain->vmd_pagequeues[PQ_INACTIVE].pq_pl,
+           &domain->vmd_inacthead, plinks.q);
 
        /*
         * The pageout daemon worker is never done, so loop forever.