All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
To: linux-mm@kvack.org, linux-kernel@vger.kernel.org
Cc: Andrew Morton <akpm@osdl.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Christoph Lameter <christoph@lameter.com>,
	Wu Fengguang <wfg@mail.ustc.edu.cn>,
	Nick Piggin <npiggin@suse.de>, Marijn Meijles <marijn@bitpit.net>,
	Rik van Riel <riel@redhat.com>,
	Marcelo Tosatti <marcelo.tosatti@cyclades.com>
Subject: [PATCH 02/14] page-replace-try_pageout.patch
Date: Fri, 30 Dec 2005 23:40:34 +0100	[thread overview]
Message-ID: <20051230224012.765.32791.sendpatchset@twins.localnet> (raw)
In-Reply-To: <20051230223952.765.21096.sendpatchset@twins.localnet>


From: Peter Zijlstra <a.p.zijlstra@chello.nl>

Move the functionality of the shrink_list() loop into its own function.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>

 mm/vmscan.c |  324 ++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 174 insertions(+), 150 deletions(-)

Index: linux-2.6-git/mm/vmscan.c
===================================================================
--- linux-2.6-git.orig/mm/vmscan.c
+++ linux-2.6-git/mm/vmscan.c
@@ -51,6 +51,16 @@ typedef enum {
 	PAGE_CLEAN,
 } pageout_t;
 
