lkml.org 
[lkml]   [2018]   [Nov]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.19 46/68] NFSv4: Fix a NFSv4 state manager deadlock
    Date
    From: Trond Myklebust <trond.myklebust@hammerspace.com>

    [ Upstream commit aeabb3c96186a0f944fc2b1f25c84d5eb3a93fa9 ]

    Fix a deadlock whereby the NFSv4 state manager can get stuck in the
    delegation return code, waiting for a layout return to complete in
    another thread. If the server reboots before that other thread
    completes, then we need to be able to start a second state
    manager thread in order to perform recovery.

    Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/nfs/nfs4_fs.h | 2 ++
    fs/nfs/nfs4state.c | 16 +++++++++++-----
    2 files changed, 13 insertions(+), 5 deletions(-)

    diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
    index 3a6904173214..63287d911c08 100644
    --- a/fs/nfs/nfs4_fs.h
    +++ b/fs/nfs/nfs4_fs.h
    @@ -41,6 +41,8 @@ enum nfs4_client_state {
    NFS4CLNT_MOVED,
    NFS4CLNT_LEASE_MOVED,
    NFS4CLNT_DELEGATION_EXPIRED,
    + NFS4CLNT_RUN_MANAGER,
    + NFS4CLNT_DELEGRETURN_RUNNING,
    };

    #define NFS4_RENEW_TIMEOUT 0x01
    diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
    index 18920152da14..d2f645d34eb1 100644
    --- a/fs/nfs/nfs4state.c
    +++ b/fs/nfs/nfs4state.c
    @@ -1210,6 +1210,7 @@ void nfs4_schedule_state_manager(struct nfs_client *clp)
    struct task_struct *task;
    char buf[INET6_ADDRSTRLEN + sizeof("-manager") + 1];

    + set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
    if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
    return;
    __module_get(THIS_MODULE);
    @@ -2485,6 +2486,7 @@ static void nfs4_state_manager(struct nfs_client *clp)

    /* Ensure exclusive access to NFSv4 state */
    do {
    + clear_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
    if (test_bit(NFS4CLNT_PURGE_STATE, &clp->cl_state)) {
    section = "purge state";
    status = nfs4_purge_lease(clp);
    @@ -2575,14 +2577,18 @@ static void nfs4_state_manager(struct nfs_client *clp)
    }

    nfs4_end_drain_session(clp);
    - if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
    - nfs_client_return_marked_delegations(clp);
    - continue;
    + nfs4_clear_state_manager_bit(clp);
    +
    + if (!test_and_set_bit(NFS4CLNT_DELEGRETURN_RUNNING, &clp->cl_state)) {
    + if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
    + nfs_client_return_marked_delegations(clp);
    + set_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state);
    + }
    + clear_bit(NFS4CLNT_DELEGRETURN_RUNNING, &clp->cl_state);
    }

    - nfs4_clear_state_manager_bit(clp);
    /* Did we race with an attempt to give us more work? */
    - if (clp->cl_state == 0)
    + if (!test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state))
    return;
    if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
    return;
    --
    2.17.1
    \
     
     \ /
      Last update: 2018-11-29 07:12    [W:4.072 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site