Re: [PATCH] thp: move preallocated PTE page table on move_huge_pmd()

2013-12-04 Thread Andrey Wagin
2013/12/4 Kirill A. Shutemov :
> Andrey Wagin reported crash on VM_BUG_ON() in pgtable_pmd_page_dtor()
> with fallowing backtrace:
>
>   [] free_pgd_range+0x2bf/0x410
>   [] free_pgtables+0xce/0x120
>   [] unmap_region+0xe0/0x120
>   [] ? move_page_tables+0x526/0x6b0
>   [] do_munmap+0x249/0x360
>   [] move_vma+0x144/0x270
>   [] SyS_mremap+0x3b9/0x510
>   [] system_call_fastpath+0x16/0x1b
>
> The crash can be reproduce with this test case:
>
>   #define _GNU_SOURCE
>   #include 
>   #include 
>   #include 
>
>   #define MB (1024 * 1024UL)
>   #define GB (1024 * MB)
>
>   int main(int argc, char **argv)
>   {
> char *p;
> int i;
>
> p = mmap((void *) GB, 10 * MB, PROT_READ | PROT_WRITE,
> MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
> for (i = 0; i < 10 * MB; i += 4096)
> p[i] = 1;
> mremap(p, 10 * MB, 10 * MB, MREMAP_FIXED | MREMAP_MAYMOVE, 2 * GB);
> return 0;
>   }
>
> Due to split PMD lock, we now store preallocated PTE tables for THP
> pages per-PMD table.  It means we need to move them to other PMD table
> if huge PMD moved there.
>
> Signed-off-by: Kirill A. Shutemov 
> Reported-by: Andrey Vagin 

My tests were working for the night without any problem.  Thanks for
the quick response.

Tested-by: Andrey Vagin 

> ---
>  mm/huge_memory.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
>
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index bccd5a628ea6..33a5dc492810 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1481,8 +1481,18 @@ int move_huge_pmd(struct vm_area_struct *vma, struct 
> vm_area_struct *new_vma,
> pmd = pmdp_get_and_clear(mm, old_addr, old_pmd);
> VM_BUG_ON(!pmd_none(*new_pmd));
> set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
> -   if (new_ptl != old_ptl)
> +   if (new_ptl != old_ptl) {
> +   pgtable_t pgtable;
> +
> +   /*
> +* Move preallocated PTE page table if new_pmd is on
> +* different PMD page table.
> +*/
> +   pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
> +   pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
> +
> spin_unlock(new_ptl);
> +   }
> spin_unlock(old_ptl);
> }
>  out:
> --
> 1.8.4.4
>
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] thp: move preallocated PTE page table on move_huge_pmd()

