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.c92
1 files changed, 34 insertions, 58 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 6ab4d5a9edf2..9a55807b2a70 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -27,7 +27,8 @@
27 27
28#define NFSDBG_FACILITY NFSDBG_PAGECACHE 28#define NFSDBG_FACILITY NFSDBG_PAGECACHE
29 29
30static int nfs_pagein_one(struct list_head *, struct inode *); 30static int nfs_pagein_multi(struct inode *, struct list_head *, unsigned int, size_t, int);
31static int nfs_pagein_one(struct inode *, struct list_head *, unsigned int, size_t, int);
31static const struct rpc_call_ops nfs_read_partial_ops; 32static const struct rpc_call_ops nfs_read_partial_ops;
32static const struct rpc_call_ops nfs_read_full_ops; 33static const struct rpc_call_ops nfs_read_full_ops;
33 34
@@ -36,9 +37,8 @@ static mempool_t *nfs_rdata_mempool;
36 37
37#define MIN_POOL_READ (32) 38#define MIN_POOL_READ (32)
38 39
39struct nfs_read_data *nfs_readdata_alloc(size_t len) 40struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
40{ 41{
41 unsigned int pagecount = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
42 struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS); 42 struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, GFP_NOFS);
43 43
44 if (p) { 44 if (p) {
@@ -133,7 +133,10 @@ static int nfs_readpage_async(struct nfs_open_context *ctx, struct inode *inode,
133 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); 133 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
134 134
135 nfs_list_add_request(new, &one_request); 135 nfs_list_add_request(new, &one_request);
136 nfs_pagein_one(&one_request, inode); 136 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE)
137 nfs_pagein_multi(inode, &one_request, 1, len, 0);
138 else
139 nfs_pagein_one(inode, &one_request, 1, len, 0);
137 return 0; 140 return 0;
138} 141}
139 142
@@ -230,7 +233,7 @@ static void nfs_execute_read(struct nfs_read_data *data)
230 * won't see the new data until our attribute cache is updated. This is more 233 * won't see the new data until our attribute cache is updated. This is more
231 * or less conventional NFS client behavior. 234 * or less conventional NFS client behavior.
232 */ 235 */
233static int nfs_pagein_multi(struct list_head *head, struct inode *inode) 236static int nfs_pagein_multi(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
234{ 237{
235 struct nfs_page *req = nfs_list_entry(head->next); 238 struct nfs_page *req = nfs_list_entry(head->next);
236 struct page *page = req->wb_page; 239 struct page *page = req->wb_page;
@@ -242,11 +245,11 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
242 245
243 nfs_list_remove_request(req); 246 nfs_list_remove_request(req);
244 247
245 nbytes = req->wb_bytes; 248 nbytes = count;
246 do { 249 do {
247 size_t len = min(nbytes,rsize); 250 size_t len = min(nbytes,rsize);
248 251
249 data = nfs_readdata_alloc(len); 252 data = nfs_readdata_alloc(1);
250 if (!data) 253 if (!data)
251 goto out_bad; 254 goto out_bad;
252 INIT_LIST_HEAD(&data->pages); 255 INIT_LIST_HEAD(&data->pages);
@@ -258,23 +261,19 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
258 261
259 ClearPageError(page); 262 ClearPageError(page);
260 offset = 0; 263 offset = 0;
261 nbytes = req->wb_bytes; 264 nbytes = count;
262 do { 265 do {
263 data = list_entry(list.next, struct nfs_read_data, pages); 266 data = list_entry(list.next, struct nfs_read_data, pages);
264 list_del_init(&data->pages); 267 list_del_init(&data->pages);
265 268
266 data->pagevec[0] = page; 269 data->pagevec[0] = page;
267 270
268 if (nbytes > rsize) { 271 if (nbytes < rsize)
269 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, 272 rsize = nbytes;
270 rsize, offset); 273 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
271 offset += rsize; 274 rsize, offset);
272 nbytes -= rsize; 275 offset += rsize;
273 } else { 276 nbytes -= rsize;
274 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
275 nbytes, offset);
276 nbytes = 0;
277 }
278 nfs_execute_read(data); 277 nfs_execute_read(data);
279 } while (nbytes != 0); 278 } while (nbytes != 0);
280 279
@@ -291,30 +290,24 @@ out_bad:
291 return -ENOMEM; 290 return -ENOMEM;
292} 291}
293 292
294static int nfs_pagein_one(struct list_head *head, struct inode *inode) 293static int nfs_pagein_one(struct inode *inode, struct list_head *head, unsigned int npages, size_t count, int flags)
295{ 294{
296 struct nfs_page *req; 295 struct nfs_page *req;
297 struct page **pages; 296 struct page **pages;
298 struct nfs_read_data *data; 297 struct nfs_read_data *data;
299 unsigned int count;
300 298
301 if (NFS_SERVER(inode)->rsize < PAGE_CACHE_SIZE) 299 data = nfs_readdata_alloc(npages);
302 return nfs_pagein_multi(head, inode);
303
304 data = nfs_readdata_alloc(NFS_SERVER(inode)->rsize);
305 if (!data) 300 if (!data)
306 goto out_bad; 301 goto out_bad;
307 302
308 INIT_LIST_HEAD(&data->pages); 303 INIT_LIST_HEAD(&data->pages);
309 pages = data->pagevec; 304 pages = data->pagevec;
310 count = 0;
311 while (!list_empty(head)) { 305 while (!list_empty(head)) {
312 req = nfs_list_entry(head->next); 306 req = nfs_list_entry(head->next);
313 nfs_list_remove_request(req); 307 nfs_list_remove_request(req);
314 nfs_list_add_request(req, &data->pages); 308 nfs_list_add_request(req, &data->pages);
315 ClearPageError(req->wb_page); 309 ClearPageError(req->wb_page);
316 *pages++ = req->wb_page; 310 *pages++ = req->wb_page;
317 count += req->wb_bytes;
318 } 311 }
319 req = nfs_list_entry(data->pages.next); 312 req = nfs_list_entry(data->pages.next);
320 313
@@ -327,28 +320,6 @@ out_bad:
327 return -ENOMEM; 320 return -ENOMEM;
328} 321}
329 322
330static int
331nfs_pagein_list(struct list_head *head, int rpages)
332{
333 LIST_HEAD(one_request);
334 struct nfs_page *req;
335 int error = 0;
336 unsigned int pages = 0;
337
338 while (!list_empty(head)) {
339 pages += nfs_coalesce_requests(head, &one_request, rpages);
340 req = nfs_list_entry(one_request.next);
341 error = nfs_pagein_one(&one_request, req->wb_context->dentry->d_inode);
342 if (error < 0)
343 break;
344 }
345 if (error >= 0)
346 return pages;
347
348 nfs_async_read_error(head);
349 return error;
350}
351
352/* 323/*
353 * This is the callback from RPC telling us whether a reply was 324 * This is the callback from RPC telling us whether a reply was
354 * received or some error occurred (timeout or socket shutdown). 325 * received or some error occurred (timeout or socket shutdown).
@@ -538,7 +509,7 @@ out_error:
538} 509}
539 510
540struct nfs_readdesc { 511struct nfs_readdesc {
541 struct list_head *head; 512 struct nfs_pageio_descriptor *pgio;
542 struct nfs_open_context *ctx; 513 struct nfs_open_context *ctx;
543}; 514};
544 515
@@ -562,19 +533,21 @@ readpage_async_filler(void *data, struct page *page)
562 } 533 }
563 if (len < PAGE_CACHE_SIZE) 534 if (len < PAGE_CACHE_SIZE)
564 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len); 535 memclear_highpage_flush(page, len, PAGE_CACHE_SIZE - len);
565 nfs_list_add_request(new, desc->head); 536 nfs_pageio_add_request(desc->pgio, new);
566 return 0; 537 return 0;
567} 538}
568 539
569int nfs_readpages(struct file *filp, struct address_space *mapping, 540int nfs_readpages(struct file *filp, struct address_space *mapping,
570 struct list_head *pages, unsigned nr_pages) 541 struct list_head *pages, unsigned nr_pages)
571{ 542{
572 LIST_HEAD(head); 543 struct nfs_pageio_descriptor pgio;
573 struct nfs_readdesc desc = { 544 struct nfs_readdesc desc = {
574 .head = &head, 545 .pgio = &pgio,
575 }; 546 };
576 struct inode *inode = mapping->host; 547 struct inode *inode = mapping->host;
577 struct nfs_server *server = NFS_SERVER(inode); 548 struct nfs_server *server = NFS_SERVER(inode);
549 size_t rsize = server->rsize;
550 unsigned long npages;
578 int ret = -ESTALE; 551 int ret = -ESTALE;
579 552
580 dprintk("NFS: nfs_readpages (%s/%Ld %d)\n", 553 dprintk("NFS: nfs_readpages (%s/%Ld %d)\n",
@@ -593,13 +566,16 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
593 } else 566 } else
594 desc.ctx = get_nfs_open_context((struct nfs_open_context *) 567 desc.ctx = get_nfs_open_context((struct nfs_open_context *)
595 filp->private_data); 568 filp->private_data);
569 if (rsize < PAGE_CACHE_SIZE)
570 nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
571 else
572 nfs_pageio_init(&pgio, inode, nfs_pagein_one, rsize, 0);
573
596 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc); 574 ret = read_cache_pages(mapping, pages, readpage_async_filler, &desc);
597 if (!list_empty(&head)) { 575
598 int err = nfs_pagein_list(&head, server->rpages); 576 nfs_pageio_complete(&pgio);
599 if (!ret) 577 npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
600 nfs_add_stats(inode, NFSIOS_READPAGES, err); 578 nfs_add_stats(inode, NFSIOS_READPAGES, npages);
601 ret = err;
602 }
603 put_nfs_open_context(desc.ctx); 579 put_nfs_open_context(desc.ctx);
604out: 580out:
605 return ret; 581 return ret;