I want to be able to remove a page from page cache so that next access to this page (by any process) will trigger a page fault. I'm doing this from the kernel, and I have a pointer to struct page
I wish to remove.
Deleting from page cache is easy (done by __delete_from_page_cache()
), but I don't know how to "unmap" this page from all processes mapping it into their VMAs. I tried using try_to_unmap(my_page, cpu_page, TTU_UNMAP|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS)
from rmap.c
but it doesn't seem to do what I want it to.
Any help is highly appreciated.
Thank you!
Asked
Active
Viewed 872 times
3

Hadi Brais
- 22,259
- 3
- 54
- 95

Tanya Linder
- 31
- 2
-
Shouldn't you call `delete_from_page_cache` instead of `__delete_from_page_cache` to get the lock on the page tree? I suppose `try_to_unmap` is returning `false` then, right? Which Linux kernel version are you using? – Hadi Brais Apr 18 '18 at 01:10
-
Hi Hadi. Thank you for your advise. You might be right about using delete_from_page_cache() and not __delete_from_page_cache(), I will look into it. I don't think it will solve my problem though since the page is deleted from cache (at the end of the run I try to delete it again and get a warning it is not there). try_to_unmap() doesn't fail but I when after calling it and trying to access same page from other process mapping it, I don't get a page fault. I'm using ubuntu with linux 4.4.15 which I modified. – Tanya Linder Apr 18 '18 at 04:42
-
It doesn't seem to me that these functions are the right entry points because they don't acquire the page lock. I think that something similar to [shrink_page_list](https://elixir.bootlin.com/linux/v4.4.15/source/mm/vmscan.c#L880) needs to be done. The major steps are the following. First a lock is acquired on the page descriptor by calling `trylock_page` (which is absolutely critical for correctness)... – Hadi Brais Apr 18 '18 at 16:50
-
...Second, `try_to_unmap` is called to unmap the page from address spaces (you can pass these flags though `TTU_UNMAP | TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS`). Different things need to be done depending on the result of that operation. Then, assuming the result was `SWAP_SUCCESS`, if the page is dirty, flush the TLBs of all cores, and write it back if required. Finally, the page is removed from the swap cache. The closest that I could find for removing pages from the page cache is `invalidate_mapping_pages`, which removes a range of pages, not just one... – Hadi Brais Apr 18 '18 at 16:51
-
...But the important part is calling `invalidate_inode_page` in a critical section guarded by the page lock. It is this function that eventually calls `__delete_from_page_cache`. However, it does not handle cases where the page is dirty, locked, under writeback or mapped into pagetables. So have to handle these cases similar to what's done in `shrink_page_list`. For example, you have to call `try_to_unmap` before attempting to remove the page from the cache. – Hadi Brais Apr 18 '18 at 16:51
-
thank you very much for the detailed reply!!! I will try to follow your advise and see if it works. – Tanya Linder Apr 19 '18 at 07:08