From patchwork Sat Sep 17 05:13:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Trond Myklebust X-Patchwork-Id: 9336997 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 F0AD46077F for ; Sat, 17 Sep 2016 05:14:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E277929FBE for ; Sat, 17 Sep 2016 05:14:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D77F129FCB; Sat, 17 Sep 2016 05:14:02 +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.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,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 5F49129FAD for ; Sat, 17 Sep 2016 05:14:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757077AbcIQFOA (ORCPT ); Sat, 17 Sep 2016 01:14:00 -0400 Received: from mail-io0-f196.google.com ([209.85.223.196]:34313 "EHLO mail-io0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756204AbcIQFN5 (ORCPT ); Sat, 17 Sep 2016 01:13:57 -0400 Received: by mail-io0-f196.google.com with SMTP id y139so2395569ioy.1 for ; Fri, 16 Sep 2016 22:13:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=0YGDG7GBm/k+x08F0uxAdezhpYpt588uEFFnf4oZQDg=; b=ASWkpx+ZjzRTR3NobBifGIqjJAIvmZ2nAiIDEU2/LJiSN+rjvNnTKEwthxYg1/2/fl k4XoyKxkN4Ku12GaGbC7qrrJyIntty6W+XuF2PJobYp+bbv3kCBQNqao6iYaRhVpuE30 uHURNClIP0J5/n0NWedpNyfBsJcVwi6zsqoOhqh9r04q/AF0xcSFPmqlyWiy+HqD7ley +Rsy1zUUyiFE/oH9gwnRKFWYZRVBEYWe+SzxONTKndJawuB5375ib/x+ntEhWoIbHtrP XfccGnrbVEv4Xn5MduUrN0YnLhCSokirwYovNNqVd4jtWyB39gH1s9rDu3zUGyVvAKew GN6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=0YGDG7GBm/k+x08F0uxAdezhpYpt588uEFFnf4oZQDg=; b=Emk+keLjFv7AgK1HvJ+rcr3wxS2g1D5/KXhnNgz8qYDLRDwVtyffDk9BkwChjq1K1D WrD1Eeux/keach17TEeaeO+ReQDlofmlNS9+25Wq6cVNa6uyxN1KGX4ZHGFJGC5GqZHV Sw2+U/4O6sSutLsDkD11TQqDUP8K+Pq/mgRSLD0pvlcgr2ipE27vYECPfsPTVJqdGEsE mmhCmd2FcQzwVE9jKi/drR79Vo7/K1B5HqK8Js//BjiF1oxzVOVNc+FvztiPCh4h3+NJ 78MipLjgOp8kenf2xCkEAmxe0jPhMt7nh7vMjzfBBfapOy6fOhiMuwVzYxFKfAEYX7zw 7N/g== X-Gm-Message-State: AE9vXwOvuY0cDehalqzJik0sS2shqQGzoU0nLGGa65EGjfkqYNJSi7iRxGx4GeEfmabQjA== X-Received: by 10.107.142.87 with SMTP id q84mr26134745iod.85.1474089236719; Fri, 16 Sep 2016 22:13:56 -0700 (PDT) Received: from leira.trondhjem.org.localdomain (c-68-49-162-121.hsd1.mi.comcast.net. [68.49.162.121]) by smtp.gmail.com with ESMTPSA id d15sm4993916ioj.19.2016.09.16.22.13.55 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 16 Sep 2016 22:13:56 -0700 (PDT) From: Trond Myklebust To: anna.schumaker@netapp.com Cc: linux-nfs@vger.kernel.org, Oleg Drokin Subject: [PATCH v5 22/25] NFSv4: Fix a race when updating an open_stateid Date: Sat, 17 Sep 2016 01:13:30 -0400 Message-Id: <1474089213-104014-23-git-send-email-trond.myklebust@primarydata.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1474089213-104014-22-git-send-email-trond.myklebust@primarydata.com> References: <1474089213-104014-1-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-2-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-3-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-4-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-5-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-6-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-7-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-8-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-9-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-10-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-11-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-12-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-13-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-14-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-15-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-16-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-17-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-18-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-19-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-20-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-21-git-send-email-trond.myklebust@primarydata.com> <1474089213-104014-22-git-send-email-trond.myklebust@primarydata.com> 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 we're replacing an old stateid which has a different 'other' field, then we probably need to free the old stateid. Signed-off-by: Trond Myklebust --- fs/nfs/nfs4proc.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 82449e578608..08c6e46c5b95 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1399,11 +1399,12 @@ static void nfs_test_and_clear_all_open_stateid(struct nfs4_state *state) } static bool nfs_need_update_open_stateid(struct nfs4_state *state, - nfs4_stateid *stateid) + const nfs4_stateid *stateid, nfs4_stateid *freeme) { if (test_and_set_bit(NFS_OPEN_STATE, &state->flags) == 0) return true; if (!nfs4_stateid_match_other(stateid, &state->open_stateid)) { + nfs4_stateid_copy(freeme, &state->open_stateid); nfs_test_and_clear_all_open_stateid(state); return true; } @@ -1467,7 +1468,9 @@ static void nfs_clear_open_stateid(struct nfs4_state *state, nfs4_schedule_state_manager(state->owner->so_server->nfs_client); } -static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid *stateid, fmode_t fmode) +static void nfs_set_open_stateid_locked(struct nfs4_state *state, + const nfs4_stateid *stateid, fmode_t fmode, + nfs4_stateid *freeme) { switch (fmode) { case FMODE_READ: @@ -1479,14 +1482,18 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state, nfs4_stateid * case FMODE_READ|FMODE_WRITE: set_bit(NFS_O_RDWR_STATE, &state->flags); } - if (!nfs_need_update_open_stateid(state, stateid)) + if (!nfs_need_update_open_stateid(state, stateid, freeme)) return; if (test_bit(NFS_DELEGATED_STATE, &state->flags) == 0) nfs4_stateid_copy(&state->stateid, stateid); nfs4_stateid_copy(&state->open_stateid, stateid); } -static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, const nfs4_stateid *deleg_stateid, fmode_t fmode) +static void __update_open_stateid(struct nfs4_state *state, + const nfs4_stateid *open_stateid, + const nfs4_stateid *deleg_stateid, + fmode_t fmode, + nfs4_stateid *freeme) { /* * Protect the call to nfs4_state_set_mode_locked and @@ -1499,16 +1506,22 @@ static void __update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_s set_bit(NFS_DELEGATED_STATE, &state->flags); } if (open_stateid != NULL) - nfs_set_open_stateid_locked(state, open_stateid, fmode); + nfs_set_open_stateid_locked(state, open_stateid, fmode, freeme); write_sequnlock(&state->seqlock); update_open_stateflags(state, fmode); spin_unlock(&state->owner->so_lock); } -static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stateid, nfs4_stateid *delegation, fmode_t fmode) +static int update_open_stateid(struct nfs4_state *state, + const nfs4_stateid *open_stateid, + const nfs4_stateid *delegation, + fmode_t fmode) { + struct nfs_server *server = NFS_SERVER(state->inode); + struct nfs_client *clp = server->nfs_client; struct nfs_inode *nfsi = NFS_I(state->inode); struct nfs_delegation *deleg_cur; + nfs4_stateid freeme = {0}; int ret = 0; fmode &= (FMODE_READ|FMODE_WRITE); @@ -1530,7 +1543,8 @@ static int update_open_stateid(struct nfs4_state *state, nfs4_stateid *open_stat goto no_delegation_unlock; nfs_mark_delegation_referenced(deleg_cur); - __update_open_stateid(state, open_stateid, &deleg_cur->stateid, fmode); + __update_open_stateid(state, open_stateid, &deleg_cur->stateid, + fmode, &freeme); ret = 1; no_delegation_unlock: spin_unlock(&deleg_cur->lock); @@ -1538,11 +1552,14 @@ no_delegation: rcu_read_unlock(); if (!ret && open_stateid != NULL) { - __update_open_stateid(state, open_stateid, NULL, fmode); + __update_open_stateid(state, open_stateid, NULL, fmode, &freeme); ret = 1; } if (test_bit(NFS_STATE_RECLAIM_NOGRACE, &state->flags)) - nfs4_schedule_state_manager(state->owner->so_server->nfs_client); + nfs4_schedule_state_manager(clp); + if (freeme.type != 0) + nfs4_test_and_free_stateid(server, &freeme, + state->owner->so_cred); return ret; }