diff options
Diffstat (limited to 'fs/nfs/read.c')
-rw-r--r-- | fs/nfs/read.c | 58 |
1 files changed, 41 insertions, 17 deletions
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index ae3ddd24cf8f..2da255f0247f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -36,8 +36,8 @@ | |||
36 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE | 36 | #define NFSDBG_FACILITY NFSDBG_PAGECACHE |
37 | 37 | ||
38 | static int nfs_pagein_one(struct list_head *, struct inode *); | 38 | static int nfs_pagein_one(struct list_head *, struct inode *); |
39 | static void nfs_readpage_result_partial(struct nfs_read_data *, int); | 39 | static const struct rpc_call_ops nfs_read_partial_ops; |
40 | static void nfs_readpage_result_full(struct nfs_read_data *, int); | 40 | static const struct rpc_call_ops nfs_read_full_ops; |
41 | 41 | ||
42 | static kmem_cache_t *nfs_rdata_cachep; | 42 | static kmem_cache_t *nfs_rdata_cachep; |
43 | mempool_t *nfs_rdata_mempool; | 43 | mempool_t *nfs_rdata_mempool; |
@@ -200,9 +200,11 @@ static void nfs_readpage_release(struct nfs_page *req) | |||
200 | * Set up the NFS read request struct | 200 | * Set up the NFS read request struct |
201 | */ | 201 | */ |
202 | static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | 202 | static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, |
203 | const struct rpc_call_ops *call_ops, | ||
203 | unsigned int count, unsigned int offset) | 204 | unsigned int count, unsigned int offset) |
204 | { | 205 | { |
205 | struct inode *inode; | 206 | struct inode *inode; |
207 | int flags; | ||
206 | 208 | ||
207 | data->req = req; | 209 | data->req = req; |
208 | data->inode = inode = req->wb_context->dentry->d_inode; | 210 | data->inode = inode = req->wb_context->dentry->d_inode; |
@@ -220,6 +222,9 @@ static void nfs_read_rpcsetup(struct nfs_page *req, struct nfs_read_data *data, | |||
220 | data->res.eof = 0; | 222 | data->res.eof = 0; |
221 | nfs_fattr_init(&data->fattr); | 223 | nfs_fattr_init(&data->fattr); |
222 | 224 | ||
225 | /* Set up the initial task struct. */ | ||
226 | flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); | ||
227 | rpc_init_task(&data->task, NFS_CLIENT(inode), flags, call_ops, data); | ||
223 | NFS_PROTO(inode)->read_setup(data); | 228 | NFS_PROTO(inode)->read_setup(data); |
224 | 229 | ||
225 | data->task.tk_cookie = (unsigned long)inode; | 230 | data->task.tk_cookie = (unsigned long)inode; |
@@ -307,14 +312,15 @@ static int nfs_pagein_multi(struct list_head *head, struct inode *inode) | |||
307 | list_del_init(&data->pages); | 312 | list_del_init(&data->pages); |
308 | 313 | ||
309 | data->pagevec[0] = page; | 314 | data->pagevec[0] = page; |
310 | data->complete = nfs_readpage_result_partial; | ||
311 | 315 | ||
312 | if (nbytes > rsize) { | 316 | if (nbytes > rsize) { |
313 | nfs_read_rpcsetup(req, data, rsize, offset); | 317 | nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, |
318 | rsize, offset); | ||
314 | offset += rsize; | 319 | offset += rsize; |
315 | nbytes -= rsize; | 320 | nbytes -= rsize; |
316 | } else { | 321 | } else { |
317 | nfs_read_rpcsetup(req, data, nbytes, offset); | 322 | nfs_read_rpcsetup(req, data, &nfs_read_partial_ops, |
323 | nbytes, offset); | ||
318 | nbytes = 0; | 324 | nbytes = 0; |
319 | } | 325 | } |
320 | nfs_execute_read(data); | 326 | nfs_execute_read(data); |
@@ -360,8 +366,7 @@ static int nfs_pagein_one(struct list_head *head, struct inode *inode) | |||
360 | } | 366 | } |
361 | req = nfs_list_entry(data->pages.next); | 367 | req = nfs_list_entry(data->pages.next); |
362 | 368 | ||
363 | data->complete = nfs_readpage_result_full; | 369 | nfs_read_rpcsetup(req, data, &nfs_read_full_ops, count, 0); |
364 | nfs_read_rpcsetup(req, data, count, 0); | ||
365 | 370 | ||
366 | nfs_execute_read(data); | 371 | nfs_execute_read(data); |
367 | return 0; | 372 | return 0; |
@@ -395,12 +400,15 @@ nfs_pagein_list(struct list_head *head, int rpages) | |||
395 | /* | 400 | /* |
396 | * Handle a read reply that fills part of a page. | 401 | * Handle a read reply that fills part of a page. |
397 | */ | 402 | */ |
398 | static void nfs_readpage_result_partial(struct nfs_read_data *data, int status) | 403 | static void nfs_readpage_result_partial(struct rpc_task *task, void *calldata) |
399 | { | 404 | { |
405 | struct nfs_read_data *data = calldata; | ||
400 | struct nfs_page *req = data->req; | 406 | struct nfs_page *req = data->req; |
401 | struct page *page = req->wb_page; | 407 | struct page *page = req->wb_page; |
402 | 408 | ||
403 | if (status >= 0) { | 409 | if (nfs_readpage_result(task, data) != 0) |
410 | return; | ||
411 | if (task->tk_status >= 0) { | ||
404 | unsigned int request = data->args.count; | 412 | unsigned int request = data->args.count; |
405 | unsigned int result = data->res.count; | 413 | unsigned int result = data->res.count; |
406 | 414 | ||
@@ -419,20 +427,28 @@ static void nfs_readpage_result_partial(struct nfs_read_data *data, int status) | |||
419 | } | 427 | } |
420 | } | 428 | } |
421 | 429 | ||
430 | static const struct rpc_call_ops nfs_read_partial_ops = { | ||
431 | .rpc_call_done = nfs_readpage_result_partial, | ||
432 | .rpc_release = nfs_readdata_release, | ||
433 | }; | ||
434 | |||
422 | /* | 435 | /* |
423 | * This is the callback from RPC telling us whether a reply was | 436 | * This is the callback from RPC telling us whether a reply was |
424 | * received or some error occurred (timeout or socket shutdown). | 437 | * received or some error occurred (timeout or socket shutdown). |
425 | */ | 438 | */ |
426 | static void nfs_readpage_result_full(struct nfs_read_data *data, int status) | 439 | static void nfs_readpage_result_full(struct rpc_task *task, void *calldata) |
427 | { | 440 | { |
441 | struct nfs_read_data *data = calldata; | ||
428 | unsigned int count = data->res.count; | 442 | unsigned int count = data->res.count; |
429 | 443 | ||
444 | if (nfs_readpage_result(task, data) != 0) | ||
445 | return; | ||
430 | while (!list_empty(&data->pages)) { | 446 | while (!list_empty(&data->pages)) { |
431 | struct nfs_page *req = nfs_list_entry(data->pages.next); | 447 | struct nfs_page *req = nfs_list_entry(data->pages.next); |
432 | struct page *page = req->wb_page; | 448 | struct page *page = req->wb_page; |
433 | nfs_list_remove_request(req); | 449 | nfs_list_remove_request(req); |
434 | 450 | ||
435 | if (status >= 0) { | 451 | if (task->tk_status >= 0) { |
436 | if (count < PAGE_CACHE_SIZE) { | 452 | if (count < PAGE_CACHE_SIZE) { |
437 | if (count < req->wb_bytes) | 453 | if (count < req->wb_bytes) |
438 | memclear_highpage_flush(page, | 454 | memclear_highpage_flush(page, |
@@ -448,19 +464,27 @@ static void nfs_readpage_result_full(struct nfs_read_data *data, int status) | |||
448 | } | 464 | } |
449 | } | 465 | } |
450 | 466 | ||
467 | static const struct rpc_call_ops nfs_read_full_ops = { | ||
468 | .rpc_call_done = nfs_readpage_result_full, | ||
469 | .rpc_release = nfs_readdata_release, | ||
470 | }; | ||
471 | |||
451 | /* | 472 | /* |
452 | * This is the callback from RPC telling us whether a reply was | 473 | * This is the callback from RPC telling us whether a reply was |
453 | * received or some error occurred (timeout or socket shutdown). | 474 | * received or some error occurred (timeout or socket shutdown). |
454 | */ | 475 | */ |
455 | void nfs_readpage_result(struct rpc_task *task, void *calldata) | 476 | int nfs_readpage_result(struct rpc_task *task, struct nfs_read_data *data) |
456 | { | 477 | { |
457 | struct nfs_read_data *data = calldata; | ||
458 | struct nfs_readargs *argp = &data->args; | 478 | struct nfs_readargs *argp = &data->args; |
459 | struct nfs_readres *resp = &data->res; | 479 | struct nfs_readres *resp = &data->res; |
460 | int status = task->tk_status; | 480 | int status; |
461 | 481 | ||
462 | dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", | 482 | dprintk("NFS: %4d nfs_readpage_result, (status %d)\n", |
463 | task->tk_pid, status); | 483 | task->tk_pid, task->tk_status); |
484 | |||
485 | status = NFS_PROTO(data->inode)->read_done(task, data); | ||
486 | if (status != 0) | ||
487 | return status; | ||
464 | 488 | ||
465 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); | 489 | nfs_add_stats(data->inode, NFSIOS_SERVERREADBYTES, resp->count); |
466 | 490 | ||
@@ -474,14 +498,14 @@ void nfs_readpage_result(struct rpc_task *task, void *calldata) | |||
474 | argp->pgbase += resp->count; | 498 | argp->pgbase += resp->count; |
475 | argp->count -= resp->count; | 499 | argp->count -= resp->count; |
476 | rpc_restart_call(task); | 500 | rpc_restart_call(task); |
477 | return; | 501 | return -EAGAIN; |
478 | } | 502 | } |
479 | task->tk_status = -EIO; | 503 | task->tk_status = -EIO; |
480 | } | 504 | } |
481 | spin_lock(&data->inode->i_lock); | 505 | spin_lock(&data->inode->i_lock); |
482 | NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME; | 506 | NFS_I(data->inode)->cache_validity |= NFS_INO_INVALID_ATIME; |
483 | spin_unlock(&data->inode->i_lock); | 507 | spin_unlock(&data->inode->i_lock); |
484 | data->complete(data, status); | 508 | return 0; |
485 | } | 509 | } |
486 | 510 | ||
487 | /* | 511 | /* |