lkml.org 
[lkml]   [2020]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.14 124/343] NFS: Fix a soft lockup in the delegation recovery code
    Date
    From: Trond Myklebust <trond.myklebust@hammerspace.com>

    [ Upstream commit 6f9449be53f3ce383caed797708b332ede8d952c ]

    Fix a soft lockup when NFS client delegation recovery is attempted
    but the inode is in the process of being freed. When the
    igrab(inode) call fails, and we have to restart the recovery process,
    we need to ensure that we won't attempt to recover the same delegation
    again.

    Fixes: 45870d6909d5a ("NFSv4.1: Test delegation stateids when server...")
    Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/nfs/delegation.c | 20 ++++++++++++--------
    fs/nfs/delegation.h | 1 +
    2 files changed, 13 insertions(+), 8 deletions(-)

    diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
    index 04d57e11577e0..09b3bcb86d328 100644
    --- a/fs/nfs/delegation.c
    +++ b/fs/nfs/delegation.c
    @@ -234,6 +234,8 @@ static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation
    spin_lock(&delegation->lock);
    if (delegation->inode != NULL)
    inode = igrab(delegation->inode);
    + if (!inode)
    + set_bit(NFS_DELEGATION_INODE_FREEING, &delegation->flags);
    spin_unlock(&delegation->lock);
    return inode;
    }
    @@ -863,10 +865,11 @@ restart:
    list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
    list_for_each_entry_rcu(delegation, &server->delegations,
    super_list) {
    - if (test_bit(NFS_DELEGATION_RETURNING,
    - &delegation->flags))
    - continue;
    - if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
    + if (test_bit(NFS_DELEGATION_INODE_FREEING,
    + &delegation->flags) ||
    + test_bit(NFS_DELEGATION_RETURNING,
    + &delegation->flags) ||
    + test_bit(NFS_DELEGATION_NEED_RECLAIM,
    &delegation->flags) == 0)
    continue;
    if (!nfs_sb_active(server->super))
    @@ -971,10 +974,11 @@ restart:
    list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
    list_for_each_entry_rcu(delegation, &server->delegations,
    super_list) {
    - if (test_bit(NFS_DELEGATION_RETURNING,
    - &delegation->flags))
    - continue;
    - if (test_bit(NFS_DELEGATION_TEST_EXPIRED,
    + if (test_bit(NFS_DELEGATION_INODE_FREEING,
    + &delegation->flags) ||
    + test_bit(NFS_DELEGATION_RETURNING,
    + &delegation->flags) ||
    + test_bit(NFS_DELEGATION_TEST_EXPIRED,
    &delegation->flags) == 0)
    continue;
    if (!nfs_sb_active(server->super))
    diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
    index df41d16dc6ab4..510c9edcc712d 100644
    --- a/fs/nfs/delegation.h
    +++ b/fs/nfs/delegation.h
    @@ -34,6 +34,7 @@ enum {
    NFS_DELEGATION_RETURNING,
    NFS_DELEGATION_REVOKED,
    NFS_DELEGATION_TEST_EXPIRED,
    + NFS_DELEGATION_INODE_FREEING,
    };

    int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
    --
    2.20.1


    \
     
     \ /
      Last update: 2020-01-24 10:52    [W:4.045 / U:0.580 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site