diff options
author | Joel Stanley <joel@jms.id.au> | 2018-11-27 08:23:56 +0300 |
---|---|---|
committer | Joel Stanley <joel@jms.id.au> | 2018-11-27 08:24:09 +0300 |
commit | d608acfd4ac3fe17f3081bee8fcd4dcd896c2ffa (patch) | |
tree | ade4450a72a2e358a1d2e5cde321de0097fb291c /mm/hugetlb.c | |
parent | 62ccc3924eff37012bd0c227d8b7dc71188fc358 (diff) | |
parent | a9da8725b7a744be3ff0ff44cab2547e4d1e6675 (diff) | |
download | linux-dev-4.18.tar.xz |
Merge tag 'v4.18.20' into dev-4.18dev-4.18
This is the 4.18.20 stable release
Signed-off-by: Joel Stanley <joel@jms.id.au>
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 5b38fbef9441..bf15bd78846b 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3240,7 +3240,7 @@ static int is_hugetlb_entry_hwpoisoned(pte_t pte) int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { - pte_t *src_pte, *dst_pte, entry; + pte_t *src_pte, *dst_pte, entry, dst_entry; struct page *ptepage; unsigned long addr; int cow; @@ -3268,15 +3268,30 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, break; } - /* If the pagetables are shared don't copy or take references */ - if (dst_pte == src_pte) + /* + * If the pagetables are shared don't copy or take references. + * dst_pte == src_pte is the common case of src/dest sharing. + * + * However, src could have 'unshared' and dst shares with + * another vma. If dst_pte !none, this implies sharing. + * Check here before taking page table lock, and once again + * after taking the lock below. + */ + dst_entry = huge_ptep_get(dst_pte); + if ((dst_pte == src_pte) || !huge_pte_none(dst_entry)) continue; dst_ptl = huge_pte_lock(h, dst, dst_pte); src_ptl = huge_pte_lockptr(h, src, src_pte); spin_lock_nested(src_ptl, SINGLE_DEPTH_NESTING); entry = huge_ptep_get(src_pte); - if (huge_pte_none(entry)) { /* skip none entry */ + dst_entry = huge_ptep_get(dst_pte); + if (huge_pte_none(entry) || !huge_pte_none(dst_entry)) { + /* + * Skip if src entry none. Also, skip in the + * unlikely case dst entry !none as this implies + * sharing with another vma. + */ ; } else if (unlikely(is_hugetlb_entry_migration(entry) || is_hugetlb_entry_hwpoisoned(entry))) { |