aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c3
-rw-r--r--net/sunrpc/cache.c6
-rw-r--r--net/sunrpc/clnt.c82
-rw-r--r--net/sunrpc/rpc_pipe.c61
-rw-r--r--net/sunrpc/xprt.c21
-rw-r--r--net/sunrpc/xprtsock.c29
6 files changed, 110 insertions, 92 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4a9aa9393b97..ef1cf5b476c8 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -718,8 +718,7 @@ gss_destroy(struct rpc_auth *auth)
718 auth, auth->au_flavor); 718 auth, auth->au_flavor);
719 719
720 gss_auth = container_of(auth, struct gss_auth, rpc_auth); 720 gss_auth = container_of(auth, struct gss_auth, rpc_auth);
721 rpc_unlink(gss_auth->path); 721 rpc_unlink(gss_auth->dentry);
722 dput(gss_auth->dentry);
723 gss_auth->dentry = NULL; 722 gss_auth->dentry = NULL;
724 gss_mech_put(gss_auth->mech); 723 gss_mech_put(gss_auth->mech);
725 724
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c
index 7026b0866b7b..00cb388ece03 100644
--- a/net/sunrpc/cache.c
+++ b/net/sunrpc/cache.c
@@ -71,7 +71,12 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
71 new = detail->alloc(); 71 new = detail->alloc();
72 if (!new) 72 if (!new)
73 return NULL; 73 return NULL;
74 /* must fully initialise 'new', else
75 * we might get lose if we need to
76 * cache_put it soon.
77 */
74 cache_init(new); 78 cache_init(new);
79 detail->init(new, key);
75 80
76 write_lock(&detail->hash_lock); 81 write_lock(&detail->hash_lock);
77 82
@@ -85,7 +90,6 @@ struct cache_head *sunrpc_cache_lookup(struct cache_detail *detail,
85 return tmp; 90 return tmp;
86 } 91 }
87 } 92 }
88 detail->init(new, key);
89 new->next = *head; 93 new->next = *head;
90 *head = new; 94 *head = new;
91 detail->entries++; 95 detail->entries++;
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 */
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c
index dc6cb93c8830..0b1a1ac8a4bc 100644
--- a/net/sunrpc/rpc_pipe.c
+++ b/net/sunrpc/rpc_pipe.c
@@ -539,6 +539,7 @@ repeat:
539 rpc_close_pipes(dentry->d_inode); 539 rpc_close_pipes(dentry->d_inode);
540 simple_unlink(dir, dentry); 540 simple_unlink(dir, dentry);
541 } 541 }
542 inode_dir_notify(dir, DN_DELETE);
542 dput(dentry); 543 dput(dentry);
543 } while (n); 544 } while (n);
544 goto repeat; 545 goto repeat;
@@ -610,8 +611,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry)
610 int error; 611 int error;
611 612
612 shrink_dcache_parent(dentry); 613 shrink_dcache_parent(dentry);
613 if (dentry->d_inode) 614 if (d_unhashed(dentry))
614 rpc_close_pipes(dentry->d_inode); 615 return 0;
615 if ((error = simple_rmdir(dir, dentry)) != 0) 616 if ((error = simple_rmdir(dir, dentry)) != 0)
616 return error; 617 return error;
617 if (!error) { 618 if (!error) {
@@ -667,10 +668,11 @@ rpc_mkdir(char *path, struct rpc_clnt *rpc_client)
667 RPCAUTH_info, RPCAUTH_EOF); 668 RPCAUTH_info, RPCAUTH_EOF);
668 if (error) 669 if (error)
669 goto err_depopulate; 670 goto err_depopulate;
671 dget(dentry);
670out: 672out:
671 mutex_unlock(&dir->i_mutex); 673 mutex_unlock(&dir->i_mutex);
672 rpc_release_path(&nd); 674 rpc_release_path(&nd);
673 return dget(dentry); 675 return dentry;
674err_depopulate: 676err_depopulate:
675 rpc_depopulate(dentry); 677 rpc_depopulate(dentry);
676 __rpc_rmdir(dir, dentry); 678 __rpc_rmdir(dir, dentry);
@@ -683,28 +685,20 @@ err_dput:
683} 685}
684 686
685int 687int
686rpc_rmdir(char *path) 688rpc_rmdir(struct dentry *dentry)
687{ 689{
688 struct nameidata nd; 690 struct dentry *parent;
689 struct dentry *dentry;
690 struct inode *dir; 691 struct inode *dir;
691 int error; 692 int error;
692 693
693 if ((error = rpc_lookup_parent(path, &nd)) != 0) 694 parent = dget_parent(dentry);
694 return error; 695 dir = parent->d_inode;
695 dir = nd.dentry->d_inode;
696 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 696 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
697 dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len);
698 if (IS_ERR(dentry)) {
699 error = PTR_ERR(dentry);
700 goto out_release;
701 }
702 rpc_depopulate(dentry); 697 rpc_depopulate(dentry);
703 error = __rpc_rmdir(dir, dentry); 698 error = __rpc_rmdir(dir, dentry);
704 dput(dentry); 699 dput(dentry);
705out_release:
706 mutex_unlock(&dir->i_mutex); 700 mutex_unlock(&dir->i_mutex);
707 rpc_release_path(&nd); 701 dput(parent);
708 return error; 702 return error;
709} 703}
710 704
@@ -731,10 +725,11 @@ rpc_mkpipe(char *path, void *private, struct rpc_pipe_ops *ops, int flags)
731 rpci->flags = flags; 725 rpci->flags = flags;
732 rpci->ops = ops; 726 rpci->ops = ops;
733 inode_dir_notify(dir, DN_CREATE); 727 inode_dir_notify(dir, DN_CREATE);
728 dget(dentry);
734out: 729out:
735 mutex_unlock(&dir->i_mutex); 730 mutex_unlock(&dir->i_mutex);
736 rpc_release_path(&nd); 731 rpc_release_path(&nd);
737 return dget(dentry); 732 return dentry;
738err_dput: 733err_dput:
739 dput(dentry); 734 dput(dentry);
740 dentry = ERR_PTR(-ENOMEM); 735 dentry = ERR_PTR(-ENOMEM);
@@ -744,32 +739,26 @@ err_dput:
744} 739}
745 740
746int 741int
747rpc_unlink(char *path) 742rpc_unlink(struct dentry *dentry)
748{ 743{
749 struct nameidata nd; 744 struct dentry *parent;
750 struct dentry *dentry;
751 struct inode *dir; 745 struct inode *dir;
752 int error; 746 int error = 0;
753 747
754 if ((error = rpc_lookup_parent(path, &nd)) != 0) 748 parent = dget_parent(dentry);
755 return error; 749 dir = parent->d_inode;
756 dir = nd.dentry->d_inode;
757 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); 750 mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT);
758 dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); 751 if (!d_unhashed(dentry)) {
759 if (IS_ERR(dentry)) { 752 d_drop(dentry);
760 error = PTR_ERR(dentry); 753 if (dentry->d_inode) {
761 goto out_release; 754 rpc_close_pipes(dentry->d_inode);
762 } 755 error = simple_unlink(dir, dentry);
763 d_drop(dentry); 756 }
764 if (dentry->d_inode) { 757 inode_dir_notify(dir, DN_DELETE);
765 rpc_close_pipes(dentry->d_inode);
766 error = simple_unlink(dir, dentry);
767 } 758 }
768 dput(dentry); 759 dput(dentry);
769 inode_dir_notify(dir, DN_DELETE);
770out_release:
771 mutex_unlock(&dir->i_mutex); 760 mutex_unlock(&dir->i_mutex);
772 rpc_release_path(&nd); 761 dput(parent);
773 return error; 762 return error;
774} 763}
775 764
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 313b68d892c6..e8c2bc4977f3 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -707,12 +707,9 @@ out_unlock:
707 return err; 707 return err;
708} 708}
709 709
710void 710void xprt_end_transmit(struct rpc_task *task)
711xprt_abort_transmit(struct rpc_task *task)
712{ 711{
713 struct rpc_xprt *xprt = task->tk_xprt; 712 xprt_release_write(task->tk_xprt, task);
714
715 xprt_release_write(xprt, task);
716} 713}
717 714
718/** 715/**
@@ -761,8 +758,6 @@ void xprt_transmit(struct rpc_task *task)
761 task->tk_status = -ENOTCONN; 758 task->tk_status = -ENOTCONN;
762 else if (!req->rq_received) 759 else if (!req->rq_received)
763 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); 760 rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer);
764
765 xprt->ops->release_xprt(xprt, task);
766 spin_unlock_bh(&xprt->transport_lock); 761 spin_unlock_bh(&xprt->transport_lock);
767 return; 762 return;
768 } 763 }
@@ -772,18 +767,8 @@ void xprt_transmit(struct rpc_task *task)
772 * schedq, and being picked up by a parallel run of rpciod(). 767 * schedq, and being picked up by a parallel run of rpciod().
773 */ 768 */
774 task->tk_status = status; 769 task->tk_status = status;
775 770 if (status == -ECONNREFUSED)
776 switch (status) {
777 case -ECONNREFUSED:
778 rpc_sleep_on(&xprt->sending, task, NULL, NULL); 771 rpc_sleep_on(&xprt->sending, task, NULL, NULL);
779 case -EAGAIN:
780 case -ENOTCONN:
781 return;
782 default:
783 break;
784 }
785 xprt_release_write(xprt, task);
786 return;
787} 772}
788 773
789static inline void do_xprt_reserve(struct rpc_task *task) 774static inline void do_xprt_reserve(struct rpc_task *task)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index ee678ed13b6f..441bd53f5eca 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -414,6 +414,33 @@ static int xs_tcp_send_request(struct rpc_task *task)
414} 414}
415 415
416/** 416/**
417 * xs_tcp_release_xprt - clean up after a tcp transmission
418 * @xprt: transport
419 * @task: rpc task
420 *
421 * This cleans up if an error causes us to abort the transmission of a request.
422 * In this case, the socket may need to be reset in order to avoid confusing
423 * the server.
424 */
425static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task)
426{
427 struct rpc_rqst *req;
428
429 if (task != xprt->snd_task)
430 return;
431 if (task == NULL)
432 goto out_release;
433 req = task->tk_rqstp;
434 if (req->rq_bytes_sent == 0)
435 goto out_release;
436 if (req->rq_bytes_sent == req->rq_snd_buf.len)
437 goto out_release;
438 set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state);
439out_release:
440 xprt_release_xprt(xprt, task);
441}
442
443/**
417 * xs_close - close a socket 444 * xs_close - close a socket
418 * @xprt: transport 445 * @xprt: transport
419 * 446 *
@@ -1250,7 +1277,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
1250 1277
1251static struct rpc_xprt_ops xs_tcp_ops = { 1278static struct rpc_xprt_ops xs_tcp_ops = {
1252 .reserve_xprt = xprt_reserve_xprt, 1279 .reserve_xprt = xprt_reserve_xprt,
1253 .release_xprt = xprt_release_xprt, 1280 .release_xprt = xs_tcp_release_xprt,
1254 .set_port = xs_set_port, 1281 .set_port = xs_set_port,
1255 .connect = xs_connect, 1282 .connect = xs_connect,
1256 .buf_alloc = rpc_malloc, 1283 .buf_alloc = rpc_malloc,