diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:27 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:27 -0500 |
commit | ec06c096edec0755534c7126f4caded69de131c2 (patch) | |
tree | 1f5b219c09dea1d9886cefe3ea3f7cef560a5e9a | |
parent | 788e7a89a03e364855583c0ab4649b94925efbb9 (diff) |
NFS: Cleanup of NFS read code
Same callback hierarchy inversion as for the NFS write calls. This patch is
not strictly speaking needed by the O_DIRECT code, but avoids confusing
differences between the asynchronous read and write code.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | fs/nfs/direct.c | 17 | ||||
-rw-r--r-- | fs/nfs/nfs3proc.c | 27 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 33 | ||||
-rw-r--r-- | fs/nfs/proc.c | 25 | ||||
-rw-r--r-- | fs/nfs/read.c | 58 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 4 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 |
7 files changed, 77 insertions, 89 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index fc07ce4885da..3f87a72bd137 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -218,14 +218,17 @@ static struct nfs_direct_req *nfs_direct_read_alloc(size_t nbytes, unsigned int | |||
218 | * until the RPCs complete. This could be long *after* we are woken up in | 218 | * until the RPCs complete. This could be long *after* we are woken up in |
219 | * nfs_direct_read_wait (for instance, if someone hits ^C on a slow server). | 219 | * nfs_direct_read_wait (for instance, if someone hits ^C on a slow server). |
220 | */ | 220 | */ |
221 | static void nfs_direct_read_result(struct nfs_read_data *data, int status) | 221 | static void nfs_direct_read_result(struct rpc_task *task, void *calldata) |
222 | { | 222 | { |
223 | struct nfs_read_data *data = calldata; | ||
223 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; | 224 | struct nfs_direct_req *dreq = (struct nfs_direct_req *) data->req; |
224 | 225 | ||
225 | if (likely(status >= 0)) | 226 | if (nfs_readpage_result(task, data) != 0) |
227 | return; | ||
228 | if (likely(task->tk_status >= 0)) | ||
226 | atomic_add(data->res.count, &dreq->count); | 229 | atomic_add(data->res.count, &dreq->count); |
227 | else | 230 | else |
228 | atomic_set(&dreq->error, status); | 231 | atomic_set(&dreq->error, task->tk_status); |
229 | 232 | ||
230 | if (unlikely(atomic_dec_and_test(&dreq->complete))) { | 233 | if (unlikely(atomic_dec_and_test(&dreq->complete))) { |
231 | nfs_free_user_pages(dreq->pages, dreq->npages, 1); | 234 | nfs_free_user_pages(dreq->pages, dreq->npages, 1); |
@@ -234,6 +237,11 @@ static void nfs_direct_read_result(struct nfs_read_data *data, int status) | |||
234 | } | 237 | } |
235 | } | 238 | } |
236 | 239 | ||
240 | static const struct rpc_call_ops nfs_read_direct_ops = { | ||
241 | .rpc_call_done = nfs_direct_read_result, | ||
242 | .rpc_release = nfs_readdata_release, | ||
243 | }; | ||
244 | |||
237 | /** | 245 | /** |
238 | * nfs_direct_read_schedule - dispatch NFS READ operations for a direct read | 246 | * nfs_direct_read_schedule - dispatch NFS READ operations for a direct read |
239 | * @dreq: address of nfs_direct_req struct for this request | 247 | * @dreq: address of nfs_direct_req struct for this request |
@@ -280,10 +288,11 @@ static void nfs_direct_read_schedule(struct nfs_direct_req *dreq, | |||
280 | data->res.eof = 0; | 288 | data->res.eof = 0; |
281 | data->res.count = bytes; | 289 | data->res.count = bytes; |
282 | 290 | ||
291 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | ||
292 | &nfs_read_direct_ops, data); | ||
283 | NFS_PROTO(inode)->read_setup(data); | 293 | NFS_PROTO(inode)->read_setup(data); |
284 | 294 | ||
285 | data->task.tk_cookie = (unsigned long) inode; | 295 | data->task.tk_cookie = (unsigned long) inode; |
286 | data->complete = nfs_direct_read_result; | ||
287 | 296 | ||
288 | lock_kernel(); | 297 | lock_kernel(); |
289 | rpc_execute(&data->task); | 298 | rpc_execute(&data->task); |
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index c4f7de8830e9..cf186f0d2b3b 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c | |||
@@ -811,29 +811,18 @@ nfs3_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
811 | 811 | ||
812 | extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); | 812 | extern u32 *nfs3_decode_dirent(u32 *, struct nfs_entry *, int); |
813 | 813 | ||
814 | static void nfs3_read_done(struct rpc_task *task, void *calldata) | 814 | static int nfs3_read_done(struct rpc_task *task, struct nfs_read_data *data) |
815 | { | 815 | { |
816 | struct nfs_read_data *data = calldata; | ||
817 | |||
818 | if (nfs3_async_handle_jukebox(task, data->inode)) | 816 | if (nfs3_async_handle_jukebox(task, data->inode)) |
819 | return; | 817 | return -EAGAIN; |
820 | /* Call back common NFS readpage processing */ | 818 | /* Call back common NFS readpage processing */ |
821 | if (task->tk_status >= 0) | 819 | if (task->tk_status >= 0) |
822 | nfs_refresh_inode(data->inode, &data->fattr); | 820 | nfs_refresh_inode(data->inode, &data->fattr); |
823 | nfs_readpage_result(task, calldata); | 821 | return 0; |
824 | } | 822 | } |
825 | 823 | ||
826 | static const struct rpc_call_ops nfs3_read_ops = { | 824 | static void nfs3_proc_read_setup(struct nfs_read_data *data) |
827 | .rpc_call_done = nfs3_read_done, | ||
828 | .rpc_release = nfs_readdata_release, | ||
829 | }; | ||
830 | |||
831 | static void | ||
832 | nfs3_proc_read_setup(struct nfs_read_data *data) | ||
833 | { | 825 | { |
834 | struct rpc_task *task = &data->task; | ||
835 | struct inode *inode = data->inode; | ||
836 | int flags; | ||
837 | struct rpc_message msg = { | 826 | struct rpc_message msg = { |
838 | .rpc_proc = &nfs3_procedures[NFS3PROC_READ], | 827 | .rpc_proc = &nfs3_procedures[NFS3PROC_READ], |
839 | .rpc_argp = &data->args, | 828 | .rpc_argp = &data->args, |
@@ -841,12 +830,7 @@ nfs3_proc_read_setup(struct nfs_read_data *data) | |||
841 | .rpc_cred = data->cred, | 830 | .rpc_cred = data->cred, |
842 | }; | 831 | }; |
843 | 832 | ||
844 | /* N.B. Do we need to test? Never called for swapfile inode */ | 833 | rpc_call_setup(&data->task, &msg, 0); |
845 | flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); | ||
846 | |||
847 | /* Finalize the task. */ | ||
848 | rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs3_read_ops, data); | ||
849 | rpc_call_setup(task, &msg, 0); | ||
850 | } | 834 | } |
851 | 835 | ||
852 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) | 836 | static int nfs3_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -935,6 +919,7 @@ struct nfs_rpc_ops nfs_v3_clientops = { | |||
935 | .pathconf = nfs3_proc_pathconf, | 919 | .pathconf = nfs3_proc_pathconf, |
936 | .decode_dirent = nfs3_decode_dirent, | 920 | .decode_dirent = nfs3_decode_dirent, |
937 | .read_setup = nfs3_proc_read_setup, | 921 | .read_setup = nfs3_proc_read_setup, |
922 | .read_done = nfs3_read_done, | ||
938 | .write_setup = nfs3_proc_write_setup, | 923 | .write_setup = nfs3_proc_write_setup, |
939 | .write_done = nfs3_write_done, | 924 | .write_done = nfs3_write_done, |
940 | .commit_setup = nfs3_proc_commit_setup, | 925 | .commit_setup = nfs3_proc_commit_setup, |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index ef4dc315ecc2..bad1eae5608a 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2345,47 +2345,31 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2345 | return err; | 2345 | return err; |
2346 | } | 2346 | } |
2347 | 2347 | ||
2348 | static void nfs4_read_done(struct rpc_task *task, void *calldata) | 2348 | static int nfs4_read_done(struct rpc_task *task, struct nfs_read_data *data) |
2349 | { | 2349 | { |
2350 | struct nfs_read_data *data = calldata; | 2350 | struct nfs_server *server = NFS_SERVER(data->inode); |
2351 | struct inode *inode = data->inode; | ||
2352 | 2351 | ||
2353 | if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { | 2352 | if (nfs4_async_handle_error(task, server) == -EAGAIN) { |
2354 | rpc_restart_call(task); | 2353 | rpc_restart_call(task); |
2355 | return; | 2354 | return -EAGAIN; |
2356 | } | 2355 | } |
2357 | if (task->tk_status > 0) | 2356 | if (task->tk_status > 0) |
2358 | renew_lease(NFS_SERVER(inode), data->timestamp); | 2357 | renew_lease(server, data->timestamp); |
2359 | /* Call back common NFS readpage processing */ | 2358 | return 0; |
2360 | nfs_readpage_result(task, calldata); | ||
2361 | } | 2359 | } |
2362 | 2360 | ||
2363 | static const struct rpc_call_ops nfs4_read_ops = { | 2361 | static void nfs4_proc_read_setup(struct nfs_read_data *data) |
2364 | .rpc_call_done = nfs4_read_done, | ||
2365 | .rpc_release = nfs_readdata_release, | ||
2366 | }; | ||
2367 | |||
2368 | static void | ||
2369 | nfs4_proc_read_setup(struct nfs_read_data *data) | ||
2370 | { | 2362 | { |
2371 | struct rpc_task *task = &data->task; | ||
2372 | struct rpc_message msg = { | 2363 | struct rpc_message msg = { |
2373 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], | 2364 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_READ], |
2374 | .rpc_argp = &data->args, | 2365 | .rpc_argp = &data->args, |
2375 | .rpc_resp = &data->res, | 2366 | .rpc_resp = &data->res, |
2376 | .rpc_cred = data->cred, | 2367 | .rpc_cred = data->cred, |
2377 | }; | 2368 | }; |
2378 | struct inode *inode = data->inode; | ||
2379 | int flags; | ||
2380 | 2369 | ||
2381 | data->timestamp = jiffies; | 2370 | data->timestamp = jiffies; |
2382 | 2371 | ||
2383 | /* N.B. Do we need to test? Never called for swapfile inode */ | 2372 | rpc_call_setup(&data->task, &msg, 0); |
2384 | flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); | ||
2385 | |||
2386 | /* Finalize the task. */ | ||
2387 | rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_read_ops, data); | ||
2388 | rpc_call_setup(task, &msg, 0); | ||
2389 | } | 2373 | } |
2390 | 2374 | ||
2391 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) | 2375 | static int nfs4_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -3617,6 +3601,7 @@ struct nfs_rpc_ops nfs_v4_clientops = { | |||
3617 | .pathconf = nfs4_proc_pathconf, | 3601 | .pathconf = nfs4_proc_pathconf, |
3618 | .decode_dirent = nfs4_decode_dirent, | 3602 | .decode_dirent = nfs4_decode_dirent, |
3619 | .read_setup = nfs4_proc_read_setup, | 3603 | .read_setup = nfs4_proc_read_setup, |
3604 | .read_done = nfs4_read_done, | ||
3620 | .write_setup = nfs4_proc_write_setup, | 3605 | .write_setup = nfs4_proc_write_setup, |
3621 | .write_done = nfs4_write_done, | 3606 | .write_done = nfs4_write_done, |
3622 | .commit_setup = nfs4_proc_commit_setup, | 3607 | .commit_setup = nfs4_proc_commit_setup, |
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 608aa5932a1d..9dd85cac2df0 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
@@ -613,10 +613,8 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
613 | 613 | ||
614 | extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); | 614 | extern u32 * nfs_decode_dirent(u32 *, struct nfs_entry *, int); |
615 | 615 | ||
616 | static void nfs_read_done(struct rpc_task *task, void *calldata) | 616 | static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) |
617 | { | 617 | { |
618 | struct nfs_read_data *data = calldata; | ||
619 | |||
620 | if (task->tk_status >= 0) { | 618 | if (task->tk_status >= 0) { |
621 | nfs_refresh_inode(data->inode, data->res.fattr); | 619 | nfs_refresh_inode(data->inode, data->res.fattr); |
622 | /* Emulate the eof flag, which isn't normally needed in NFSv2 | 620 | /* Emulate the eof flag, which isn't normally needed in NFSv2 |
@@ -625,20 +623,11 @@ static void nfs_read_done(struct rpc_task *task, void *calldata) | |||
625 | if (data->args.offset + data->args.count >= data->res.fattr->size) | 623 | if (data->args.offset + data->args.count >= data->res.fattr->size) |
626 | data->res.eof = 1; | 624 | data->res.eof = 1; |
627 | } | 625 | } |
628 | nfs_readpage_result(task, calldata); | 626 | return 0; |
629 | } | 627 | } |
630 | 628 | ||
631 | static const struct rpc_call_ops nfs_read_ops = { | 629 | static void nfs_proc_read_setup(struct nfs_read_data *data) |
632 | .rpc_call_done = nfs_read_done, | ||
633 | .rpc_release = nfs_readdata_release, | ||
634 | }; | ||
635 | |||
636 | static void | ||
637 | nfs_proc_read_setup(struct nfs_read_data *data) | ||
638 | { | 630 | { |
639 | struct rpc_task *task = &data->task; | ||
640 | struct inode *inode = data->inode; | ||
641 | int flags; | ||
642 | struct rpc_message msg = { | 631 | struct rpc_message msg = { |
643 | .rpc_proc = &nfs_procedures[NFSPROC_READ], | 632 | .rpc_proc = &nfs_procedures[NFSPROC_READ], |
644 | .rpc_argp = &data->args, | 633 | .rpc_argp = &data->args, |
@@ -646,12 +635,7 @@ nfs_proc_read_setup(struct nfs_read_data *data) | |||
646 | .rpc_cred = data->cred, | 635 | .rpc_cred = data->cred, |
647 | }; | 636 | }; |
648 | 637 | ||
649 | /* N.B. Do we need to test? Never called for swapfile inode */ | 638 | rpc_call_setup(&data->task, &msg, 0); |
650 | flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); | ||
651 | |||
652 | /* Finalize the task. */ | ||
653 | rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs_read_ops, data); | ||
654 | rpc_call_setup(task, &msg, 0); | ||
655 | } | 639 | } |
656 | 640 | ||
657 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) | 641 | static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) |
@@ -720,6 +704,7 @@ struct nfs_rpc_ops nfs_v2_clientops = { | |||
720 | .pathconf = nfs_proc_pathconf, | 704 | .pathconf = nfs_proc_pathconf, |
721 | .decode_dirent = nfs_decode_dirent, | 705 | .decode_dirent = nfs_decode_dirent, |
722 | .read_setup = nfs_proc_read_setup, | 706 | .read_setup = nfs_proc_read_setup, |
707 | .read_done = nfs_read_done, | ||
723 | .write_setup = nfs_proc_write_setup, | 708 | .write_setup = nfs_proc_write_setup, |
724 | .write_done = nfs_write_done, | 709 | .write_done = nfs_write_done, |
725 | .commit_setup = nfs_proc_commit_setup, | 710 | .commit_setup = nfs_proc_commit_setup, |
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 | /* |
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 782e59765696..f55827be4f8e 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -492,8 +492,8 @@ static inline void nfs_writedata_free(struct nfs_write_data *p) | |||
492 | extern int nfs_readpage(struct file *, struct page *); | 492 | extern int nfs_readpage(struct file *, struct page *); |
493 | extern int nfs_readpages(struct file *, struct address_space *, | 493 | extern int nfs_readpages(struct file *, struct address_space *, |
494 | struct list_head *, unsigned); | 494 | struct list_head *, unsigned); |
495 | extern void nfs_readpage_result(struct rpc_task *, void *); | 495 | extern int nfs_readpage_result(struct rpc_task *, struct nfs_read_data *); |
496 | extern void nfs_readdata_release(void *data); | 496 | extern void nfs_readdata_release(void *data); |
497 | 497 | ||
498 | 498 | ||
499 | /* | 499 | /* |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 277750cc70c0..7fafc4c546b7 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -695,7 +695,6 @@ struct nfs_read_data { | |||
695 | #ifdef CONFIG_NFS_V4 | 695 | #ifdef CONFIG_NFS_V4 |
696 | unsigned long timestamp; /* For lease renewal */ | 696 | unsigned long timestamp; /* For lease renewal */ |
697 | #endif | 697 | #endif |
698 | void (*complete) (struct nfs_read_data *, int); | ||
699 | struct page *page_array[NFS_PAGEVEC_SIZE + 1]; | 698 | struct page *page_array[NFS_PAGEVEC_SIZE + 1]; |
700 | }; | 699 | }; |
701 | 700 | ||
@@ -768,6 +767,7 @@ struct nfs_rpc_ops { | |||
768 | struct nfs_pathconf *); | 767 | struct nfs_pathconf *); |
769 | u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); | 768 | u32 * (*decode_dirent)(u32 *, struct nfs_entry *, int plus); |
770 | void (*read_setup) (struct nfs_read_data *); | 769 | void (*read_setup) (struct nfs_read_data *); |
770 | int (*read_done) (struct rpc_task *, struct nfs_read_data *); | ||
771 | void (*write_setup) (struct nfs_write_data *, int how); | 771 | void (*write_setup) (struct nfs_write_data *, int how); |
772 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); | 772 | int (*write_done) (struct rpc_task *, struct nfs_write_data *); |
773 | void (*commit_setup) (struct nfs_write_data *, int how); | 773 | void (*commit_setup) (struct nfs_write_data *, int how); |