diff options
author | Kirill A. Shutemov <kirill.shutemov@linux.intel.com> | 2016-11-30 18:54:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-30 19:32:52 -0500 |
commit | 5cbc198ae08d84bd416b672ad8bd1222acd0855c (patch) | |
tree | 985d1c3e96076aaca0f485d26f04b9957f920013 /include/linux/pagemap.h | |
parent | 828347f8f9a558cf1af2faa46387a26564f2ac3e (diff) |
mm: fix false-positive WARN_ON() in truncate/invalidate for hugetlb
Hugetlb pages have ->index in size of the huge pages (PMD_SIZE or
PUD_SIZE), not in PAGE_SIZE as other types of pages. This means we
cannot user page_to_pgoff() to check whether we've got the right page
for the radix-tree index.
Let's introduce page_to_index() which would return radix-tree index for
given page.
We will be able to get rid of this once hugetlb will be switched to
multi-order entries.
Fixes: fc127da085c2 ("truncate: handle file thp")
Link: http://lkml.kernel.org/r/20161123093053.mjbnvn5zwxw5e6lk@black.fi.intel.com
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reported-by: Doug Nelson <doug.nelson@intel.com>
Tested-by: Doug Nelson <doug.nelson@intel.com>
Reviewed-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Cc: <stable@vger.kernel.org> [4.8+]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/pagemap.h')
-rw-r--r-- | include/linux/pagemap.h | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index dd15d39e1985..7dbe9148b2f8 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h | |||
@@ -374,16 +374,13 @@ static inline struct page *read_mapping_page(struct address_space *mapping, | |||
374 | } | 374 | } |
375 | 375 | ||
376 | /* | 376 | /* |
377 | * Get the offset in PAGE_SIZE. | 377 | * Get index of the page with in radix-tree |
378 | * (TODO: hugepage should have ->index in PAGE_SIZE) | 378 | * (TODO: remove once hugetlb pages will have ->index in PAGE_SIZE) |
379 | */ | 379 | */ |
380 | static inline pgoff_t page_to_pgoff(struct page *page) | 380 | static inline pgoff_t page_to_index(struct page *page) |
381 | { | 381 | { |
382 | pgoff_t pgoff; | 382 | pgoff_t pgoff; |
383 | 383 | ||
384 | if (unlikely(PageHeadHuge(page))) | ||
385 | return page->index << compound_order(page); | ||
386 | |||
387 | if (likely(!PageTransTail(page))) | 384 | if (likely(!PageTransTail(page))) |
388 | return page->index; | 385 | return page->index; |
389 | 386 | ||
@@ -397,6 +394,18 @@ static inline pgoff_t page_to_pgoff(struct page *page) | |||
397 | } | 394 | } |
398 | 395 | ||
399 | /* | 396 | /* |
397 | * Get the offset in PAGE_SIZE. | ||
398 | * (TODO: hugepage should have ->index in PAGE_SIZE) | ||
399 | */ | ||
400 | static inline pgoff_t page_to_pgoff(struct page *page) | ||
401 | { | ||
402 | if (unlikely(PageHeadHuge(page))) | ||
403 | return page->index << compound_order(page); | ||
404 | |||
405 | return page_to_index(page); | ||
406 | } | ||
407 | |||
408 | /* | ||
400 | * Return byte-offset into filesystem object for page. | 409 | * Return byte-offset into filesystem object for page. |
401 | */ | 410 | */ |
402 | static inline loff_t page_offset(struct page *page) | 411 | static inline loff_t page_offset(struct page *page) |