From patchwork Mon Aug 13 21:21:51 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 1316201 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 6BD0240B05 for ; Mon, 13 Aug 2012 21:22:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753238Ab2HMVV7 (ORCPT ); Mon, 13 Aug 2012 17:21:59 -0400 Received: from mail-yx0-f174.google.com ([209.85.213.174]:41701 "EHLO mail-yx0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752719Ab2HMVVx (ORCPT ); Mon, 13 Aug 2012 17:21:53 -0400 Received: by mail-yx0-f174.google.com with SMTP id l14so2487139yen.19 for ; Mon, 13 Aug 2012 14:21:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:subject:to:cc:date:message-id:in-reply-to:references :user-agent:mime-version:content-type:content-transfer-encoding; bh=HaDjIrzh76tFi+HG8Ns9z4LWE7SZUPUTIKkNjXRHIZA=; b=ETFnYSRDfn8Kp/iCqUD0Bk77P7RWEOKus9FpbzJ16TFIbSD/61FnGf7vQ8fy2T5jAL vaDH6qc6PpLXnyiKDtbX7EfISfthieZD/Q0l9ovElziaSZGT/fKNStC0DO79xQn/gD74 GwtjRQnPh7RQBNwN/VB7mA3SBOJrl6A0Fx/Oq4mgSTMYKNVzBxDf2AdCD9VAfDMv78Vr Isf4OslA7qThkc+IOk909FAiQIeDjb/UAqbe2YpSpDYdXbYjR6Oe/jgU38r1Bvzhguq+ PY8LpBGOtQFHeYgS4StUrp+eqNn3XJJqkLQYkuKm0aqKpjOhO7ib1XOeEBSGz3ROEBez aFig== Received: by 10.50.6.168 with SMTP id c8mr7349898iga.21.1344892912549; Mon, 13 Aug 2012 14:21:52 -0700 (PDT) Received: from degas.1015granger.net (adsl-99-26-161-222.dsl.sfldmi.sbcglobal.net. [99.26.161.222]) by mx.google.com with ESMTPS id hg1sm8164346igc.12.2012.08.13.14.21.51 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 13 Aug 2012 14:21:52 -0700 (PDT) From: Chuck Lever Subject: [PATCH 3/5] SUNRPC: Prepare gss_pipes_dentries_create() for sharing pipe data To: trond.myklebust@netapp.com Cc: linux-nfs@vger.kernel.org Date: Mon, 13 Aug 2012 17:21:51 -0400 Message-ID: <20120813212150.1680.96757.stgit@degas.1015granger.net> In-Reply-To: <20120813210739.1680.53741.stgit@degas.1015granger.net> References: <20120813210739.1680.53741.stgit@degas.1015granger.net> User-Agent: StGIT/0.14.3 MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org We are about to make pipe data shareable. gss_pipes_dentries_create() and gss_pipes_dentries_destroy() have to be more careful when dealing with their dentry pointers. Namely: 1. When asked to create a dentry, don't write over possibly valid pointers, but instead preserve an existing dentry 2. When unlinking a dentry, make sure the ->dentry pointer is NULL 3. If creating a dentry fails, don't leak the ERR_PTR value, make sure the ->dentry pointer is NULL 2. and 3. are needed so that 1. can recognize when a new dentry should be created. This is clean up, mostly. But it's necessary because unmounting a pipe FS can cause pipe dentries, but not the pipe data, to be released (via ->pipes_destroy). The functions that manage pipe data for gss_create() have to be prepared for finding an existing shared rpc_pipe_data object that has a dentry, or doesn't, and then do the correct thing in either case. Signed-off-by: Chuck Lever Acked-by: Stanislav Kinsbursky --- net/sunrpc/auth_gss/auth_gss.c | 67 +++++++++++++++++++++++++++++----------- 1 files changed, 49 insertions(+), 18 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 909dc0c..947ab01 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -757,42 +757,73 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg) } } +static void gss_pipe_dentry_destroy(struct rpc_pipe *pipe) +{ + if (pipe->dentry != NULL) { + rpc_unlink(pipe->dentry); + pipe->dentry = NULL; + } +} + +/* + * Release existing pipe dentries, but leave the rpc_pipe data + * ready to receive fresh dentries if subsequently needed. + */ static void gss_pipes_dentries_destroy(struct rpc_auth *auth) { struct gss_auth *gss_auth; gss_auth = container_of(auth, struct gss_auth, rpc_auth); - if (gss_auth->pipe[0]->dentry) - rpc_unlink(gss_auth->pipe[0]->dentry); - if (gss_auth->pipe[1]->dentry) - rpc_unlink(gss_auth->pipe[1]->dentry); + + dprintk("RPC: %s auth=%p, clnt=%p\n", + __func__, auth, gss_auth->client); + + gss_pipe_dentry_destroy(gss_auth->pipe[0]); + gss_pipe_dentry_destroy(gss_auth->pipe[1]); } +/* + * On success, zero is returned and both elements of the rpc_pipe + * array are populated with valid dentries. Otherwise an error value + * is returned, the dentries are freed, and both ->dentry pointers are + * set to NULL. + */ static int gss_pipes_dentries_create(struct rpc_auth *auth) { - int err; + int err = 0; struct gss_auth *gss_auth; struct rpc_clnt *clnt; gss_auth = container_of(auth, struct gss_auth, rpc_auth); clnt = gss_auth->client; - gss_auth->pipe[1]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, - "gssd", - clnt, gss_auth->pipe[1]); - if (IS_ERR(gss_auth->pipe[1]->dentry)) - return PTR_ERR(gss_auth->pipe[1]->dentry); - gss_auth->pipe[0]->dentry = rpc_mkpipe_dentry(clnt->cl_dentry, - gss_auth->mech->gm_name, - clnt, gss_auth->pipe[0]); - if (IS_ERR(gss_auth->pipe[0]->dentry)) { - err = PTR_ERR(gss_auth->pipe[0]->dentry); - goto err_unlink_pipe_1; + if (gss_auth->pipe[1]->dentry == NULL) { + gss_auth->pipe[1]->dentry = + rpc_mkpipe_dentry(clnt->cl_dentry, "gssd", clnt, + gss_auth->pipe[1]); + if (IS_ERR(gss_auth->pipe[1]->dentry)) { + err = PTR_ERR(gss_auth->pipe[1]->dentry); + gss_auth->pipe[1]->dentry = NULL; + goto out_err; + } } + + if (gss_auth->pipe[0]->dentry == NULL) { + gss_auth->pipe[0]->dentry = + rpc_mkpipe_dentry(clnt->cl_dentry, + gss_auth->mech->gm_name, + clnt, gss_auth->pipe[0]); + if (IS_ERR(gss_auth->pipe[0]->dentry)) { + err = PTR_ERR(gss_auth->pipe[0]->dentry); + gss_auth->pipe[0]->dentry = NULL; + goto out_err; + } + } + return 0; -err_unlink_pipe_1: - rpc_unlink(gss_auth->pipe[1]->dentry); +out_err: + gss_pipes_dentries_destroy(auth); return err; }