diff options
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r-- | fs/nfs/read.c | 30 |
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 | ||
46 | struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount) | 46 | struct 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 | ||
210 | io_error: | 214 | io_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 | ||