Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Jun 2014 11:15:10 +0000 (UTC)
From:      Attilio Rao <attilio@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r268038 - user/attilio/rm_vmobj_cache/sys/vm
Message-ID:  <201406301115.s5UBFAh5034269@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: attilio
Date: Mon Jun 30 11:15:10 2014
New Revision: 268038
URL: http://svnweb.freebsd.org/changeset/base/268038

Log:
  - Implement a "disposed" pagequeue, where pages are firstly freed to
    satisfy the pageout free requirements.
    This frees happen just before the inactive queue scan, in pass == 1
  - Implement vm_page_dispose() that inserts pages into the disposed queue.
    Pages must be unbusy, unwired, unheld, managed and clean.

Modified:
  user/attilio/rm_vmobj_cache/sys/vm/vm_page.c
  user/attilio/rm_vmobj_cache/sys/vm/vm_page.h
  user/attilio/rm_vmobj_cache/sys/vm/vm_pageout.c

Modified: user/attilio/rm_vmobj_cache/sys/vm/vm_page.c
==============================================================================
--- user/attilio/rm_vmobj_cache/sys/vm/vm_page.c	Mon Jun 30 09:59:23 2014	(r268037)
+++ user/attilio/rm_vmobj_cache/sys/vm/vm_page.c	Mon Jun 30 11:15:10 2014	(r268038)
@@ -2437,6 +2437,47 @@ vm_page_deactivate(vm_page_t m)
 }
 
 /*
+ * Move the specified page to the disposed queue.
+ *
+ * XXXWIP
+ *
+ * The page must be locked.
+ * The page also must be unqueued already and not wired or busy.
+ * Finally, the page must also belong to an object, so it must not be
+ * unmanaged.
+ */
+static inline void
+vm_page_dispose(vm_page_t m)
+{
+	struct vm_pagequeue *pq;
+	int queue;
+
+	vm_page_lock_assert(m, MA_OWNED);
+	KASSERT(m->queue == PQ_NONE,
+	    ("vm_page_dispose: page %p already queued on %u queue", m,
+	    m->queue));
+
+	if (m->hold_count != 0)
+		panic("vm_page_dispose: page %p hold count %d",
+		    m, m->hold_count);
+	if (m->wire_count != 0)
+		panic("vm_page_dispose: page %p wire count %d",
+		    m, m->wire_count);
+	if (vm_page_busied(m))
+		panic("vm_page_dispose: page %p is busied", m);
+	if ((m->oflags & VPO_UNMANAGED) != 0)
+		panic("vm_page_dispose: page %p is unmanaged", m);
+
+	m->flags &= ~PG_WINATCFLS;
+	pq = &vm_phys_domain(m)->vmd_pagequeues[PQ_DISPOSED];
+	vm_pagequeue_lock(pq);
+	m->queue = PQ_DISPOSED;
+	TAILQ_INSERT_TAIL(&pq->pq_pl, m, plinks.q);
+	vm_pagequeue_cnt_inc(pq);
+	vm_pagequeue_unlock(pq);
+}
+
+/*
  * vm_page_try_to_cache:
  *
  * Returns 0 on failure, 1 on success

Modified: user/attilio/rm_vmobj_cache/sys/vm/vm_page.h
==============================================================================
--- user/attilio/rm_vmobj_cache/sys/vm/vm_page.h	Mon Jun 30 09:59:23 2014	(r268037)
+++ user/attilio/rm_vmobj_cache/sys/vm/vm_page.h	Mon Jun 30 11:15:10 2014	(r268038)
@@ -439,6 +439,7 @@ int vm_page_try_to_free (vm_page_t);
 void vm_page_deactivate (vm_page_t);
 void vm_page_dequeue(vm_page_t m);
 void vm_page_dequeue_locked(vm_page_t m);
+void vm_page_dispose(vm_page_t m);
 vm_page_t vm_page_find_least(vm_object_t, vm_pindex_t);
 vm_page_t vm_page_getfake(vm_paddr_t paddr, vm_memattr_t memattr);
 void vm_page_initfake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr);

Modified: user/attilio/rm_vmobj_cache/sys/vm/vm_pageout.c
==============================================================================
--- user/attilio/rm_vmobj_cache/sys/vm/vm_pageout.c	Mon Jun 30 09:59:23 2014	(r268037)
+++ user/attilio/rm_vmobj_cache/sys/vm/vm_pageout.c	Mon Jun 30 11:15:10 2014	(r268038)
@@ -244,10 +244,10 @@ vm_pageout_init_marker(vm_page_t marker,
  * vm_pageout_fallback_object_lock:
  * 
  * Lock vm object currently associated with `m'. VM_OBJECT_TRYWLOCK is
- * known to have failed and page queue must be either PQ_ACTIVE or
- * PQ_INACTIVE.  To avoid lock order violation, unlock the page queues
- * while locking the vm object.  Use marker page to detect page queue
- * changes and maintain notion of next page on page queue.  Return
+ * known to have failed and page queue must be either PQ_ACTIVE,
+ * PQ_INACTIVE or PQ_DISPOSED.  To avoid lock order violation, unlock the
+ * page queues while locking the vm object.  Use marker page to detect page
+ * queue changes and maintain notion of next page on page queue.  Return
  * TRUE if no changes were detected, FALSE otherwise.  vm object is
  * locked on return.
  * 
@@ -901,7 +901,7 @@ vm_pageout_map_deactivate_pages(map, des
  *	vm_pageout_scan does the dirty work for the pageout daemon.
  *
  *	pass 0 - Update active LRU/deactivate pages
- *	pass 1 - Move inactive to cache or free
+ *	pass 1 - Free disposed pages and move inactive to cache or free
  *	pass 2 - Launder dirty pages
  */
 static void
