aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/clnt.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r--net/sunrpc/clnt.c82
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
184out_no_auth: 184out_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 }
190out_no_path: 189out_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)
331out_free: 332out_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);
941out_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 */
947static void
948call_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 */
997static void
998call_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 */