+/* possible outcome of try_pageout() */
+typedef enum {
+	/* unable to perform pageout */
+	PAGEOUT_KEEP,
+	/* unable to perform pageout, page is in active use */
+	PAGEOUT_ACTIVATE,
+	/* pageout succeded, page is gone */
+	PAGEOUT_SUCCESS,
+} try_pageout_t;
+
 struct scan_control {
 	/* Ask refill_inactive_zone, or shrink_cache to scan this many pages */
 	unsigned long nr_to_scan;
@@ -382,189 +392,203 @@ static pageout_t pageout(struct page *pa
 	return PAGE_CLEAN;
 }
 
-/*
- * shrink_list adds the number of reclaimed pages to sc->nr_reclaimed
- */
-static int shrink_list(struct list_head *page_list, struct scan_control *sc)
+static try_pageout_t try_pageout(struct page *page, struct scan_control *sc)
 {
-	LIST_HEAD(ret_pages);
-	struct pagevec freed_pvec;
-	int pgactivate = 0;
-	int reclaimed = 0;
-
-	cond_resched();
-
-	pagevec_init(&freed_pvec, 1);
-	while (!list_empty(page_list)) {
-		struct address_space *mapping;
-		struct page *page;
-		int may_enter_fs;
-		int referenced;
-
-		cond_resched();
-
-		page = lru_to_page(page_list);
-		list_del(&page->lru);
+	struct address_space *mapping;
+	int may_enter_fs;
+	int referenced;
 
-		if (TestSetPageLocked(page))
-			goto keep;
+	if (TestSetPageLocked(page))
+		goto keep;
 
-		BUG_ON(PageActive(page));
+	BUG_ON(PageActive(page));
 
+	sc->nr_scanned++;
+	/* Double the slab pressure for mapped and swapcache pages */
+	if (page_mapped(page) || PageSwapCache(page))
 		sc->nr_scanned++;
-		/* Double the slab pressure for mapped and swapcache pages */
-		if (page_mapped(page) || PageSwapCache(page))
-			sc->nr_scanned++;
 
-		if (PageWriteback(page))
-			goto keep_locked;
+	if (PageWriteback(page))
+		goto keep_locked;
 
-		referenced = page_referenced(page, 1);
-		/* In active use or really unfreeable?  Activate it. */
-		if (referenced && page_mapping_inuse(page))
-			goto activate_locked;
+	referenced = page_referenced(page, 1);
+	/* In active use or really unfreeable?  Activate it. */
+	if (referenced && page_mapping_inuse(page))
+		goto activate_locked;
 
 #ifdef CONFIG_SWAP
-		/*
-		 * Anonymous process memory has backing store?
-		 * Try to allocate it some swap space here.
-		 */
-		if (PageAnon(page) && !PageSwapCache(page)) {
-			if (!sc->may_swap)
-				goto keep_locked;
-			if (!add_to_swap(page))
-				goto activate_locked;
-		}
+	/*
+	 * Anonymous process memory has backing store?
+	 * Try to allocate it some swap space here.
+	 */
+	if (PageAnon(page) && !PageSwapCache(page)) {
+		if (!sc->may_swap)
+			goto keep_locked;
+		if (!add_to_swap(page))
+			goto activate_locked;
+	}
 #endif /* CONFIG_SWAP */
 
-		mapping = page_mapping(page);
-		may_enter_fs = (sc->gfp_mask & __GFP_FS) ||
-			(PageSwapCache(page) && (sc->gfp_mask & __GFP_IO));
+	mapping = page_mapping(page);
+	may_enter_fs = (sc->gfp_mask & __GFP_FS) ||
+		(PageSwapCache(page) && (sc->gfp_mask & __GFP_IO));
 
-		/*
-		 * The page is mapped into the page tables of one or more
-		 * processes. Try to unmap it here.
-		 */
-		if (page_mapped(page) && mapping) {
-			switch (try_to_unmap(page)) {
-			case SWAP_FAIL:
-				goto activate_locked;
-			case SWAP_AGAIN:
-				goto keep_locked;
-			case SWAP_SUCCESS:
-				; /* try to free the page below */
-			}
+	/*
+	 * The page is mapped into the page tables of one or more
+	 * processes. Try to unmap it here.
+	 */
+	if (page_mapped(page) && mapping) {
+		switch (try_to_unmap(page)) {
+		case SWAP_FAIL:
+			goto activate_locked;
+		case SWAP_AGAIN:
+			goto keep_locked;
+		case SWAP_SUCCESS:
+			; /* try to free the page below */
 		}
+	}
 
-		if (PageDirty(page)) {
-			if (referenced)
-				goto keep_locked;
-			if (!may_enter_fs)
-				goto keep_locked;
-			if (laptop_mode && !sc->may_writepage)
-				goto keep_locked;
+	if (PageDirty(page)) {
+		if (referenced)
+			goto keep_locked;
+		if (!may_enter_fs)
+			goto keep_locked;
+		if (laptop_mode && !sc->may_writepage)
+			goto keep_locked;
 
-			/* Page is dirty, try to write it out here */
-			switch(pageout(page, mapping)) {
-			case PAGE_KEEP:
-				goto keep_locked;
-			case PAGE_ACTIVATE:
-				goto activate_locked;
-			case PAGE_SUCCESS:
-				if (PageWriteback(page) || PageDirty(page))
-					goto keep;
+		/* Page is dirty, try to write it out here */
+		switch(pageout(page, mapping)) {
+		case PAGE_KEEP:
+			goto keep_locked;
+		case PAGE_ACTIVATE:
+			goto activate_locked;
+		case PAGE_SUCCESS:
+			if (PageWriteback(page) || PageDirty(page))
+				goto keep;
 				/*
-				 * A synchronous write - probably a ramdisk.  Go
-				 * ahead and try to reclaim the page.
-				 */
-				if (TestSetPageLocked(page))
-					goto keep;
-				if (PageDirty(page) || PageWriteback(page))
-					goto keep_locked;
-				mapping = page_mapping(page);
-			case PAGE_CLEAN:
-				; /* try to free the page below */
-			}
+				* A synchronous write - probably a ramdisk.  Go
+				* ahead and try to reclaim the page.
+				*/
+			if (TestSetPageLocked(page))
+				goto keep;
+			if (PageDirty(page) || PageWriteback(page))
+				goto keep_locked;
+			mapping = page_mapping(page);
+		case PAGE_CLEAN:
+			; /* try to free the page below */
 		}
+	}
 
-		/*
-		 * If the page has buffers, try to free the buffer mappings
-		 * associated with this page. If we succeed we try to free
-		 * the page as well.
-		 *
-		 * We do this even if the page is PageDirty().
-		 * try_to_release_page() does not perform I/O, but it is
-		 * possible for a page to have PageDirty set, but it is actually
-		 * clean (all its buffers are clean).  This happens if the
-		 * buffers were written out directly, with submit_bh(). ext3
-		 * will do this, as well as the blockdev mapping. 
-		 * try_to_release_page() will discover that cleanness and will
-		 * drop the buffers and mark the page clean - it can be freed.
-		 *
-		 * Rarely, pages can have buffers and no ->mapping.  These are
-		 * the pages which were not successfully invalidated in
-		 * truncate_complete_page().  We try to drop those buffers here
-		 * and if that worked, and the page is no longer mapped into
-		 * process address space (page_count == 1) it can be freed.
-		 * Otherwise, leave the page on the LRU so it is swappable.
-		 */
-		if (PagePrivate(page)) {
-			if (!try_to_release_page(page, sc->gfp_mask))
-				goto activate_locked;
-			if (!mapping && page_count(page) == 1)
-				goto free_it;
-		}
+	/*
+	 * If the page has buffers, try to free the buffer mappings
+	 * associated with this page. If we succeed we try to free
+	 * the page as well.
+	 *
+	 * We do this even if the page is PageDirty().
+	 * try_to_release_page() does not perform I/O, but it is
+	 * possible for a page to have PageDirty set, but it is actually
+	 * clean (all its buffers are clean).  This happens if the
+	 * buffers were written out directly, with submit_bh(). ext3
+	 * will do this, as well as the blockdev mapping.
+	 * try_to_release_page() will discover that cleanness and will
+	 * drop the buffers and mark the page clean - it can be freed.
+	 *
+	 * Rarely, pages can have buffers and no ->mapping.  These are
+	 * the pages which were not successfully invalidated in
+	 * truncate_complete_page().  We try to drop those buffers here
+	 * and if that worked, and the page is no longer mapped into
+	 * process address space (page_count == 1) it can be freed.
+	 * Otherwise, leave the page on the LRU so it is swappable.
+	 */
+	if (PagePrivate(page)) {
+		if (!try_to_release_page(page, sc->gfp_mask))
+			goto activate_locked;
+		if (!mapping && page_count(page) == 1)
+			goto free_it;
+	}
 
-		if (!mapping)
-			goto keep_locked;	/* truncate got there first */
+	if (!mapping)
+		goto keep_locked;	/* truncate got there first */
 
-		write_lock_irq(&mapping->tree_lock);
+	write_lock_irq(&mapping->tree_lock);
 
-		/*
-		 * The non-racy check for busy page.  It is critical to check
-		 * PageDirty _after_ making sure that the page is freeable and
-		 * not in use by anybody. 	(pagecache + us == 2)
-		 */
-		if (unlikely(page_count(page) != 2))
-			goto cannot_free;
-		smp_rmb();
-		if (unlikely(PageDirty(page)))
-			goto cannot_free;
+	/*
+	 * The non-racy check for busy page.  It is critical to check
+	 * PageDirty _after_ making sure that the page is freeable and
+	 * not in use by anybody. 	(pagecache + us == 2)
+	 */
+	if (unlikely(page_count(page) != 2))
+		goto cannot_free;
+	smp_rmb();
+	if (unlikely(PageDirty(page)))
+		goto cannot_free;
 
 #ifdef CONFIG_SWAP
-		if (PageSwapCache(page)) {
-			swp_entry_t swap = { .val = page_private(page) };
-			__delete_from_swap_cache(page);
-			write_unlock_irq(&mapping->tree_lock);
-			swap_free(swap);
-			__put_page(page);	/* The pagecache ref */
-			goto free_it;
-		}
+	if (PageSwapCache(page)) {
+		swp_entry_t swap = { .val = page_private(page) };
+		__delete_from_swap_cache(page);
+		write_unlock_irq(&mapping->tree_lock);
+		swap_free(swap);
+		__put_page(page);	/* The pagecache ref */
+		goto free_it;
+	}
 #endif /* CONFIG_SWAP */
 
-		__remove_from_page_cache(page);
-		write_unlock_irq(&mapping->tree_lock);
-		__put_page(page);
+	__remove_from_page_cache(page);
+	write_unlock_irq(&mapping->tree_lock);
+	__put_page(page);
 
 free_it:
-		unlock_page(page);
-		reclaimed++;
-		if (!pagevec_add(&freed_pvec, page))
-			__pagevec_release_nonlru(&freed_pvec);
-		continue;
+	unlock_page(page);
+	return PAGEOUT_SUCCESS;
 
 cannot_free:
-		write_unlock_irq(&mapping->tree_lock);
-		goto keep_locked;
+	write_unlock_irq(&mapping->tree_lock);
+	goto keep_locked;
 
 activate_locked:
-		SetPageActive(page);
-		pgactivate++;
+	unlock_page(page);
+	return PAGEOUT_ACTIVATE;
 keep_locked:
-		unlock_page(page);
+	unlock_page(page);
 keep:
-		list_add(&page->lru, &ret_pages);
-		BUG_ON(PageLRU(page));
+	return PAGEOUT_KEEP;
+}
+
+static int shrink_list(struct list_head *page_list, struct scan_control *sc)
+{
+	LIST_HEAD(ret_pages);
+	struct pagevec freed_pvec;
+	int pgactivate = 0;
+	int reclaimed = 0;
+
+	cond_resched();
+
+	pagevec_init(&freed_pvec, 1);
+	while (!list_empty(page_list)) {
+		struct page *page;
+
+		cond_resched();
+
+		page = lru_to_page(page_list);
+		list_del(&page->lru);
+
+		switch(try_pageout(page, sc)) {
+		case PAGEOUT_ACTIVATE:
+			SetPageActive(page);
+			pgactivate++;
+			/* fall through */
+		case PAGEOUT_KEEP:
+			list_add(&page->lru, &ret_pages);
+			BUG_ON(PageLRU(page));
+			break;
+
+		case PAGEOUT_SUCCESS:
+			reclaimed++;
+			if (!pagevec_add(&freed_pvec, page))
+				__pagevec_release_nonlru(&freed_pvec);
+			break;
+		}
 	}
 	list_splice(&ret_pages, page_list);
 	if (pagevec_count(&freed_pvec))

WARNING: multiple messages have this Message-ID (diff)
From: Peter Zijlstra <a.p.zijlstra@chello.nl>
To: linux-mm@kvack.org, linux-kernel@vger.kernel.org
Cc: Andrew Morton <akpm@osdl.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>,
	Christoph Lameter <christoph@lameter.com>,
	Wu Fengguang <wfg@mail.ustc.edu.cn>,
	Nick Piggin <npiggin@suse.de>, Marijn Meijles <marijn@bitpit.net>,
	Rik van Riel <riel@redhat.com>,
	Marcelo Tosatti <marcelo.tosatti@cyclades.com>
Subject: [PATCH 02/14] page-replace-try_pageout.patch
Date: Fri, 30 Dec 2005 23:40:34 +0100	[thread overview]
Message-ID: <20051230224012.765.32791.sendpatchset@twins.localnet> (raw)
In-Reply-To: <20051230223952.765.21096.sendpatchset@twins.localnet>

From: Peter Zijlstra <a.p.zijlstra@chello.nl>

Move the functionality of the shrink_list() loop into its own function.

Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>

 mm/vmscan.c |  324 ++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 174 insertions(+), 150 deletions(-)

Index: linux-2.6-git/mm/vmscan.c
===================================================================
--- linux-2.6-git.orig/mm/vmscan.c
+++ linux-2.6-git/mm/vmscan.c
@@ -51,6 +51,16 @@ typedef enum {
 	PAGE_CLEAN,
 } pageout_t;
 
+/* possible outcome of try_pageout() */
+typedef enum {
+	/* unable to perform pageout */
+	PAGEOUT_KEEP,
+	/* unable to perform pageout, page is in active use */
+	PAGEOUT_ACTIVATE,
+	/* pageout succeded, page is gone */
+	PAGEOUT_SUCCESS,
+} try_pageout_t;
+
 struct scan_control {
 	/* Ask refill_inactive_zone, or shrink_cache to scan this many pages */
 	unsigned long nr_to_scan;
@@ -382,189 +392,203 @@ static pageout_t pageout(struct page *pa
 	return PAGE_CLEAN;
 }
 
-/*
- * shrink_list adds the number of reclaimed pages to sc->nr_reclaimed
- */
-static int shrink_list(struct list_head *page_list, struct scan_control *sc)
+static try_pageout_t try_pageout(struct page *page, struct scan_control *sc)
 {
-	LIST_HEAD(ret_pages);
-	struct pagevec freed_pvec;
-	int pgactivate = 0;
-	int reclaimed = 0;
-
-	cond_resched();
-
-	pagevec_init(&freed_pvec, 1);
-	while (!list_empty(page_list)) {
-		struct address_space *mapping;
-		struct page *page;
-		int may_enter_fs;
-		int referenced;
-
-		cond_resched();
-
-		page = lru_to_page(page_list);
-		list_del(&page->lru);
+	struct address_space *mapping;
+	int may_enter_fs;
+	int referenced;
 
-		if (TestSetPageLocked(page))
-			goto keep;
+	if (TestSetPageLocked(page))
+		goto keep;
 
-		BUG_ON(PageActive(page));
+	BUG_ON(PageActive(page));
 
+	sc->nr_scanned++;
+	/* Double the slab pressure for mapped and swapcache pages */
+	if (page_mapped(page) || PageSwapCache(page))
 		sc->nr_scanned++;
-		/* Double the slab pressure for mapped and swapcache pages */
-		if (page_mapped(page) || PageSwapCache(page))
-			sc->nr_scanned++;
 
-		if (PageWriteback(page))
-			goto keep_locked;
+	if (PageWriteback(page))
+		goto keep_locked;
 
-		referenced = page_referenced(page, 1);
-		/* In active use or really unfreeable?  Activate it. */
-		if (referenced && page_mapping_inuse(page))
-			goto activate_locked;
+	referenced = page_referenced(page, 1);
+	/* In active use or really unfreeable?  Activate it. */
+	if (referenced && page_mapping_inuse(page))
+		goto activate_locked;
 
 #ifdef CONFIG_SWAP
-		/*
-		 * Anonymous process memory has backing store?
-		 * Try to allocate it some swap space here.
-		 */
-		if (PageAnon(page) && !PageSwapCache(page)) {
-			if (!sc->may_swap)
-				goto keep_locked;
-			if (!add_to_swap(page))
-				goto activate_locked;
-		}
+	/*
+	 * Anonymous process memory has backing store?
+	 * Try to allocate it some swap space here.
+	 */
+	if (PageAnon(page) && !PageSwapCache(page)) {
+		if (!sc->may_swap)
+			goto keep_locked;
+		if (!add_to_swap(page))
+			goto activate_locked;
+	}
 #endif /* CONFIG_SWAP */
 
-		mapping = page_mapping(page);
-		may_enter_fs = (sc->gfp_mask & __GFP_FS) ||
-			(PageSwapCache(page) && (sc->gfp_mask & __GFP_IO));
+	mapping = page_mapping(page);
+	may_enter_fs = (sc->gfp_mask & __GFP_FS) ||
+		(PageSwapCache(page) && (sc->gfp_mask & __GFP_IO));
 
-		/*
-		 * The page is mapped into the page tables of one or more
-		 * processes. Try to unmap it here.
-		 */
-		if (page_mapped(page) && mapping) {
-			switch (try_to_unmap(page)) {
-			case SWAP_FAIL:
-				goto activate_locked;
-			case SWAP_AGAIN:
-				goto keep_locked;
-			case SWAP_SUCCESS:
-				; /* try to free the page below */
-			}
+	/*
+	 * The page is mapped into the page tables of one or more
+	 * processes. Try to unmap it here.
+	 */
+	if (page_mapped(page) && mapping) {
+		switch (try_to_unmap(page)) {
+		case SWAP_FAIL:
+			goto activate_locked;
+		case SWAP_AGAIN:
+			goto keep_locked;
+		case SWAP_SUCCESS:
+			; /* try to free the page below */
 		}
+	}
 
-		if (PageDirty(page)) {
-			if (referenced)
-				goto keep_locked;
-			if (!may_enter_fs)
-				goto keep_locked;
-			if (laptop_mode && !sc->may_writepage)
-				goto keep_locked;
+	if (PageDirty(page)) {
+		if (referenced)
+			goto keep_locked;
+		if (!may_enter_fs)
+			goto keep_locked;
+		if (laptop_mode && !sc->may_writepage)
+			goto keep_locked;
 
-			/* Page is dirty, try to write it out here */
-			switch(pageout(page, mapping)) {
-			case PAGE_KEEP:
-				goto keep_locked;
-			case PAGE_ACTIVATE:
-				goto activate_locked;
-			case PAGE_SUCCESS:
-				if (PageWriteback(page) || PageDirty(page))
-					goto keep;
+		/* Page is dirty, try to write it out here */
+		switch(pageout(page, mapping)) {
+		case PAGE_KEEP:
+			goto keep_locked;
+		case PAGE_ACTIVATE:
+			goto activate_locked;
+		case PAGE_SUCCESS:
+			if (PageWriteback(page) || PageDirty(page))
+				goto keep;
 				/*
-				 * A synchronous write - probably a ramdisk.  Go
-				 * ahead and try to reclaim the page.
-				 */
-				if (TestSetPageLocked(page))
-					goto keep;
-				if (PageDirty(page) || PageWriteback(page))
-					goto keep_locked;
-				mapping = page_mapping(page);
-			case PAGE_CLEAN:
-				; /* try to free the page below */
-			}
+				* A synchronous write - probably a ramdisk.  Go
+				* ahead and try to reclaim the page.
+				*/
+			if (TestSetPageLocked(page))
+				goto keep;
+			if (PageDirty(page) || PageWriteback(page))
+				goto keep_locked;
+			mapping = page_mapping(page);
+		case PAGE_CLEAN:
+			; /* try to free the page below */
 		}
+	}
 
-		/*
-		 * If the page has buffers, try to free the buffer mappings
-		 * associated with this page. If we succeed we try to free
-		 * the page as well.
-		 *
-		 * We do this even if the page is PageDirty().
-		 * try_to_release_page() does not perform I/O, but it is
-		 * possible for a page to have PageDirty set, but it is actually
-		 * clean (all its buffers are clean).  This happens if the
-		 * buffers were written out directly, with submit_bh(). ext3
-		 * will do this, as well as the blockdev mapping. 
-		 * try_to_release_page() will discover that cleanness and will
-		 * drop the buffers and mark the page clean - it can be freed.
-		 *
-		 * Rarely, pages can have buffers and no ->mapping.  These are
-		 * the pages which were not successfully invalidated in
-		 * truncate_complete_page().  We try to drop those buffers here
-		 * and if that worked, and the page is no longer mapped into
-		 * process address space (page_count == 1) it can be freed.
-		 * Otherwise, leave the page on the LRU so it is swappable.
-		 */
-		if (PagePrivate(page)) {
-			if (!try_to_release_page(page, sc->gfp_mask))
-				goto activate_locked;
-			if (!mapping && page_count(page) == 1)
-				goto free_it;
-		}
+	/*
+	 * If the page has buffers, try to free the buffer mappings
+	 * associated with this page. If we succeed we try to free
+	 * the page as well.
+	 *
+	 * We do this even if the page is PageDirty().
+	 * try_to_release_page() does not perform I/O, but it is
+	 * possible for a page to have PageDirty set, but it is actually
+	 * clean (all its buffers are clean).  This happens if the
+	 * buffers were written out directly, with submit_bh(). ext3
+	 * will do this, as well as the blockdev mapping.
+	 * try_to_release_page() will discover that cleanness and will
+	 * drop the buffers and mark the page clean - it can be freed.
+	 *
+	 * Rarely, pages can have buffers and no ->mapping.  These are
+	 * the pages which were not successfully invalidated in
+	 * truncate_complete_page().  We try to drop those buffers here
+	 * and if that worked, and the page is no longer mapped into
+	 * process address space (page_count == 1) it can be freed.
+	 * Otherwise, leave the page on the LRU so it is swappable.
+	 */
+	if (PagePrivate(page)) {
+		if (!try_to_release_page(page, sc->gfp_mask))
+			goto activate_locked;
+		if (!mapping && page_count(page) == 1)
+			goto free_it;
+	}
 
-		if (!mapping)
-			goto keep_locked;	/* truncate got there first */
+	if (!mapping)
+		goto keep_locked;	/* truncate got there first */
 
-		write_lock_irq(&mapping->tree_lock);
+	write_lock_irq(&mapping->tree_lock);
 
-		/*
-		 * The non-racy check for busy page.  It is critical to check
-		 * PageDirty _after_ making sure that the page is freeable and
-		 * not in use by anybody. 	(pagecache + us == 2)
-		 */
-		if (unlikely(page_count(page) != 2))
-			goto cannot_free;
-		smp_rmb();
-		if (unlikely(PageDirty(page)))
-			goto cannot_free;
+	/*
+	 * The non-racy check for busy page.  It is critical to check
+	 * PageDirty _after_ making sure that the page is freeable and
+	 * not in use by anybody. 	(pagecache + us == 2)
+	 */
+	if (unlikely(page_count(page) != 2))
+		goto cannot_free;
+	smp_rmb();
+	if (unlikely(PageDirty(page)))
+		goto cannot_free;
 
 #ifdef CONFIG_SWAP
-		if (PageSwapCache(page)) {
-			swp_entry_t swap = { .val = page_private(page) };
-			__delete_from_swap_cache(page);
-			write_unlock_irq(&mapping->tree_lock);
-			swap_free(swap);
-			__put_page(page);	/* The pagecache ref */
-			goto free_it;
-		}
+	if (PageSwapCache(page)) {
+		swp_entry_t swap = { .val = page_private(page) };
+		__delete_from_swap_cache(page);
+		write_unlock_irq(&mapping->tree_lock);
+		swap_free(swap);
+		__put_page(page);	/* The pagecache ref */
+		goto free_it;
+	}
 #endif /* CONFIG_SWAP */
 
-		__remove_from_page_cache(page);
-		write_unlock_irq(&mapping->tree_lock);
-		__put_page(page);
+	__remove_from_page_cache(page);
+	write_unlock_irq(&mapping->tree_lock);
+	__put_page(page);
 
 free_it:
-		unlock_page(page);
-		reclaimed++;
-		if (!pagevec_add(&freed_pvec, page))
-			__pagevec_release_nonlru(&freed_pvec);
-		continue;
+	unlock_page(page);
+	return PAGEOUT_SUCCESS;
 
 cannot_free:
-		write_unlock_irq(&mapping->tree_lock);
-		goto keep_locked;
+	write_unlock_irq(&mapping->tree_lock);
+	goto keep_locked;
 
 activate_locked:
-		SetPageActive(page);
-		pgactivate++;
+	unlock_page(page);
+	return PAGEOUT_ACTIVATE;
 keep_locked:
-		unlock_page(page);
+	unlock_page(page);
 keep:
-		list_add(&page->lru, &ret_pages);
-		BUG_ON(PageLRU(page));
+	return PAGEOUT_KEEP;
+}
+
+static int shrink_list(struct list_head *page_list, struct scan_control *sc)
+{
+	LIST_HEAD(ret_pages);
+	struct pagevec freed_pvec;
+	int pgactivate = 0;
+	int reclaimed = 0;
+
+	cond_resched();
+
+	pagevec_init(&freed_pvec, 1);
+	while (!list_empty(page_list)) {
+		struct page *page;
+
+		cond_resched();
+
+		page = lru_to_page(page_list);
+		list_del(&page->lru);
+
+		switch(try_pageout(page, sc)) {
+		case PAGEOUT_ACTIVATE:
+			SetPageActive(page);
+			pgactivate++;
+			/* fall through */
+		case PAGEOUT_KEEP:
+			list_add(&page->lru, &ret_pages);
+			BUG_ON(PageLRU(page));
+			break;
+
+		case PAGEOUT_SUCCESS:
+			reclaimed++;
+			if (!pagevec_add(&freed_pvec, page))
+				__pagevec_release_nonlru(&freed_pvec);
+			break;
+		}
 	}
 	list_splice(&ret_pages, page_list);
 	if (pagevec_count(&freed_pvec))

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

  parent reply	other threads:[~2005-12-30 22:40 UTC|newest]

Thread overview: 117+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-12-30 22:40 [PATCH] vm: page-replace and clockpro Peter Zijlstra
2005-12-30 22:40 ` Peter Zijlstra
2005-12-30 22:40 ` [PATCH 01/14] page-replace-single-batch-insert.patch Peter Zijlstra
2005-12-30 22:40   ` Peter Zijlstra
2005-12-31  7:03   ` Marcelo Tosatti
2005-12-31  7:03     ` Marcelo Tosatti
2005-12-31  9:43     ` Peter Zijlstra
2005-12-31  9:43       ` Peter Zijlstra
2005-12-31 14:44     ` Rik van Riel
2005-12-31 14:44       ` Rik van Riel
2005-12-31 22:19       ` Marcelo Tosatti
2005-12-31 22:19         ` Marcelo Tosatti
2005-12-30 22:40 ` Peter Zijlstra [this message]
2005-12-30 22:40   ` [PATCH 02/14] page-replace-try_pageout.patch Peter Zijlstra
2005-12-30 22:40 ` [PATCH 03/14] page-replace-remove-sc-from-refill.patch Peter Zijlstra
2005-12-30 22:40   ` Peter Zijlstra
2005-12-30 22:40 ` [PATCH 04/14] page-replace-activate_page.patch Peter Zijlstra
2005-12-30 22:40   ` Peter Zijlstra
2005-12-30 22:41 ` [PATCH 05/14] page-replace-remove-loop.patch Peter Zijlstra
2005-12-30 22:41   ` Peter Zijlstra
2005-12-30 22:41 ` [PATCH 06/14] page-replace-move-macros.patch Peter Zijlstra
2005-12-30 22:41   ` Peter Zijlstra
2005-12-30 22:41 ` [PATCH 07/14] page-replace-move-isolate_lru_pages.patch Peter Zijlstra
2005-12-30 22:41   ` Peter Zijlstra
2005-12-30 22:41 ` [PATCH 08/14] page-replace-candidates.patch Peter Zijlstra
2005-12-30 22:41   ` Peter Zijlstra
2005-12-30 22:41 ` [PATCH 09/14] page-replace-reinsert.patch Peter Zijlstra
2005-12-30 22:41   ` Peter Zijlstra
2005-12-30 22:41 ` [PATCH 10/14] page-replace-remove-mm_inline.patch Peter Zijlstra
2005-12-30 22:41   ` Peter Zijlstra
2005-12-30 22:42 ` [PATCH 11/14] page-replace-move-refill.patch Peter Zijlstra
2005-12-30 22:42   ` Peter Zijlstra
2005-12-30 22:42 ` [PATCH 12/14] page-replace-rotate.patch Peter Zijlstra
2005-12-30 22:42   ` Peter Zijlstra
2005-12-30 22:42 ` [PATCH 13/14] page-replace-init.patch Peter Zijlstra
2005-12-30 22:42   ` Peter Zijlstra
2005-12-30 22:42 ` [PATCH 14/14] page-replace-kswapd-incmin.patch Peter Zijlstra
2005-12-30 22:42   ` Peter Zijlstra
2005-12-31  1:15   ` Marcelo Tosatti
2005-12-31  1:15     ` Marcelo Tosatti
2005-12-31  9:40     ` Peter Zijlstra
2005-12-31  9:40       ` Peter Zijlstra
2005-12-30 22:42 ` [PATCH 1/9] clockpro-nonresident.patch Peter Zijlstra
2005-12-30 22:42   ` Peter Zijlstra
2005-12-31  1:13   ` Marcelo Tosatti
2005-12-31  1:13     ` Marcelo Tosatti
2005-12-31  9:54     ` Peter Zijlstra
2005-12-31  9:54       ` Peter Zijlstra
2005-12-31 14:53       ` Rik van Riel
2005-12-31 14:53         ` Rik van Riel
2005-12-31 22:20         ` Marcelo Tosatti
2005-12-31 22:20           ` Marcelo Tosatti
2005-12-30 22:42 ` [PATCH 2/9] clockpro-nonresident-del.patch Peter Zijlstra
2005-12-30 22:42   ` Peter Zijlstra
2005-12-30 22:43 ` [PATCH 3/9] clockpro-PG_test.patch Peter Zijlstra
2005-12-30 22:43   ` Peter Zijlstra
2005-12-30 22:43 ` [PATCH 4/9] clockpro-use-once.patch Peter Zijlstra
2005-12-30 22:43   ` Peter Zijlstra
2005-12-30 22:43 ` [PATCH 5/9] clockpro-ignore_token.patch Peter Zijlstra
2005-12-30 22:43   ` Peter Zijlstra
2005-12-30 22:43 ` [PATCH 6/9] clockpro-clockpro.patch Peter Zijlstra
2005-12-30 22:43   ` Peter Zijlstra
2005-12-31  0:24   ` Marcelo Tosatti
2005-12-31  0:24     ` Marcelo Tosatti
2005-12-31  1:22     ` Rik van Riel
2005-12-31  1:22       ` Rik van Riel
2005-12-31  3:27       ` Marcelo Tosatti
2005-12-31  3:27         ` Marcelo Tosatti
2005-12-31  5:24         ` Rik van Riel
2005-12-31  5:24           ` Rik van Riel
2005-12-31 10:57           ` Peter Zijlstra
2005-12-31 10:57             ` Peter Zijlstra
2005-12-31 10:48     ` Peter Zijlstra
2005-12-31 10:48       ` Peter Zijlstra
2005-12-31 22:12       ` Marcelo Tosatti
2005-12-31 22:12         ` Marcelo Tosatti
2006-01-03 19:30         ` Christoph Lameter
2006-01-03 19:30           ` Christoph Lameter
2005-12-31 11:29     ` Peter Zijlstra
2005-12-31 11:29       ` Peter Zijlstra
2006-01-05  9:47       ` IWAMOTO Toshihiro
2006-01-05  9:47         ` IWAMOTO Toshihiro
2006-01-05 13:32         ` Rik van Riel
2006-01-05 13:32           ` Rik van Riel
2006-01-06  9:01           ` IWAMOTO Toshihiro
2006-01-06  9:01             ` IWAMOTO Toshihiro
2006-01-24  6:30             ` IWAMOTO Toshihiro
2006-01-24  6:30               ` IWAMOTO Toshihiro
2006-01-24  7:25               ` IWAMOTO Toshihiro
2006-01-25  8:00                 ` Peter Zijlstra
2006-02-03  9:25                 ` Peter Zijlstra
2006-02-06  9:30                   ` IWAMOTO Toshihiro
2006-02-06 10:07                     ` Peter Zijlstra
2006-02-08 10:05                   ` IWAMOTO Toshihiro
2006-02-08 20:00                     ` Peter Zijlstra
2006-02-09  6:57                       ` Peter Zijlstra
2006-02-09  7:22                       ` IWAMOTO Toshihiro
2006-02-09 10:07                         ` IWAMOTO Toshihiro
2006-02-09 15:23                       ` Rik van Riel
2006-02-08  9:53                 ` IWAMOTO Toshihiro
2005-12-31 22:40   ` Marcelo Tosatti
2005-12-31 22:40     ` Marcelo Tosatti
2006-01-01 10:37     ` Peter Zijlstra
2006-01-01 10:37       ` Peter Zijlstra
2006-01-03 12:21       ` Marcelo Tosatti
2006-01-03 12:21         ` Marcelo Tosatti
2006-02-14  7:29   ` IWAMOTO Toshihiro
2006-02-15  6:35     ` Peter Zijlstra
2006-02-16  6:25       ` IWAMOTO Toshihiro
2005-12-30 22:43 ` [PATCH 7/9] clockpro-remove-old.patch Peter Zijlstra
2005-12-30 22:43   ` Peter Zijlstra
2005-12-30 22:43 ` [PATCH 8/9] clockpro-rename_PG_active.patch Peter Zijlstra
2005-12-30 22:43   ` Peter Zijlstra
2005-12-30 22:44 ` [PATCH 9/9] clockpro-clockpro-stats.patch Peter Zijlstra
2005-12-30 22:44   ` Peter Zijlstra
2005-12-31 18:59 ` [PATCH 10/9] clockpro-document.patch Peter Zijlstra
2005-12-31 18:59   ` Peter Zijlstra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20051230224012.765.32791.sendpatchset@twins.localnet \
    --to=a.p.zijlstra@chello.nl \
    --cc=akpm@osdl.org \
    --cc=christoph@lameter.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=marcelo.tosatti@cyclades.com \
    --cc=marijn@bitpit.net \
    --cc=npiggin@suse.de \
    --cc=riel@redhat.com \
    --cc=wfg@mail.ustc.edu.cn \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.