avoid allocating pte_chains for unshared pages
Subsystems (6)
PATCH 3/13 avoid allocating pte_chains for unshared pages
Patch from David McCracken. It is an optimisation to the rmap pte_chains.
In the common case where a page is mapped by only a single pte, we don't need to allocate a pte_chain structure. Just make the page's pte_chain pointer point straight at that pte and flag this with PG_direct.
include/linux/mm.h | 5 + include/linux/page-flags.h | 12 +++- mm/page_alloc.c | 2 mm/rmap.c | 128 ++++++++++++++++++++++++++++++++------------- mm/vmscan.c | 8 +- 5 files changed, 112 insertions(+), 43 deletions(-)
include/linux/mm.h renamed from include/linux/mm.h~rmap-opt +4 -1
@@ -157,8 +157,11 @@ struct page {updated asynchronously */ struct list_head lru;/* Pageout list, eg. active_list; protected by pagemap_lru_lock !! */ -struct pte_chain * pte_chain;/* Reverse pte mapping pointer. +union { +struct pte_chain * chain;/* Reverse pte mapping pointer. * protected by PG_chainlock */ +pte_t * direct; + } pte;unsigned long private;/* mapping-private opaque data */ /*
include/linux/page-flags.h renamed from include/linux/page-flags.h~rmap-opt +10 -2
@@ -64,8 +64,10 @@#define PG_private 12/* Has something at ->private */ #define PG_writeback 13/* Page is under writeback */ -#define PG_nosave 15/* Used for system suspend/resume */ -#define PG_chainlock 16/* lock bit for ->pte_chain */ +#define PG_nosave 14/* Used for system suspend/resume */ +#define PG_chainlock 15/* lock bit for ->pte_chain */ + +#define PG_direct 16/* ->pte_chain points directly at pte */ /* * Global page accounting. One instance per CPU.
@@ -217,6 +219,12 @@ extern void get_page_state(struct page_s#define ClearPageNosave (page) clear_bit(PG_nosave, &(page)->flags)#define TestClearPageNosave (page) test_and_clear_bit(PG_nosave, &(page)->flags) +#define PageDirect (page) test_bit(PG_direct, &(page)->flags) +#define SetPageDirect (page) set_bit(PG_direct, &(page)->flags) +#define TestSetPageDirect (page) test_and_set_bit(PG_direct, &(page)->flags) +#define ClearPageDirect (page) clear_bit(PG_direct, &(page)->flags) +#define TestClearPageDirect (page) test_and_clear_bit(PG_direct, &(page)->flags) +/* * inlines for acquisition and release of PG_chainlock */
mm/page_alloc.c renamed from mm/page_alloc.c~rmap-opt +1 -1
@@ -92,7 +92,7 @@ static void __free_pages_ok (struct pageBUG_ON (PageLRU (page));BUG_ON (PageActive (page));BUG_ON (PageWriteback (page)); -BUG_ON (page->pte_chain !=NULL ); +BUG_ON (page->pte.chain !=NULL );if (PageDirty (page))ClearPageDirty (page);BUG_ON (page_count (page) !=0 );
mm/rmap.c renamed from mm/rmap.c~rmap-opt +93 -35
182 lines not on this page · raw message
mm/vmscan.c renamed from mm/vmscan.c~rmap-opt +4 -4
@@ -48,7 +48,7 @@ static inline int page_mapping_inuse(strstruct address_space *mapping = page->mapping;/* Page is in somebody's page tables. */ -if (page->pte_chain) +if (page->pte.chain)return 1 ;/* XXX: does this happen ? */
@@ -151,7 +151,7 @@ shrink_cache(int nr_pages, zone_t *class* * XXX: implement swap clustering ? */ -if (page->pte_chain && !page->mapping && !PagePrivate (page)) { +if (page->pte.chain && !page->mapping && !PagePrivate (page)) {page_cache_get (page);pte_chain_unlock (page);spin_unlock (&pagemap_lru_lock);
@@ -171,7 +171,7 @@ shrink_cache(int nr_pages, zone_t *class* The page is mapped into the page tables of one or more * processes. Try to unmap it here. */ -if (page->pte_chain) { +if (page->pte.chain) {switch (try_to_unmap (page)) {case SWAP_ERROR :case SWAP_FAIL :
@@ -340,7 +340,7 @@ static void refill_inactive(int nr_pages entry = entry->prev;pte_chain_lock (page); -if (page->pte_chain &&page_referenced (page)) { +if (page->pte.chain &&page_referenced (page)) {list_del (&page->lru);list_add (&page->lru, &active_list);pte_chain_unlock (page);
.