[PATCH 21/34] mm: page-replace-nonresident.patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Peter Zijlstra <[email protected]>

Add hooks for nonresident page tracking.
The policy has to define MM_POLICY_HAS_NONRESIDENT when it makes
use of these.

API:
	void page_replace_remember(struct zone *, struct page *);

Remeber a page - insert it into the nonresident page tracking.

	void page_replace_forget(struct address_space *, unsigned long);

Forget about a page - remove it from the nonresident page tracking.

Signed-off-by: Peter Zijlstra <[email protected]>
Signed-off-by: Marcelo Tosatti <[email protected]>

---

 include/linux/mm_page_replace.h    |    2 ++
 include/linux/mm_use_once_policy.h |    3 +++
 mm/memory.c                        |   28 ++++++++++++++++++++++++++++
 mm/swapfile.c                      |   13 +++++++++++--
 mm/vmscan.c                        |    2 ++
 5 files changed, 46 insertions(+), 2 deletions(-)

Index: linux-2.6-git/include/linux/mm_use_once_policy.h
===================================================================
--- linux-2.6-git.orig/include/linux/mm_use_once_policy.h
+++ linux-2.6-git/include/linux/mm_use_once_policy.h
@@ -161,6 +161,9 @@ static inline int page_replace_is_active
 	return PageActive(page);
 }
 
+#define page_replace_remember(z, p) do { } while (0)
+#define page_replace_forget(m, i) do { } while (0)
+
 static inline unsigned long __page_replace_nr_pages(struct zone *zone)
 {
 	return zone->policy.nr_active + zone->policy.nr_inactive;
Index: linux-2.6-git/include/linux/mm_page_replace.h
===================================================================
--- linux-2.6-git.orig/include/linux/mm_page_replace.h
+++ linux-2.6-git/include/linux/mm_page_replace.h
@@ -96,6 +96,8 @@ extern void page_replace_shrink(struct z
 /* void page_replace_copy_state(struct page *, struct page *); */
 /* void page_replace_clear_state(struct page *); */
 /* int page_replace_is_active(struct page *); */
+/* void page_replace_remember(struct zone *, struct page*); */
+/* void page_replace_forget(struct address_space *, unsigned long); */
 extern void page_replace_show(struct zone *);
 extern void page_replace_zoneinfo(struct zone *, struct seq_file *);
 extern void __page_replace_counts(unsigned long *, unsigned long *,
Index: linux-2.6-git/mm/memory.c
===================================================================
--- linux-2.6-git.orig/mm/memory.c
+++ linux-2.6-git/mm/memory.c
@@ -606,6 +606,31 @@ int copy_page_range(struct mm_struct *ds
 	return 0;
 }
 
+#if defined MM_POLICY_HAS_NONRESIDENT
+static void free_file(struct vm_area_struct *vma,
+				unsigned long offset)
+{
+	struct address_space *mapping;
+	struct page *page;
+
+	if (!vma ||
+	    !vma->vm_file ||
+	    !vma->vm_file->f_mapping)
+		return;
+
+	mapping = vma->vm_file->f_mapping;
+	page = find_get_page(mapping, offset);
+	if (page) {
+		page_cache_release(page);
+		return;
+	}
+
+	page_replace_forget(mapping, offset);
+}
+#else
+#define free_file(a,b) do { } while (0)
+#endif
+
 static unsigned long zap_pte_range(struct mmu_gather *tlb,
 				struct vm_area_struct *vma, pmd_t *pmd,
 				unsigned long addr, unsigned long end,
@@ -621,6 +646,7 @@ static unsigned long zap_pte_range(struc
 	do {
 		pte_t ptent = *pte;
 		if (pte_none(ptent)) {
+			free_file(vma, pte_to_pgoff(ptent));
 			(*zap_work)--;
 			continue;
 		}
@@ -679,6 +705,8 @@ static unsigned long zap_pte_range(struc
 			continue;
 		if (!pte_file(ptent))
 			free_swap_and_cache(pte_to_swp_entry(ptent));
+		else
+			free_file(vma, pte_to_pgoff(ptent));
 		pte_clear_full(mm, addr, pte, tlb->fullmm);
 	} while (pte++, addr += PAGE_SIZE, (addr != end && *zap_work > 0));
 
Index: linux-2.6-git/mm/swapfile.c
===================================================================
--- linux-2.6-git.orig/mm/swapfile.c
+++ linux-2.6-git/mm/swapfile.c
@@ -28,6 +28,7 @@
 #include <linux/mutex.h>
 #include <linux/capability.h>
 #include <linux/syscalls.h>
+#include <linux/mm_page_replace.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -300,7 +301,8 @@ void swap_free(swp_entry_t entry)
 
 	p = swap_info_get(entry);
 	if (p) {
-		swap_entry_free(p, swp_offset(entry));
+		if (!swap_entry_free(p, swp_offset(entry)))
+			page_replace_forget(&swapper_space, entry.val);
 		spin_unlock(&swap_lock);
 	}
 }
@@ -397,8 +399,15 @@ void free_swap_and_cache(swp_entry_t ent
 
 	p = swap_info_get(entry);
 	if (p) {
-		if (swap_entry_free(p, swp_offset(entry)) == 1)
+		switch (swap_entry_free(p, swp_offset(entry))) {
+		case 1:
 			page = find_trylock_page(&swapper_space, entry.val);
+			break;
+
+		case 0:
+			page_replace_forget(&swapper_space, entry.val);
+			break;
+		}
 		spin_unlock(&swap_lock);
 	}
 	if (page) {
Index: linux-2.6-git/mm/vmscan.c
===================================================================
--- linux-2.6-git.orig/mm/vmscan.c
+++ linux-2.6-git/mm/vmscan.c
@@ -315,6 +315,7 @@ static int remove_mapping(struct address
 
 	if (PageSwapCache(page)) {
 		swp_entry_t swap = { .val = page_private(page) };
+		page_replace_remember(page_zone(page), page);
 		__delete_from_swap_cache(page);
 		write_unlock_irq(&mapping->tree_lock);
 		swap_free(swap);
@@ -322,6 +323,7 @@ static int remove_mapping(struct address
 		return 1;
 	}
 
+	page_replace_remember(page_zone(page), page);
 	__remove_from_page_cache(page);
 	write_unlock_irq(&mapping->tree_lock);
 	__put_page(page);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux