diff options
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r-- | fs/nfs/nfs4proc.c | 107 |
1 files changed, 62 insertions, 45 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index f988a9417b13..3d5d3c07d621 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -196,14 +196,12 @@ static void update_changeattr(struct inode *inode, struct nfs4_change_info *cinf | |||
196 | 196 | ||
197 | /* Helper for asynchronous RPC calls */ | 197 | /* Helper for asynchronous RPC calls */ |
198 | static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin, | 198 | static int nfs4_call_async(struct rpc_clnt *clnt, rpc_action tk_begin, |
199 | rpc_action tk_exit, void *calldata) | 199 | const struct rpc_call_ops *tk_ops, void *calldata) |
200 | { | 200 | { |
201 | struct rpc_task *task; | 201 | struct rpc_task *task; |
202 | 202 | ||
203 | if (!(task = rpc_new_task(clnt, tk_exit, RPC_TASK_ASYNC))) | 203 | if (!(task = rpc_new_task(clnt, RPC_TASK_ASYNC, tk_ops, calldata))) |
204 | return -ENOMEM; | 204 | return -ENOMEM; |
205 | |||
206 | task->tk_calldata = calldata; | ||
207 | task->tk_action = tk_begin; | 205 | task->tk_action = tk_begin; |
208 | rpc_execute(task); | 206 | rpc_execute(task); |
209 | return 0; | 207 | return 0; |
@@ -867,10 +865,10 @@ struct nfs4_closedata { | |||
867 | struct nfs_fattr fattr; | 865 | struct nfs_fattr fattr; |
868 | }; | 866 | }; |
869 | 867 | ||
870 | static void nfs4_free_closedata(struct nfs4_closedata *calldata) | 868 | static void nfs4_free_closedata(void *data) |
871 | { | 869 | { |
872 | struct nfs4_state *state = calldata->state; | 870 | struct nfs4_closedata *calldata = data; |
873 | struct nfs4_state_owner *sp = state->owner; | 871 | struct nfs4_state_owner *sp = calldata->state->owner; |
874 | 872 | ||
875 | nfs4_put_open_state(calldata->state); | 873 | nfs4_put_open_state(calldata->state); |
876 | nfs_free_seqid(calldata->arg.seqid); | 874 | nfs_free_seqid(calldata->arg.seqid); |
@@ -878,9 +876,9 @@ static void nfs4_free_closedata(struct nfs4_closedata *calldata) | |||
878 | kfree(calldata); | 876 | kfree(calldata); |
879 | } | 877 | } |
880 | 878 | ||
881 | static void nfs4_close_done(struct rpc_task *task) | 879 | static void nfs4_close_done(struct rpc_task *task, void *data) |
882 | { | 880 | { |
883 | struct nfs4_closedata *calldata = (struct nfs4_closedata *)task->tk_calldata; | 881 | struct nfs4_closedata *calldata = data; |
884 | struct nfs4_state *state = calldata->state; | 882 | struct nfs4_state *state = calldata->state; |
885 | struct nfs_server *server = NFS_SERVER(calldata->inode); | 883 | struct nfs_server *server = NFS_SERVER(calldata->inode); |
886 | 884 | ||
@@ -904,7 +902,6 @@ static void nfs4_close_done(struct rpc_task *task) | |||
904 | } | 902 | } |
905 | } | 903 | } |
906 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); | 904 | nfs_refresh_inode(calldata->inode, calldata->res.fattr); |
907 | nfs4_free_closedata(calldata); | ||
908 | } | 905 | } |
909 | 906 | ||
910 | static void nfs4_close_begin(struct rpc_task *task) | 907 | static void nfs4_close_begin(struct rpc_task *task) |
@@ -918,10 +915,8 @@ static void nfs4_close_begin(struct rpc_task *task) | |||
918 | .rpc_cred = state->owner->so_cred, | 915 | .rpc_cred = state->owner->so_cred, |
919 | }; | 916 | }; |
920 | int mode = 0, old_mode; | 917 | int mode = 0, old_mode; |
921 | int status; | ||
922 | 918 | ||
923 | status = nfs_wait_on_sequence(calldata->arg.seqid, task); | 919 | if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0) |
924 | if (status != 0) | ||
925 | return; | 920 | return; |
926 | /* Recalculate the new open mode in case someone reopened the file | 921 | /* Recalculate the new open mode in case someone reopened the file |
927 | * while we were waiting in line to be scheduled. | 922 | * while we were waiting in line to be scheduled. |
@@ -937,9 +932,8 @@ static void nfs4_close_begin(struct rpc_task *task) | |||
937 | spin_unlock(&calldata->inode->i_lock); | 932 | spin_unlock(&calldata->inode->i_lock); |
938 | spin_unlock(&state->owner->so_lock); | 933 | spin_unlock(&state->owner->so_lock); |
939 | if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) { | 934 | if (mode == old_mode || test_bit(NFS_DELEGATED_STATE, &state->flags)) { |
940 | nfs4_free_closedata(calldata); | 935 | /* Note: exit _without_ calling nfs4_close_done */ |
941 | task->tk_exit = NULL; | 936 | task->tk_action = NULL; |
942 | rpc_exit(task, 0); | ||
943 | return; | 937 | return; |
944 | } | 938 | } |
945 | nfs_fattr_init(calldata->res.fattr); | 939 | nfs_fattr_init(calldata->res.fattr); |
@@ -949,6 +943,11 @@ static void nfs4_close_begin(struct rpc_task *task) | |||
949 | rpc_call_setup(task, &msg, 0); | 943 | rpc_call_setup(task, &msg, 0); |
950 | } | 944 | } |
951 | 945 | ||
946 | static const struct rpc_call_ops nfs4_close_ops = { | ||
947 | .rpc_call_done = nfs4_close_done, | ||
948 | .rpc_release = nfs4_free_closedata, | ||
949 | }; | ||
950 | |||
952 | /* | 951 | /* |
953 | * It is possible for data to be read/written from a mem-mapped file | 952 | * It is possible for data to be read/written from a mem-mapped file |
954 | * after the sys_close call (which hits the vfs layer as a flush). | 953 | * after the sys_close call (which hits the vfs layer as a flush). |
@@ -982,7 +981,7 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state) | |||
982 | calldata->res.server = server; | 981 | calldata->res.server = server; |
983 | 982 | ||
984 | status = nfs4_call_async(server->client, nfs4_close_begin, | 983 | status = nfs4_call_async(server->client, nfs4_close_begin, |
985 | nfs4_close_done, calldata); | 984 | &nfs4_close_ops, calldata); |
986 | if (status == 0) | 985 | if (status == 0) |
987 | goto out; | 986 | goto out; |
988 | 987 | ||
@@ -2125,10 +2124,9 @@ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2125 | return err; | 2124 | return err; |
2126 | } | 2125 | } |
2127 | 2126 | ||
2128 | static void | 2127 | static void nfs4_read_done(struct rpc_task *task, void *calldata) |
2129 | nfs4_read_done(struct rpc_task *task) | ||
2130 | { | 2128 | { |
2131 | struct nfs_read_data *data = (struct nfs_read_data *) task->tk_calldata; | 2129 | struct nfs_read_data *data = calldata; |
2132 | struct inode *inode = data->inode; | 2130 | struct inode *inode = data->inode; |
2133 | 2131 | ||
2134 | if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { | 2132 | if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { |
@@ -2138,9 +2136,14 @@ nfs4_read_done(struct rpc_task *task) | |||
2138 | if (task->tk_status > 0) | 2136 | if (task->tk_status > 0) |
2139 | renew_lease(NFS_SERVER(inode), data->timestamp); | 2137 | renew_lease(NFS_SERVER(inode), data->timestamp); |
2140 | /* Call back common NFS readpage processing */ | 2138 | /* Call back common NFS readpage processing */ |
2141 | nfs_readpage_result(task); | 2139 | nfs_readpage_result(task, calldata); |
2142 | } | 2140 | } |
2143 | 2141 | ||
2142 | static const struct rpc_call_ops nfs4_read_ops = { | ||
2143 | .rpc_call_done = nfs4_read_done, | ||
2144 | .rpc_release = nfs_readdata_release, | ||
2145 | }; | ||
2146 | |||
2144 | static void | 2147 | static void |
2145 | nfs4_proc_read_setup(struct nfs_read_data *data) | 2148 | nfs4_proc_read_setup(struct nfs_read_data *data) |
2146 | { | 2149 | { |
@@ -2160,14 +2163,13 @@ nfs4_proc_read_setup(struct nfs_read_data *data) | |||
2160 | flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); | 2163 | flags = RPC_TASK_ASYNC | (IS_SWAPFILE(inode)? NFS_RPC_SWAPFLAGS : 0); |
2161 | 2164 | ||
2162 | /* Finalize the task. */ | 2165 | /* Finalize the task. */ |
2163 | rpc_init_task(task, NFS_CLIENT(inode), nfs4_read_done, flags); | 2166 | rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_read_ops, data); |
2164 | rpc_call_setup(task, &msg, 0); | 2167 | rpc_call_setup(task, &msg, 0); |
2165 | } | 2168 | } |
2166 | 2169 | ||
2167 | static void | 2170 | static void nfs4_write_done(struct rpc_task *task, void *calldata) |
2168 | nfs4_write_done(struct rpc_task *task) | ||
2169 | { | 2171 | { |
2170 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; | 2172 | struct nfs_write_data *data = calldata; |
2171 | struct inode *inode = data->inode; | 2173 | struct inode *inode = data->inode; |
2172 | 2174 | ||
2173 | if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { | 2175 | if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { |
@@ -2179,9 +2181,14 @@ nfs4_write_done(struct rpc_task *task) | |||
2179 | nfs_post_op_update_inode(inode, data->res.fattr); | 2181 | nfs_post_op_update_inode(inode, data->res.fattr); |
2180 | } | 2182 | } |
2181 | /* Call back common NFS writeback processing */ | 2183 | /* Call back common NFS writeback processing */ |
2182 | nfs_writeback_done(task); | 2184 | nfs_writeback_done(task, calldata); |
2183 | } | 2185 | } |
2184 | 2186 | ||
2187 | static const struct rpc_call_ops nfs4_write_ops = { | ||
2188 | .rpc_call_done = nfs4_write_done, | ||
2189 | .rpc_release = nfs_writedata_release, | ||
2190 | }; | ||
2191 | |||
2185 | static void | 2192 | static void |
2186 | nfs4_proc_write_setup(struct nfs_write_data *data, int how) | 2193 | nfs4_proc_write_setup(struct nfs_write_data *data, int how) |
2187 | { | 2194 | { |
@@ -2214,14 +2221,13 @@ nfs4_proc_write_setup(struct nfs_write_data *data, int how) | |||
2214 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | 2221 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; |
2215 | 2222 | ||
2216 | /* Finalize the task. */ | 2223 | /* Finalize the task. */ |
2217 | rpc_init_task(task, NFS_CLIENT(inode), nfs4_write_done, flags); | 2224 | rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_write_ops, data); |
2218 | rpc_call_setup(task, &msg, 0); | 2225 | rpc_call_setup(task, &msg, 0); |
2219 | } | 2226 | } |
2220 | 2227 | ||
2221 | static void | 2228 | static void nfs4_commit_done(struct rpc_task *task, void *calldata) |
2222 | nfs4_commit_done(struct rpc_task *task) | ||
2223 | { | 2229 | { |
2224 | struct nfs_write_data *data = (struct nfs_write_data *) task->tk_calldata; | 2230 | struct nfs_write_data *data = calldata; |
2225 | struct inode *inode = data->inode; | 2231 | struct inode *inode = data->inode; |
2226 | 2232 | ||
2227 | if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { | 2233 | if (nfs4_async_handle_error(task, NFS_SERVER(inode)) == -EAGAIN) { |
@@ -2231,9 +2237,14 @@ nfs4_commit_done(struct rpc_task *task) | |||
2231 | if (task->tk_status >= 0) | 2237 | if (task->tk_status >= 0) |
2232 | nfs_post_op_update_inode(inode, data->res.fattr); | 2238 | nfs_post_op_update_inode(inode, data->res.fattr); |
2233 | /* Call back common NFS writeback processing */ | 2239 | /* Call back common NFS writeback processing */ |
2234 | nfs_commit_done(task); | 2240 | nfs_commit_done(task, calldata); |
2235 | } | 2241 | } |
2236 | 2242 | ||
2243 | static const struct rpc_call_ops nfs4_commit_ops = { | ||
2244 | .rpc_call_done = nfs4_commit_done, | ||
2245 | .rpc_release = nfs_commit_release, | ||
2246 | }; | ||
2247 | |||
2237 | static void | 2248 | static void |
2238 | nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | 2249 | nfs4_proc_commit_setup(struct nfs_write_data *data, int how) |
2239 | { | 2250 | { |
@@ -2255,7 +2266,7 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | |||
2255 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; | 2266 | flags = (how & FLUSH_SYNC) ? 0 : RPC_TASK_ASYNC; |
2256 | 2267 | ||
2257 | /* Finalize the task. */ | 2268 | /* Finalize the task. */ |
2258 | rpc_init_task(task, NFS_CLIENT(inode), nfs4_commit_done, flags); | 2269 | rpc_init_task(task, NFS_CLIENT(inode), flags, &nfs4_commit_ops, data); |
2259 | rpc_call_setup(task, &msg, 0); | 2270 | rpc_call_setup(task, &msg, 0); |
2260 | } | 2271 | } |
2261 | 2272 | ||
@@ -2263,11 +2274,10 @@ nfs4_proc_commit_setup(struct nfs_write_data *data, int how) | |||
2263 | * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special | 2274 | * nfs4_proc_async_renew(): This is not one of the nfs_rpc_ops; it is a special |
2264 | * standalone procedure for queueing an asynchronous RENEW. | 2275 | * standalone procedure for queueing an asynchronous RENEW. |
2265 | */ | 2276 | */ |
2266 | static void | 2277 | static void nfs4_renew_done(struct rpc_task *task, void *data) |
2267 | renew_done(struct rpc_task *task) | ||
2268 | { | 2278 | { |
2269 | struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; | 2279 | struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; |
2270 | unsigned long timestamp = (unsigned long)task->tk_calldata; | 2280 | unsigned long timestamp = (unsigned long)data; |
2271 | 2281 | ||
2272 | if (task->tk_status < 0) { | 2282 | if (task->tk_status < 0) { |
2273 | switch (task->tk_status) { | 2283 | switch (task->tk_status) { |
@@ -2284,6 +2294,10 @@ renew_done(struct rpc_task *task) | |||
2284 | spin_unlock(&clp->cl_lock); | 2294 | spin_unlock(&clp->cl_lock); |
2285 | } | 2295 | } |
2286 | 2296 | ||
2297 | static const struct rpc_call_ops nfs4_renew_ops = { | ||
2298 | .rpc_call_done = nfs4_renew_done, | ||
2299 | }; | ||
2300 | |||
2287 | int | 2301 | int |
2288 | nfs4_proc_async_renew(struct nfs4_client *clp) | 2302 | nfs4_proc_async_renew(struct nfs4_client *clp) |
2289 | { | 2303 | { |
@@ -2294,7 +2308,7 @@ nfs4_proc_async_renew(struct nfs4_client *clp) | |||
2294 | }; | 2308 | }; |
2295 | 2309 | ||
2296 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, | 2310 | return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_SOFT, |
2297 | renew_done, (void *)jiffies); | 2311 | &nfs4_renew_ops, (void *)jiffies); |
2298 | } | 2312 | } |
2299 | 2313 | ||
2300 | int | 2314 | int |
@@ -2866,15 +2880,16 @@ static void nfs4_locku_release_calldata(struct nfs4_unlockdata *calldata) | |||
2866 | } | 2880 | } |
2867 | } | 2881 | } |
2868 | 2882 | ||
2869 | static void nfs4_locku_complete(struct nfs4_unlockdata *calldata) | 2883 | static void nfs4_locku_complete(void *data) |
2870 | { | 2884 | { |
2885 | struct nfs4_unlockdata *calldata = data; | ||
2871 | complete(&calldata->completion); | 2886 | complete(&calldata->completion); |
2872 | nfs4_locku_release_calldata(calldata); | 2887 | nfs4_locku_release_calldata(calldata); |
2873 | } | 2888 | } |
2874 | 2889 | ||
2875 | static void nfs4_locku_done(struct rpc_task *task) | 2890 | static void nfs4_locku_done(struct rpc_task *task, void *data) |
2876 | { | 2891 | { |
2877 | struct nfs4_unlockdata *calldata = (struct nfs4_unlockdata *)task->tk_calldata; | 2892 | struct nfs4_unlockdata *calldata = data; |
2878 | 2893 | ||
2879 | nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid); | 2894 | nfs_increment_lock_seqid(task->tk_status, calldata->luargs.seqid); |
2880 | switch (task->tk_status) { | 2895 | switch (task->tk_status) { |
@@ -2890,10 +2905,8 @@ static void nfs4_locku_done(struct rpc_task *task) | |||
2890 | default: | 2905 | default: |
2891 | if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) { | 2906 | if (nfs4_async_handle_error(task, calldata->res.server) == -EAGAIN) { |
2892 | rpc_restart_call(task); | 2907 | rpc_restart_call(task); |
2893 | return; | ||
2894 | } | 2908 | } |
2895 | } | 2909 | } |
2896 | nfs4_locku_complete(calldata); | ||
2897 | } | 2910 | } |
2898 | 2911 | ||
2899 | static void nfs4_locku_begin(struct rpc_task *task) | 2912 | static void nfs4_locku_begin(struct rpc_task *task) |
@@ -2911,14 +2924,18 @@ static void nfs4_locku_begin(struct rpc_task *task) | |||
2911 | if (status != 0) | 2924 | if (status != 0) |
2912 | return; | 2925 | return; |
2913 | if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { | 2926 | if ((calldata->lsp->ls_flags & NFS_LOCK_INITIALIZED) == 0) { |
2914 | nfs4_locku_complete(calldata); | 2927 | /* Note: exit _without_ running nfs4_locku_done */ |
2915 | task->tk_exit = NULL; | 2928 | task->tk_action = NULL; |
2916 | rpc_exit(task, 0); | ||
2917 | return; | 2929 | return; |
2918 | } | 2930 | } |
2919 | rpc_call_setup(task, &msg, 0); | 2931 | rpc_call_setup(task, &msg, 0); |
2920 | } | 2932 | } |
2921 | 2933 | ||
2934 | static const struct rpc_call_ops nfs4_locku_ops = { | ||
2935 | .rpc_call_done = nfs4_locku_done, | ||
2936 | .rpc_release = nfs4_locku_complete, | ||
2937 | }; | ||
2938 | |||
2922 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) | 2939 | static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request) |
2923 | { | 2940 | { |
2924 | struct nfs4_unlockdata *calldata; | 2941 | struct nfs4_unlockdata *calldata; |
@@ -2963,7 +2980,7 @@ static int nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock * | |||
2963 | init_completion(&calldata->completion); | 2980 | init_completion(&calldata->completion); |
2964 | 2981 | ||
2965 | status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin, | 2982 | status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_locku_begin, |
2966 | nfs4_locku_done, calldata); | 2983 | &nfs4_locku_ops, calldata); |
2967 | if (status == 0) | 2984 | if (status == 0) |
2968 | wait_for_completion_interruptible(&calldata->completion); | 2985 | wait_for_completion_interruptible(&calldata->completion); |
2969 | do_vfs_lock(request->fl_file, request); | 2986 | do_vfs_lock(request->fl_file, request); |