diff options
| -rw-r--r-- | net/sunrpc/clnt.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index dab09dac8fc7..f09b7db2c492 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -750,14 +750,16 @@ EXPORT_SYMBOL_GPL(rpc_shutdown_client); | |||
| 750 | /* | 750 | /* |
| 751 | * Free an RPC client | 751 | * Free an RPC client |
| 752 | */ | 752 | */ |
| 753 | static void | 753 | static struct rpc_clnt * |
| 754 | rpc_free_client(struct rpc_clnt *clnt) | 754 | rpc_free_client(struct rpc_clnt *clnt) |
| 755 | { | 755 | { |
| 756 | struct rpc_clnt *parent = NULL; | ||
| 757 | |||
| 756 | dprintk_rcu("RPC: destroying %s client for %s\n", | 758 | dprintk_rcu("RPC: destroying %s client for %s\n", |
| 757 | clnt->cl_program->name, | 759 | clnt->cl_program->name, |
| 758 | rcu_dereference(clnt->cl_xprt)->servername); | 760 | rcu_dereference(clnt->cl_xprt)->servername); |
| 759 | if (clnt->cl_parent != clnt) | 761 | if (clnt->cl_parent != clnt) |
| 760 | rpc_release_client(clnt->cl_parent); | 762 | parent = clnt->cl_parent; |
| 761 | rpc_clnt_remove_pipedir(clnt); | 763 | rpc_clnt_remove_pipedir(clnt); |
| 762 | rpc_unregister_client(clnt); | 764 | rpc_unregister_client(clnt); |
| 763 | rpc_free_iostats(clnt->cl_metrics); | 765 | rpc_free_iostats(clnt->cl_metrics); |
| @@ -766,18 +768,17 @@ rpc_free_client(struct rpc_clnt *clnt) | |||
| 766 | rpciod_down(); | 768 | rpciod_down(); |
| 767 | rpc_free_clid(clnt); | 769 | rpc_free_clid(clnt); |
| 768 | kfree(clnt); | 770 | kfree(clnt); |
| 771 | return parent; | ||
| 769 | } | 772 | } |
| 770 | 773 | ||
| 771 | /* | 774 | /* |
| 772 | * Free an RPC client | 775 | * Free an RPC client |
| 773 | */ | 776 | */ |
| 774 | static void | 777 | static struct rpc_clnt * |
| 775 | rpc_free_auth(struct rpc_clnt *clnt) | 778 | rpc_free_auth(struct rpc_clnt *clnt) |
| 776 | { | 779 | { |
| 777 | if (clnt->cl_auth == NULL) { | 780 | if (clnt->cl_auth == NULL) |
| 778 | rpc_free_client(clnt); | 781 | return rpc_free_client(clnt); |
| 779 | return; | ||
| 780 | } | ||
| 781 | 782 | ||
| 782 | /* | 783 | /* |
| 783 | * Note: RPCSEC_GSS may need to send NULL RPC calls in order to | 784 | * Note: RPCSEC_GSS may need to send NULL RPC calls in order to |
| @@ -788,7 +789,8 @@ rpc_free_auth(struct rpc_clnt *clnt) | |||
| 788 | rpcauth_release(clnt->cl_auth); | 789 | rpcauth_release(clnt->cl_auth); |
| 789 | clnt->cl_auth = NULL; | 790 | clnt->cl_auth = NULL; |
| 790 | if (atomic_dec_and_test(&clnt->cl_count)) | 791 | if (atomic_dec_and_test(&clnt->cl_count)) |
| 791 | rpc_free_client(clnt); | 792 | return rpc_free_client(clnt); |
| 793 | return NULL; | ||
| 792 | } | 794 | } |
| 793 | 795 | ||
| 794 | /* | 796 | /* |
| @@ -799,10 +801,13 @@ rpc_release_client(struct rpc_clnt *clnt) | |||
| 799 | { | 801 | { |
| 800 | dprintk("RPC: rpc_release_client(%p)\n", clnt); | 802 | dprintk("RPC: rpc_release_client(%p)\n", clnt); |
| 801 | 803 | ||
| 802 | if (list_empty(&clnt->cl_tasks)) | 804 | do { |
| 803 | wake_up(&destroy_wait); | 805 | if (list_empty(&clnt->cl_tasks)) |
| 804 | if (atomic_dec_and_test(&clnt->cl_count)) | 806 | wake_up(&destroy_wait); |
| 805 | rpc_free_auth(clnt); | 807 | if (!atomic_dec_and_test(&clnt->cl_count)) |
| 808 | break; | ||
| 809 | clnt = rpc_free_auth(clnt); | ||
| 810 | } while (clnt != NULL); | ||
| 806 | } | 811 | } |
| 807 | EXPORT_SYMBOL_GPL(rpc_release_client); | 812 | EXPORT_SYMBOL_GPL(rpc_release_client); |
| 808 | 813 | ||