2013-12-04 Thread Naoya Horiguchi
On Wed, Dec 04, 2013 at 09:03:06PM +0200, Kirill A. Shutemov wrote:
> Andrey Wagin reported crash on VM_BUG_ON() in pgtable_pmd_page_dtor()
> with fallowing backtrace:
> 
>   [] free_pgd_range+0x2bf/0x410
>   [] free_pgtables+0xce/0x120
>   [] unmap_region+0xe0/0x120
>   [] ? move_page_tables+0x526/0x6b0
>   [] do_munmap+0x249/0x360
>   [] move_vma+0x144/0x270
>   [] SyS_mremap+0x3b9/0x510
>   [] system_call_fastpath+0x16/0x1b
> 
> The crash can be reproduce with this test case:
> 
>   #define _GNU_SOURCE
>   #include 
>   #include 
>   #include 
> 
>   #define MB (1024 * 1024UL)
>   #define GB (1024 * MB)
> 
>   int main(int argc, char **argv)
>   {
>   char *p;
>   int i;
> 
>   p = mmap((void *) GB, 10 * MB, PROT_READ | PROT_WRITE,
>   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
>   for (i = 0; i < 10 * MB; i += 4096)
>   p[i] = 1;
>   mremap(p, 10 * MB, 10 * MB, MREMAP_FIXED | MREMAP_MAYMOVE, 2 * GB);
>   return 0;
>   }
> 
> Due to split PMD lock, we now store preallocated PTE tables for THP
> pages per-PMD table.  It means we need to move them to other PMD table
> if huge PMD moved there.
> 
> Signed-off-by: Kirill A. Shutemov 
> Reported-by: Andrey Vagin 

looks good to me.

Reviewed-by: Naoya Horiguchi 

> ---
>  mm/huge_memory.c | 12 +++-
>  1 file changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/mm/huge_memory.c b/mm/huge_memory.c
> index bccd5a628ea6..33a5dc492810 100644
> --- a/mm/huge_memory.c
> +++ b/mm/huge_memory.c
> @@ -1481,8 +1481,18 @@ int move_huge_pmd(struct vm_area_struct *vma, struct 
> vm_area_struct *new_vma,
>   pmd = pmdp_get_and_clear(mm, old_addr, old_pmd);
>   VM_BUG_ON(!pmd_none(*new_pmd));
>   set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
> - if (new_ptl != old_ptl)
> + if (new_ptl != old_ptl) {
> + pgtable_t pgtable;
> +
> + /*
> +  * Move preallocated PTE page table if new_pmd is on
> +  * different PMD page table.
> +  */
> + pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
> + pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
> +
>   spin_unlock(new_ptl);
> + }
>   spin_unlock(old_ptl);
>   }
>  out:
> -- 
> 1.8.4.4
> 
> --
> To unsubscribe, send a message with 'unsubscribe linux-mm' in
> the body to majord...@kvack.org.  For more info on Linux MM,
> see: http://www.linux-mm.org/ .
> Don't email: mailto:"d...@kvack.org";> em...@kvack.org 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] thp: move preallocated PTE page table on move_huge_pmd()

2013-12-04 Thread Kirill A. Shutemov
Andrey Wagin reported crash on VM_BUG_ON() in pgtable_pmd_page_dtor()
with fallowing backtrace:

  [] free_pgd_range+0x2bf/0x410
  [] free_pgtables+0xce/0x120
  [] unmap_region+0xe0/0x120
  [] ? move_page_tables+0x526/0x6b0
  [] do_munmap+0x249/0x360
  [] move_vma+0x144/0x270
  [] SyS_mremap+0x3b9/0x510
  [] system_call_fastpath+0x16/0x1b

The crash can be reproduce with this test case:

  #define _GNU_SOURCE
  #include 
  #include 
  #include 

  #define MB (1024 * 1024UL)
  #define GB (1024 * MB)

  int main(int argc, char **argv)
  {
char *p;
int i;

p = mmap((void *) GB, 10 * MB, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
for (i = 0; i < 10 * MB; i += 4096)
p[i] = 1;
mremap(p, 10 * MB, 10 * MB, MREMAP_FIXED | MREMAP_MAYMOVE, 2 * GB);
return 0;
  }

Due to split PMD lock, we now store preallocated PTE tables for THP
pages per-PMD table.  It means we need to move them to other PMD table
if huge PMD moved there.

Signed-off-by: Kirill A. Shutemov 
Reported-by: Andrey Vagin 
---
 mm/huge_memory.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index bccd5a628ea6..33a5dc492810 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1481,8 +1481,18 @@ int move_huge_pmd(struct vm_area_struct *vma, struct 
vm_area_struct *new_vma,
pmd = pmdp_get_and_clear(mm, old_addr, old_pmd);
VM_BUG_ON(!pmd_none(*new_pmd));
set_pmd_at(mm, new_addr, new_pmd, pmd_mksoft_dirty(pmd));
-   if (new_ptl != old_ptl)
+   if (new_ptl != old_ptl) {
+   pgtable_t pgtable;
+
+   /*
+* Move preallocated PTE page table if new_pmd is on
+* different PMD page table.
+*/
+   pgtable = pgtable_trans_huge_withdraw(mm, old_pmd);
+   pgtable_trans_huge_deposit(mm, new_pmd, pgtable);
+
spin_unlock(new_ptl);
+   }
spin_unlock(old_ptl);
}
 out:
-- 
1.8.4.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/