mirror of
https://github.com/ceph/ceph
synced 2025-01-21 02:31:19 +00:00
mds: validate the state+rank in MDS map
Especially: * once I have been assigned a rank, it can't be taken away without restarting the daemon. * once I have entered standby, I can only go upwards through the states. Fixes: #11481 Signed-off-by: John Spray <john.spray@redhat.com>
This commit is contained in:
parent
46a8e0864d
commit
0c5b9a2bab
112
src/mds/MDS.cc
112
src/mds/MDS.cc
@ -1567,11 +1567,53 @@ void MDS::handle_mds_map(MMDSMap *m)
|
||||
// see who i am
|
||||
addr = messenger->get_myaddr();
|
||||
whoami = mdsmap->get_rank_gid(mds_gid_t(monc->get_global_id()));
|
||||
if (whoami == MDS_RANK_NONE && (
|
||||
state == MDSMap::STATE_STANDBY_REPLAY || state == MDSMap::STATE_ONESHOT_REPLAY)) {
|
||||
whoami = mdsmap->get_mds_info_gid(mds_gid_t(monc->get_global_id())).standby_for_rank;
|
||||
}
|
||||
|
||||
state = mdsmap->get_state_gid(mds_gid_t(monc->get_global_id()));
|
||||
incarnation = mdsmap->get_inc_gid(mds_gid_t(monc->get_global_id()));
|
||||
dout(10) << "map says i am " << addr << " mds." << whoami << "." << incarnation
|
||||
<< " state " << ceph_mds_state_name(state) << dendl;
|
||||
|
||||
// Once I hold a rank it can't be taken away without
|
||||
// restarting this daemon
|
||||
if (whoami != oldwhoami && oldwhoami != MDS_RANK_NONE) {
|
||||
derr << "Invalid rank transition " << oldwhoami << "->" << whoami << dendl;
|
||||
respawn();
|
||||
}
|
||||
|
||||
// Validate state transitions while I hold a rank
|
||||
{
|
||||
bool state_valid = true;
|
||||
if (whoami != MDS_RANK_NONE && 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) {
|
||||
derr << "Invalid state transition " << ceph_mds_state_name(oldstate)
|
||||
<< "->" << ceph_mds_state_name(state) << dendl;
|
||||
respawn();
|
||||
}
|
||||
}
|
||||
|
||||
// mark down any failed peers
|
||||
for (map<mds_gid_t,MDSMap::mds_info_t>::const_iterator p = oldmap->get_mds_info().begin();
|
||||
p != oldmap->get_mds_info().end();
|
||||
@ -1603,48 +1645,38 @@ void MDS::handle_mds_map(MMDSMap *m)
|
||||
}
|
||||
}
|
||||
|
||||
if (whoami < 0) {
|
||||
if (state == MDSMap::STATE_STANDBY_REPLAY ||
|
||||
state == MDSMap::STATE_ONESHOT_REPLAY) {
|
||||
// fill in whoami from standby-for-rank. If we let this be changed
|
||||
// the logic used to set it here will need to be adjusted.
|
||||
whoami = mdsmap->get_mds_info_gid(mds_gid_t(monc->get_global_id())).standby_for_rank;
|
||||
} else {
|
||||
if (want_state == MDSMap::STATE_STANDBY) {
|
||||
dout(10) << "dropped out of mdsmap, try to re-add myself" << dendl;
|
||||
state = MDSMap::STATE_BOOT;
|
||||
set_want_state(state);
|
||||
goto out;
|
||||
}
|
||||
if (want_state == MDSMap::STATE_BOOT) {
|
||||
dout(10) << "not in map yet" << dendl;
|
||||
} else {
|
||||
// did i get kicked by someone else?
|
||||
if (g_conf->mds_enforce_unique_name) {
|
||||
if (mds_gid_t existing = mdsmap->find_mds_gid_by_name(name)) {
|
||||
MDSMap::mds_info_t& i = mdsmap->get_info_gid(existing);
|
||||
if (i.global_id > monc->get_global_id()) {
|
||||
dout(1) << "handle_mds_map i (" << addr
|
||||
<< ") dne in the mdsmap, new instance has larger gid " << i.global_id
|
||||
<< ", suicide" << dendl;
|
||||
// Call suicide() rather than respawn() because if someone else
|
||||
// has taken our ID, we don't want to keep restarting and
|
||||
// fighting them for the ID.
|
||||
suicide();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dout(1) << "handle_mds_map i (" << addr
|
||||
<< ") dne in the mdsmap, respawning myself" << dendl;
|
||||
respawn();
|
||||
}
|
||||
if (whoami == MDS_RANK_NONE) {
|
||||
if (want_state == MDSMap::STATE_STANDBY) {
|
||||
dout(10) << "dropped out of mdsmap, try to re-add myself" << dendl;
|
||||
state = MDSMap::STATE_BOOT;
|
||||
set_want_state(state);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
} else if (want_state == MDSMap::STATE_BOOT) {
|
||||
dout(10) << "not in map yet" << dendl;
|
||||
} else {
|
||||
// did i get kicked by someone else?
|
||||
if (g_conf->mds_enforce_unique_name) {
|
||||
if (mds_gid_t existing = mdsmap->find_mds_gid_by_name(name)) {
|
||||
MDSMap::mds_info_t& i = mdsmap->get_info_gid(existing);
|
||||
if (i.global_id > monc->get_global_id()) {
|
||||
dout(1) << "handle_mds_map i (" << addr
|
||||
<< ") dne in the mdsmap, new instance has larger gid " << i.global_id
|
||||
<< ", suicide" << dendl;
|
||||
// Call suicide() rather than respawn() because if someone else
|
||||
// has taken our ID, we don't want to keep restarting and
|
||||
// fighting them for the ID.
|
||||
suicide();
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ??
|
||||
dout(1) << "handle_mds_map i (" << addr
|
||||
<< ") dne in the mdsmap, respawning myself" << dendl;
|
||||
respawn();
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (oldwhoami != whoami || oldstate != state) {
|
||||
// update messenger.
|
||||
|
Loading…
Reference in New Issue
Block a user