From patchwork Mon Sep 2 18:16:59 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 2852948 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 07C6A9F494 for ; Mon, 2 Sep 2013 18:23:42 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 23A7B202D1 for ; Mon, 2 Sep 2013 18:23:41 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2EDC6202C6 for ; Mon, 2 Sep 2013 18:23:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756329Ab3IBSXj (ORCPT ); Mon, 2 Sep 2013 14:23:39 -0400 Received: from mx12.netapp.com ([216.240.18.77]:44124 "EHLO mx12.netapp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755681Ab3IBSXj (ORCPT ); Mon, 2 Sep 2013 14:23:39 -0400 X-IronPort-AV: E=Sophos;i="4.89,1008,1367996400"; d="scan'208";a="86036990" Received: from vmwexceht01-prd.hq.netapp.com ([10.106.76.239]) by mx12-out.netapp.com with ESMTP; 02 Sep 2013 11:23:38 -0700 Received: from smtp1.corp.netapp.com (10.57.156.124) by VMWEXCEHT01-PRD.hq.netapp.com (10.106.76.239) with Microsoft SMTP Server id 14.3.123.3; Mon, 2 Sep 2013 11:23:38 -0700 Received: from leira.trondhjem.org.com (leira.trondhjem.org.vpn.netapp.com [10.55.73.213]) by smtp1.corp.netapp.com (8.13.1/8.13.1/NTAP-1.6) with ESMTP id r82IH4NJ006298; Mon, 2 Sep 2013 11:17:17 -0700 (PDT) From: Trond Myklebust To: CC: Subject: [PATCH v3 16/17] RPCSEC_GSS: Share all credential caches on a per-transport basis Date: Mon, 2 Sep 2013 14:16:59 -0400 Message-ID: <1378145820-29990-16-git-send-email-Trond.Myklebust@netapp.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1378145820-29990-15-git-send-email-Trond.Myklebust@netapp.com> References: <1378145820-29990-1-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-2-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-3-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-4-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-5-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-6-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-7-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-8-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-9-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-10-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-11-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-12-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-13-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-14-git-send-email-Trond.Myklebust@netapp.com> <1378145820-29990-15-git-send-email-Trond.Myklebust@netapp.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-9.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Ensure that all struct rpc_clnt for any given socket/rdma channel share the same RPCSEC_GSS/krb5,krb5i,krb5p caches. Signed-off-by: Trond Myklebust --- net/sunrpc/auth_gss/auth_gss.c | 92 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 5ec15bb..dc4b449 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "../netns.h" @@ -71,6 +72,9 @@ static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED; * using integrity (two 4-byte integers): */ #define GSS_VERF_SLACK 100 +static DEFINE_HASHTABLE(gss_auth_hash_table, 16); +static DEFINE_SPINLOCK(gss_auth_hash_lock); + struct gss_pipe { struct rpc_pipe_dir_object pdo; struct rpc_pipe *pipe; @@ -81,6 +85,7 @@ struct gss_pipe { struct gss_auth { struct kref kref; + struct hlist_node hash; struct rpc_auth rpc_auth; struct gss_api_mech *mech; enum rpc_gss_svc service; @@ -940,8 +945,8 @@ static void gss_pipe_free(struct gss_pipe *p) * NOTE: we have the opportunity to use different * parameters based on the input flavor (which must be a pseudoflavor) */ -static struct rpc_auth * -gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) +static struct gss_auth * +gss_create_new(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) { rpc_authflavor_t flavor = args->pseudoflavor; struct gss_auth *gss_auth; @@ -955,6 +960,7 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) return ERR_PTR(err); if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL))) goto out_dec; + INIT_HLIST_NODE(&gss_auth->hash); gss_auth->target_name = NULL; if (args->target_name) { gss_auth->target_name = kstrdup(args->target_name, GFP_KERNEL); @@ -1004,7 +1010,7 @@ gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) } gss_auth->gss_pipe[0] = gss_pipe; - return auth; + return gss_auth; err_destroy_pipe_1: gss_pipe_free(gss_auth->gss_pipe[1]); err_destroy_credcache: @@ -1051,6 +1057,12 @@ gss_destroy(struct rpc_auth *auth) dprintk("RPC: destroying GSS authenticator %p flavor %d\n", auth, auth->au_flavor); + if (hash_hashed(&gss_auth->hash)) { + spin_lock(&gss_auth_hash_lock); + hash_del(&gss_auth->hash); + spin_unlock(&gss_auth_hash_lock); + } + gss_pipe_free(gss_auth->gss_pipe[0]); gss_auth->gss_pipe[0] = NULL; gss_pipe_free(gss_auth->gss_pipe[1]); @@ -1060,6 +1072,80 @@ gss_destroy(struct rpc_auth *auth) kref_put(&gss_auth->kref, gss_free_callback); } +static struct gss_auth * +gss_auth_find_or_add_hashed(struct rpc_auth_create_args *args, + struct rpc_clnt *clnt, + struct gss_auth *new) +{ + struct gss_auth *gss_auth; + unsigned long hashval = (unsigned long)clnt; + + spin_lock(&gss_auth_hash_lock); + hash_for_each_possible(gss_auth_hash_table, + gss_auth, + hash, + hashval) { + if (gss_auth->rpc_auth.au_flavor != args->pseudoflavor) + continue; + if (gss_auth->target_name != args->target_name) { + if (gss_auth->target_name == NULL) + continue; + if (args->target_name == NULL) + continue; + if (strcmp(gss_auth->target_name, args->target_name)) + continue; + } + if (!atomic_inc_not_zero(&gss_auth->rpc_auth.au_count)) + continue; + goto out; + } + if (new) + hash_add(gss_auth_hash_table, &new->hash, hashval); + gss_auth = new; +out: + spin_unlock(&gss_auth_hash_lock); + return gss_auth; +} + +static struct gss_auth * +gss_create_hashed(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) +{ + struct gss_auth *gss_auth; + struct gss_auth *new; + + gss_auth = gss_auth_find_or_add_hashed(args, clnt, NULL); + if (gss_auth != NULL) + goto out; + new = gss_create_new(args, clnt); + if (IS_ERR(new)) + return new; + gss_auth = gss_auth_find_or_add_hashed(args, clnt, new); + if (gss_auth != new) + gss_destroy(&new->rpc_auth); +out: + return gss_auth; +} + +static struct rpc_auth * +gss_create(struct rpc_auth_create_args *args, struct rpc_clnt *clnt) +{ + struct gss_auth *gss_auth; + struct rpc_xprt *xprt = rcu_access_pointer(clnt->cl_xprt); + + while (clnt != clnt->cl_parent) { + struct rpc_clnt *parent = clnt->cl_parent; + /* Find the original parent for this transport */ + if (rcu_access_pointer(parent->cl_xprt) != xprt) + break; + clnt = parent; + } + + gss_auth = gss_create_hashed(args, clnt); + if (IS_ERR(gss_auth)) + return ERR_CAST(gss_auth); + return &gss_auth->rpc_auth; +} + /* * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call * to the server with the GSS control procedure field set to