]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
NFSv4.1: Don't deadlock the state manager on the SEQUENCE status flags
authorTrond Myklebust <trond.myklebust@primarydata.com>
Thu, 22 Sep 2016 17:38:51 +0000 (13:38 -0400)
committerChuck Anderson <chuck.anderson@oracle.com>
Fri, 15 Sep 2017 03:27:50 +0000 (20:27 -0700)
As described in RFC5661, section 18.46, some of the status flags exist
in order to tell the client when it needs to acknowledge the existence of
revoked state on the server and/or to recover state.
Those flags will then remain set until the recovery procedure is done.

In order to avoid looping, the client therefore needs to ignore
those particular flags while recovering.

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Tested-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
(cherry picked from commit 0a014a44a50839a8064618e959fae5bbc44c2fd5)

orabug: 25513155
Signed-off-by: Todd Vierling <todd.vierling@oracle.com>
Reviewed-By: Jack Vogel <jack.vogel@oracle.com>
Tested-by: xuan.qi@oracle.com
Signed-off-by: Manjunath Patil <manjunath.b.patil@oracle.com>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4session.h
fs/nfs/nfs4state.c

index fdef424b0cd3c6120ddc7d9e379e49647b7b24fb..7e9cc0c2ecb018dc3dffe702138adeb6f41b9c54 100644 (file)
@@ -432,7 +432,7 @@ extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
 extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
 extern int nfs4_schedule_migration_recovery(const struct nfs_server *);
 extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *);
-extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags);
+extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags, bool);
 extern void nfs41_handle_server_scope(struct nfs_client *,
                                      struct nfs41_server_scope **);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
index 907de70afe25f248f6f39c6da0dc07ff389140b7..823bd0ec423e52575eeb7a6a95e603e5ce24e90e 100644 (file)
@@ -523,6 +523,7 @@ int nfs40_setup_sequence(struct nfs4_slot_table *tbl,
        }
        spin_unlock(&tbl->slot_tbl_lock);
 
+       slot->privileged = args->sa_privileged ? 1 : 0;
        args->sa_slot = slot;
        res->sr_slot = slot;
 
@@ -630,7 +631,8 @@ int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *res)
                clp = session->clp;
                do_renew_lease(clp, res->sr_timestamp);
                /* Check sequence flags */
-               nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags);
+               nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags,
+                               !!slot->privileged);
                nfs41_update_target_slotid(slot->table, slot, res);
                break;
        case 1:
@@ -748,6 +750,7 @@ int nfs41_setup_sequence(struct nfs4_session *session,
        }
        spin_unlock(&tbl->slot_tbl_lock);
 
+       slot->privileged = args->sa_privileged ? 1 : 0;
        args->sa_slot = slot;
 
        dprintk("<-- %s slotid=%u seqid=%u\n", __func__,
index c3597b033fd8223466d8b97ac38e45b9de924e01..ed5c624a62aa0706bf1f1f05ea35d00ebcf06c15 100644 (file)
@@ -22,6 +22,7 @@ struct nfs4_slot {
        u32                     slot_nr;
        u32                     seq_nr;
        unsigned int            interrupted : 1,
+                               privileged : 1,
                                seq_done : 1;
 };
 
index 486973c54c5efa76cbf6ba336211ab870a5243ec..20e098488df756f488990fe684b414e1c738f877 100644 (file)
@@ -2228,13 +2228,22 @@ static void nfs41_handle_cb_path_down(struct nfs_client *clp)
                nfs4_schedule_state_manager(clp);
 }
 
-void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
+void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags,
+               bool recovery)
 {
        if (!flags)
                return;
 
        dprintk("%s: \"%s\" (client ID %llx) flags=0x%08x\n",
                __func__, clp->cl_hostname, clp->cl_clientid, flags);
+       /*
+        * If we're called from the state manager thread, then assume we're
+        * already handling the RECLAIM_NEEDED and/or STATE_REVOKED.
+        * Those flags are expected to remain set until we're done
+        * recovering (see RFC5661, section 18.46.3).
+        */
+       if (recovery)
+               goto out_recovery;
 
        if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
                nfs41_handle_server_reboot(clp);
@@ -2246,6 +2255,7 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
                nfs4_schedule_lease_moved_recovery(clp);
        if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
                nfs41_handle_recallable_state_revoked(clp);
+out_recovery:
        if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT)
                nfs41_handle_backchannel_fault(clp);
        else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |