Move the complicated condition and the calculations out of filemap_update_page() into its own function. --- mm/filemap.c | 49 +++++++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/mm/filemap.c b/mm/filemap.c index 41b90243f4ee..81b569d818a3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -2228,11 +2228,39 @@ static int filemap_read_page(struct file *file, struct address_space *mapping, return error; } +static bool filemap_range_uptodate(struct kiocb *iocb, + struct address_space *mapping, struct iov_iter *iter, + struct page *page) +{ + loff_t pos; + int count; + + if (PageUptodate(page)) + return true; + /* pipes can't handle partially uptodate pages */ + if (iov_iter_is_pipe(iter)) + return false; + if (!mapping->a_ops->is_partially_uptodate) + return false; + if (mapping->host->i_blkbits >= (PAGE_SHIFT + thp_order(page))) + return false; + + pos = (loff_t) page->index << PAGE_SHIFT; + if (pos > iocb->ki_pos) { + count = iocb->ki_pos + iter->count - pos; + pos = 0; + } else { + count = iter->count; + pos = iocb->ki_pos & (thp_size(page) - 1); + } + + return mapping->a_ops->is_partially_uptodate(page, pos, count); +} + static int filemap_update_page(struct kiocb *iocb, struct address_space *mapping, struct iov_iter *iter, struct page *page, loff_t pos, loff_t count, bool first) { - struct inode *inode = mapping->host; int error = -EAGAIN; if (!trylock_page(page)) { @@ -2252,22 +2280,11 @@ static int filemap_update_page(struct kiocb *iocb, if (!page->mapping) goto truncated; - if (PageUptodate(page)) - goto uptodate; - if (inode->i_blkbits == PAGE_SHIFT || - !mapping->a_ops->is_partially_uptodate) - goto readpage; - /* pipes can't handle partially uptodate pages */ - if (unlikely(iov_iter_is_pipe(iter))) - goto readpage; - if (!mapping->a_ops->is_partially_uptodate(page, - pos & (thp_size(page) - 1), count)) - goto readpage; -uptodate: - unlock_page(page); - return 0; + if (filemap_range_uptodate(iocb, mapping, iter, page)) { + unlock_page(page); + return 0; + } -readpage: if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ)) { unlock_page(page); error = -EAGAIN; -- 2.28.0