diff options
Diffstat (limited to 'mm/truncate.c')
| -rw-r--r-- | mm/truncate.c | 28 | 
1 files changed, 23 insertions, 5 deletions
diff --git a/mm/truncate.c b/mm/truncate.c index 4064f8f53daa..a01cce450a26 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -155,10 +155,14 @@ invalidate_complete_page(struct address_space *mapping, struct page *page)  int truncate_inode_page(struct address_space *mapping, struct page *page)  { +	loff_t holelen; +	VM_BUG_ON_PAGE(PageTail(page), page); + +	holelen = PageTransHuge(page) ? HPAGE_PMD_SIZE : PAGE_SIZE;  	if (page_mapped(page)) {  		unmap_mapping_range(mapping,  				   (loff_t)page->index << PAGE_SHIFT, -				   PAGE_SIZE, 0); +				   holelen, 0);  	}  	return truncate_complete_page(mapping, page);  } @@ -279,7 +283,7 @@ void truncate_inode_pages_range(struct address_space *mapping,  			if (!trylock_page(page))  				continue; -			WARN_ON(page->index != index); +			WARN_ON(page_to_pgoff(page) != index);  			if (PageWriteback(page)) {  				unlock_page(page);  				continue; @@ -367,7 +371,7 @@ void truncate_inode_pages_range(struct address_space *mapping,  			}  			lock_page(page); -			WARN_ON(page->index != index); +			WARN_ON(page_to_pgoff(page) != index);  			wait_on_page_writeback(page);  			truncate_inode_page(mapping, page);  			unlock_page(page); @@ -487,7 +491,21 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,  			if (!trylock_page(page))  				continue; -			WARN_ON(page->index != index); + +			WARN_ON(page_to_pgoff(page) != index); + +			/* Middle of THP: skip */ +			if (PageTransTail(page)) { +				unlock_page(page); +				continue; +			} else if (PageTransHuge(page)) { +				index += HPAGE_PMD_NR - 1; +				i += HPAGE_PMD_NR - 1; +				/* 'end' is in the middle of THP */ +				if (index ==  round_down(end, HPAGE_PMD_NR)) +					continue; +			} +  			ret = invalidate_inode_page(page);  			unlock_page(page);  			/* @@ -594,7 +612,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,  			}  			lock_page(page); -			WARN_ON(page->index != index); +			WARN_ON(page_to_pgoff(page) != index);  			if (page->mapping != mapping) {  				unlock_page(page);  				continue;  |