diff options
Diffstat (limited to 'fs/nfs/read.c')
| -rw-r--r-- | fs/nfs/read.c | 24 |
1 files changed, 13 insertions, 11 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index da9cf11c326f..7a9ee00e0c61 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 | ||
| @@ -336,25 +338,25 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode) | |||
| 336 | struct nfs_page *req = nfs_list_entry(head->next); | 338 | struct nfs_page *req = nfs_list_entry(head->next); |
| 337 | struct page *page = req->wb_page; | 339 | struct page *page = req->wb_page; |
| 338 | struct nfs_read_data *data; | 340 | struct nfs_read_data *data; |
| 339 | unsigned int rsize = NFS_SERVER(inode)->rsize; | 341 | size_t rsize = NFS_SERVER(inode)->rsize, nbytes; |
| 340 | unsigned int nbytes, offset; | 342 | unsigned int offset; |
| 341 | int requests = 0; | 343 | int requests = 0; |
| 342 | LIST_HEAD(list); | 344 | LIST_HEAD(list); |
| 343 | 345 | ||
| 344 | nfs_list_remove_request(req); | 346 | nfs_list_remove_request(req); |
| 345 | 347 | ||
| 346 | nbytes = req->wb_bytes; | 348 | nbytes = req->wb_bytes; |
| 347 | for(;;) { | 349 | do { |
| 348 | data = nfs_readdata_alloc(1); | 350 | size_t len = min(nbytes,rsize); |
| 351 | |||
| 352 | data = nfs_readdata_alloc(len); | ||
| 349 | if (!data) | 353 | if (!data) |
| 350 | goto out_bad; | 354 | goto out_bad; |
| 351 | INIT_LIST_HEAD(&data->pages); | 355 | INIT_LIST_HEAD(&data->pages); |
| 352 | list_add(&data->pages, &list); | 356 | list_add(&data->pages, &list); |
| 353 | requests++; | 357 | requests++; |
| 354 | if (nbytes <= rsize) | 358 | nbytes -= len; |
| 355 | break; | 359 | } while(nbytes != 0); |
| 356 | nbytes -= rsize; | ||
| 357 | } | ||
| 358 | atomic_set(&req->wb_complete, requests); | 360 | atomic_set(&req->wb_complete, requests); |
| 359 | 361 | ||
| 360 | ClearPageError(page); | 362 | ClearPageError(page); |
| @@ -402,7 +404,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode) | |||
| 402 | if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) | 404 | if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) |
| 403 | return nfs_pagein_multi(head, inode); | 405 | return nfs_pagein_multi(head, inode); |
| 404 | 406 | ||
| 405 | data = nfs_readdata_alloc(NFS_SERVER(inode)->rpages); | 407 | data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize); |
| 406 | if (!data) | 408 | if (!data) |
| 407 | goto out_bad; | 409 | goto out_bad; |
| 408 | 410 | ||
