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_RESOLVE && 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;
- }
+ if (next == prev)
+ return true;
+ if (next == MDSMap::STATE_DAMAGED)
+ return true;
+
+ if (prev == MDSMap::STATE_BOOT) {
+ return next == MDSMap::STATE_STANDBY;
+ } else if (prev == MDSMap::STATE_STANDBY) {
+ return next == MDSMap::STATE_STANDBY_REPLAY ||
+ next == MDSMap::STATE_REPLAY ||
+ next == MDSMap::STATE_CREATING ||
+ next == MDSMap::STATE_STARTING;
+ } else if (prev == MDSMap::STATE_CREATING || prev == MDSMap::STATE_STARTING) {
+ return next == MDSMap::STATE_ACTIVE;
+ } else if (prev == MDSMap::STATE_STANDBY_REPLAY) {
+ return next == MDSMap::STATE_REPLAY;
+ } else if (prev == MDSMap::STATE_REPLAY) {
+ return next == MDSMap::STATE_RESOLVE ||
+ next == MDSMap::STATE_RECONNECT;
+ } else if (prev >= MDSMap::STATE_RESOLVE && prev < MDSMap::STATE_ACTIVE) {
+ // Once I have entered replay, the only allowable transitions are to
+ // the next next along in the sequence.
+ // Except...
+ if (prev == MDSMap::STATE_REJOIN &&
+ (next == MDSMap::STATE_ACTIVE || // No need to do client replay
+ next == MDSMap::STATE_STOPPED)) { // no subtrees
+ return true;
}
+ return next == prev + 1;
+ } else if (prev == MDSMap::STATE_ACTIVE) {
+ return next == MDSMap::STATE_STOPPING;
+ } else if (prev == MDSMap::STATE_STOPPING) {
+ return next == MDSMap::STATE_STOPPED;
+ } else {
+ derr << __func__ << ": Unknown prev state "
+ << ceph_mds_state_name(prev) << "(" << prev << ")" << dendl;
+ return false;
}
-
- return state_valid;
}
bool MDSMap::check_health(mds_rank_t standby_daemon_count)
// I am only to be passed MDSMaps in which I hold a rank
ceph_assert(whoami != MDS_RANK_NONE);
- MDSMap::DaemonState oldstate = state;
mds_gid_t mds_gid = mds_gid_t(monc->get_global_id());
+ MDSMap::DaemonState oldstate = oldmap.get_state_gid(mds_gid);
+ if (oldstate == MDSMap::STATE_NULL) {
+ // monitor may skip sending me the STANDBY map (e.g. if paxos_propose_interval is high)
+ // Assuming I have passed STANDBY state if I got a rank in the first map.
+ oldstate = MDSMap::STATE_STANDBY;
+ }
+ // I should not miss map update
+ ceph_assert(state == oldstate);
state = mdsmap->get_state_gid(mds_gid);
if (state != oldstate) {
last_state = oldstate;