aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2013-08-27 16:52:16 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2013-09-01 11:12:43 -0400
commit414a629598409497c05f2387c22c77dee143b4ff (patch)
tree5e3e8d53c332feb71c6f6cb2f219a6cca3cea946 /net/sunrpc
parent298fc3558b9c1f5324c5ec6d5c587ca9ae6cc826 (diff)
RPCSEC_GSS: Share rpc_pipes when an rpc_clnt owns multiple rpcsec auth caches
Ensure that if an rpc_clnt owns more than one RPCSEC_GSS-based authentication mechanism, then those caches will share the same 'gssd' upcall pipe. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c77
1 files changed, 68 insertions, 9 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index d214aecdbeef..5ec15bb43e83 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -76,6 +76,7 @@ struct gss_pipe {
76 struct rpc_pipe *pipe; 76 struct rpc_pipe *pipe;
77 struct rpc_clnt *clnt; 77 struct rpc_clnt *clnt;
78 const char *name; 78 const char *name;
79 struct kref kref;
79}; 80};
80 81
81struct gss_auth { 82struct gss_auth {
@@ -832,7 +833,6 @@ static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt,
832 const char *name, 833 const char *name,
833 const struct rpc_pipe_ops *upcall_ops) 834 const struct rpc_pipe_ops *upcall_ops)
834{ 835{
835 struct net *net = rpc_net_ns(clnt);
836 struct gss_pipe *p; 836 struct gss_pipe *p;
837 int err = -ENOMEM; 837 int err = -ENOMEM;
838 838
@@ -846,19 +846,71 @@ static struct gss_pipe *gss_pipe_alloc(struct rpc_clnt *clnt,
846 } 846 }
847 p->name = name; 847 p->name = name;
848 p->clnt = clnt; 848 p->clnt = clnt;
849 kref_init(&p->kref);
849 rpc_init_pipe_dir_object(&p->pdo, 850 rpc_init_pipe_dir_object(&p->pdo,
850 &gss_pipe_dir_object_ops, 851 &gss_pipe_dir_object_ops,
851 p); 852 p);
852 err = rpc_add_pipe_dir_object(net, &clnt->cl_pipedir_objects, &p->pdo); 853 return p;
853 if (!err)
854 return p;
855 rpc_destroy_pipe_data(p->pipe);
856err_free_gss_pipe: 854err_free_gss_pipe:
857 kfree(p); 855 kfree(p);
858err: 856err:
859 return ERR_PTR(err); 857 return ERR_PTR(err);
860} 858}
861 859
860struct gss_alloc_pdo {
861 struct rpc_clnt *clnt;
862 const char *name;
863 const struct rpc_pipe_ops *upcall_ops;
864};
865
866static int gss_pipe_match_pdo(struct rpc_pipe_dir_object *pdo, void *data)
867{
868 struct gss_pipe *gss_pipe;
869 struct gss_alloc_pdo *args = data;
870
871 if (pdo->pdo_ops != &gss_pipe_dir_object_ops)
872 return 0;
873 gss_pipe = container_of(pdo, struct gss_pipe, pdo);
874 if (strcmp(gss_pipe->name, args->name) != 0)
875 return 0;
876 if (!kref_get_unless_zero(&gss_pipe->kref))
877 return 0;
878 return 1;
879}
880
881static struct rpc_pipe_dir_object *gss_pipe_alloc_pdo(void *data)
882{
883 struct gss_pipe *gss_pipe;
884 struct gss_alloc_pdo *args = data;
885
886 gss_pipe = gss_pipe_alloc(args->clnt, args->name, args->upcall_ops);
887 if (!IS_ERR(gss_pipe))
888 return &gss_pipe->pdo;
889 return NULL;
890}
891
892static struct gss_pipe *gss_pipe_get(struct rpc_clnt *clnt,
893 const char *name,
894 const struct rpc_pipe_ops *upcall_ops)
895{
896 struct net *net = rpc_net_ns(clnt);
897 struct rpc_pipe_dir_object *pdo;
898 struct gss_alloc_pdo args = {
899 .clnt = clnt,
900 .name = name,
901 .upcall_ops = upcall_ops,
902 };
903
904 pdo = rpc_find_or_alloc_pipe_dir_object(net,
905 &clnt->cl_pipedir_objects,
906 gss_pipe_match_pdo,
907 gss_pipe_alloc_pdo,
908 &args);
909 if (pdo != NULL)
910 return container_of(pdo, struct gss_pipe, pdo);
911 return ERR_PTR(-ENOMEM);
912}
913
862static void __gss_pipe_free(struct gss_pipe *p) 914static void __gss_pipe_free(struct gss_pipe *p)
863{ 915{
864 struct rpc_clnt *clnt = p->clnt; 916 struct rpc_clnt *clnt = p->clnt;
@@ -871,10 +923,17 @@ static void __gss_pipe_free(struct gss_pipe *p)
871 kfree(p); 923 kfree(p);
872} 924}
873 925
926static void __gss_pipe_release(struct kref *kref)
927{
928 struct gss_pipe *p = container_of(kref, struct gss_pipe, kref);
929
930 __gss_pipe_free(p);
931}
932
874static void gss_pipe_free(struct gss_pipe *p) 933static void gss_pipe_free(struct gss_pipe *p)
875{ 934{
876 if (p != NULL) 935 if (p != NULL)
877 __gss_pipe_free(p); 936 kref_put(&p->kref, __gss_pipe_release);
878} 937}
879 938
880/* 939/*
@@ -930,14 +989,14 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
930 * that we supported only the old pipe. So we instead create 989 * that we supported only the old pipe. So we instead create
931 * the new pipe first. 990 * the new pipe first.
932 */ 991 */
933 gss_pipe = gss_pipe_alloc(clnt, "gssd", &gss_upcall_ops_v1); 992 gss_pipe = gss_pipe_get(clnt, "gssd", &gss_upcall_ops_v1);
934 if (IS_ERR(gss_pipe)) { 993 if (IS_ERR(gss_pipe)) {
935 err = PTR_ERR(gss_pipe); 994 err = PTR_ERR(gss_pipe);
936 goto err_destroy_credcache; 995 goto err_destroy_credcache;
937 } 996 }
938 gss_auth->gss_pipe[1] = gss_pipe; 997 gss_auth->gss_pipe[1] = gss_pipe;
939 998
940 gss_pipe = gss_pipe_alloc(clnt, gss_auth->mech->gm_name, 999 gss_pipe = gss_pipe_get(clnt, gss_auth->mech->gm_name,
941 &gss_upcall_ops_v0); 1000 &gss_upcall_ops_v0);
942 if (IS_ERR(gss_pipe)) { 1001 if (IS_ERR(gss_pipe)) {
943 err = PTR_ERR(gss_pipe); 1002 err = PTR_ERR(gss_pipe);
@@ -947,7 +1006,7 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt)
947 1006
948 return auth; 1007 return auth;
949err_destroy_pipe_1: 1008err_destroy_pipe_1:
950 __gss_pipe_free(gss_auth->gss_pipe[1]); 1009 gss_pipe_free(gss_auth->gss_pipe[1]);
951err_destroy_credcache: 1010err_destroy_credcache:
952 rpcauth_destroy_credcache(auth); 1011 rpcauth_destroy_credcache(auth);
953err_put_mech: 1012err_put_mech: