Received: by 2002:a05:6a10:1287:0:0:0:0 with SMTP id d7csp3851338pxv; Mon, 19 Jul 2021 10:14:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy07xd2NWGIZ4gJMWRVzKShWlCeGQBJQ86Lf8zFN52eJJAyh4KKVDLCQS2gcfI+YsmZYZ7+ X-Received: by 2002:a17:907:6297:: with SMTP id nd23mr27249472ejc.62.1626714880597; Mon, 19 Jul 2021 10:14:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1626714880; cv=none; d=google.com; s=arc-20160816; b=GmPhvaoCQWQoze4szZourMC6EJrDxL/wAWtu/AuVgwetVha26kUoY4Yquo3iTPLW1i oV9FsNv8Ee0MBhI1NqKKYRF67tCeYXrNLXztwITwiBrC1AOt6dGsCIkbg3CgK8SgmwTf kLzE8sZ92n9ISowV069GhZ45BJELBl9aOP+YIZnlRQsow/P2BkWYDxKxNRj1cDQ624+M iaOebbTwfbURkgWwR/bCYpDWkxRUZkjy+ATzWeTX3ttin5SkzpYLqB2ywg+uxZM3BXh7 lB+50imL9ANxLzYgkrCgrZ3lJdkf2b/PsIifr2tm7bcnRYg31SrSgQ3bQw0kzYhjrARb H7OQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=RTC2bJwy8cFS45RrSyGibKTJZG8tCvD/aysSQcXXAzg=; b=yfZmxsLrilaFgss6ft4fDa2S0Oeyu76cR9kO2h+sq6GvXqspa/5jFs2wbBlpPGAD7w OCDlKdxJhywtKq4f8g4FPT6mQx6lETnVxCuUWURCz+exaywi8MCXiqBy1oAIsv9ThPk6 +/M0yY9qvJ6xPGK7zDOETAR+dAZfmtX8ppFxRDy/6tX5D4bCeTkLZOGsRapisDviQW41 FMMtMEw4FCy0e9pjGzZ4wJNMjWXsQdmK6nm2B9sY1bbt20tSTIO0bZcvc3M2arlEEpjf Eyq94/Ij22VuYrmuUk0IT5w877I2NrLp72IxBQ1rKZpGIpfk/PdMv/vwd54+kgSqUEOV CBWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=ACJr1Rei; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id y6si6501512edd.522.2021.07.19.10.14.15; Mon, 19 Jul 2021 10:14:40 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=ACJr1Rei; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1354018AbhGSQ3s (ORCPT + 99 others); Mon, 19 Jul 2021 12:29:48 -0400 Received: from mail.kernel.org ([198.145.29.99]:56496 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1347390AbhGSPQI (ORCPT ); Mon, 19 Jul 2021 11:16:08 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 4E0E8600EF; Mon, 19 Jul 2021 15:56:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1626710206; bh=ybvUtNuGypjJFWfgp/sKHdVTtpWTQZCCW8JhunagGBg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ACJr1ReiJm2CZg7HKWXYRh5AubUs9zudxqA1Pog9RoovuIFjrIMgo+Wh9vZWItXM2 c/q0iPIaJrfzIm3pBrcsJesG+5mzXnQU2m+qgsCbsJUE6v9XtLPJCtn8TbvoURKFik IiLTi3bnG+qZafYwad8uIjsZMkRr8hcHbHVdCDt4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Trond Myklebust , Sasha Levin Subject: [PATCH 5.10 121/243] NFSv4: Fix delegation return in cases where we have to retry Date: Mon, 19 Jul 2021 16:52:30 +0200 Message-Id: <20210719144944.819068888@linuxfoundation.org> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20210719144940.904087935@linuxfoundation.org> References: <20210719144940.904087935@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Trond Myklebust [ Upstream commit be20037725d17935ec669044bd2b15bc40c3b5ab ] If we're unable to immediately recover all locks because the server is unable to immediately service our reclaim calls, then we want to retry after we've finished servicing all the other asynchronous delegation returns on our queue. Signed-off-by: Trond Myklebust Signed-off-by: Sasha Levin --- fs/nfs/delegation.c | 71 +++++++++++++++++++++++++++++++++++---------- fs/nfs/delegation.h | 1 + fs/nfs/nfs4_fs.h | 1 + 3 files changed, 58 insertions(+), 15 deletions(-) diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 04bf8066980c..d6ac2c4f88b6 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -75,6 +75,13 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags); } +static void nfs_mark_return_delegation(struct nfs_server *server, + struct nfs_delegation *delegation) +{ + set_bit(NFS_DELEGATION_RETURN, &delegation->flags); + set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); +} + static bool nfs4_is_valid_delegation(const struct nfs_delegation *delegation, fmode_t flags) @@ -293,6 +300,7 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi) goto out; spin_lock(&delegation->lock); if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { + clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); /* Refcount matched in nfs_end_delegation_return() */ ret = nfs_get_delegation(delegation); } @@ -314,16 +322,17 @@ nfs_start_delegation_return(struct nfs_inode *nfsi) return delegation; } -static void -nfs_abort_delegation_return(struct nfs_delegation *delegation, - struct nfs_client *clp) +static void nfs_abort_delegation_return(struct nfs_delegation *delegation, + struct nfs_client *clp, int err) { spin_lock(&delegation->lock); clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags); - set_bit(NFS_DELEGATION_RETURN, &delegation->flags); + if (err == -EAGAIN) { + set_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); + set_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state); + } spin_unlock(&delegation->lock); - set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); } static struct nfs_delegation * @@ -528,7 +537,7 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation } while (err == 0); if (err) { - nfs_abort_delegation_return(delegation, clp); + nfs_abort_delegation_return(delegation, clp, err); goto out; } @@ -557,6 +566,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) if (ret) clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags) || + test_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags) || test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) ret = false; @@ -636,6 +646,38 @@ out: return err; } +static bool nfs_server_clear_delayed_delegations(struct nfs_server *server) +{ + struct nfs_delegation *d; + bool ret = false; + + list_for_each_entry_rcu (d, &server->delegations, super_list) { + if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags)) + continue; + nfs_mark_return_delegation(server, d); + clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags); + ret = true; + } + return ret; +} + +static bool nfs_client_clear_delayed_delegations(struct nfs_client *clp) +{ + struct nfs_server *server; + bool ret = false; + + if (!test_and_clear_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state)) + goto out; + rcu_read_lock(); + list_for_each_entry_rcu (server, &clp->cl_superblocks, client_link) { + if (nfs_server_clear_delayed_delegations(server)) + ret = true; + } + rcu_read_unlock(); +out: + return ret; +} + /** * nfs_client_return_marked_delegations - return previously marked delegations * @clp: nfs_client to process @@ -648,8 +690,14 @@ out: */ int nfs_client_return_marked_delegations(struct nfs_client *clp) { - return nfs_client_for_each_server(clp, - nfs_server_return_marked_delegations, NULL); + int err = nfs_client_for_each_server( + clp, nfs_server_return_marked_delegations, NULL); + if (err) + return err; + /* If a return was delayed, sleep to prevent hard looping */ + if (nfs_client_clear_delayed_delegations(clp)) + ssleep(1); + return 0; } /** @@ -764,13 +812,6 @@ static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); } -static void nfs_mark_return_delegation(struct nfs_server *server, - struct nfs_delegation *delegation) -{ - set_bit(NFS_DELEGATION_RETURN, &delegation->flags); - set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); -} - static bool nfs_server_mark_return_all_delegations(struct nfs_server *server) { struct nfs_delegation *delegation; diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 9b00a0b7f832..26f57a99da84 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -36,6 +36,7 @@ enum { NFS_DELEGATION_REVOKED, NFS_DELEGATION_TEST_EXPIRED, NFS_DELEGATION_INODE_FREEING, + NFS_DELEGATION_RETURN_DELAYED, }; int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred, diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 543d916f79ab..3e344bec3647 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -45,6 +45,7 @@ enum nfs4_client_state { NFS4CLNT_RECALL_RUNNING, NFS4CLNT_RECALL_ANY_LAYOUT_READ, NFS4CLNT_RECALL_ANY_LAYOUT_RW, + NFS4CLNT_DELEGRETURN_DELAYED, }; #define NFS4_RENEW_TIMEOUT 0x01 -- 2.30.2