svn commit: r288122 - in head/sys: kern vm

Scott Long scott4long at yahoo.com
Wed Sep 23 07:17:37 UTC 2015


It should be noted that Netflix has been running with an earlier version of this patch for nearly 10 months.

Scott

> On Sep 22, 2015, at 11:16 AM, Alan Cox <alc at freebsd.org> wrote:
> 
> Author: alc
> Date: Tue Sep 22 18:16:52 2015
> New Revision: 288122
> URL: https://svnweb.freebsd.org/changeset/base/288122
> 
> Log:
>  Change vm_page_unwire() such that it (1) accepts PQ_NONE as the specified
>  queue and (2) returns a Boolean indicating whether the page's wire count
>  transitioned to zero.
> 
>  Exploit this change in vfs_vmio_release() to avoid pointlessly enqueueing
>  a page that is about to be freed.
> 
>  (An earlier version of this change was developed by attilio@ and kmacy at .
>  Any errors in this version are my own.)
> 
>  Reviewed by:	kib
>  Sponsored by:	EMC / Isilon Storage Division
> 
> Modified:
>  head/sys/kern/vfs_bio.c
>  head/sys/vm/vm_page.c
>  head/sys/vm/vm_page.h
> 
> Modified: head/sys/kern/vfs_bio.c
> ==============================================================================
> --- head/sys/kern/vfs_bio.c	Tue Sep 22 17:34:51 2015	(r288121)
> +++ head/sys/kern/vfs_bio.c	Tue Sep 22 18:16:52 2015	(r288122)
> @@ -2076,6 +2076,7 @@ vfs_vmio_release(struct buf *bp)
> 	vm_object_t obj;
> 	vm_page_t m;
> 	int i;
> +	bool freed;
> 
> 	if (buf_mapped(bp)) {
> 		BUF_CHECK_MAPPED(bp);
> @@ -2088,23 +2089,28 @@ vfs_vmio_release(struct buf *bp)
> 	for (i = 0; i < bp->b_npages; i++) {
> 		m = bp->b_pages[i];
> 		bp->b_pages[i] = NULL;
> -		/*
> -		 * In order to keep page LRU ordering consistent, put
> -		 * everything on the inactive queue.
> -		 */
> 		vm_page_lock(m);
> -		vm_page_unwire(m, PQ_INACTIVE);
> -
> -		/*
> -		 * Might as well free the page if we can and it has
> -		 * no valid data.  We also free the page if the
> -		 * buffer was used for direct I/O
> -		 */
> -		if ((bp->b_flags & B_ASYNC) == 0 && !m->valid) {
> -			if (m->wire_count == 0 && !vm_page_busied(m))
> -				vm_page_free(m);
> -		} else if (bp->b_flags & B_DIRECT)
> -			vm_page_try_to_free(m);
> +		if (vm_page_unwire(m, PQ_NONE)) {
> +			/*
> +			 * Determine if the page should be freed before adding
> +			 * it to the inactive queue.
> +			 */
> +			if ((bp->b_flags & B_ASYNC) == 0 && m->valid == 0) {
> +				freed = !vm_page_busied(m);
> +				if (freed)
> +					vm_page_free(m);
> +			} else if ((bp->b_flags & B_DIRECT) != 0)
> +				freed = vm_page_try_to_free(m);
> +			else
> +				freed = false;
> +			if (!freed) {
> +				/*
> +				 * In order to maintain LRU page ordering, put
> +				 * the page at the tail of the inactive queue.
> +				 */
> +				vm_page_deactivate(m);
> +			}
> +		}
> 		vm_page_unlock(m);
> 	}
> 	if (obj != NULL)
> 
> Modified: head/sys/vm/vm_page.c
> ==============================================================================
> --- head/sys/vm/vm_page.c	Tue Sep 22 17:34:51 2015	(r288121)
> +++ head/sys/vm/vm_page.c	Tue Sep 22 18:16:52 2015	(r288122)
> @@ -2476,42 +2476,46 @@ vm_page_wire(vm_page_t m)
> /*
>  * vm_page_unwire:
>  *
> - * Release one wiring of the specified page, potentially enabling it to be
> - * paged again.  If paging is enabled, then the value of the parameter
> - * "queue" determines the queue to which the page is added.
> - *
> - * However, unless the page belongs to an object, it is not enqueued because
> - * it cannot be paged out.
> + * Release one wiring of the specified page, potentially allowing it to be
> + * paged out.  Returns TRUE if the number of wirings transitions to zero and
> + * FALSE otherwise.
> + *
> + * Only managed pages belonging to an object can be paged out.  If the number
> + * of wirings transitions to zero and the page is eligible for page out, then
> + * the page is added to the specified paging queue (unless PQ_NONE is
> + * specified).
>  *
>  * If a page is fictitious, then its wire count must always be one.
>  *
>  * A managed page must be locked.
>  */
> -void
> +boolean_t
> vm_page_unwire(vm_page_t m, uint8_t queue)
> {
> 
> -	KASSERT(queue < PQ_COUNT,
> +	KASSERT(queue < PQ_COUNT || queue == PQ_NONE,
> 	    ("vm_page_unwire: invalid queue %u request for page %p",
> 	    queue, m));
> 	if ((m->oflags & VPO_UNMANAGED) == 0)
> -		vm_page_lock_assert(m, MA_OWNED);
> +		vm_page_assert_locked(m);
> 	if ((m->flags & PG_FICTITIOUS) != 0) {
> 		KASSERT(m->wire_count == 1,
> 	    ("vm_page_unwire: fictitious page %p's wire count isn't one", m));
> -		return;
> +		return (FALSE);
> 	}
> 	if (m->wire_count > 0) {
> 		m->wire_count--;
> 		if (m->wire_count == 0) {
> 			atomic_subtract_int(&vm_cnt.v_wire_count, 1);
> -			if ((m->oflags & VPO_UNMANAGED) != 0 ||
> -			    m->object == NULL)
> -				return;
> -			if (queue == PQ_INACTIVE)
> -				m->flags &= ~PG_WINATCFLS;
> -			vm_page_enqueue(queue, m);
> -		}
> +			if ((m->oflags & VPO_UNMANAGED) == 0 &&
> +			    m->object != NULL && queue != PQ_NONE) {
> +				if (queue == PQ_INACTIVE)
> +					m->flags &= ~PG_WINATCFLS;
> +				vm_page_enqueue(queue, m);
> +			}
> +			return (TRUE);
> +		} else
> +			return (FALSE);
> 	} else
> 		panic("vm_page_unwire: page %p's wire count is zero", m);
> }
> 
> Modified: head/sys/vm/vm_page.h
> ==============================================================================
> --- head/sys/vm/vm_page.h	Tue Sep 22 17:34:51 2015	(r288121)
> +++ head/sys/vm/vm_page.h	Tue Sep 22 18:16:52 2015	(r288122)
> @@ -480,7 +480,7 @@ vm_offset_t vm_page_startup(vm_offset_t 
> void vm_page_sunbusy(vm_page_t m);
> int vm_page_trysbusy(vm_page_t m);
> void vm_page_unhold_pages(vm_page_t *ma, int count);
> -void vm_page_unwire (vm_page_t m, uint8_t queue);
> +boolean_t vm_page_unwire(vm_page_t m, uint8_t queue);
> void vm_page_updatefake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr);
> void vm_page_wire (vm_page_t);
> void vm_page_xunbusy_hard(vm_page_t m);
> 



More information about the svn-src-all mailing list