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.c102
1 files changed, 84 insertions, 18 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 05eb43fadf8e..3961524fd4ab 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -31,17 +31,49 @@
31 31
32#include <asm/system.h> 32#include <asm/system.h>
33 33
34#include "iostat.h"
35
34#define NFSDBG_FACILITY NFSDBG_PAGECACHE 36#define NFSDBG_FACILITY NFSDBG_PAGECACHE
35 37
36static int nfs_pagein_one(struct list_head *, struct inode *); 38static int nfs_pagein_one(struct list_head *, struct inode *);
37static void nfs_readpage_result_partial(struct nfs_read_data *, int); 39static const struct rpc_call_ops nfs_read_partial_ops;
38static void nfs_readpage_result_full(struct nfs_read_data *, int); 40static const struct rpc_call_ops nfs_read_full_ops;
39 41
40static kmem_cache_t *nfs_rdata_cachep; 42static kmem_cache_t *nfs_rdata_cachep;
41mempool_t *nfs_rdata_mempool; 43static mempool_t *nfs_rdata_mempool;
42 44
43#define MIN_POOL_READ (32) 45#define MIN_POOL_READ (32)
44 46
47struct nfs_read_data *nfs_readdata_alloc(unsigned int pagecount)
48{
49 struct nfs_read_data *p = mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
50
51 if (p) {
52 memset(p, 0, sizeof(*p));
53 INIT_LIST_HEAD(&p->pages);
54 if (pagecount < NFS_PAGEVEC_SIZE)
55 p->pagevec = &p->page_array[0];
56 else {
57 size_t size = ++pagecount * sizeof(struct page *);
58 p->pagevec = kmalloc(size, GFP_NOFS);
59 if (p->pagevec) {
60 memset(p->pagevec, 0, size);
61 } else {
62 mempool_free(p, nfs_rdata_mempool);
63 p = NULL;
64 }
65 }
66 }
67 return p;
68}
69
70void nfs_readdata_free(struct nfs_read_data *p)
71{
72 if (p && (p->pagevec != &p->page_array[0]))
73 kfree(p->pagevec);
74 mempool_free(p, nfs_rdata_mempool);
75}
76
45void nfs_readdata_release(void *data) 77void nfs_readdata_release(void *data)
46{ 78{
47 nfs_readdata_free(data); 79 nfs_readdata_free(data);
@@ -133,6 +165,8 @@ static int nfs_readpage_sync(struct nfs_open_context *ctx, struct inode *inode,
133 } 165 }
134 count -= result; 166 count -= result;
135 rdata->args.pgbase += result; 167 rdata->args.pgbase += result;
168 nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, result);
169
136 /* Note: result == 0 should only happen if we're caching 170 /* Note: result == 0 should only happen if we're caching
137 * a write that extends the file and punches a hole. 171 * a write that extends the file and punches a hole.
138 */ 172 */
@@ -196,9 +230,11 @@ static void nfs_readpage_release(struct nfs_page *req)
196 * Set up the NFS read request struct 230 * Set up the NFS read request struct
197 */ 231 */
198static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, 232static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
233 const struct rpc_call_ops *call_ops,
199 unsigned int count, unsigned int offset) 234 unsigned int count, unsigned int offset)
200{ 235{
201 struct inode *inode; 236 struct inode *inode;
237 int flags;
202 238
203 data->req = req; 239 data->req = req;
204 data->inode = inode = req->wb_context->dentry->d_inode; 240 data->inode = inode = req->wb_context->dentry->d_inode;
@@ -216,6 +252,9 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data,
216 data->res.eof = 0; 252 data->res.eof = 0;
217 nfs_fattr_init(&data->fattr); 253 nfs_fattr_init(&data->fattr);
218 254
255 /* Set up the initial task struct. */
256 flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0);
257 rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data);
219 NFS_PROTO(inode)->read_setup(data); 258 NFS_PROTO(inode)->read_setup(data);
220 259
221 data->task.tk_cookie = (unsigned long)inode; 260 data->task.tk_cookie = (unsigned long)inode;
@@ -303,14 +342,15 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode)
303 list_del_init(&data->pages); 342 list_del_init(&data->pages);
304 343
305 data->pagevec[0] = page; 344 data->pagevec[0] = page;
306 data->complete = nfs_readpage_result_partial;
307 345
308 if (nbytes > rsize) { 346 if (nbytes > rsize) {
309 nfs_read_rpcsetup(req, data, rsize, offset); 347 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
348 rsize, offset);
310 offset += rsize; 349 offset += rsize;
311 nbytes -= rsize; 350 nbytes -= rsize;
312 } else { 351 } else {
313 nfs_read_rpcsetup(req, data, nbytes, offset); 352 nfs_read_rpcsetup(req, data, &nfs_read_partial_ops,
353 nbytes, offset);
314 nbytes = 0; 354 nbytes = 0;
315 } 355 }
316 nfs_execute_read(data); 356 nfs_execute_read(data);
@@ -356,8 +396,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode)
356 } 396 }
357 req = nfs_list_entry(data->pages.next); 397 req = nfs_list_entry(data->pages.next);
358 398
359 data->complete = nfs_readpage_result_full; 399 nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0);
360 nfs_read_rpcsetup(req, data, count, 0);
361 400
362 nfs_execute_read(data); 401 nfs_execute_read(data);
363 return 0; 402 return 0;
@@ -391,12 +430,15 @@ nfs_pagein_list(struct list_head *head, int rpages)
391/* 430/*
392 * Handle a read reply that fills part of a page. 431 * Handle a read reply that fills part of a page.
393 */ 432 */
394static void nfs_readpage_result_partial(struct nfs_read_data *data, int status) 433static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata)
395{ 434{
435 struct nfs_read_data *data = calldata;
396 struct nfs_page *req = data->req; 436 struct nfs_page *req = data->req;
397 struct page *page = req->wb_page; 437 struct page *page = req->wb_page;
398 438
399 if (status >= 0) { 439 if (nfs_readpage_result(task, data) != 0)
440 return;
441 if (task->tk_status >= 0) {
400 unsigned int request = data->args.count; 442 unsigned int request = data->args.count;
401 unsigned int result = data->res.count; 443 unsigned int result = data->res.count;
402 444
@@ -415,20 +457,28 @@ static void nfs_readpage_result_partial(struct nfs_read_data *data, int status)
415 } 457 }
416} 458}
417 459
460static const struct rpc_call_ops nfs_read_partial_ops = {
461 .rpc_call_done = nfs_readpage_result_partial,
462 .rpc_release = nfs_readdata_release,
463};
464
418/* 465/*
419 * This is the callback from RPC telling us whether a reply was 466 * This is the callback from RPC telling us whether a reply was
420 * received or some error occurred (timeout or socket shutdown). 467 * received or some error occurred (timeout or socket shutdown).
421 */ 468 */
422static void nfs_readpage_result_full(struct nfs_read_data *data, int status) 469static void nfs_readpage_result_full(struct rpc_task *task, void *calldata)
423{ 470{
471 struct nfs_read_data *data = calldata;
424 unsigned int count = data->res.count; 472 unsigned int count = data->res.count;
425 473
474 if (nfs_readpage_result(task, data) != 0)
475 return;
426 while (!list_empty(&data->pages)) { 476 while (!list_empty(&data->pages)) {
427 struct nfs_page *req = nfs_list_entry(data->pages.next); 477 struct nfs_page *req = nfs_list_entry(data->pages.next);
428 struct page *page = req->wb_page; 478 struct page *page = req->wb_page;
429 nfs_list_remove_request(req); 479 nfs_list_remove_request(req);
430 480
431 if (status >= 0) { 481 if (task->tk_status >= 0) {
432 if (count < PAGE_CACHE_SIZE) { 482 if (count < PAGE_CACHE_SIZE) {
433 if (count < req->wb_bytes) 483 if (count < req->wb_bytes)
434 memclear_highpage_flush(page, 484 memclear_highpage_flush(page,
@@ -444,22 +494,33 @@ static void nfs_readpage_result_full(struct nfs_read_data *data, int status)
444 } 494 }
445} 495}
446 496
497static const struct rpc_call_ops nfs_read_full_ops = {
498 .rpc_call_done = nfs_readpage_result_full,
499 .rpc_release = nfs_readdata_release,
500};
501
447/* 502/*
448 * This is the callback from RPC telling us whether a reply was 503 * This is the callback from RPC telling us whether a reply was
449 * received or some error occurred (timeout or socket shutdown). 504 * received or some error occurred (timeout or socket shutdown).
450 */ 505 */
451void nfs_readpage_result(struct rpc_task *task, void *calldata) 506int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data)
452{ 507{
453 struct nfs_read_data *data = calldata;
454 struct nfs_readargs *argp = &data->args; 508 struct nfs_readargs *argp = &data->args;
455 struct nfs_readres *resp = &data->res; 509 struct nfs_readres *resp = &data->res;
456 int status = task->tk_status; 510 int status;
457 511
458 dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", 512 dprintk("NFS: %4d nfs_readpage_result, (status %d)\n",
459 task->tk_pid, status); 513 task->tk_pid, task->tk_status);
514
515 status = NFS_PROTO(data->inode)->read_done(task, data);
516 if (status != 0)
517 return status;
518
519 nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count);
460 520
461 /* Is this a short read? */ 521 /* Is this a short read? */
462 if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) { 522 if (task->tk_status >= 0 && resp->count < argp->count && !resp->eof) {
523 nfs_inc_stats(data->inode, NFSIOS_SHORTREAD);
463 /* Has the server at least made some progress? */ 524 /* Has the server at least made some progress? */
464 if (resp->count != 0) { 525 if (resp->count != 0) {
465 /* Yes, so retry the read at the end of the data */ 526 /* Yes, so retry the read at the end of the data */
@@ -467,14 +528,14 @@ void nfs_readpage_result(struct rpc_task *task, void *calldata)
467 argp->pgbase += resp->count; 528 argp->pgbase += resp->count;
468 argp->count -= resp->count; 529 argp->count -= resp->count;
469 rpc_restart_call(task); 530 rpc_restart_call(task);
470 return; 531 return -EAGAIN;
471 } 532 }
472 task->tk_status = -EIO; 533 task->tk_status = -EIO;
473 } 534 }
474 spin_lock(&data->inode->i_lock); 535 spin_lock(&data->inode->i_lock);
475 NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME; 536 NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME;
476 spin_unlock(&data->inode->i_lock); 537 spin_unlock(&data->inode->i_lock);
477 data->complete(data, status); 538 return 0;
478} 539}
479 540
480/* 541/*
@@ -491,6 +552,9 @@ int nfs_readpage(struct file *file, struct page *page)
491 552
492 dprintk("NFS: nfs_readpage (%p %ld@%lu)\n", 553 dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
493 page, PAGE_CACHE_SIZE, page->index); 554 page, PAGE_CACHE_SIZE, page->index);
555 nfs_inc_stats(inode, NFSIOS_VFSREADPAGE);
556 nfs_add_stats(inode, NFSIOS_READPAGES, 1);
557
494 /* 558 /*
495 * Try to flush any pending writes to the file.. 559 * Try to flush any pending writes to the file..
496 * 560 *
@@ -570,6 +634,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
570 inode->i_sb->s_id, 634 inode->i_sb->s_id,
571 (long long)NFS_FILEID(inode), 635 (long long)NFS_FILEID(inode),
572 nr_pages); 636 nr_pages);
637 nfs_inc_stats(inode, NFSIOS_VFSREADPAGES);
573 638
574 if (filp == NULL) { 639 if (filp == NULL) {
575 desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); 640 desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ);
@@ -582,6 +647,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
582 if (!list_empty(&head)) { 647 if (!list_empty(&head)) {
583 int err = nfs_pagein_list(&head, server->rpages); 648 int err = nfs_pagein_list(&head, server->rpages);
584 if (!ret) 649 if (!ret)
650 nfs_add_stats(inode, NFSIOS_READPAGES, err);
585 ret = err; 651 ret = err;
586 } 652 }
587 put_nfs_open_context(desc.ctx); 653 put_nfs_open_context(desc.ctx);