Commit 32a7d7c223484fd9b8c5143bdbb08d3146931f1a

Authored by Michal Hocko
Committed by Greg Kroah-Hartman
1 parent a01e1611c0

memcg, shmem: fix shmem migration to use lrucare

commit f5e03a4989e80a86f8b514659dca8539132e6e09 upstream.

It has been reported that 965GM might trigger

  VM_BUG_ON_PAGE(!lrucare && PageLRU(oldpage), oldpage)

in mem_cgroup_migrate when shmem wants to replace a swap cache page
because of shmem_should_replace_page (the page is allocated from an
inappropriate zone).  shmem_replace_page expects that the oldpage is not
on LRU list and calls mem_cgroup_migrate without lrucare.  This is
obviously incorrect because swapcache pages might be on the LRU list
(e.g. swapin readahead page).

Fix this by enabling lrucare for the migration in shmem_replace_page.
Also clarify that lrucare should be used even if one of the pages might
be on LRU list.

The BUG_ON will trigger only when CONFIG_DEBUG_VM is enabled but even
without that the migration code might leave the old page on an
inappropriate memcg' LRU which is not that critical because the page
would get removed with its last reference but it is still confusing.

Fixes: 0a31bc97c80c ("mm: memcontrol: rewrite uncharge API")
Signed-off-by: Michal Hocko <mhocko@suse.cz>
Reported-by: Chris Wilson <chris@chris-wilson.co.uk>
Reported-by: Dave Airlie <airlied@gmail.com>
Acked-by: Hugh Dickins <hughd@google.com>
Acked-by: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 2 changed files with 2 additions and 2 deletions Side-by-side Diff

... ... @@ -6589,7 +6589,7 @@
6589 6589 * mem_cgroup_migrate - migrate a charge to another page
6590 6590 * @oldpage: currently charged page
6591 6591 * @newpage: page to transfer the charge to
6592   - * @lrucare: both pages might be on the LRU already
  6592 + * @lrucare: either or both pages might be on the LRU already
6593 6593 *
6594 6594 * Migrate the charge from @oldpage to @newpage.
6595 6595 *
... ... @@ -1013,7 +1013,7 @@
1013 1013 */
1014 1014 oldpage = newpage;
1015 1015 } else {
1016   - mem_cgroup_migrate(oldpage, newpage, false);
  1016 + mem_cgroup_migrate(oldpage, newpage, true);
1017 1017 lru_cache_add_anon(newpage);
1018 1018 *pagep = newpage;
1019 1019 }