Callbacks to remove individual pages if the subsystem has an
rmap capability. The pagelock is held but no spinlocks are held.
The refcount of the page is elevated so that dropping the refcount
in the subsystem will not directly free the page.
The callbacks occur after the Linux rmaps have been walked.
Signed-off-by: Christoph Lameter <[email protected]>
---
mm/rmap.c | 6 ++++++
1 file changed, 6 insertions(+)
Index: linux-2.6/mm/rmap.c
===================================================================
--- linux-2.6.orig/mm/rmap.c 2008-01-25 14:24:19.000000000 -0800
+++ linux-2.6/mm/rmap.c 2008-01-25 14:24:38.000000000 -0800
@@ -49,6 +49,7 @@
#include <linux/rcupdate.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
+#include <linux/mmu_notifier.h>
#include <asm/tlbflush.h>
@@ -473,6 +474,8 @@ int page_mkclean(struct page *page)
struct address_space *mapping = page_mapping(page);
if (mapping) {
ret = page_mkclean_file(mapping, page);
+ if (unlikely(PageExternalRmap(page)))
+ mmu_rmap_notifier(invalidate_page, page);
if (page_test_dirty(page)) {
page_clear_dirty(page);
ret = 1;
@@ -971,6 +974,9 @@ int try_to_unmap(struct page *page, int
else
ret = try_to_unmap_file(page, migration);
+ if (unlikely(PageExternalRmap(page)))
+ mmu_rmap_notifier(invalidate_page, page);
+
if (!page_mapped(page))
ret = SWAP_SUCCESS;
return ret;
--
This is the second part of a patch posted to patch 1/6.
Index: git-linus/mm/rmap.c
===================================================================
--- git-linus.orig/mm/rmap.c 2008-01-30 11:55:56.000000000 -0600
+++ git-linus/mm/rmap.c 2008-01-30 12:01:28.000000000 -0600
@@ -476,8 +476,10 @@ int page_mkclean(struct page *page)
struct address_space *mapping = page_mapping(page);
if (mapping) {
ret = page_mkclean_file(mapping, page);
- if (unlikely(PageExternalRmap(page)))
+ if (unlikely(PageExternalRmap(page))) {
mmu_rmap_notifier(invalidate_page, page);
+ ClearPageExported(page);
+ }
if (page_test_dirty(page)) {
page_clear_dirty(page);
ret = 1;
@@ -980,8 +982,10 @@ int try_to_unmap(struct page *page, int
else
ret = try_to_unmap_file(page, migration);
- if (unlikely(PageExternalRmap(page)))
+ if (unlikely(PageExternalRmap(page))) {
mmu_rmap_notifier(invalidate_page, page);
+ ClearPageExported(page);
+ }
if (!page_mapped(page))
ret = SWAP_SUCCESS;