From patchwork Tue Oct 31 20:07:20 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 10035357 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9376D602B9 for ; Tue, 31 Oct 2017 20:07:28 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 849F428A9D for ; Tue, 31 Oct 2017 20:07:28 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7654828AD6; Tue, 31 Oct 2017 20:07:28 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.3 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8DC1828A9D for ; Tue, 31 Oct 2017 20:07:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752135AbdJaUH0 (ORCPT ); Tue, 31 Oct 2017 16:07:26 -0400 Received: from mail-io0-f196.google.com ([209.85.223.196]:52927 "EHLO mail-io0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752023AbdJaUHZ (ORCPT ); Tue, 31 Oct 2017 16:07:25 -0400 Received: by mail-io0-f196.google.com with SMTP id f20so1463023ioj.9 for ; Tue, 31 Oct 2017 13:07:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=UAVToElFvjL2o9NX4BEyiV75uQWC5QH7knlt/jZo3p4=; b=AIGCXOVytQYTIVVXEVB1eSu6sx/gAfUYWlygoyBXmwtmHtT5JWIEvfqF62T7oda9r2 PoIs16RF/Ise/vP9zLBrsWDKc1Bxo3utAZyoGIUY59/78oIhvQJ4Ch1LK5w20u08C2uX OEbvGDx1/4eDBLmr382/E2VL4sVdCJRiCC3/F197o6nOPVGGUuNNIqnxbU/X+iCjgyIM mFvpOl+5pKOPZprC4yz/omziQPRSX/T4t4BIAF5VP1pnREvyL9e/Dut8sOBCmtVwFjlh JAlVlN0rxamL3S6OP/extFaEjuvVwBVJbMP/CS6pnkTTSH0esXzvy22nfmHSJvjq9D7G wryw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :mime-version:content-transfer-encoding; bh=UAVToElFvjL2o9NX4BEyiV75uQWC5QH7knlt/jZo3p4=; b=cNJOOvx2796zKTJUAuMSWeNAjRIyBpopxXMG9xkFMSiBY7mIy6+StCnBFLyBvjfl1F tmUizR9xcxixrhs+i6uURi6NJZ1L7g3sZbiE1hU1dNWwj0xF5U08Z25rO3OTPgioANYH pPJ2XgZmAM4bOeemIvdI02uAtT6f/Br+W1P6GrvpJxk9lvD+UjAGlTtA2MmfD7cnYnNg u7V8SIr/zFcjAjLs4o2miZaH0pJPV9UQoyo821fjFKOa6hqGHw4zc4VXALjKBdBo0Cr7 XOUz1qK9XxcGGN/fxwkSgnemdkiFogsUtMxB/tinWceYOmf+hMwWvnk7vq74gYkUCqZG 4fVw== X-Gm-Message-State: AMCzsaVDajlWc7aOj3Y7LPQjhFmozCMAP89cFlcazeRGhJvs2Ps3YQw8 UwNgwb7SFjGNXbrEQ0c4YcpRt3k= X-Google-Smtp-Source: ABhQp+TNrlD1TYLUzZ8xhrM6nZpZ6fAWIIXjQBPiyGZBzXu0jp/1wlHTRrN+CoDlqOmVX5SbCOEJOA== X-Received: by 10.36.87.2 with SMTP id u2mr4687086ita.151.1509480445051; Tue, 31 Oct 2017 13:07:25 -0700 (PDT) Received: from localhost.localdomain (c-68-49-162-121.hsd1.mi.comcast.net. [68.49.162.121]) by smtp.gmail.com with ESMTPSA id a72sm1241340itb.34.2017.10.31.13.07.23 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 31 Oct 2017 13:07:24 -0700 (PDT) From: Trond Myklebust To: Anna Schumaker Cc: Tigran Mkrtchyan , linux-nfs@vger.kernel.org Subject: [PATCH] NFSv4: Fix open create exclusive when the server reboots Date: Tue, 31 Oct 2017 16:07:20 -0400 Message-Id: <20171031200720.45000-1-trond.myklebust@primarydata.com> X-Mailer: git-send-email 2.13.6 MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If the server that does not implement NFSv4.1 persistent session semantics reboots while we are performing an exclusive create, then the return value of NFS4ERR_DELAY when we replay the open during the grace period causes us to lose the verifier. When the grace period expires, and we present a new verifier, the server will then correctly reply NFS4ERR_EXIST. This commit ensures that we always present the same verifier when replaying the OPEN. Reported-by: Tigran Mkrtchyan Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1b42e051eaec..1ca9349513f3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1086,6 +1086,12 @@ struct nfs4_opendata { int rpc_status; }; +struct nfs4_open_createattrs { + struct nfs4_label *label; + struct iattr *sattr; + const __u32 verf[2]; +}; + static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server, int err, struct nfs4_exception *exception) { @@ -1155,8 +1161,7 @@ static void nfs4_init_opendata_res(struct nfs4_opendata *p) static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, struct nfs4_state_owner *sp, fmode_t fmode, int flags, - const struct iattr *attrs, - struct nfs4_label *label, + const struct nfs4_open_createattrs *c, enum open_claim_type4 claim, gfp_t gfp_mask) { @@ -1164,6 +1169,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, struct inode *dir = d_inode(parent); struct nfs_server *server = NFS_SERVER(dir); struct nfs_seqid *(*alloc_seqid)(struct nfs_seqid_counter *, gfp_t); + struct nfs4_label *label = (c != NULL) ? c->label : NULL; struct nfs4_opendata *p; p = kzalloc(sizeof(*p), gfp_mask); @@ -1229,15 +1235,11 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, case NFS4_OPEN_CLAIM_DELEG_PREV_FH: p->o_arg.fh = NFS_FH(d_inode(dentry)); } - if (attrs != NULL && attrs->ia_valid != 0) { - __u32 verf[2]; - + if (c != NULL && c->sattr != NULL && c->sattr->ia_valid != 0) { p->o_arg.u.attrs = &p->attrs; - memcpy(&p->attrs, attrs, sizeof(p->attrs)); + memcpy(&p->attrs, c->sattr, sizeof(p->attrs)); - verf[0] = jiffies; - verf[1] = current->pid; - memcpy(p->o_arg.u.verifier.data, verf, + memcpy(p->o_arg.u.verifier.data, c->verf, sizeof(p->o_arg.u.verifier.data)); } p->c_arg.fh = &p->o_res.fh; @@ -1882,7 +1884,7 @@ static struct nfs4_opendata *nfs4_open_recoverdata_alloc(struct nfs_open_context struct nfs4_opendata *opendata; opendata = nfs4_opendata_alloc(ctx->dentry, state->owner, 0, 0, - NULL, NULL, claim, GFP_NOFS); + NULL, claim, GFP_NOFS); if (opendata == NULL) return ERR_PTR(-ENOMEM); opendata->state = state; @@ -2813,8 +2815,7 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, static int _nfs4_do_open(struct inode *dir, struct nfs_open_context *ctx, int flags, - struct iattr *sattr, - struct nfs4_label *label, + const struct nfs4_open_createattrs *c, int *opened) { struct nfs4_state_owner *sp; @@ -2826,6 +2827,8 @@ static int _nfs4_do_open(struct inode *dir, struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; + struct iattr *sattr = c->sattr; + struct nfs4_label *label = c->label; struct nfs4_label *olabel = NULL; int status; @@ -2844,8 +2847,8 @@ static int _nfs4_do_open(struct inode *dir, status = -ENOMEM; if (d_really_is_positive(dentry)) claim = NFS4_OPEN_CLAIM_FH; - opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, sattr, - label, claim, GFP_KERNEL); + opendata = nfs4_opendata_alloc(dentry, sp, fmode, flags, + c, claim, GFP_KERNEL); if (opendata == NULL) goto err_put_state_owner; @@ -2926,10 +2929,18 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct nfs_server *server = NFS_SERVER(dir); struct nfs4_exception exception = { }; struct nfs4_state *res; + struct nfs4_open_createattrs c = { + .label = label, + .sattr = sattr, + .verf = { + [0] = (__u32)jiffies, + [1] = (__u32)current->pid, + }, + }; int status; do { - status = _nfs4_do_open(dir, ctx, flags, sattr, label, opened); + status = _nfs4_do_open(dir, ctx, flags, &c, opened); res = ctx->state; trace_nfs4_open_file(ctx, flags, status); if (status == 0)