diff options
Diffstat (limited to 'fs/nfsd/nfs4callback.c')
-rw-r--r-- | fs/nfsd/nfs4callback.c | 91 |
1 files changed, 29 insertions, 62 deletions
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index d97e2009e310..4fe4be1ee82e 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
@@ -824,18 +824,8 @@ static void nfsd4_cb_done(struct rpc_task *task, void *calldata) | |||
824 | dprintk("%s: freed slot, new seqid=%d\n", __func__, | 824 | dprintk("%s: freed slot, new seqid=%d\n", __func__, |
825 | clp->cl_cb_session->se_cb_seq_nr); | 825 | clp->cl_cb_session->se_cb_seq_nr); |
826 | } | 826 | } |
827 | } | ||
828 | 827 | ||
829 | static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) | 828 | if (clp->cl_cb_client != task->tk_client) { |
830 | { | ||
831 | struct nfsd4_callback *cb = calldata; | ||
832 | struct nfs4_delegation *dp = to_delegation(cb); | ||
833 | struct nfs4_client *clp = cb->cb_clp; | ||
834 | struct rpc_clnt *current_rpc_client = clp->cl_cb_client; | ||
835 | |||
836 | nfsd4_cb_done(task, calldata); | ||
837 | |||
838 | if (current_rpc_client != task->tk_client) { | ||
839 | /* We're shutting down or changing cl_cb_client; leave | 829 | /* We're shutting down or changing cl_cb_client; leave |
840 | * it to nfsd4_process_cb_update to restart the call if | 830 | * it to nfsd4_process_cb_update to restart the call if |
841 | * necessary. */ | 831 | * necessary. */ |
@@ -844,45 +834,42 @@ static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) | |||
844 | 834 | ||
845 | if (cb->cb_done) | 835 | if (cb->cb_done) |
846 | return; | 836 | return; |
847 | switch (task->tk_status) { | 837 | |
838 | switch (cb->cb_ops->done(cb, task)) { | ||
848 | case 0: | 839 | case 0: |
840 | task->tk_status = 0; | ||
841 | rpc_restart_call_prepare(task); | ||
842 | return; | ||
843 | case 1: | ||
849 | break; | 844 | break; |
850 | case -EBADHANDLE: | 845 | case -1: |
851 | case -NFS4ERR_BAD_STATEID: | ||
852 | /* Race: client probably got cb_recall | ||
853 | * before open reply granting delegation */ | ||
854 | if (dp->dl_retries--) { | ||
855 | rpc_delay(task, 2*HZ); | ||
856 | task->tk_status = 0; | ||
857 | rpc_restart_call_prepare(task); | ||
858 | return; | ||
859 | } | ||
860 | default: | ||
861 | /* Network partition? */ | 846 | /* Network partition? */ |
862 | nfsd4_mark_cb_down(clp, task->tk_status); | 847 | nfsd4_mark_cb_down(clp, task->tk_status); |
848 | break; | ||
849 | default: | ||
850 | BUG(); | ||
863 | } | 851 | } |
864 | cb->cb_done = true; | 852 | cb->cb_done = true; |
865 | } | 853 | } |
866 | 854 | ||
867 | static void nfsd4_cb_recall_release(void *calldata) | 855 | static void nfsd4_cb_release(void *calldata) |
868 | { | 856 | { |
869 | struct nfsd4_callback *cb = calldata; | 857 | struct nfsd4_callback *cb = calldata; |
870 | struct nfs4_client *clp = cb->cb_clp; | 858 | struct nfs4_client *clp = cb->cb_clp; |
871 | 859 | ||
872 | if (cb->cb_done) { | 860 | if (cb->cb_done) { |
873 | struct nfs4_delegation *dp = to_delegation(cb); | ||
874 | |||
875 | spin_lock(&clp->cl_lock); | 861 | spin_lock(&clp->cl_lock); |
876 | list_del(&cb->cb_per_client); | 862 | list_del(&cb->cb_per_client); |
877 | spin_unlock(&clp->cl_lock); | 863 | spin_unlock(&clp->cl_lock); |
878 | nfs4_put_stid(&dp->dl_stid); | 864 | |
865 | cb->cb_ops->release(cb); | ||
879 | } | 866 | } |
880 | } | 867 | } |
881 | 868 | ||
882 | static const struct rpc_call_ops nfsd4_cb_recall_ops = { | 869 | static const struct rpc_call_ops nfsd4_cb_ops = { |
883 | .rpc_call_prepare = nfsd4_cb_prepare, | 870 | .rpc_call_prepare = nfsd4_cb_prepare, |
884 | .rpc_call_done = nfsd4_cb_recall_done, | 871 | .rpc_call_done = nfsd4_cb_done, |
885 | .rpc_release = nfsd4_cb_recall_release, | 872 | .rpc_release = nfsd4_cb_release, |
886 | }; | 873 | }; |
887 | 874 | ||
888 | int nfsd4_create_callback_queue(void) | 875 | int nfsd4_create_callback_queue(void) |
@@ -911,12 +898,6 @@ void nfsd4_shutdown_callback(struct nfs4_client *clp) | |||
911 | flush_workqueue(callback_wq); | 898 | flush_workqueue(callback_wq); |
912 | } | 899 | } |
913 | 900 | ||
914 | static void nfsd4_release_cb(struct nfsd4_callback *cb) | ||
915 | { | ||
916 | if (cb->cb_ops->rpc_release) | ||
917 | cb->cb_ops->rpc_release(cb); | ||
918 | } | ||
919 | |||
920 | /* requires cl_lock: */ | 901 | /* requires cl_lock: */ |
921 | static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp) | 902 | static struct nfsd4_conn * __nfsd4_find_backchannel(struct nfs4_client *clp) |
922 | { | 903 | { |
@@ -983,54 +964,40 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb) | |||
983 | } | 964 | } |
984 | 965 | ||
985 | static void | 966 | static void |
986 | nfsd4_run_callback_rpc(struct nfsd4_callback *cb) | 967 | nfsd4_run_cb_work(struct work_struct *work) |
987 | { | 968 | { |
969 | struct nfsd4_callback *cb = | ||
970 | container_of(work, struct nfsd4_callback, cb_work); | ||
988 | struct nfs4_client *clp = cb->cb_clp; | 971 | struct nfs4_client *clp = cb->cb_clp; |
989 | struct rpc_clnt *clnt; | 972 | struct rpc_clnt *clnt; |
990 | 973 | ||
974 | if (cb->cb_ops && cb->cb_ops->prepare) | ||
975 | cb->cb_ops->prepare(cb); | ||
976 | |||
991 | if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK) | 977 | if (clp->cl_flags & NFSD4_CLIENT_CB_FLAG_MASK) |
992 | nfsd4_process_cb_update(cb); | 978 | nfsd4_process_cb_update(cb); |
993 | 979 | ||
994 | clnt = clp->cl_cb_client; | 980 | clnt = clp->cl_cb_client; |
995 | if (!clnt) { | 981 | if (!clnt) { |
996 | /* Callback channel broken, or client killed; give up: */ | 982 | /* Callback channel broken, or client killed; give up: */ |
997 | nfsd4_release_cb(cb); | 983 | if (cb->cb_ops && cb->cb_ops->release) |
984 | cb->cb_ops->release(cb); | ||
998 | return; | 985 | return; |
999 | } | 986 | } |
1000 | cb->cb_msg.rpc_cred = clp->cl_cb_cred; | 987 | cb->cb_msg.rpc_cred = clp->cl_cb_cred; |
1001 | rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN, | 988 | rpc_call_async(clnt, &cb->cb_msg, RPC_TASK_SOFT | RPC_TASK_SOFTCONN, |
1002 | cb->cb_ops, cb); | 989 | cb->cb_ops ? &nfsd4_cb_ops : &nfsd4_cb_probe_ops, cb); |
1003 | } | ||
1004 | |||
1005 | void | ||
1006 | nfsd4_run_cb_null(struct work_struct *w) | ||
1007 | { | ||
1008 | struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, | ||
1009 | cb_work); | ||
1010 | nfsd4_run_callback_rpc(cb); | ||
1011 | } | ||
1012 | |||
1013 | void | ||
1014 | nfsd4_run_cb_recall(struct work_struct *w) | ||
1015 | { | ||
1016 | struct nfsd4_callback *cb = container_of(w, struct nfsd4_callback, | ||
1017 | cb_work); | ||
1018 | |||
1019 | nfsd4_prepare_cb_recall(to_delegation(cb)); | ||
1020 | nfsd4_run_callback_rpc(cb); | ||
1021 | } | 990 | } |
1022 | 991 | ||
1023 | void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, | 992 | void nfsd4_init_cb(struct nfsd4_callback *cb, struct nfs4_client *clp, |
1024 | enum nfsd4_cb_op op) | 993 | struct nfsd4_callback_ops *ops, enum nfsd4_cb_op op) |
1025 | { | 994 | { |
1026 | cb->cb_clp = clp; | 995 | cb->cb_clp = clp; |
1027 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[op]; | 996 | cb->cb_msg.rpc_proc = &nfs4_cb_procedures[op]; |
1028 | cb->cb_msg.rpc_argp = cb; | 997 | cb->cb_msg.rpc_argp = cb; |
1029 | cb->cb_msg.rpc_resp = cb; | 998 | cb->cb_msg.rpc_resp = cb; |
1030 | if (op == NFSPROC4_CLNT_CB_NULL) | 999 | cb->cb_ops = ops; |
1031 | cb->cb_ops = &nfsd4_cb_probe_ops; | 1000 | INIT_WORK(&cb->cb_work, nfsd4_run_cb_work); |
1032 | else | ||
1033 | cb->cb_ops = &nfsd4_cb_recall_ops; | ||
1034 | INIT_LIST_HEAD(&cb->cb_per_client); | 1001 | INIT_LIST_HEAD(&cb->cb_per_client); |
1035 | cb->cb_done = true; | 1002 | cb->cb_done = true; |
1036 | } | 1003 | } |