mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
mm: try_to_unmap_cluster() should lock_page() before mlocking
commit 57e68e9cd6
upstream.
A BUG_ON(!PageLocked) was triggered in mlock_vma_page() by Sasha Levin
fuzzing with trinity. The call site try_to_unmap_cluster() does not lock
the pages other than its check_page parameter (which is already locked).
The BUG_ON in mlock_vma_page() is not documented and its purpose is
somewhat unclear, but apparently it serializes against page migration,
which could otherwise fail to transfer the PG_mlocked flag. This would
not be fatal, as the page would be eventually encountered again, but
NR_MLOCK accounting would become distorted nevertheless. This patch adds
a comment to the BUG_ON in mlock_vma_page() and munlock_vma_page() to that
effect.
The call site try_to_unmap_cluster() is fixed so that for page !=
check_page, trylock_page() is attempted (to avoid possible deadlocks as we
already have check_page locked) and mlock_vma_page() is performed only
upon success. If the page lock cannot be obtained, the page is left
without PG_mlocked, which is again not a problem in the whole unevictable
memory design.
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Bob Liu <bob.liu@oracle.com>
Reported-by: Sasha Levin <sasha.levin@oracle.com>
Cc: Wanpeng Li <liwanp@linux.vnet.ibm.com>
Cc: Michel Lespinasse <walken@google.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Acked-by: Rik van Riel <riel@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Hugh Dickins <hughd@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Cc: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
9c98268072
commit
21dbd45fb3
2 changed files with 14 additions and 2 deletions
|
@ -78,6 +78,7 @@ void __clear_page_mlock(struct page *page)
|
|||
*/
|
||||
void mlock_vma_page(struct page *page)
|
||||
{
|
||||
/* Serialize with page migration */
|
||||
BUG_ON(!PageLocked(page));
|
||||
|
||||
if (!TestSetPageMlocked(page)) {
|
||||
|
@ -105,6 +106,7 @@ void mlock_vma_page(struct page *page)
|
|||
*/
|
||||
void munlock_vma_page(struct page *page)
|
||||
{
|
||||
/* For try_to_munlock() and to serialize with page migration */
|
||||
BUG_ON(!PageLocked(page));
|
||||
|
||||
if (TestClearPageMlocked(page)) {
|
||||
|
|
14
mm/rmap.c
14
mm/rmap.c
|
@ -1449,9 +1449,19 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
|
|||
BUG_ON(!page || PageAnon(page));
|
||||
|
||||
if (locked_vma) {
|
||||
mlock_vma_page(page); /* no-op if already mlocked */
|
||||
if (page == check_page)
|
||||
if (page == check_page) {
|
||||
/* we know we have check_page locked */
|
||||
mlock_vma_page(page);
|
||||
ret = SWAP_MLOCK;
|
||||
} else if (trylock_page(page)) {
|
||||
/*
|
||||
* If we can lock the page, perform mlock.
|
||||
* Otherwise leave the page alone, it will be
|
||||
* eventually encountered again later.
|
||||
*/
|
||||
mlock_vma_page(page);
|
||||
unlock_page(page);
|
||||
}
|
||||
continue; /* don't unmap */
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue