aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sunrpc/clnt.c29
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 */
753static void 753static struct rpc_clnt *
754rpc_free_client(struct rpc_clnt *clnt) 754rpc_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 */
774static void 777static struct rpc_clnt *
775rpc_free_auth(struct rpc_clnt *clnt) 778rpc_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}
807EXPORT_SYMBOL_GPL(rpc_release_client); 812EXPORT_SYMBOL_GPL(rpc_release_client);
808 813