]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - mm/hugetlb.c
Merge tag 'for-linus-5.2b-rc4-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / mm / hugetlb.c
index 89d206d6ecf39f33c108ad9adec9db983ca90bee..ac843d32b0193924bd90dc96afc5aae6d35b4102 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * Generic hugetlb support.
  * (C) Nadia Yvette Chambers, April 2004
@@ -740,7 +741,15 @@ void resv_map_release(struct kref *ref)
 
 static inline struct resv_map *inode_resv_map(struct inode *inode)
 {
-       return inode->i_mapping->private_data;
+       /*
+        * At inode evict time, i_mapping may not point to the original
+        * address space within the inode.  This original address space
+        * contains the pointer to the resv_map.  So, always use the
+        * address space embedded within the inode.
+        * The VERY common case is inode->mapping == &inode->i_data but,
+        * this may not be true for device special inodes.
+        */
+       return (struct resv_map *)(&inode->i_data)->private_data;
 }
 
 static struct resv_map *vma_resv_map(struct vm_area_struct *vma)
@@ -3294,7 +3303,7 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
        cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
 
        if (cow) {
-               mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, src,
+               mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, src,
                                        vma->vm_start,
                                        vma->vm_end);
                mmu_notifier_invalidate_range_start(&range);
@@ -3675,7 +3684,7 @@ static vm_fault_t hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma,
                            pages_per_huge_page(h));
        __SetPageUptodate(new_page);
 
-       mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, mm, haddr,
+       mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, mm, haddr,
                                haddr + huge_page_size(h));
        mmu_notifier_invalidate_range_start(&range);
 
@@ -4411,8 +4420,8 @@ unsigned long hugetlb_change_protection(struct vm_area_struct *vma,
         * start/end.  Set range.start/range.end to cover the maximum possible
         * range if PMD sharing is possible.
         */
-       mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0, vma, mm, start,
-                               end);
+       mmu_notifier_range_init(&range, MMU_NOTIFY_PROTECTION_VMA,
+                               0, vma, mm, start, end);
        adjust_range_if_pmd_sharing_possible(vma, &range.start, &range.end);
 
        BUG_ON(address >= end);
@@ -4518,6 +4527,11 @@ int hugetlb_reserve_pages(struct inode *inode,
         * called to make the mapping read-write. Assume !vma is a shm mapping
         */
        if (!vma || vma->vm_flags & VM_MAYSHARE) {
+               /*
+                * resv_map can not be NULL as hugetlb_reserve_pages is only
+                * called for inodes for which resv_maps were created (see
+                * hugetlbfs_get_inode).
+                */
                resv_map = inode_resv_map(inode);
 
                chg = region_chg(resv_map, from, to);
@@ -4609,6 +4623,10 @@ long hugetlb_unreserve_pages(struct inode *inode, long start, long end,
        struct hugepage_subpool *spool = subpool_inode(inode);
        long gbl_reserve;
 
+       /*
+        * Since this routine can be called in the evict inode path for all
+        * hugetlbfs inodes, resv_map could be NULL.
+        */
        if (resv_map) {
                chg = region_del(resv_map, start, end);
                /*