mm: fix swapops.h:131 bug if remap_file_pages raced migration
Add remove_linear_migration_ptes_from_nonlinear(), to fix an interesting little include/linux/swapops.h:131 BUG_ON(!PageLocked) found by trinity: indicating that remove_migration_ptes() failed to find one of the migration entries that was temporarily inserted. The problem comes from remap_file_pages()'s switch from vma_interval_tree (good for inserting the migration entry) to i_mmap_nonlinear list (no good for locating it again); but can only be a problem if the remap_file_pages() range does not cover the whole of the vma (zap_pte() clears the range). remove_migration_ptes() needs a file_nonlinear method to go down the i_mmap_nonlinear list, applying linear location to look for migration entries in those vmas too, just in case there was this race. The file_nonlinear method does need rmap_walk_control.arg to do this; but it never needed vma passed in - vma comes from its own iteration. Reported-and-tested-by: Dave Jones <davej@redhat.com> Reported-and-tested-by: Sasha Levin <sasha.levin@oracle.com> Signed-off-by: Hugh Dickins <hughd@google.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
3fb725c48b
commit
7e09e738af
3 changed files with 36 additions and 4 deletions
|
@ -1360,8 +1360,9 @@ static int try_to_unmap_cluster(unsigned long cursor, unsigned int *mapcount,
|
|||
}
|
||||
|
||||
static int try_to_unmap_nonlinear(struct page *page,
|
||||
struct address_space *mapping, struct vm_area_struct *vma)
|
||||
struct address_space *mapping, void *arg)
|
||||
{
|
||||
struct vm_area_struct *vma;
|
||||
int ret = SWAP_AGAIN;
|
||||
unsigned long cursor;
|
||||
unsigned long max_nl_cursor = 0;
|
||||
|
@ -1663,7 +1664,7 @@ static int rmap_walk_file(struct page *page, struct rmap_walk_control *rwc)
|
|||
if (list_empty(&mapping->i_mmap_nonlinear))
|
||||
goto done;
|
||||
|
||||
ret = rwc->file_nonlinear(page, mapping, vma);
|
||||
ret = rwc->file_nonlinear(page, mapping, rwc->arg);
|
||||
|
||||
done:
|
||||
mutex_unlock(&mapping->i_mmap_mutex);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue