diff options
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 3 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 6 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 82 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 61 | ||||
-rw-r--r-- | net/sunrpc/xprt.c | 21 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 29 |
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 | ||
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 */ |
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); | ||
670 | out: | 672 | out: |
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; |
674 | err_depopulate: | 676 | err_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 | ||
685 | int | 687 | int |
686 | rpc_rmdir(char *path) | 688 | rpc_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); |
705 | out_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); | ||
734 | out: | 729 | out: |
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; |
738 | err_dput: | 733 | err_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 | ||
746 | int | 741 | int |
747 | rpc_unlink(char *path) | 742 | rpc_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); | ||
770 | out_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 | ||
710 | void | 710 | void xprt_end_transmit(struct rpc_task *task) |
711 | xprt_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 | ||
789 | static inline void do_xprt_reserve(struct rpc_task *task) | 774 | static 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 | */ | ||
425 | static 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); | ||
439 | out_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 | ||
1251 | static struct rpc_xprt_ops xs_tcp_ops = { | 1278 | static 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, |