return error;
}
-static int generic_file_buffered_read_pagenotuptodate(struct kiocb *iocb,
- struct iov_iter *iter, struct page *page, loff_t pos,
- loff_t count, bool first)
+static int filemap_make_page_uptodate(struct kiocb *iocb, struct iov_iter *iter,
+ struct page *page, pgoff_t pg_index, bool first)
{
- struct address_space *mapping = iocb->ki_filp->f_mapping;
+ struct file *file = iocb->ki_filp;
+ struct address_space *mapping = file->f_mapping;
+ loff_t last = iocb->ki_pos + iter->count;
+ pgoff_t last_index = (last + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ loff_t pos = max(iocb->ki_pos, (loff_t)pg_index << PAGE_SHIFT);
int error = -EAGAIN;
+ if (PageReadahead(page)) {
+ if (iocb->ki_flags & IOCB_NOIO)
+ goto put_page;
+ page_cache_async_readahead(mapping, &file->f_ra, file, page,
+ pg_index, last_index - pg_index);
+ }
+
+ if (PageUptodate(page))
+ return 0;
+
if (iocb->ki_flags & IOCB_NOWAIT)
goto put_page;
/* Did it get truncated before we got the lock? */
if (!page->mapping)
goto page_not_up_to_date_locked;
- if (!mapping->a_ops->is_partially_uptodate(page,
- pos & ~PAGE_MASK, count))
+ if (!mapping->a_ops->is_partially_uptodate(page, pos & ~PAGE_MASK,
+ last - pos))
goto page_not_up_to_date_locked;
unlock_page:
nr_got = 1;
got_pages:
for (i = 0; i < nr_got; i++) {
- struct page *page = pages[i];
- pgoff_t pg_index = index + i;
- loff_t pg_pos = max(iocb->ki_pos,
- (loff_t) pg_index << PAGE_SHIFT);
- loff_t pg_count = iocb->ki_pos + iter->count - pg_pos;
-
- if (PageReadahead(page)) {
- if (iocb->ki_flags & IOCB_NOIO) {
- for (j = i; j < nr_got; j++)
- put_page(pages[j]);
- nr_got = i;
- err = -EAGAIN;
- break;
- }
- page_cache_async_readahead(mapping, ra, filp, page,
- pg_index, last_index - pg_index);
- }
-
- if (!PageUptodate(page)) {
- err = generic_file_buffered_read_pagenotuptodate(iocb,
- iter, page, pg_pos, pg_count, i == 0);
- if (err) {
- if (err == AOP_TRUNCATED_PAGE)
- err = 0;
- for (j = i + 1; j < nr_got; j++)
- put_page(pages[j]);
- nr_got = i;
- break;
- }
+ err = filemap_make_page_uptodate(iocb, iter, pages[i],
+ index + i, i == 0);
+ if (err) {
+ if (err == AOP_TRUNCATED_PAGE)
+ err = 0;
+ for (j = i + 1; j < nr_got; j++)
+ put_page(pages[j]);
+ nr_got = i;
+ break;
}
}