Skip to contentSkip to conversation

Page host virtual assist: discarded page list.

PATCH In review Martin Schwidefsky 1 participant 1 message Apr 24, 2006

Subsystems (7)
lore
Share & tools
lore
#0 lore raw

PATCH 7/8 Page host virtual assist: discarded page list.

[patch 7/8] Page host virtual assist: discarded page list.

The discarded page list is used to postpone the freeing of discarded pages. A check is added to __remove_from_page_cache and __delete_from_swap_cache that sets the PG_discarded bit if the page has been removed by the host. free_hot_cold_page tests for the bit and puts the page to a per-cpu discarded page list if it is set. try_to_free_pages does an smp_call_function to collect all the partial discarded page lists and frees them.

There are two reasons why this is desirable. First, discarded page are really cold. Before the guest can reaccess the page frame the host needs to provide a fresh page. It is faster to use only non-discarded pages which do not require a host action as long as the working set of the guest allows it.

The second reason has to do with the peculiars of the s390 architecture. The discard fault exception delivers the absolute address of the page that caused the fault to the guest instead of the virtual address. With the virtual address we could have used the page table entry of the current process to safely get a reference to the discarded page. We can get the struct page pointer from the absolute page address but its rather hard to get to a proper page reference. The page that caused the fault could already have been freed and reused for a different purpose. None of the fields in the struct page would be reliable to use. The smp_call_function makes sure that the discard fault handler is called only for discarded pages that have not been freed yet. A call to get_page_unless_zero can then be used to get a proper page reference.

---

 include/linux/page_hva.h |    4 +++
 mm/filemap.c             |    4 +++
 mm/page_alloc.c          |   57 +++++++++++++++++++++++++++++++++++++++++++++++
 mm/swap_state.c          |    4 +++
 mm/vmscan.c              |    1 
 5 files changed, 70 insertions(+)
include/linux/page_hva.h +4 -0
diff -urpN linux-2.6/include/linux/page_hva.h linux-2.6-patched/include/linux/page_hva.h
@@ -18,6 +18,7 @@
 
 extern void page_hva_unmap_all(struct page *page);
 extern void page_hva_discard_page(struct page *page);
+extern unsigned long page_hva_shrink_discards(void);
 
 extern int  __page_hva_make_stable(struct page *page);
 extern void __page_hva_make_volatile(struct page *page, unsigned int offset);
@@ -64,6 +65,8 @@ static inline void page_hva_reset_write(
 #define page_hva_set_volatile(_page,_writable)	do { } while (0)
 #define page_hva_cond_set_stable(_page)		(1)
 
+#define page_hva_discarded(_page)		(0)
+
 #define page_hva_make_stable(_page)		(1)
 #define page_hva_make_volatile(_page,_offset)	do { } while (0)
 
@@ -71,6 +74,7 @@ static inline void page_hva_reset_write(
 #define page_hva_reset_write(_page)		do { } while (0)
 
 #define page_hva_discard_page(_page)		do { } while (0)
+#define page_hva_shrink_discards()		(0)
 
 #endif
 
mm/filemap.c +4 -0
diff -urpN linux-2.6/mm/filemap.c linux-2.6-patched/mm/filemap.c
@@ -117,6 +117,10 @@ void __remove_from_page_cache(struct pag
 {
 	struct address_space *mapping = page->mapping;
 
+	/* Set the PageDiscarded bit if the page has been discarded. */
+	if (page_hva_enabled() &&
+	    unlikely(!PageDiscarded(page) && page_hva_discarded(page)))
+		SetPageDiscarded(page);
 	radix_tree_delete(&mapping->page_tree, page->index);
 	page->mapping = NULL;
 	mapping->nrpages--;
mm/page_alloc.c +57 -0

81 lines not on this page · raw message

mm/swap_state.c +4 -0
diff -urpN linux-2.6/mm/swap_state.c linux-2.6-patched/mm/swap_state.c
@@ -131,6 +131,10 @@ void __delete_from_swap_cache(struct pag
 	BUG_ON(PageWriteback(page));
 	BUG_ON(PagePrivate(page));
 
+	/* Set the PageDiscarded bit if the page has been discarded. */
+	if (page_hva_enabled() &&
+	    unlikely(!PageDiscarded(page) && page_hva_discarded(page)))
+		SetPageDiscarded(page);
 	radix_tree_delete(&swapper_space.page_tree, page_private(page));
 	set_page_private(page, 0);
 	ClearPageSwapCache(page);
mm/vmscan.c +1 -0
diff -urpN linux-2.6/mm/vmscan.c linux-2.6-patched/mm/vmscan.c
@@ -993,6 +993,7 @@ unsigned long try_to_free_pages(struct z
 		sc.nr_scanned = 0;
 		if (!priority)
 			disable_swap_token();
+		nr_reclaimed += page_hva_shrink_discards();
 		nr_reclaimed += shrink_zones(priority, zones, &sc);
 		shrink_slab(sc.nr_scanned, gfp_mask, lru_pages);
 		if (reclaim_state) {

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