diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-08-27 16:52:16 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-01 11:12:43 -0400 |
commit | 414a629598409497c05f2387c22c77dee143b4ff (patch) | |
tree | 5e3e8d53c332feb71c6f6cb2f219a6cca3cea946 /net/sunrpc | |
parent | 298fc3558b9c1f5324c5ec6d5c587ca9ae6cc826 (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.c | 77 |
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 | ||
81 | struct gss_auth { | 82 | struct 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); | ||
856 | err_free_gss_pipe: | 854 | err_free_gss_pipe: |
857 | kfree(p); | 855 | kfree(p); |
858 | err: | 856 | err: |
859 | return ERR_PTR(err); | 857 | return ERR_PTR(err); |
860 | } | 858 | } |
861 | 859 | ||
860 | struct gss_alloc_pdo { | ||
861 | struct rpc_clnt *clnt; | ||
862 | const char *name; | ||
863 | const struct rpc_pipe_ops *upcall_ops; | ||
864 | }; | ||
865 | |||
866 | static 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 | |||
881 | static 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 | |||
892 | static 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 | |||
862 | static void __gss_pipe_free(struct gss_pipe *p) | 914 | static 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 | ||
926 | static 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 | |||
874 | static void gss_pipe_free(struct gss_pipe *p) | 933 | static 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; |
949 | err_destroy_pipe_1: | 1008 | err_destroy_pipe_1: |
950 | __gss_pipe_free(gss_auth->gss_pipe[1]); | 1009 | gss_pipe_free(gss_auth->gss_pipe[1]); |
951 | err_destroy_credcache: | 1010 | err_destroy_credcache: |
952 | rpcauth_destroy_credcache(auth); | 1011 | rpcauth_destroy_credcache(auth); |
953 | err_put_mech: | 1012 | err_put_mech: |