From db6c8f9ab32a7bc0dc8bca94f79812bfb9e7b123 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 24 Feb 2021 14:59:57 -0600 Subject: [PATCH] mon/OSDMonitor: fix safety/idempotency of {set,rm}-device-class If the command is resent (e.g., due to network reconnect), the second instance may find that the pending crush map already has the changes and not wait for it to commit. Note that the stderr message will be misleading in this case; that is a problem with most of our mon commands. :( Fixes: https://tracker.ceph.com/issues/49212 Signed-off-by: Sage Weil --- src/mon/OSDMonitor.cc | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 3d2528ec002..eef39a6b4da 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -9896,16 +9896,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, } } - if (!updated.empty()) { - pending_inc.crush.clear(); - newcrush.encode(pending_inc.crush, mon.get_quorum_con_features()); - ss << "set osd(s) " << updated << " to class '" << device_class << "'"; - getline(ss, rs); - wait_for_finished_proposal(op, - new Monitor::C_Command(mon,op, 0, rs, get_last_committed() + 1)); - return true; - } - + pending_inc.crush.clear(); + newcrush.encode(pending_inc.crush, mon.get_quorum_con_features()); + ss << "set osd(s) " << updated << " to class '" << device_class << "'"; + getline(ss, rs); + wait_for_finished_proposal( + op, + new Monitor::C_Command(mon,op, 0, rs, get_last_committed() + 1)); + return true; } else if (prefix == "osd crush rm-device-class") { bool stop = false; vector idvec; @@ -9958,15 +9956,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, } } - if (!updated.empty()) { - pending_inc.crush.clear(); - newcrush.encode(pending_inc.crush, mon.get_quorum_con_features()); - ss << "done removing class of osd(s): " << updated; - getline(ss, rs); - wait_for_finished_proposal(op, - new Monitor::C_Command(mon,op, 0, rs, get_last_committed() + 1)); - return true; - } + pending_inc.crush.clear(); + newcrush.encode(pending_inc.crush, mon.get_quorum_con_features()); + ss << "done removing class of osd(s): " << updated; + getline(ss, rs); + wait_for_finished_proposal( + op, + new Monitor::C_Command(mon,op, 0, rs, get_last_committed() + 1)); + return true; } else if (prefix == "osd crush class create") { string device_class; if (!cmd_getval(cmdmap, "class", device_class)) {