Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Jun 1995 04:41:58 -0700
From:      Matt Dillon <dillon@best.com>
To:        bugs@freebsd.org
Cc:        rdy@best.com
Subject:   non-fatal bug in vm/vm_pageout.c
Message-ID:  <199506241141.EAA11425@shell1.best.com>

next in thread | raw e-mail | index | archive | help
    I think I've found an algorithmic bug in the pager code.

    in vm/vm_pageout.c, in vm_pageout_scan(), a page is moved to the end of 
    the active queue if:

	* if its busy or held
	* if it has been referenced
	* act_count is greater the zero.

    The problem is that in the case where the page has been referenced, the
    reference flag is *cleared* and the page is then moved to the end of 
    the queue.

    Noe, if the scan happens to reach the end of the queue, it will hit that
    page AGAIN, the reference count will be cleared, so it will decrement
    the act_count and move the page to the end of the queue AGAIN... in
    otherwords, it will repeatedly access the last N pages hundreds of times
    in that one loop, blowing their act_count and then deciding to page
    them out, EVEN THOUGH THEY MAY BE HEAVILY REFERENCED!

    The result is that act_count is effectively defeated.

    vm_pageout_object_deactivate_pages() would also have this problem
    but since it limits its scan to object->resident_page_count I think
    it's safe.

    My suggestion:  When act_count is decremented, leave the page where
    it is... don't move it to the end of the queue.  That is, around line
    717 of vm/vm_pageout.c, remove the TAILQ_REMOVE/TAILQ_INSERT calls
    in the else.  This way, all page's act_count's get equal treatment,
    and if the page happens to get referenced again it will be moved to
    the end of the queue anyway.

    Secondary problem:

    act_count only declines when paging is required.  This virtually 
    guarentees that no pages will necessarily be pagable in the first loop, 
    before it resorts to vm_daemon().  What really needs to happen is for the 
    active queue to be scanned say once every few seconds and act_count 
    decremented or incremented according to whether the page has been 
    referenced or not.  Thus, when paging finally becomes necessary, 
    act_count already has a basis.

    My suggestion: wakeup the pagedaemon once every 5 seconds and have it
    do a full scan checking for referenced/unreferenced pages, incrementing
    or decrementing act_count as appropriate.  It would move pages to the
    end of the queue if it finds them referenced (as per normal), and it
    would move pages to the front of the queue if act_count reaches 0
    (never minding the fact that newer pages more recently dropping to 0
    will be paged out before older pages that have dropped to 0).

					-Matt

    Matthew Dillon   VP Engineering, BEST Internet Communications, Inc.
		    <dillon@best.com>, <dillon@apollo.west.oic.com>
    [always include a portion of the original email in any response!]



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