[PATCH] oom: cpuset hint
[linux-2.6-microblaze.git] / mm / rmap.c
index 882a858..e2155d7 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -434,6 +434,71 @@ int page_referenced(struct page *page, int is_locked)
        return referenced;
 }
 
+static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       unsigned long address;
+       pte_t *pte, entry;
+       spinlock_t *ptl;
+       int ret = 0;
+
+       address = vma_address(page, vma);
+       if (address == -EFAULT)
+               goto out;
+
+       pte = page_check_address(page, mm, address, &ptl);
+       if (!pte)
+               goto out;
+
+       if (!pte_dirty(*pte) && !pte_write(*pte))
+               goto unlock;
+
+       entry = ptep_get_and_clear(mm, address, pte);
+       entry = pte_mkclean(entry);
+       entry = pte_wrprotect(entry);
+       ptep_establish(vma, address, pte, entry);
+       lazy_mmu_prot_update(entry);
+       ret = 1;
+
+unlock:
+       pte_unmap_unlock(pte, ptl);
+out:
+       return ret;
+}
+
+static int page_mkclean_file(struct address_space *mapping, struct page *page)
+{
+       pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
+       struct vm_area_struct *vma;
+       struct prio_tree_iter iter;
+       int ret = 0;
+
+       BUG_ON(PageAnon(page));
+
+       spin_lock(&mapping->i_mmap_lock);
+       vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
+               if (vma->vm_flags & VM_SHARED)
+                       ret += page_mkclean_one(page, vma);
+       }
+       spin_unlock(&mapping->i_mmap_lock);
+       return ret;
+}
+
+int page_mkclean(struct page *page)
+{
+       int ret = 0;
+
+       BUG_ON(!PageLocked(page));
+
+       if (page_mapped(page)) {
+               struct address_space *mapping = page_mapping(page);
+               if (mapping)
+                       ret = page_mkclean_file(mapping, page);
+       }
+
+       return ret;
+}
+
 /**
  * page_set_anon_rmap - setup new anonymous rmap
  * @page:      the page to add the mapping to
@@ -455,7 +520,7 @@ static void __page_set_anon_rmap(struct page *page,
         * nr_mapped state can be updated without turning off
         * interrupts because it is not modified via interrupt.
         */
-       __inc_page_state(nr_mapped);
+       __inc_zone_page_state(page, NR_ANON_PAGES);
 }
 
 /**
@@ -499,7 +564,7 @@ void page_add_new_anon_rmap(struct page *page,
 void page_add_file_rmap(struct page *page)
 {
        if (atomic_inc_and_test(&page->_mapcount))
-               __inc_page_state(nr_mapped);
+               __inc_zone_page_state(page, NR_FILE_MAPPED);
 }
 
 /**
@@ -531,7 +596,8 @@ void page_remove_rmap(struct page *page)
                 */
                if (page_test_and_clear_dirty(page))
                        set_page_dirty(page);
-               __dec_page_state(nr_mapped);
+               __dec_zone_page_state(page,
+                               PageAnon(page) ? NR_ANON_PAGES : NR_FILE_MAPPED);
        }
 }
 
@@ -562,9 +628,8 @@ static int try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * If it's recently referenced (perhaps page_referenced
         * skipped over this mm) then we should reactivate it.
         */
-       if ((vma->vm_flags & VM_LOCKED) ||
-                       (ptep_clear_flush_young(vma, address, pte)
-                               && !migration)) {
+       if (!migration && ((vma->vm_flags & VM_LOCKED) ||
+                       (ptep_clear_flush_young(vma, address, pte)))) {
                ret = SWAP_FAIL;
                goto out_unmap;
        }
@@ -771,7 +836,7 @@ static int try_to_unmap_file(struct page *page, int migration)
 
        list_for_each_entry(vma, &mapping->i_mmap_nonlinear,
                                                shared.vm_set.list) {
-               if (vma->vm_flags & VM_LOCKED)
+               if ((vma->vm_flags & VM_LOCKED) && !migration)
                        continue;
                cursor = (unsigned long) vma->vm_private_data;
                if (cursor > max_nl_cursor)
@@ -805,7 +870,7 @@ static int try_to_unmap_file(struct page *page, int migration)
        do {
                list_for_each_entry(vma, &mapping->i_mmap_nonlinear,
                                                shared.vm_set.list) {
-                       if (vma->vm_flags & VM_LOCKED)
+                       if ((vma->vm_flags & VM_LOCKED) && !migration)
                                continue;
                        cursor = (unsigned long) vma->vm_private_data;
                        while ( cursor < max_nl_cursor &&