aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-09-22 13:38:51 -0400
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-09-27 14:31:27 -0400
commit0a014a44a50839a8064618e959fae5bbc44c2fd5 (patch)
treed5817c8c204ed6f710f87a1fc1019283a6372351 /fs/nfs
parent5690a22d8612e1788b48b4ea53c59868589cd2db (diff)
NFSv4.1: Don't deadlock the state manager on the SEQUENCE status flags
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>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4_fs.h2
-rw-r--r--fs/nfs/nfs4proc.c5
-rw-r--r--fs/nfs/nfs4session.h1
-rw-r--r--fs/nfs/nfs4state.c12
4 files changed, 17 insertions, 3 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 55cfeadedb6e..2d1889de69fb 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -448,7 +448,7 @@ extern void nfs4_schedule_path_down_recovery(struct nfs_client *clp);
448extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *); 448extern int nfs4_schedule_stateid_recovery(const struct nfs_server *, struct nfs4_state *);
449extern int nfs4_schedule_migration_recovery(const struct nfs_server *); 449extern int nfs4_schedule_migration_recovery(const struct nfs_server *);
450extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *); 450extern void nfs4_schedule_lease_moved_recovery(struct nfs_client *);
451extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags); 451extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags, bool);
452extern void nfs41_handle_server_scope(struct nfs_client *, 452extern void nfs41_handle_server_scope(struct nfs_client *,
453 struct nfs41_server_scope **); 453 struct nfs41_server_scope **);
454extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 454extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 5ec333f3a19b..9369639fef05 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -616,6 +616,7 @@ int nfs40_setup_sequence(struct nfs4_slot_table *tbl,
616 } 616 }
617 spin_unlock(&tbl->slot_tbl_lock); 617 spin_unlock(&tbl->slot_tbl_lock);
618 618
619 slot->privileged = args->sa_privileged ? 1 : 0;
619 args->sa_slot = slot; 620 args->sa_slot = slot;
620 res->sr_slot = slot; 621 res->sr_slot = slot;
621 622
@@ -728,7 +729,8 @@ static int nfs41_sequence_process(struct rpc_task *task,
728 clp = session->clp; 729 clp = session->clp;
729 do_renew_lease(clp, res->sr_timestamp); 730 do_renew_lease(clp, res->sr_timestamp);
730 /* Check sequence flags */ 731 /* Check sequence flags */
731 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags); 732 nfs41_handle_sequence_flag_errors(clp, res->sr_status_flags,
733 !!slot->privileged);
732 nfs41_update_target_slotid(slot->table, slot, res); 734 nfs41_update_target_slotid(slot->table, slot, res);
733 break; 735 break;
734 case 1: 736 case 1:
@@ -875,6 +877,7 @@ int nfs41_setup_sequence(struct nfs4_session *session,
875 } 877 }
876 spin_unlock(&tbl->slot_tbl_lock); 878 spin_unlock(&tbl->slot_tbl_lock);
877 879
880 slot->privileged = args->sa_privileged ? 1 : 0;
878 args->sa_slot = slot; 881 args->sa_slot = slot;
879 882
880 dprintk("<-- %s slotid=%u seqid=%u\n", __func__, 883 dprintk("<-- %s slotid=%u seqid=%u\n", __func__,
diff --git a/fs/nfs/nfs4session.h b/fs/nfs/nfs4session.h
index 3bb6af70973c..dae385500005 100644
--- a/fs/nfs/nfs4session.h
+++ b/fs/nfs/nfs4session.h
@@ -23,6 +23,7 @@ struct nfs4_slot {
23 u32 slot_nr; 23 u32 slot_nr;
24 u32 seq_nr; 24 u32 seq_nr;
25 unsigned int interrupted : 1, 25 unsigned int interrupted : 1,
26 privileged : 1,
26 seq_done : 1; 27 seq_done : 1;
27}; 28};
28 29
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index cada00aa5096..9801b5bb5fac 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -2227,13 +2227,22 @@ static void nfs41_handle_cb_path_down(struct nfs_client *clp)
2227 nfs4_schedule_state_manager(clp); 2227 nfs4_schedule_state_manager(clp);
2228} 2228}
2229 2229
2230void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) 2230void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags,
2231 bool recovery)
2231{ 2232{
2232 if (!flags) 2233 if (!flags)
2233 return; 2234 return;
2234 2235
2235 dprintk("%s: \"%s\" (client ID %llx) flags=0x%08x\n", 2236 dprintk("%s: \"%s\" (client ID %llx) flags=0x%08x\n",
2236 __func__, clp->cl_hostname, clp->cl_clientid, flags); 2237 __func__, clp->cl_hostname, clp->cl_clientid, flags);
2238 /*
2239 * If we're called from the state manager thread, then assume we're
2240 * already handling the RECLAIM_NEEDED and/or STATE_REVOKED.
2241 * Those flags are expected to remain set until we're done
2242 * recovering (see RFC5661, section 18.46.3).
2243 */
2244 if (recovery)
2245 goto out_recovery;
2237 2246
2238 if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED) 2247 if (flags & SEQ4_STATUS_RESTART_RECLAIM_NEEDED)
2239 nfs41_handle_server_reboot(clp); 2248 nfs41_handle_server_reboot(clp);
@@ -2246,6 +2255,7 @@ void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
2246 nfs4_schedule_lease_moved_recovery(clp); 2255 nfs4_schedule_lease_moved_recovery(clp);
2247 if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED) 2256 if (flags & SEQ4_STATUS_RECALLABLE_STATE_REVOKED)
2248 nfs41_handle_recallable_state_revoked(clp); 2257 nfs41_handle_recallable_state_revoked(clp);
2258out_recovery:
2249 if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT) 2259 if (flags & SEQ4_STATUS_BACKCHANNEL_FAULT)
2250 nfs41_handle_backchannel_fault(clp); 2260 nfs41_handle_backchannel_fault(clp);
2251 else if (flags & (SEQ4_STATUS_CB_PATH_DOWN | 2261 else if (flags & (SEQ4_STATUS_CB_PATH_DOWN |