include/linux/mm_lru_policy.h | 3 +++ include/linux/mm_page_replace.h | 2 ++ mm/memory.c | 24 ++++++++++++++++++++++++ mm/swapfile.c | 13 +++++++++++-- mm/vmscan.c | 2 ++ 5 files changed, 42 insertions(+), 2 deletions(-) Index: linux-2.6-uml/include/linux/mm_lru_policy.h =================================================================== --- linux-2.6-uml.orig/include/linux/mm_lru_policy.h 2006-02-23 22:02:30.000000000 +0100 +++ linux-2.6-uml/include/linux/mm_lru_policy.h 2006-02-23 22:02:32.000000000 +0100 @@ -71,6 +71,9 @@ static inline void __page_replace_rotate } } +#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-uml/include/linux/mm_page_replace.h =================================================================== --- linux-2.6-uml.orig/include/linux/mm_page_replace.h 2006-02-23 22:02:25.000000000 +0100 +++ linux-2.6-uml/include/linux/mm_page_replace.h 2006-02-23 22:02:32.000000000 +0100 @@ -62,6 +62,8 @@ extern void page_replace_reinsert(struct extern void page_replace_reinsert_zone(struct zone *, struct list_head *, int); /* void page_replace_remove(struct zone *, struct page *); */ /* void __page_replace_rotate_reclaimable(struct zone *, 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-uml/mm/memory.c =================================================================== --- linux-2.6-uml.orig/mm/memory.c 2006-02-23 22:01:45.000000000 +0100 +++ linux-2.6-uml/mm/memory.c 2006-02-23 22:02:32.000000000 +0100 @@ -596,6 +596,27 @@ int copy_page_range(struct mm_struct *ds return 0; } +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); +} + static unsigned long zap_pte_range(struct mmu_gather *tlb, struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, unsigned long end, @@ -611,6 +632,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; } @@ -669,6 +691,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-uml/mm/swapfile.c =================================================================== --- linux-2.6-uml.orig/mm/swapfile.c 2006-02-23 22:01:39.000000000 +0100 +++ linux-2.6-uml/mm/swapfile.c 2006-02-23 22:02:32.000000000 +0100 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -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-uml/mm/vmscan.c =================================================================== --- linux-2.6-uml.orig/mm/vmscan.c 2006-02-23 22:02:25.000000000 +0100 +++ linux-2.6-uml/mm/vmscan.c 2006-02-23 22:02:32.000000000 +0100 @@ -338,6 +338,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); @@ -345,6 +346,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);