mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-31 04:01:48 -04:00
ksm: let shared pages be swappable
Initial implementation for swapping out KSM's shared pages: add page_referenced_ksm() and try_to_unmap_ksm(), which rmap.c calls when faced with a PageKsm page. Most of what's needed can be got from the rmap_items listed from the stable_node of the ksm page, without discovering the actual vma: so in this patch just fake up a struct vma for page_referenced_one() or try_to_unmap_one(), then refine that in the next patch. Add VM_NONLINEAR to ksm_madvise()'s list of exclusions: it has always been implicit there (being only set with VM_SHARED, already excluded), but let's make it explicit, to help justify the lack of nonlinear unmap. Rely on the page lock to protect against concurrent modifications to that page's node of the stable tree. The awkward part is not swapout but swapin: do_swap_page() and page_add_anon_rmap() now have to allow for new possibilities - perhaps a ksm page still in swapcache, perhaps a swapcache page associated with one location in one anon_vma now needed for another location or anon_vma. (And the vma might even be no longer VM_MERGEABLE when that happens.) ksm_might_need_to_copy() checks for that case, and supplies a duplicate page when necessary, simply leaving it to a subsequent pass of ksmd to rediscover the identity and merge them back into one ksm page. Disappointingly primitive: but the alternative would have to accumulate unswappable info about the swapped out ksm pages, limiting swappability. Remove page_add_ksm_rmap(): page_add_anon_rmap() now has to allow for the particular case it was handling, so just use it instead. Signed-off-by: Hugh Dickins <[email protected]> Cc: Izik Eidus <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Chris Wright <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
73848b4684
commit
5ad6468801
6 changed files with 264 additions and 49 deletions
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/seq_file.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ksm.h>
|
||||
#include <linux/rmap.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/backing-dev.h>
|
||||
|
|
@ -650,6 +651,8 @@ int reuse_swap_page(struct page *page)
|
|||
int count;
|
||||
|
||||
VM_BUG_ON(!PageLocked(page));
|
||||
if (unlikely(PageKsm(page)))
|
||||
return 0;
|
||||
count = page_mapcount(page);
|
||||
if (count <= 1 && PageSwapCache(page)) {
|
||||
count += page_swapcount(page);
|
||||
|
|
@ -658,7 +661,7 @@ int reuse_swap_page(struct page *page)
|
|||
SetPageDirty(page);
|
||||
}
|
||||
}
|
||||
return count == 1;
|
||||
return count <= 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1185,6 +1188,12 @@ static int try_to_unuse(unsigned int type)
|
|||
* read from disk into another page. Splitting into two
|
||||
* pages would be incorrect if swap supported "shared
|
||||
* private" pages, but they are handled by tmpfs files.
|
||||
*
|
||||
* Given how unuse_vma() targets one particular offset
|
||||
* in an anon_vma, once the anon_vma has been determined,
|
||||
* this splitting happens to be just what is needed to
|
||||
* handle where KSM pages have been swapped out: re-reading
|
||||
* is unnecessarily slow, but we can fix that later on.
|
||||
*/
|
||||
if (swap_count(*swap_map) &&
|
||||
PageDirty(page) && PageSwapCache(page)) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue