diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 182 |
1 files changed, 133 insertions, 49 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 756fc324db9e..2388d83b68ff 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -414,6 +414,35 @@ out_no_clnt: | |||
414 | EXPORT_SYMBOL_GPL(rpc_clone_client); | 414 | EXPORT_SYMBOL_GPL(rpc_clone_client); |
415 | 415 | ||
416 | /* | 416 | /* |
417 | * Kill all tasks for the given client. | ||
418 | * XXX: kill their descendants as well? | ||
419 | */ | ||
420 | void rpc_killall_tasks(struct rpc_clnt *clnt) | ||
421 | { | ||
422 | struct rpc_task *rovr; | ||
423 | |||
424 | |||
425 | if (list_empty(&clnt->cl_tasks)) | ||
426 | return; | ||
427 | dprintk("RPC: killing all tasks for client %p\n", clnt); | ||
428 | /* | ||
429 | * Spin lock all_tasks to prevent changes... | ||
430 | */ | ||
431 | spin_lock(&clnt->cl_lock); | ||
432 | list_for_each_entry(rovr, &clnt->cl_tasks, tk_task) { | ||
433 | if (!RPC_IS_ACTIVATED(rovr)) | ||
434 | continue; | ||
435 | if (!(rovr->tk_flags & RPC_TASK_KILLED)) { | ||
436 | rovr->tk_flags |= RPC_TASK_KILLED; | ||
437 | rpc_exit(rovr, -EIO); | ||
438 | rpc_wake_up_queued_task(rovr->tk_waitqueue, rovr); | ||
439 | } | ||
440 | } | ||
441 | spin_unlock(&clnt->cl_lock); | ||
442 | } | ||
443 | EXPORT_SYMBOL_GPL(rpc_killall_tasks); | ||
444 | |||
445 | /* | ||
417 | * Properly shut down an RPC client, terminating all outstanding | 446 | * Properly shut down an RPC client, terminating all outstanding |
418 | * requests. | 447 | * requests. |
419 | */ | 448 | */ |
@@ -538,6 +567,49 @@ out: | |||
538 | } | 567 | } |
539 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); | 568 | EXPORT_SYMBOL_GPL(rpc_bind_new_program); |
540 | 569 | ||
570 | void rpc_task_release_client(struct rpc_task *task) | ||
571 | { | ||
572 | struct rpc_clnt *clnt = task->tk_client; | ||
573 | |||
574 | if (clnt != NULL) { | ||
575 | /* Remove from client task list */ | ||
576 | spin_lock(&clnt->cl_lock); | ||
577 | list_del(&task->tk_task); | ||
578 | spin_unlock(&clnt->cl_lock); | ||
579 | task->tk_client = NULL; | ||
580 | |||
581 | rpc_release_client(clnt); | ||
582 | } | ||
583 | } | ||
584 | |||
585 | static | ||
586 | void rpc_task_set_client(struct rpc_task *task, struct rpc_clnt *clnt) | ||
587 | { | ||
588 | if (clnt != NULL) { | ||
589 | rpc_task_release_client(task); | ||
590 | task->tk_client = clnt; | ||
591 | kref_get(&clnt->cl_kref); | ||
592 | if (clnt->cl_softrtry) | ||
593 | task->tk_flags |= RPC_TASK_SOFT; | ||
594 | /* Add to the client's list of all tasks */ | ||
595 | spin_lock(&clnt->cl_lock); | ||
596 | list_add_tail(&task->tk_task, &clnt->cl_tasks); | ||
597 | spin_unlock(&clnt->cl_lock); | ||
598 | } | ||
599 | } | ||
600 | |||
601 | static void | ||
602 | rpc_task_set_rpc_message(struct rpc_task *task, const struct rpc_message *msg) | ||
603 | { | ||
604 | if (msg != NULL) { | ||
605 | task->tk_msg.rpc_proc = msg->rpc_proc; | ||
606 | task->tk_msg.rpc_argp = msg->rpc_argp; | ||
607 | task->tk_msg.rpc_resp = msg->rpc_resp; | ||
608 | if (msg->rpc_cred != NULL) | ||
609 | task->tk_msg.rpc_cred = get_rpccred(msg->rpc_cred); | ||
610 | } | ||
611 | } | ||
612 | |||
541 | /* | 613 | /* |
542 | * Default callback for async RPC calls | 614 | * Default callback for async RPC calls |
543 | */ | 615 | */ |
@@ -562,6 +634,18 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data) | |||
562 | if (IS_ERR(task)) | 634 | if (IS_ERR(task)) |
563 | goto out; | 635 | goto out; |
564 | 636 | ||
637 | rpc_task_set_client(task, task_setup_data->rpc_client); | ||
638 | rpc_task_set_rpc_message(task, task_setup_data->rpc_message); | ||
639 | |||
640 | if (task->tk_status != 0) { | ||
641 | int ret = task->tk_status; | ||
642 | rpc_put_task(task); | ||
643 | return ERR_PTR(ret); | ||
644 | } | ||
645 | |||
646 | if (task->tk_action == NULL) | ||
647 | rpc_call_start(task); | ||
648 | |||
565 | atomic_inc(&task->tk_count); | 649 | atomic_inc(&task->tk_count); |
566 | rpc_execute(task); | 650 | rpc_execute(task); |
567 | out: | 651 | out: |
@@ -756,12 +840,13 @@ EXPORT_SYMBOL_GPL(rpc_force_rebind); | |||
756 | * Restart an (async) RPC call from the call_prepare state. | 840 | * Restart an (async) RPC call from the call_prepare state. |
757 | * Usually called from within the exit handler. | 841 | * Usually called from within the exit handler. |
758 | */ | 842 | */ |
759 | void | 843 | int |
760 | rpc_restart_call_prepare(struct rpc_task *task) | 844 | rpc_restart_call_prepare(struct rpc_task *task) |
761 | { | 845 | { |
762 | if (RPC_ASSASSINATED(task)) | 846 | if (RPC_ASSASSINATED(task)) |
763 | return; | 847 | return 0; |
764 | task->tk_action = rpc_prepare_task; | 848 | task->tk_action = rpc_prepare_task; |
849 | return 1; | ||
765 | } | 850 | } |
766 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | 851 | EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); |
767 | 852 | ||
@@ -769,13 +854,13 @@ EXPORT_SYMBOL_GPL(rpc_restart_call_prepare); | |||
769 | * Restart an (async) RPC call. Usually called from within the | 854 | * Restart an (async) RPC call. Usually called from within the |
770 | * exit handler. | 855 | * exit handler. |
771 | */ | 856 | */ |
772 | void | 857 | int |
773 | rpc_restart_call(struct rpc_task *task) | 858 | rpc_restart_call(struct rpc_task *task) |
774 | { | 859 | { |
775 | if (RPC_ASSASSINATED(task)) | 860 | if (RPC_ASSASSINATED(task)) |
776 | return; | 861 | return 0; |
777 | |||
778 | task->tk_action = call_start; | 862 | task->tk_action = call_start; |
863 | return 1; | ||
779 | } | 864 | } |
780 | EXPORT_SYMBOL_GPL(rpc_restart_call); | 865 | EXPORT_SYMBOL_GPL(rpc_restart_call); |
781 | 866 | ||
@@ -824,11 +909,6 @@ call_reserve(struct rpc_task *task) | |||
824 | { | 909 | { |
825 | dprint_status(task); | 910 | dprint_status(task); |
826 | 911 | ||
827 | if (!rpcauth_uptodatecred(task)) { | ||
828 | task->tk_action = call_refresh; | ||
829 | return; | ||
830 | } | ||
831 | |||
832 | task->tk_status = 0; | 912 | task->tk_status = 0; |
833 | task->tk_action = call_reserveresult; | 913 | task->tk_action = call_reserveresult; |
834 | xprt_reserve(task); | 914 | xprt_reserve(task); |
@@ -892,7 +972,7 @@ call_reserveresult(struct rpc_task *task) | |||
892 | static void | 972 | static void |
893 | call_allocate(struct rpc_task *task) | 973 | call_allocate(struct rpc_task *task) |
894 | { | 974 | { |
895 | unsigned int slack = task->tk_msg.rpc_cred->cr_auth->au_cslack; | 975 | unsigned int slack = task->tk_client->cl_auth->au_cslack; |
896 | struct rpc_rqst *req = task->tk_rqstp; | 976 | struct rpc_rqst *req = task->tk_rqstp; |
897 | struct rpc_xprt *xprt = task->tk_xprt; | 977 | struct rpc_xprt *xprt = task->tk_xprt; |
898 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; | 978 | struct rpc_procinfo *proc = task->tk_msg.rpc_proc; |
@@ -900,7 +980,7 @@ call_allocate(struct rpc_task *task) | |||
900 | dprint_status(task); | 980 | dprint_status(task); |
901 | 981 | ||
902 | task->tk_status = 0; | 982 | task->tk_status = 0; |
903 | task->tk_action = call_bind; | 983 | task->tk_action = call_refresh; |
904 | 984 | ||
905 | if (req->rq_buffer) | 985 | if (req->rq_buffer) |
906 | return; | 986 | return; |
@@ -937,6 +1017,47 @@ call_allocate(struct rpc_task *task) | |||
937 | rpc_exit(task, -ERESTARTSYS); | 1017 | rpc_exit(task, -ERESTARTSYS); |
938 | } | 1018 | } |
939 | 1019 | ||
1020 | /* | ||
1021 | * 2a. Bind and/or refresh the credentials | ||
1022 | */ | ||
1023 | static void | ||
1024 | call_refresh(struct rpc_task *task) | ||
1025 | { | ||
1026 | dprint_status(task); | ||
1027 | |||
1028 | task->tk_action = call_refreshresult; | ||
1029 | task->tk_status = 0; | ||
1030 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
1031 | rpcauth_refreshcred(task); | ||
1032 | } | ||
1033 | |||
1034 | /* | ||
1035 | * 2b. Process the results of a credential refresh | ||
1036 | */ | ||
1037 | static void | ||
1038 | call_refreshresult(struct rpc_task *task) | ||
1039 | { | ||
1040 | int status = task->tk_status; | ||
1041 | |||
1042 | dprint_status(task); | ||
1043 | |||
1044 | task->tk_status = 0; | ||
1045 | task->tk_action = call_bind; | ||
1046 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
1047 | return; | ||
1048 | switch (status) { | ||
1049 | case -EACCES: | ||
1050 | rpc_exit(task, -EACCES); | ||
1051 | return; | ||
1052 | case -ENOMEM: | ||
1053 | rpc_exit(task, -ENOMEM); | ||
1054 | return; | ||
1055 | case -ETIMEDOUT: | ||
1056 | rpc_delay(task, 3*HZ); | ||
1057 | } | ||
1058 | task->tk_action = call_refresh; | ||
1059 | } | ||
1060 | |||
940 | static inline int | 1061 | static inline int |
941 | rpc_task_need_encode(struct rpc_task *task) | 1062 | rpc_task_need_encode(struct rpc_task *task) |
942 | { | 1063 | { |
@@ -1472,43 +1593,6 @@ out_retry: | |||
1472 | } | 1593 | } |
1473 | } | 1594 | } |
1474 | 1595 | ||
1475 | /* | ||
1476 | * 8. Refresh the credentials if rejected by the server | ||
1477 | */ | ||
1478 | static void | ||
1479 | call_refresh(struct rpc_task *task) | ||
1480 | { | ||
1481 | dprint_status(task); | ||
1482 | |||
1483 | task->tk_action = call_refreshresult; | ||
1484 | task->tk_status = 0; | ||
1485 | task->tk_client->cl_stats->rpcauthrefresh++; | ||
1486 | rpcauth_refreshcred(task); | ||
1487 | } | ||
1488 | |||
1489 | /* | ||
1490 | * 8a. Process the results of a credential refresh | ||
1491 | */ | ||
1492 | static void | ||
1493 | call_refreshresult(struct rpc_task *task) | ||
1494 | { | ||
1495 | int status = task->tk_status; | ||
1496 | |||
1497 | dprint_status(task); | ||
1498 | |||
1499 | task->tk_status = 0; | ||
1500 | task->tk_action = call_reserve; | ||
1501 | if (status >= 0 && rpcauth_uptodatecred(task)) | ||
1502 | return; | ||
1503 | if (status == -EACCES) { | ||
1504 | rpc_exit(task, -EACCES); | ||
1505 | return; | ||
1506 | } | ||
1507 | task->tk_action = call_refresh; | ||
1508 | if (status != -ETIMEDOUT) | ||
1509 | rpc_delay(task, 3*HZ); | ||
1510 | } | ||
1511 | |||
1512 | static __be32 * | 1596 | static __be32 * |
1513 | rpc_encode_header(struct rpc_task *task) | 1597 | rpc_encode_header(struct rpc_task *task) |
1514 | { | 1598 | { |