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;
--
I don't understand how this is intended to work. I think the page flag
needs to be maintained by the mmu_notifier subsystem.
Let's assume we have a mapping that has a grant from xpmem and an
additional grant from kvm. The exporters are not important, the fact
that there may be two is.
Assume that the user revokes the grant from xpmem (we call that
xpmem_remove). As far as xpmem is concerned, there are no longer any
exports of that page so the page should no longer have its exported
flag set. Note: This is not a process exit, but a function of xpmem.
In that case, at the remove time, we have no idea whether the flag should
be cleared.
For the invalidate_page side, I think we should have:
> @@ -473,6 +474,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))) {
> + mmu_rmap_notifier(invalidate_page, page);
> + ClearPageExternalRmap(page);
> + }
> if (page_test_dirty(page)) {
> page_clear_dirty(page);
> ret = 1;
I would assume we would then want a function which sets the page flag.
Additionally, I would think we would want some intervention in the
freeing of the page side to ensure the page flag is cleared as well.
Thanks,
Robin