Skip to content

Commit 5cbc198

Browse files
kiryltorvalds
authored andcommitted
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: fc127da ("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>
1 parent 828347f commit 5cbc198

2 files changed

Lines changed: 19 additions & 10 deletions

File tree

include/linux/pagemap.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -374,16 +374,13 @@ static inline struct page *read_mapping_page(struct address_space *mapping,
374374
}
375375

376376
/*
377-
* Get the offset in PAGE_SIZE.
378-
* (TODO: hugepage should have ->index in PAGE_SIZE)
377+
* Get index of the page with in radix-tree
378+
* (TODO: remove once hugetlb pages will have ->index in PAGE_SIZE)
379379
*/
380-
static inline pgoff_t page_to_pgoff(struct page *page)
380+
static inline pgoff_t page_to_index(struct page *page)
381381
{
382382
pgoff_t pgoff;
383383

384-
if (unlikely(PageHeadHuge(page)))
385-
return page->index << compound_order(page);
386-
387384
if (likely(!PageTransTail(page)))
388385
return page->index;
389386

@@ -396,6 +393,18 @@ static inline pgoff_t page_to_pgoff(struct page *page)
396393
return pgoff;
397394
}
398395

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+
399408
/*
400409
* Return byte-offset into filesystem object for page.
401410
*/

mm/truncate.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
283283

284284
if (!trylock_page(page))
285285
continue;
286-
WARN_ON(page_to_pgoff(page) != index);
286+
WARN_ON(page_to_index(page) != index);
287287
if (PageWriteback(page)) {
288288
unlock_page(page);
289289
continue;
@@ -371,7 +371,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
371371
}
372372

373373
lock_page(page);
374-
WARN_ON(page_to_pgoff(page) != index);
374+
WARN_ON(page_to_index(page) != index);
375375
wait_on_page_writeback(page);
376376
truncate_inode_page(mapping, page);
377377
unlock_page(page);
@@ -492,7 +492,7 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
492492
if (!trylock_page(page))
493493
continue;
494494

495-
WARN_ON(page_to_pgoff(page) != index);
495+
WARN_ON(page_to_index(page) != index);
496496

497497
/* Middle of THP: skip */
498498
if (PageTransTail(page)) {
@@ -612,7 +612,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
612612
}
613613

614614
lock_page(page);
615-
WARN_ON(page_to_pgoff(page) != index);
615+
WARN_ON(page_to_index(page) != index);
616616
if (page->mapping != mapping) {
617617
unlock_page(page);
618618
continue;

0 commit comments

Comments
 (0)