@@ -952,6 +952,75 @@ vm_pageout_scan(struct vm_domain *vmd, i
 	} else
 		page_shortage = deficit = 0;
 
+	pq = &vmd->vmd_pagequeues[PQ_DISPOSED];
+	maxscan = pq->pq_cnt;
+	vm_pagequeue_lock(pq);
+	for (m = TAILQ_FIRST(&pq->pq_pl);
+	     m != NULL && maxscan-- > 0 && page_shortage > 0;
+	     m = next) {
+		vm_pagequeue_assert_locked(pq);
+		KASSERT(m->queue == PQ_DISPOSED, ("Disposed queue %p", m));
+
+		PCPU_INC(cnt.v_pdpages);
+		next = TAILQ_NEXT(m, plinks.q);
+
+		/*
+		 * skip marker pages
+		 */
+		if (m->flags & PG_MARKER)
+			continue;
+
+		KASSERT((m->flags & PG_FICTITIOUS) == 0,
+		    ("Fictitious page %p cannot be in disposed queue", m));
+		KASSERT((m->oflags & VPO_UNMANAGED) == 0,
+		    ("Unmanaged page %p cannot be in disposed queue", m));
+
+		/*
+		 * The page or object lock acquisitions fail if the
+		 * page was removed from the queue or moved to a
+		 * different position within the queue.  In either
+		 * case, addl_page_shortage should not be incremented.
+		 */
+		if (!vm_pageout_page_lock(m, &next)) {
+			vm_page_unlock(m);
+			continue;
+		}
+		object = m->object;
+		if (!VM_OBJECT_TRYWLOCK(object) &&
+		    !vm_pageout_fallback_object_lock(m, &next)) {
+			vm_page_unlock(m);
+			VM_OBJECT_WUNLOCK(object);
+			continue;
+		}
+		vm_page_test_dirty(m);
+
+		if (m->dirty != 0)
+			panic("Disposed page %p is dirty", m);
+		if (pmap_page_is_mapped(m))
+			panic("Disposed page %p has active mappings", m);
+		if ((m->aflags & PGA_REFERENCED) != 0)
+			panic("Disposed page %p is referenced", m);
+
+		/*
+		 * These checks are already present when inserting pages
+		 * into the disposed queue, so make them just asserts here.
+		 */
+		KASSERT(!vm_page_busied(m) && m->hold_count == 0 &&
+		    m->wire_count == 0, ("Disposed page %p busied", m));
+
+		/*
+		 * Dequeue the page first in order to avoid pagequeue
+		 * lock recursion.
+		 */
+		vm_page_dequeue_locked(m);
+		vm_page_free(m);
+		vm_page_unlock(m);
+		VM_OBJECT_WUNLOCK(object);
+		PCPU_INC(cnt.v_dfree);
+		--page_shortage;
+	}
+	vm_pagequeue_unlock(pq);
+
 	/*
 	 * maxlaunder limits the number of dirty pages we flush per scan.
 	 * For most systems a smaller value (16 or 32) is more robust under



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201406301115.s5UBFAh5034269>