Message ID | 20200212041845.25879-12-willy@infradead.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Large pages in the page cache | expand |
On Tue, Feb 11, 2020 at 08:18:31PM -0800, Matthew Wilcox wrote: > From: "Matthew Wilcox (Oracle)" <willy@infradead.org> > > If the page is compound, check the appropriate indices and return the > appropriate sizes. Is it guarnteed that the page is never called on tail page?
On Thu, Feb 13, 2020 at 06:44:19PM +0300, Kirill A. Shutemov wrote: > On Tue, Feb 11, 2020 at 08:18:31PM -0800, Matthew Wilcox wrote: > > From: "Matthew Wilcox (Oracle)" <willy@infradead.org> > > > > If the page is compound, check the appropriate indices and return the > > appropriate sizes. > > Is it guarnteed that the page is never called on tail page? I think so. page_mkwrite_check_truncate() is only called on pages which belong to a particular filesystem. Only filesystems which have the FS_LARGE_PAGES flag set will have compound pages allocated in the page cache for their files. As filesystems are converted, they will only see large head pages. I'll happily put in a VM_BUG_ON(PageTail(page), page); to ensure we don't screw that up.
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index aa925295347c..2ec33aabdbf6 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -732,17 +732,18 @@ static inline int page_mkwrite_check_truncate(struct page *page, struct inode *inode) { loff_t size = i_size_read(inode); - pgoff_t index = size >> PAGE_SHIFT; - int offset = offset_in_page(size); + pgoff_t first_index = size >> PAGE_SHIFT; + pgoff_t last_index = first_index + hpage_nr_pages(page) - 1; + unsigned long offset = offset_in_this_page(page, size); if (page->mapping != inode->i_mapping) return -EFAULT; /* page is wholly inside EOF */ - if (page->index < index) - return PAGE_SIZE; + if (page->index < first_index) + return thp_size(page); /* page is wholly past EOF */ - if (page->index > index || !offset) + if (page->index > last_index || !offset) return -EFAULT; /* page is partially inside EOF */ return offset;