]> err.no Git - linux-2.6/blobdiff - mm/rmap.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb
[linux-2.6] / mm / rmap.c
index 13fad5fcdf7996eab9812d5cb781d9157f8cc55e..d8ce5ff6145492469a3b81640946fca58d7e8002 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -206,6 +206,44 @@ out:
        return anon_vma;
 }
 
+#ifdef CONFIG_MIGRATION
+/*
+ * Remove an anonymous page from swap replacing the swap pte's
+ * through real pte's pointing to valid pages and then releasing
+ * the page from the swap cache.
+ *
+ * Must hold page lock on page and mmap_sem of one vma that contains
+ * the page.
+ */
+void remove_from_swap(struct page *page)
+{
+       struct anon_vma *anon_vma;
+       struct vm_area_struct *vma;
+       unsigned long mapping;
+
+       if (!PageSwapCache(page))
+               return;
+
+       mapping = (unsigned long)page->mapping;
+
+       if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0)
+               return;
+
+       /*
+        * We hold the mmap_sem lock. So no need to call page_lock_anon_vma.
+        */
+       anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON);
+       spin_lock(&anon_vma->lock);
+
+       list_for_each_entry(vma, &anon_vma->head, anon_vma_node)
+               remove_vma_swap(vma, page);
+
+       spin_unlock(&anon_vma->lock);
+       delete_from_swap_cache(page);
+}
+EXPORT_SYMBOL(remove_from_swap);
+#endif
+
 /*
  * At what user virtual address is page expected in vma?
  */