提交 2def7424 编写于 作者: H Hugh Dickins 提交者: Linus Torvalds

mm: page migration use the put_new_page whenever necessary

I don't know of any problem from the way it's used in our current tree,
but there is one defect in page migration's custom put_new_page feature.

An unused newpage is expected to be released with the put_new_page(), but
there was one MIGRATEPAGE_SUCCESS (0) path which released it with
putback_lru_page(): which can be very wrong for a custom pool.

Fixed more easily by resetting put_new_page once it won't be needed, than
by adding a further flag to modify the rc test.
Signed-off-by: NHugh Dickins <hughd@google.com>
Cc: Christoph Lameter <cl@linux.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Rik van Riel <riel@redhat.com>
Acked-by: NVlastimil Babka <vbabka@suse.cz>
Cc: Davidlohr Bueso <dave@stgolabs.net>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Sasha Levin <sasha.levin@oracle.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 14e0f9bc
...@@ -938,10 +938,11 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page, ...@@ -938,10 +938,11 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page,
int force, enum migrate_mode mode, int force, enum migrate_mode mode,
enum migrate_reason reason) enum migrate_reason reason)
{ {
int rc = 0; int rc = MIGRATEPAGE_SUCCESS;
int *result = NULL; int *result = NULL;
struct page *newpage = get_new_page(page, private, &result); struct page *newpage;
newpage = get_new_page(page, private, &result);
if (!newpage) if (!newpage)
return -ENOMEM; return -ENOMEM;
...@@ -955,6 +956,8 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page, ...@@ -955,6 +956,8 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page,
goto out; goto out;
rc = __unmap_and_move(page, newpage, force, mode); rc = __unmap_and_move(page, newpage, force, mode);
if (rc == MIGRATEPAGE_SUCCESS)
put_new_page = NULL;
out: out:
if (rc != -EAGAIN) { if (rc != -EAGAIN) {
...@@ -981,7 +984,7 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page, ...@@ -981,7 +984,7 @@ static ICE_noinline int unmap_and_move(new_page_t get_new_page,
* it. Otherwise, putback_lru_page() will drop the reference grabbed * it. Otherwise, putback_lru_page() will drop the reference grabbed
* during isolation. * during isolation.
*/ */
if (rc != MIGRATEPAGE_SUCCESS && put_new_page) { if (put_new_page) {
ClearPageSwapBacked(newpage); ClearPageSwapBacked(newpage);
put_new_page(newpage, private); put_new_page(newpage, private);
} else if (unlikely(__is_movable_balloon_page(newpage))) { } else if (unlikely(__is_movable_balloon_page(newpage))) {
...@@ -1022,7 +1025,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, ...@@ -1022,7 +1025,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
struct page *hpage, int force, struct page *hpage, int force,
enum migrate_mode mode) enum migrate_mode mode)
{ {
int rc = 0; int rc = -EAGAIN;
int *result = NULL; int *result = NULL;
int page_was_mapped = 0; int page_was_mapped = 0;
struct page *new_hpage; struct page *new_hpage;
...@@ -1044,8 +1047,6 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, ...@@ -1044,8 +1047,6 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
if (!new_hpage) if (!new_hpage)
return -ENOMEM; return -ENOMEM;
rc = -EAGAIN;
if (!trylock_page(hpage)) { if (!trylock_page(hpage)) {
if (!force || mode != MIGRATE_SYNC) if (!force || mode != MIGRATE_SYNC)
goto out; goto out;
...@@ -1070,8 +1071,10 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, ...@@ -1070,8 +1071,10 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
if (anon_vma) if (anon_vma)
put_anon_vma(anon_vma); put_anon_vma(anon_vma);
if (rc == MIGRATEPAGE_SUCCESS) if (rc == MIGRATEPAGE_SUCCESS) {
hugetlb_cgroup_migrate(hpage, new_hpage); hugetlb_cgroup_migrate(hpage, new_hpage);
put_new_page = NULL;
}
unlock_page(hpage); unlock_page(hpage);
out: out:
...@@ -1083,7 +1086,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page, ...@@ -1083,7 +1086,7 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
* it. Otherwise, put_page() will drop the reference grabbed during * it. Otherwise, put_page() will drop the reference grabbed during
* isolation. * isolation.
*/ */
if (rc != MIGRATEPAGE_SUCCESS && put_new_page) if (put_new_page)
put_new_page(new_hpage, private); put_new_page(new_hpage, private);
else else
putback_active_hugepage(new_hpage); putback_active_hugepage(new_hpage);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册