diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 82 |
1 files changed, 48 insertions, 34 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 4ba271f892c8..3e19d321067a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -183,8 +183,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
183 | 183 | ||
184 | out_no_auth: | 184 | out_no_auth: |
185 | if (!IS_ERR(clnt->cl_dentry)) { | 185 | if (!IS_ERR(clnt->cl_dentry)) { |
186 | rpc_rmdir(clnt->cl_pathname); | 186 | rpc_rmdir(clnt->cl_dentry); |
187 | dput(clnt->cl_dentry); | ||
188 | rpc_put_mount(); | 187 | rpc_put_mount(); |
189 | } | 188 | } |
190 | out_no_path: | 189 | out_no_path: |
@@ -251,10 +250,8 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
251 | new->cl_autobind = 0; | 250 | new->cl_autobind = 0; |
252 | new->cl_oneshot = 0; | 251 | new->cl_oneshot = 0; |
253 | new->cl_dead = 0; | 252 | new->cl_dead = 0; |
254 | if (!IS_ERR(new->cl_dentry)) { | 253 | if (!IS_ERR(new->cl_dentry)) |
255 | dget(new->cl_dentry); | 254 | dget(new->cl_dentry); |
256 | rpc_get_mount(); | ||
257 | } | ||
258 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 255 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
259 | if (new->cl_auth) | 256 | if (new->cl_auth) |
260 | atomic_inc(&new->cl_auth->au_count); | 257 | atomic_inc(&new->cl_auth->au_count); |
@@ -317,11 +314,15 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
317 | clnt->cl_auth = NULL; | 314 | clnt->cl_auth = NULL; |
318 | } | 315 | } |
319 | if (clnt->cl_parent != clnt) { | 316 | if (clnt->cl_parent != clnt) { |
317 | if (!IS_ERR(clnt->cl_dentry)) | ||
318 | dput(clnt->cl_dentry); | ||
320 | rpc_destroy_client(clnt->cl_parent); | 319 | rpc_destroy_client(clnt->cl_parent); |
321 | goto out_free; | 320 | goto out_free; |
322 | } | 321 | } |
323 | if (clnt->cl_pathname[0]) | 322 | if (!IS_ERR(clnt->cl_dentry)) { |
324 | rpc_rmdir(clnt->cl_pathname); | 323 | rpc_rmdir(clnt->cl_dentry); |
324 | rpc_put_mount(); | ||
325 | } | ||
325 | if (clnt->cl_xprt) { | 326 | if (clnt->cl_xprt) { |
326 | xprt_destroy(clnt->cl_xprt); | 327 | xprt_destroy(clnt->cl_xprt); |
327 | clnt->cl_xprt = NULL; | 328 | clnt->cl_xprt = NULL; |
@@ -331,10 +332,6 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
331 | out_free: | 332 | out_free: |
332 | rpc_free_iostats(clnt->cl_metrics); | 333 | rpc_free_iostats(clnt->cl_metrics); |
333 | clnt->cl_metrics = NULL; | 334 | clnt->cl_metrics = NULL; |
334 | if (!IS_ERR(clnt->cl_dentry)) { | ||
335 | dput(clnt->cl_dentry); | ||
336 | rpc_put_mount(); | ||
337 | } | ||
338 | kfree(clnt); | 335 | kfree(clnt); |
339 | return 0; | 336 | return 0; |
340 | } | 337 | } |
@@ -921,26 +918,43 @@ call_transmit(struct rpc_task *task) | |||
921 | task->tk_status = xprt_prepare_transmit(task); | 918 | task->tk_status = xprt_prepare_transmit(task); |
922 | if (task->tk_status != 0) | 919 | if (task->tk_status != 0) |
923 | return; | 920 | return; |
921 | task->tk_action = call_transmit_status; | ||
924 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 922 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
925 | if (rpc_task_need_encode(task)) { | 923 | if (rpc_task_need_encode(task)) { |
926 | task->tk_rqstp->rq_bytes_sent = 0; | 924 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); |
927 | call_encode(task); | 925 | call_encode(task); |
928 | /* Did the encode result in an error condition? */ | 926 | /* Did the encode result in an error condition? */ |
929 | if (task->tk_status != 0) | 927 | if (task->tk_status != 0) |
930 | goto out_nosend; | 928 | return; |
931 | } | 929 | } |
932 | task->tk_action = call_transmit_status; | ||
933 | xprt_transmit(task); | 930 | xprt_transmit(task); |
934 | if (task->tk_status < 0) | 931 | if (task->tk_status < 0) |
935 | return; | 932 | return; |
936 | if (!task->tk_msg.rpc_proc->p_decode) { | 933 | /* |
937 | task->tk_action = rpc_exit_task; | 934 | * On success, ensure that we call xprt_end_transmit() before sleeping |
938 | rpc_wake_up_task(task); | 935 | * in order to allow access to the socket to other RPC requests. |
939 | } | 936 | */ |
940 | return; | 937 | call_transmit_status(task); |
941 | out_nosend: | 938 | if (task->tk_msg.rpc_proc->p_decode != NULL) |
942 | /* release socket write lock before attempting to handle error */ | 939 | return; |
943 | xprt_abort_transmit(task); | 940 | task->tk_action = rpc_exit_task; |
941 | rpc_wake_up_task(task); | ||
942 | } | ||
943 | |||
944 | /* | ||
945 | * 5a. Handle cleanup after a transmission | ||
946 | */ | ||
947 | static void | ||
948 | call_transmit_status(struct rpc_task *task) | ||
949 | { | ||
950 | task->tk_action = call_status; | ||
951 | /* | ||
952 | * Special case: if we've been waiting on the socket's write_space() | ||
953 | * callback, then don't call xprt_end_transmit(). | ||
954 | */ | ||
955 | if (task->tk_status == -EAGAIN) | ||
956 | return; | ||
957 | xprt_end_transmit(task); | ||
944 | rpc_task_force_reencode(task); | 958 | rpc_task_force_reencode(task); |
945 | } | 959 | } |
946 | 960 | ||
@@ -992,18 +1006,7 @@ call_status(struct rpc_task *task) | |||
992 | } | 1006 | } |
993 | 1007 | ||
994 | /* | 1008 | /* |
995 | * 6a. Handle transmission errors. | 1009 | * 6a. Handle RPC timeout |
996 | */ | ||
997 | static void | ||
998 | call_transmit_status(struct rpc_task *task) | ||
999 | { | ||
1000 | if (task->tk_status != -EAGAIN) | ||
1001 | rpc_task_force_reencode(task); | ||
1002 | call_status(task); | ||
1003 | } | ||
1004 | |||
1005 | /* | ||
1006 | * 6b. Handle RPC timeout | ||
1007 | * We do not release the request slot, so we keep using the | 1010 | * We do not release the request slot, so we keep using the |
1008 | * same XID for all retransmits. | 1011 | * same XID for all retransmits. |
1009 | */ | 1012 | */ |
@@ -1178,6 +1181,17 @@ call_verify(struct rpc_task *task) | |||
1178 | u32 *p = iov->iov_base, n; | 1181 | u32 *p = iov->iov_base, n; |
1179 | int error = -EACCES; | 1182 | int error = -EACCES; |
1180 | 1183 | ||
1184 | if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { | ||
1185 | /* RFC-1014 says that the representation of XDR data must be a | ||
1186 | * multiple of four bytes | ||
1187 | * - if it isn't pointer subtraction in the NFS client may give | ||
1188 | * undefined results | ||
1189 | */ | ||
1190 | printk(KERN_WARNING | ||
1191 | "call_verify: XDR representation not a multiple of" | ||
1192 | " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); | ||
1193 | goto out_eio; | ||
1194 | } | ||
1181 | if ((len -= 3) < 0) | 1195 | if ((len -= 3) < 0) |
1182 | goto out_overflow; | 1196 | goto out_overflow; |
1183 | p += 1; /* skip XID */ | 1197 | p += 1; /* skip XID */ |