Skip to contentSkip to conversation

avoid allocating pte_chains for unshared pages

PATCH In review Andrew Morton 1 participant 1 message Jul 17, 2002

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

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 page
 	BUG_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(str
 	struct 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);

.