From patchwork Thu Aug 9 21:31:18 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 1303031 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 512EF3FD8C for ; Thu, 9 Aug 2012 21:31:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756014Ab2HIVbV (ORCPT ); Thu, 9 Aug 2012 17:31:21 -0400 Received: from mail-gh0-f174.google.com ([209.85.160.174]:36347 "EHLO mail-gh0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755970Ab2HIVbU (ORCPT ); Thu, 9 Aug 2012 17:31:20 -0400 Received: by ghrr11 with SMTP id r11so1001521ghr.19 for ; Thu, 09 Aug 2012 14:31:20 -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=AfTWluJEZJVrvzwYH373oF6911IIbdRRawMbc6Cp/tU=; b=CwwXD30yi2nQE+nPvme8z986tnSb+azr4JHkkT0VDF5hTYYyZ0fPZEEAF45WTUtsXr xA1zjFZZd6rgVaf0CTtbfa7djJVF8M2VwrZMxs1JwcTiVHPJFk6hWy3Jzifufvda8iRL 2xWEltL8uN2Ko+RZkH0+fMbBKSen0fZaazJD77xmrZZ+qGWR23hz/ZzfIOGwikroaMxo RFQuYMD4yD9HsqT1uMP3n37jK7rD7XYC1KHALJNzeikMOuqvRdtnQ50fIODpNacsX0u8 3dJKbqlM7gvAMz9PdfGhmogZn35b1mxwES/OQhh1FfKZl2jNi2+0/x5nD1XWxZeSvX0B jraw== Received: by 10.50.91.165 with SMTP id cf5mr3607igb.7.1344547879822; Thu, 09 Aug 2012 14:31:19 -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 va9sm1660625igb.17.2012.08.09.14.31.18 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 09 Aug 2012 14:31:19 -0700 (PDT) From: Chuck Lever Subject: [PATCH 1/3] SUNRPC: Prepare gss_pipes_dentries_create() for sharing pipe data To: linux-nfs@vger.kernel.org Cc: skinsbursky@parallels.com Date: Thu, 09 Aug 2012 17:31:18 -0400 Message-ID: <20120809213117.12984.99824.stgit@degas.1015granger.net> In-Reply-To: <20120809205748.12984.88991.stgit@degas.1015granger.net> References: <20120809205748.12984.88991.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 Cc: 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 f5147ef..dfe7825 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; }