3

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!

Hadi Brais
  • 22,259
  • 3
  • 54
  • 95
  • 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

0 Answers0