mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
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: fc127da085
("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>
This commit is contained in:
parent
828347f8f9
commit
5cbc198ae0
@ -374,16 +374,13 @@ static inline struct page *read_mapping_page(struct address_space *mapping,
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the offset in PAGE_SIZE.
|
||||
* (TODO: hugepage should have ->index in PAGE_SIZE)
|
||||
* Get index of the page with in radix-tree
|
||||
* (TODO: remove once hugetlb pages will have ->index in PAGE_SIZE)
|
||||
*/
|
||||
static inline pgoff_t page_to_pgoff(struct page *page)
|
||||
static inline pgoff_t page_to_index(struct page *page)
|
||||
{
|
||||
pgoff_t pgoff;
|
||||
|
||||
if (unlikely(PageHeadHuge(page)))
|
||||
return page->index << compound_order(page);
|
||||
|
||||
if (likely(!PageTransTail(page)))
|
||||
return page->index;
|
||||
|
||||
@ -396,6 +393,18 @@ static inline pgoff_t page_to_pgoff(struct page *page)
|
||||
return pgoff;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the offset in PAGE_SIZE.
|
||||
* (TODO: hugepage should have ->index in PAGE_SIZE)
|
||||
*/
|
||||
static inline pgoff_t page_to_pgoff(struct page *page)
|
||||
{
|
||||
if (unlikely(PageHeadHuge(page)))
|
||||
return page->index << compound_order(page);
|
||||
|
||||
return page_to_index(page);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return byte-offset into filesystem object for page.
|
||||
*/
|
||||
|
@ -283,7 +283,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
|
||||
|
||||
if (!trylock_page(page))
|
||||
continue;
|
||||
WARN_ON(page_to_pgoff(page) != index);
|
||||
WARN_ON(page_to_index(page) != index);
|
||||
if (PageWriteback(page)) {
|
||||
unlock_page(page);
|
||||
continue;
|
||||
@ -371,7 +371,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
|
||||
}
|
||||
|
||||
lock_page(page);
|
||||
WARN_ON(page_to_pgoff(page) != index);
|
||||
WARN_ON(page_to_index(page) != index);
|
||||
wait_on_page_writeback(page);
|
||||
truncate_inode_page(mapping, page);
|
||||
unlock_page(page);
|
||||
@ -492,7 +492,7 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
|
||||
if (!trylock_page(page))
|
||||
continue;
|
||||
|
||||
WARN_ON(page_to_pgoff(page) != index);
|
||||
WARN_ON(page_to_index(page) != index);
|
||||
|
||||
/* Middle of THP: skip */
|
||||
if (PageTransTail(page)) {
|
||||
@ -612,7 +612,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
|
||||
}
|
||||
|
||||
lock_page(page);
|
||||
WARN_ON(page_to_pgoff(page) != index);
|
||||
WARN_ON(page_to_index(page) != index);
|
||||
if (page->mapping != mapping) {
|
||||
unlock_page(page);
|
||||
continue;
|
||||
|
Loading…
Reference in New Issue
Block a user