page_mapped_in_vma() really just wants to walk one page, but as the code stands, if passed the head page of a compound page, it will walk every page in the compound page. Extract pfn/nr_pages/pgoff from the struct page early, so they can be overridden by page_mapped_in_vma().
Showing the changes to include (2 of 6 files). Show all
Unified · Split
| @@ -970,6 +970,11 @@ static inline struct hstate *page_hstate(struct page *page) · 969 unmodified lines | |||
| 970 | return NULL; | 970 | return NULL; |
| 971 | } | 971 | } |
| 972 | 972 | ||
| 973 | static inline struct hstate *size_to_hstate(unsigned long size) | ||
| 974 | { | ||
| 975 | return NULL; | ||
| 976 | } | ||
| 977 | |||
| 973 | static inline unsigned long huge_page_size(struct hstate *h) | 978 | static inline unsigned long huge_page_size(struct hstate *h) |
| 974 | { | 979 | { |
| 975 | return PAGE_SIZE; | 980 | return PAGE_SIZE; |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | |||
| 11 | #include <linux/rwsem.h> | 11 | #include <linux/rwsem.h> |
| 12 | #include <linux/memcontrol.h> | 12 | #include <linux/memcontrol.h> |
| 13 | #include <linux/highmem.h> | 13 | #include <linux/highmem.h> |
| 14 | #include <linux/pagemap.h> | ||
| 14 | 15 | ||
| 15 | /* | 16 | /* |
| 16 | * The anon_vma heads a list of private "related" vmas, to scan if | 17 | * The anon_vma heads a list of private "related" vmas, to scan if |
| @@ -201,11 +202,13 @@ int make_device_exclusive_range(struct mm_struct *mm, unsigned long start, · 184 unmodified lines | |||
| 201 | 202 | ||
| 202 | /* Avoid racy checks */ | 203 | /* Avoid racy checks */ |
| 203 | #define PVMW_SYNC (1 << 0) | 204 | #define PVMW_SYNC (1 << 0) |
| 204 | /* Look for migarion entries rather than present PTEs */ | 205 | /* Look for migration entries rather than present PTEs */ |
| 205 | #define PVMW_MIGRATION (1 << 1) | 206 | #define PVMW_MIGRATION (1 << 1) |
| 206 | 207 | ||
| 207 | struct page_vma_mapped_walk { | 208 | struct page_vma_mapped_walk { |
| 208 | struct page *page; | 209 | unsigned long pfn; |
| 210 | unsigned long nr_pages; | ||
| 211 | pgoff_t pgoff; | ||
| 209 | struct vm_area_struct *vma; | 212 | struct vm_area_struct *vma; |
| 210 | unsigned long address; | 213 | unsigned long address; |
| 211 | pmd_t *pmd; | 214 | pmd_t *pmd; |
| @@ -216,7 +219,9 @@ struct page_vma_mapped_walk { · 4 unmodified lines | |||
| 216 | 219 | ||
| 217 | #define DEFINE_PAGE_VMA_WALK(name, _page, _vma, _address, _flags) \ | 220 | #define DEFINE_PAGE_VMA_WALK(name, _page, _vma, _address, _flags) \ |
| 218 | struct page_vma_mapped_walk name = { \ | 221 | struct page_vma_mapped_walk name = { \ |
| 219 | .page = _page, \ | 222 | .pfn = page_to_pfn(_page), \ |
| 223 | .nr_pages = compound_nr(page), \ | ||
| 224 | .pgoff = page_to_pgoff(page), \ | ||
| 220 | .vma = _vma, \ | 225 | .vma = _vma, \ |
| 221 | .address = _address, \ | 226 | .address = _address, \ |
| 222 | .flags = _flags, \ | 227 | .flags = _flags, \ |
| @@ -224,7 +229,9 @@ struct page_vma_mapped_walk { · 1 unmodified line | |||
| 224 | 229 | ||
| 225 | #define DEFINE_FOLIO_VMA_WALK(name, _folio, _vma, _address, _flags) \ | 230 | #define DEFINE_FOLIO_VMA_WALK(name, _folio, _vma, _address, _flags) \ |
| 226 | struct page_vma_mapped_walk name = { \ | 231 | struct page_vma_mapped_walk name = { \ |
| 227 | .page = &_folio->page, \ | 232 | .pfn = folio_pfn(_folio), \ |
| 233 | .nr_pages = folio_nr_pages(_folio), \ | ||
| 234 | .pgoff = folio_pgoff(_folio), \ | ||
| 228 | .vma = _vma, \ | 235 | .vma = _vma, \ |
| 229 | .address = _address, \ | 236 | .address = _address, \ |
| 230 | .flags = _flags, \ | 237 | .flags = _flags, \ |
| @@ -233,7 +240,7 @@ struct page_vma_mapped_walk { · 2 unmodified lines | |||
| 233 | static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw) | 240 | static inline void page_vma_mapped_walk_done(struct page_vma_mapped_walk *pvmw) |
| 234 | { | 241 | { |
| 235 | /* HugeTLB pte is set to the relevant page table entry without pte_mapped. */ | 242 | /* HugeTLB pte is set to the relevant page table entry without pte_mapped. */ |
| 236 | if (pvmw->pte && !PageHuge(pvmw->page)) | 243 | if (pvmw->pte && !is_vm_hugetlb_page(pvmw->vma)) |
| 237 | pte_unmap(pvmw->pte); | 244 | pte_unmap(pvmw->pte); |
| 238 | if (pvmw->ptl) | 245 | if (pvmw->ptl) |
| 239 | spin_unlock(pvmw->ptl); | 246 | spin_unlock(pvmw->ptl); |