aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r--fs/nfs/read.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index da9cf11c326f..f0aff824a291 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -43,13 +43,15 @@ static mempool_t *nfs_rdata_mempool;
43 43
44#define MIN_POOL_READ (32) 44#define MIN_POOL_READ (32)
45 45
46struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) 46struct nfs_read_data *nfs_readdata_alloc(size_t len)
47{ 47{
48 unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
48 struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS); 49 struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
49 50
50 if (p) { 51 if (p) {
51 memset(p, 0, sizeof(*p)); 52 memset(p, 0, sizeof(*p));
52 INIT_LIST_HEAD(&p->pages); 53 INIT_LIST_HEAD(&p->pages);
54 p->npages = pagecount;
53 if (pagecount <= ARRAY_SIZE(p->page_array)) 55 if (pagecount <= ARRAY_SIZE(p->page_array))
54 p->pagevec = p->page_array; 56 p->pagevec = p->page_array;
55 else { 57 else {
@@ -140,7 +142,7 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
140 int result; 142 int result;
141 struct nfs_read_data *rdata; 143 struct nfs_read_data *rdata;
142 144
143 rdata = nfs_readdata_alloc(1); 145 rdata = nfs_readdata_alloc(count);
144 if (!rdata) 146 if (!rdata)
145 return -ENOMEM; 147 return -ENOMEM;
146 148
@@ -202,9 +204,11 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
202 NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME; 204 NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATIME;
203 spin_unlock(&inode->i_lock); 205 spin_unlock(&inode->i_lock);
204 206
205 nfs_readpage_truncate_uninitialised_page(rdata); 207 if (rdata->res.eof || rdata->res.count == rdata->args.count) {
206 if (rdata->res.eof || rdata->res.count == rdata->args.count)
207 SetPageUptodate(page); 208 SetPageUptodate(page);
209 if (rdata->res.eof && count != 0)
210 memclear_highpage_flush(page, rdata->args.pgbase, count);
211 }
208 result = 0; 212 result = 0;
209 213
210io_error: 214io_error:
@@ -336,25 +340,25 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
336 struct nfs_page *req = nfs_list_entry(head->next); 340 struct nfs_page *req = nfs_list_entry(head->next);
337 struct page *page = req->wb_page; 341 struct page *page = req->wb_page;
338 struct nfs_read_data *data; 342 struct nfs_read_data *data;
339 unsigned int rsize = NFS_SERVER(inode)->rsize; 343 size_t rsize = NFS_SERVER(inode)->rsize, nbytes;
340 unsigned int nbytes, offset; 344 unsigned int offset;
341 int requests = 0; 345 int requests = 0;
342 LIST_HEAD(list); 346 LIST_HEAD(list);
343 347
344 nfs_list_remove_request(req); 348 nfs_list_remove_request(req);
345 349
346 nbytes = req->wb_bytes; 350 nbytes = req->wb_bytes;
347 for(;;) { 351 do {
348 data = nfs_readdata_alloc(1); 352 size_t len = min(nbytes,rsize);
353
354 data = nfs_readdata_alloc(len);
349 if (!data) 355 if (!data)
350 goto out_bad; 356 goto out_bad;
351 INIT_LIST_HEAD(&data->pages); 357 INIT_LIST_HEAD(&data->pages);
352 list_add(&data->pages, &list); 358 list_add(&data->pages, &list);
353 requests++; 359 requests++;
354 if (nbytes <= rsize) 360 nbytes -= len;
355 break; 361 } while(nbytes != 0);
356 nbytes -= rsize;
357 }
358 atomic_set(&req->wb_complete, requests); 362 atomic_set(&req->wb_complete, requests);
359 363
360 ClearPageError(page); 364 ClearPageError(page);
@@ -402,7 +406,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode)
402 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) 406 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
403 return nfs_pagein_multi(head, inode); 407 return nfs_pagein_multi(head, inode);
404 408
405 data = nfs_readdata_alloc(NFS_SERVER(inode)->rpages); 409 data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize);
406 if (!data) 410 if (!data)
407 goto out_bad; 411 goto out_bad;
408 412