return STUCK_UNAVAILABLE;
}
}
+
+bool MDSMap::state_transition_valid(DaemonState prev, DaemonState next)
+{
+ bool state_valid = true;
+ if (next != prev) {
+ if (prev == MDSMap::STATE_REPLAY) {
+ if (next != MDSMap::STATE_RESOLVE && next != MDSMap::STATE_RECONNECT) {
+ state_valid = false;
+ }
+ } else if (prev == MDSMap::STATE_REJOIN) {
+ if (next != MDSMap::STATE_ACTIVE
+ && next != MDSMap::STATE_CLIENTREPLAY
+ && next != MDSMap::STATE_STOPPED) {
+ state_valid = false;
+ }
+ } else if (prev >= MDSMap::STATE_RECONNECT && prev < MDSMap::STATE_ACTIVE) {
+ // Once I have entered replay, the only allowable transitions are to
+ // the next next along in the sequence.
+ if (next != prev + 1) {
+ state_valid = false;
+ }
+ }
+ }
+
+ return state_valid;
+}
void dump(Formatter *f) const;
static void generate_test_instances(list<MDSMap*>& ls);
+
+ static bool state_transition_valid(DaemonState prev, DaemonState next);
};
WRITE_CLASS_ENCODER_FEATURES(MDSMap::mds_info_t)
WRITE_CLASS_ENCODER_FEATURES(MDSMap)
}
// Validate state transitions while I hold a rank
- bool state_valid = true;
- if (state != oldstate) {
- if (oldstate == MDSMap::STATE_REPLAY) {
- if (state != MDSMap::STATE_RESOLVE && state != MDSMap::STATE_RECONNECT) {
- state_valid = false;
- }
- } else if (oldstate == MDSMap::STATE_REJOIN) {
- if (state != MDSMap::STATE_ACTIVE
- && state != MDSMap::STATE_CLIENTREPLAY
- && state != MDSMap::STATE_STOPPED) {
- state_valid = false;
- }
- } else if (oldstate >= MDSMap::STATE_RECONNECT && oldstate < MDSMap::STATE_ACTIVE) {
- // Once I have entered replay, the only allowable transitions are to
- // the next state along in the sequence.
- if (state != oldstate + 1) {
- state_valid = false;
- }
- }
- }
-
- if (!state_valid) {
+ if (!MDSMap::state_transition_valid(oldstate, state)) {
derr << "Invalid state transition " << ceph_mds_state_name(oldstate)
<< "->" << ceph_mds_state_name(state) << dendl;
respawn();
mon->monmap->fsid, m->get_global_id(),
m->get_name(), fsmap.get_epoch(), state, seq,
CEPH_FEATURES_SUPPORTED_DEFAULT));
+ } else if (info.state == MDSMap::STATE_STANDBY && state != info.state) {
+ // Standby daemons should never modify their own
+ // state. Reject any attempts to do so.
+ derr << "standby " << gid << " attempted to change state to "
+ << ceph_mds_state_name(state) << ", rejecting" << dendl;
+ return true;
+ } else if (info.state != MDSMap::STATE_STANDBY && state != info.state &&
+ !MDSMap::state_transition_valid(info.state, state)) {
+ // Validate state transitions for daemons that hold a rank
+ derr << "daemon " << gid << " (rank " << info.rank << ") "
+ << "reported invalid state transition "
+ << ceph_mds_state_name(info.state) << " -> "
+ << ceph_mds_state_name(state) << dendl;
+ return true;
} else {
+ // Made it through special cases and validations, record the
+ // daemon's reported state to the FSMap.
pending_fsmap.modify_daemon(gid, [state, seq](MDSMap::mds_info_t *info) {
info->state = state;
info->state_seq = seq;