summaryrefslogtreecommitdiff
path: root/mm/filemap.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/filemap.c')
-rw-r--r--mm/filemap.c53
1 files changed, 27 insertions, 26 deletions
diff --git a/mm/filemap.c b/mm/filemap.c
index 0b7310971678..c0e5aff274f3 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -2290,32 +2290,33 @@ truncated:
return NULL;
}
-static struct page *filemap_create_page(struct kiocb *iocb,
- struct iov_iter *iter)
+static int filemap_create_page(struct file *file,
+ struct address_space *mapping, pgoff_t index,
+ struct pagevec *pvec)
{
- struct file *filp = iocb->ki_filp;
- struct address_space *mapping = filp->f_mapping;
- pgoff_t index = iocb->ki_pos >> PAGE_SHIFT;
struct page *page;
int error;
- if (iocb->ki_flags & (IOCB_NOIO | IOCB_NOWAIT | IOCB_WAITQ))
- return ERR_PTR(-EAGAIN);
-
page = page_cache_alloc(mapping);
if (!page)
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
error = add_to_page_cache_lru(page, mapping, index,
- mapping_gfp_constraint(mapping, GFP_KERNEL));
- if (!error)
- error = filemap_read_page(iocb->ki_filp, mapping, page);
- if (!error)
- return page;
+ mapping_gfp_constraint(mapping, GFP_KERNEL));
+ if (error == -EEXIST)
+ error = AOP_TRUNCATED_PAGE;
+ if (error)
+ goto error;
+
+ error = filemap_read_page(file, mapping, page);
+ if (error)
+ goto error;
+
+ pagevec_add(pvec, page);
+ return 0;
+error:
put_page(page);
- if (error == -EEXIST || error == AOP_TRUNCATED_PAGE)
- return NULL;
- return ERR_PTR(error);
+ return error;
}
static int filemap_get_pages(struct kiocb *iocb, struct iov_iter *iter,
@@ -2343,15 +2344,15 @@ find_page:
page_cache_sync_readahead(mapping, ra, filp, index, last_index - index);
filemap_get_read_batch(mapping, index, last_index, pvec);
- if (pvec->nr)
- goto got_pages;
-
- pvec->pages[0] = filemap_create_page(iocb, iter);
- err = PTR_ERR_OR_ZERO(pvec->pages[0]);
- if (IS_ERR_OR_NULL(pvec->pages[0]))
- goto err;
- pvec->nr = 1;
- return 0;
+ if (!pagevec_count(pvec)) {
+ if (iocb->ki_flags & (IOCB_NOWAIT | IOCB_WAITQ))
+ return -EAGAIN;
+ err = filemap_create_page(filp, mapping,
+ iocb->ki_pos >> PAGE_SHIFT, pvec);
+ if (err == AOP_TRUNCATED_PAGE)
+ goto find_page;
+ return err;
+ }
got_pages:
{
struct page *page = pvec->pages[pvec->nr - 1];