diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-30 03:54:24 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-01-30 03:54:24 -0500 |
commit | 85004cc367abc000aa36c0d0e270ab609a68b0cb (patch) | |
tree | 5739aae778d67b6d119fe5c668313fc2823e9836 /fs/nfs/direct.c | |
parent | 149a051f82d2b3860fe32fa182dbc83a66274894 (diff) | |
parent | 3fbd67ad61f6d5a09ea717b56c50bc5c3d8042a8 (diff) |
Merge git://git.linux-nfs.org/pub/linux/nfs-2.6
* git://git.linux-nfs.org/pub/linux/nfs-2.6: (118 commits)
NFSv4: Iterate through all nfs_clients when the server recalls a delegation
NFSv4: Deal more correctly with duplicate delegations
NFS: Fix a potential race between umount and nfs_access_cache_shrinker()
NFS: Add an asynchronous delegreturn operation for use in nfs_clear_inode
nfs: convert NFS_*(inode) helpers to static inline
nfs: obliterate NFS_FLAGS macro
NFS: Address memory leaks in the NFS client mount option parser
nfs4: allow nfsv4 acls on non-regular-files
NFS: Optimise away the sigmask code in aio/dio reads and writes
SUNRPC: Don't bother changing the sigmask for asynchronous RPC calls
SUNRPC: rpcb_getport_sync() passes incorrect address size to rpc_create()
SUNRPC: Clean up block comment preceding rpcb_getport_sync()
SUNRPC: Use appropriate argument types in rpcb client
SUNRPC: rpcb_getport_sync() should use built-in hostname generator
SUNRPC: Clean up functions that free address_strings array
NFS: NFS version number is unsigned
NLM: Fix a bogus 'return' in nlmclnt_rpc_release
NLM: Introduce an arguments structure for nlmclnt_init()
NLM/NFS: Use cached nlm_host when calling nlmclnt_proc()
NFS: Invoke nlmclnt_init during NFS mount processing
...
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 124 |
1 files changed, 85 insertions, 39 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 3c9d16b4f80c..f8e165c7d5a6 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
@@ -188,12 +188,17 @@ static void nfs_direct_req_release(struct nfs_direct_req *dreq) | |||
188 | static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) | 188 | static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) |
189 | { | 189 | { |
190 | ssize_t result = -EIOCBQUEUED; | 190 | ssize_t result = -EIOCBQUEUED; |
191 | struct rpc_clnt *clnt; | ||
192 | sigset_t oldset; | ||
191 | 193 | ||
192 | /* Async requests don't wait here */ | 194 | /* Async requests don't wait here */ |
193 | if (dreq->iocb) | 195 | if (dreq->iocb) |
194 | goto out; | 196 | goto out; |
195 | 197 | ||
198 | clnt = NFS_CLIENT(dreq->inode); | ||
199 | rpc_clnt_sigmask(clnt, &oldset); | ||
196 | result = wait_for_completion_interruptible(&dreq->completion); | 200 | result = wait_for_completion_interruptible(&dreq->completion); |
201 | rpc_clnt_sigunmask(clnt, &oldset); | ||
197 | 202 | ||
198 | if (!result) | 203 | if (!result) |
199 | result = dreq->error; | 204 | result = dreq->error; |
@@ -272,6 +277,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
272 | unsigned long user_addr = (unsigned long)iov->iov_base; | 277 | unsigned long user_addr = (unsigned long)iov->iov_base; |
273 | size_t count = iov->iov_len; | 278 | size_t count = iov->iov_len; |
274 | size_t rsize = NFS_SERVER(inode)->rsize; | 279 | size_t rsize = NFS_SERVER(inode)->rsize; |
280 | struct rpc_task *task; | ||
281 | struct rpc_message msg = { | ||
282 | .rpc_cred = ctx->cred, | ||
283 | }; | ||
284 | struct rpc_task_setup task_setup_data = { | ||
285 | .rpc_client = NFS_CLIENT(inode), | ||
286 | .rpc_message = &msg, | ||
287 | .callback_ops = &nfs_read_direct_ops, | ||
288 | .flags = RPC_TASK_ASYNC, | ||
289 | }; | ||
275 | unsigned int pgbase; | 290 | unsigned int pgbase; |
276 | int result; | 291 | int result; |
277 | ssize_t started = 0; | 292 | ssize_t started = 0; |
@@ -311,7 +326,7 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
311 | 326 | ||
312 | data->req = (struct nfs_page *) dreq; | 327 | data->req = (struct nfs_page *) dreq; |
313 | data->inode = inode; | 328 | data->inode = inode; |
314 | data->cred = ctx->cred; | 329 | data->cred = msg.rpc_cred; |
315 | data->args.fh = NFS_FH(inode); | 330 | data->args.fh = NFS_FH(inode); |
316 | data->args.context = ctx; | 331 | data->args.context = ctx; |
317 | data->args.offset = pos; | 332 | data->args.offset = pos; |
@@ -321,14 +336,16 @@ static ssize_t nfs_direct_read_schedule_segment(struct nfs_direct_req *dreq, | |||
321 | data->res.fattr = &data->fattr; | 336 | data->res.fattr = &data->fattr; |
322 | data->res.eof = 0; | 337 | data->res.eof = 0; |
323 | data->res.count = bytes; | 338 | data->res.count = bytes; |
339 | msg.rpc_argp = &data->args; | ||
340 | msg.rpc_resp = &data->res; | ||
324 | 341 | ||
325 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 342 | task_setup_data.task = &data->task; |
326 | &nfs_read_direct_ops, data); | 343 | task_setup_data.callback_data = data; |
327 | NFS_PROTO(inode)->read_setup(data); | 344 | NFS_PROTO(inode)->read_setup(data, &msg); |
328 | |||
329 | data->task.tk_cookie = (unsigned long) inode; | ||
330 | 345 | ||
331 | rpc_execute(&data->task); | 346 | task = rpc_run_task(&task_setup_data); |
347 | if (!IS_ERR(task)) | ||
348 | rpc_put_task(task); | ||
332 | 349 | ||
333 | dprintk("NFS: %5u initiated direct read call " | 350 | dprintk("NFS: %5u initiated direct read call " |
334 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 351 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -391,9 +408,7 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
391 | unsigned long nr_segs, loff_t pos) | 408 | unsigned long nr_segs, loff_t pos) |
392 | { | 409 | { |
393 | ssize_t result = 0; | 410 | ssize_t result = 0; |
394 | sigset_t oldset; | ||
395 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 411 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
396 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | ||
397 | struct nfs_direct_req *dreq; | 412 | struct nfs_direct_req *dreq; |
398 | 413 | ||
399 | dreq = nfs_direct_req_alloc(); | 414 | dreq = nfs_direct_req_alloc(); |
@@ -405,11 +420,9 @@ static ssize_t nfs_direct_read(struct kiocb *iocb, const struct iovec *iov, | |||
405 | if (!is_sync_kiocb(iocb)) | 420 | if (!is_sync_kiocb(iocb)) |
406 | dreq->iocb = iocb; | 421 | dreq->iocb = iocb; |
407 | 422 | ||
408 | rpc_clnt_sigmask(clnt, &oldset); | ||
409 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); | 423 | result = nfs_direct_read_schedule_iovec(dreq, iov, nr_segs, pos); |
410 | if (!result) | 424 | if (!result) |
411 | result = nfs_direct_wait(dreq); | 425 | result = nfs_direct_wait(dreq); |
412 | rpc_clnt_sigunmask(clnt, &oldset); | ||
413 | nfs_direct_req_release(dreq); | 426 | nfs_direct_req_release(dreq); |
414 | 427 | ||
415 | return result; | 428 | return result; |
@@ -431,6 +444,15 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
431 | struct inode *inode = dreq->inode; | 444 | struct inode *inode = dreq->inode; |
432 | struct list_head *p; | 445 | struct list_head *p; |
433 | struct nfs_write_data *data; | 446 | struct nfs_write_data *data; |
447 | struct rpc_task *task; | ||
448 | struct rpc_message msg = { | ||
449 | .rpc_cred = dreq->ctx->cred, | ||
450 | }; | ||
451 | struct rpc_task_setup task_setup_data = { | ||
452 | .rpc_client = NFS_CLIENT(inode), | ||
453 | .callback_ops = &nfs_write_direct_ops, | ||
454 | .flags = RPC_TASK_ASYNC, | ||
455 | }; | ||
434 | 456 | ||
435 | dreq->count = 0; | 457 | dreq->count = 0; |
436 | get_dreq(dreq); | 458 | get_dreq(dreq); |
@@ -440,6 +462,9 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
440 | 462 | ||
441 | get_dreq(dreq); | 463 | get_dreq(dreq); |
442 | 464 | ||
465 | /* Use stable writes */ | ||
466 | data->args.stable = NFS_FILE_SYNC; | ||
467 | |||
443 | /* | 468 | /* |
444 | * Reset data->res. | 469 | * Reset data->res. |
445 | */ | 470 | */ |
@@ -451,17 +476,18 @@ static void nfs_direct_write_reschedule(struct nfs_direct_req *dreq) | |||
451 | * Reuse data->task; data->args should not have changed | 476 | * Reuse data->task; data->args should not have changed |
452 | * since the original request was sent. | 477 | * since the original request was sent. |
453 | */ | 478 | */ |
454 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 479 | task_setup_data.task = &data->task; |
455 | &nfs_write_direct_ops, data); | 480 | task_setup_data.callback_data = data; |
456 | NFS_PROTO(inode)->write_setup(data, FLUSH_STABLE); | 481 | msg.rpc_argp = &data->args; |
457 | 482 | msg.rpc_resp = &data->res; | |
458 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 483 | NFS_PROTO(inode)->write_setup(data, &msg); |
459 | data->task.tk_cookie = (unsigned long) inode; | ||
460 | 484 | ||
461 | /* | 485 | /* |
462 | * We're called via an RPC callback, so BKL is already held. | 486 | * We're called via an RPC callback, so BKL is already held. |
463 | */ | 487 | */ |
464 | rpc_execute(&data->task); | 488 | task = rpc_run_task(&task_setup_data); |
489 | if (!IS_ERR(task)) | ||
490 | rpc_put_task(task); | ||
465 | 491 | ||
466 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", | 492 | dprintk("NFS: %5u rescheduled direct write call (req %s/%Ld, %u bytes @ offset %Lu)\n", |
467 | data->task.tk_pid, | 493 | data->task.tk_pid, |
@@ -504,9 +530,23 @@ static const struct rpc_call_ops nfs_commit_direct_ops = { | |||
504 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | 530 | static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) |
505 | { | 531 | { |
506 | struct nfs_write_data *data = dreq->commit_data; | 532 | struct nfs_write_data *data = dreq->commit_data; |
533 | struct rpc_task *task; | ||
534 | struct rpc_message msg = { | ||
535 | .rpc_argp = &data->args, | ||
536 | .rpc_resp = &data->res, | ||
537 | .rpc_cred = dreq->ctx->cred, | ||
538 | }; | ||
539 | struct rpc_task_setup task_setup_data = { | ||
540 | .task = &data->task, | ||
541 | .rpc_client = NFS_CLIENT(dreq->inode), | ||
542 | .rpc_message = &msg, | ||
543 | .callback_ops = &nfs_commit_direct_ops, | ||
544 | .callback_data = data, | ||
545 | .flags = RPC_TASK_ASYNC, | ||
546 | }; | ||
507 | 547 | ||
508 | data->inode = dreq->inode; | 548 | data->inode = dreq->inode; |
509 | data->cred = dreq->ctx->cred; | 549 | data->cred = msg.rpc_cred; |
510 | 550 | ||
511 | data->args.fh = NFS_FH(data->inode); | 551 | data->args.fh = NFS_FH(data->inode); |
512 | data->args.offset = 0; | 552 | data->args.offset = 0; |
@@ -515,18 +555,16 @@ static void nfs_direct_commit_schedule(struct nfs_direct_req *dreq) | |||
515 | data->res.fattr = &data->fattr; | 555 | data->res.fattr = &data->fattr; |
516 | data->res.verf = &data->verf; | 556 | data->res.verf = &data->verf; |
517 | 557 | ||
518 | rpc_init_task(&data->task, NFS_CLIENT(dreq->inode), RPC_TASK_ASYNC, | 558 | NFS_PROTO(data->inode)->commit_setup(data, &msg); |
519 | &nfs_commit_direct_ops, data); | ||
520 | NFS_PROTO(data->inode)->commit_setup(data, 0); | ||
521 | 559 | ||
522 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | ||
523 | data->task.tk_cookie = (unsigned long)data->inode; | ||
524 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ | 560 | /* Note: task.tk_ops->rpc_release will free dreq->commit_data */ |
525 | dreq->commit_data = NULL; | 561 | dreq->commit_data = NULL; |
526 | 562 | ||
527 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 563 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); |
528 | 564 | ||
529 | rpc_execute(&data->task); | 565 | task = rpc_run_task(&task_setup_data); |
566 | if (!IS_ERR(task)) | ||
567 | rpc_put_task(task); | ||
530 | } | 568 | } |
531 | 569 | ||
532 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) | 570 | static void nfs_direct_write_complete(struct nfs_direct_req *dreq, struct inode *inode) |
@@ -641,6 +679,16 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
641 | struct inode *inode = ctx->path.dentry->d_inode; | 679 | struct inode *inode = ctx->path.dentry->d_inode; |
642 | unsigned long user_addr = (unsigned long)iov->iov_base; | 680 | unsigned long user_addr = (unsigned long)iov->iov_base; |
643 | size_t count = iov->iov_len; | 681 | size_t count = iov->iov_len; |
682 | struct rpc_task *task; | ||
683 | struct rpc_message msg = { | ||
684 | .rpc_cred = ctx->cred, | ||
685 | }; | ||
686 | struct rpc_task_setup task_setup_data = { | ||
687 | .rpc_client = NFS_CLIENT(inode), | ||
688 | .rpc_message = &msg, | ||
689 | .callback_ops = &nfs_write_direct_ops, | ||
690 | .flags = RPC_TASK_ASYNC, | ||
691 | }; | ||
644 | size_t wsize = NFS_SERVER(inode)->wsize; | 692 | size_t wsize = NFS_SERVER(inode)->wsize; |
645 | unsigned int pgbase; | 693 | unsigned int pgbase; |
646 | int result; | 694 | int result; |
@@ -683,25 +731,27 @@ static ssize_t nfs_direct_write_schedule_segment(struct nfs_direct_req *dreq, | |||
683 | 731 | ||
684 | data->req = (struct nfs_page *) dreq; | 732 | data->req = (struct nfs_page *) dreq; |
685 | data->inode = inode; | 733 | data->inode = inode; |
686 | data->cred = ctx->cred; | 734 | data->cred = msg.rpc_cred; |
687 | data->args.fh = NFS_FH(inode); | 735 | data->args.fh = NFS_FH(inode); |
688 | data->args.context = ctx; | 736 | data->args.context = ctx; |
689 | data->args.offset = pos; | 737 | data->args.offset = pos; |
690 | data->args.pgbase = pgbase; | 738 | data->args.pgbase = pgbase; |
691 | data->args.pages = data->pagevec; | 739 | data->args.pages = data->pagevec; |
692 | data->args.count = bytes; | 740 | data->args.count = bytes; |
741 | data->args.stable = sync; | ||
693 | data->res.fattr = &data->fattr; | 742 | data->res.fattr = &data->fattr; |
694 | data->res.count = bytes; | 743 | data->res.count = bytes; |
695 | data->res.verf = &data->verf; | 744 | data->res.verf = &data->verf; |
696 | 745 | ||
697 | rpc_init_task(&data->task, NFS_CLIENT(inode), RPC_TASK_ASYNC, | 746 | task_setup_data.task = &data->task; |
698 | &nfs_write_direct_ops, data); | 747 | task_setup_data.callback_data = data; |
699 | NFS_PROTO(inode)->write_setup(data, sync); | 748 | msg.rpc_argp = &data->args; |
700 | 749 | msg.rpc_resp = &data->res; | |
701 | data->task.tk_priority = RPC_PRIORITY_NORMAL; | 750 | NFS_PROTO(inode)->write_setup(data, &msg); |
702 | data->task.tk_cookie = (unsigned long) inode; | ||
703 | 751 | ||
704 | rpc_execute(&data->task); | 752 | task = rpc_run_task(&task_setup_data); |
753 | if (!IS_ERR(task)) | ||
754 | rpc_put_task(task); | ||
705 | 755 | ||
706 | dprintk("NFS: %5u initiated direct write call " | 756 | dprintk("NFS: %5u initiated direct write call " |
707 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", | 757 | "(req %s/%Ld, %zu bytes @ offset %Lu)\n", |
@@ -767,12 +817,10 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
767 | size_t count) | 817 | size_t count) |
768 | { | 818 | { |
769 | ssize_t result = 0; | 819 | ssize_t result = 0; |
770 | sigset_t oldset; | ||
771 | struct inode *inode = iocb->ki_filp->f_mapping->host; | 820 | struct inode *inode = iocb->ki_filp->f_mapping->host; |
772 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | ||
773 | struct nfs_direct_req *dreq; | 821 | struct nfs_direct_req *dreq; |
774 | size_t wsize = NFS_SERVER(inode)->wsize; | 822 | size_t wsize = NFS_SERVER(inode)->wsize; |
775 | int sync = 0; | 823 | int sync = NFS_UNSTABLE; |
776 | 824 | ||
777 | dreq = nfs_direct_req_alloc(); | 825 | dreq = nfs_direct_req_alloc(); |
778 | if (!dreq) | 826 | if (!dreq) |
@@ -780,18 +828,16 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
780 | nfs_alloc_commit_data(dreq); | 828 | nfs_alloc_commit_data(dreq); |
781 | 829 | ||
782 | if (dreq->commit_data == NULL || count < wsize) | 830 | if (dreq->commit_data == NULL || count < wsize) |
783 | sync = FLUSH_STABLE; | 831 | sync = NFS_FILE_SYNC; |
784 | 832 | ||
785 | dreq->inode = inode; | 833 | dreq->inode = inode; |
786 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); | 834 | dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); |
787 | if (!is_sync_kiocb(iocb)) | 835 | if (!is_sync_kiocb(iocb)) |
788 | dreq->iocb = iocb; | 836 | dreq->iocb = iocb; |
789 | 837 | ||
790 | rpc_clnt_sigmask(clnt, &oldset); | ||
791 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); | 838 | result = nfs_direct_write_schedule_iovec(dreq, iov, nr_segs, pos, sync); |
792 | if (!result) | 839 | if (!result) |
793 | result = nfs_direct_wait(dreq); | 840 | result = nfs_direct_wait(dreq); |
794 | rpc_clnt_sigunmask(clnt, &oldset); | ||
795 | nfs_direct_req_release(dreq); | 841 | nfs_direct_req_release(dreq); |
796 | 842 | ||
797 | return result; | 843 | return result; |