diff options
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 67a71191136e..38633864a93e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -2008,7 +2008,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2008 | entry = huge_ptep_get(ptep); | 2008 | entry = huge_ptep_get(ptep); |
2009 | if (huge_pte_none(entry)) { | 2009 | if (huge_pte_none(entry)) { |
2010 | ret = hugetlb_no_page(mm, vma, address, ptep, write_access); | 2010 | ret = hugetlb_no_page(mm, vma, address, ptep, write_access); |
2011 | goto out_unlock; | 2011 | goto out_mutex; |
2012 | } | 2012 | } |
2013 | 2013 | ||
2014 | ret = 0; | 2014 | ret = 0; |
@@ -2024,7 +2024,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2024 | if (write_access && !pte_write(entry)) { | 2024 | if (write_access && !pte_write(entry)) { |
2025 | if (vma_needs_reservation(h, vma, address) < 0) { | 2025 | if (vma_needs_reservation(h, vma, address) < 0) { |
2026 | ret = VM_FAULT_OOM; | 2026 | ret = VM_FAULT_OOM; |
2027 | goto out_unlock; | 2027 | goto out_mutex; |
2028 | } | 2028 | } |
2029 | 2029 | ||
2030 | if (!(vma->vm_flags & VM_SHARED)) | 2030 | if (!(vma->vm_flags & VM_SHARED)) |
@@ -2034,10 +2034,23 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2034 | 2034 | ||
2035 | spin_lock(&mm->page_table_lock); | 2035 | spin_lock(&mm->page_table_lock); |
2036 | /* Check for a racing update before calling hugetlb_cow */ | 2036 | /* Check for a racing update before calling hugetlb_cow */ |
2037 | if (likely(pte_same(entry, huge_ptep_get(ptep)))) | 2037 | if (unlikely(!pte_same(entry, huge_ptep_get(ptep)))) |
2038 | if (write_access && !pte_write(entry)) | 2038 | goto out_page_table_lock; |
2039 | |||
2040 | |||
2041 | if (write_access) { | ||
2042 | if (!pte_write(entry)) { | ||
2039 | ret = hugetlb_cow(mm, vma, address, ptep, entry, | 2043 | ret = hugetlb_cow(mm, vma, address, ptep, entry, |
2040 | pagecache_page); | 2044 | pagecache_page); |
2045 | goto out_page_table_lock; | ||
2046 | } | ||
2047 | entry = pte_mkdirty(entry); | ||
2048 | } | ||
2049 | entry = pte_mkyoung(entry); | ||
2050 | if (huge_ptep_set_access_flags(vma, address, ptep, entry, write_access)) | ||
2051 | update_mmu_cache(vma, address, entry); | ||
2052 | |||
2053 | out_page_table_lock: | ||
2041 | spin_unlock(&mm->page_table_lock); | 2054 | spin_unlock(&mm->page_table_lock); |
2042 | 2055 | ||
2043 | if (pagecache_page) { | 2056 | if (pagecache_page) { |
@@ -2045,7 +2058,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, | |||
2045 | put_page(pagecache_page); | 2058 | put_page(pagecache_page); |
2046 | } | 2059 | } |
2047 | 2060 | ||
2048 | out_unlock: | 2061 | out_mutex: |
2049 | mutex_unlock(&hugetlb_instantiation_mutex); | 2062 | mutex_unlock(&hugetlb_instantiation_mutex); |
2050 | 2063 | ||
2051 | return ret; | 2064 | return ret; |