]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/mon/OSDMonitor.cc
update ceph source to reef 18.2.1
[ceph.git] / ceph / src / mon / OSDMonitor.cc
index 3acafbb82e682b812e468749815ba786ad9ea2e4..360bd036bf977888786230a018e59167b066de57 100644 (file)
@@ -2769,7 +2769,7 @@ bool OSDMonitor::preprocess_query(MonOpRequestRef op)
 
   default:
     ceph_abort();
-    return true;
+    return false;
   }
 }
 
@@ -2808,7 +2808,7 @@ bool OSDMonitor::prepare_update(MonOpRequestRef op)
     } catch (const bad_cmd_get& e) {
       bufferlist bl;
       mon.reply_command(op, -EINVAL, e.what(), bl, get_last_committed());
-      return true;
+      return false; /* nothing to propose */
     }
 
   case CEPH_MSG_POOLOP:
@@ -4057,7 +4057,7 @@ bool OSDMonitor::prepare_pg_ready_to_merge(MonOpRequestRef op)
             << " race with concurrent pg_num[_pending] update, will retry"
             << dendl;
     wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-    return true;
+    return false; /* nothing to propose, yet */
   }
 
   if (m->ready) {
@@ -4438,7 +4438,7 @@ bool OSDMonitor::prepare_beacon(MonOpRequestRef op)
       send_latest(op, beacon->version+1);
     }
     dout(1) << " ignoring beacon from non-active osd." << from << dendl;
-    return false;
+    return false; /* nothing to propose */
   }
 
   last_osd_report[from].first = ceph_clock_now();
@@ -4461,7 +4461,7 @@ bool OSDMonitor::prepare_beacon(MonOpRequestRef op)
       beacon->last_purged_snaps_scrub;
     return true;
   } else {
-    return false;
+    return false; /* nothing to propose */
   }
 }
 
@@ -9776,14 +9776,14 @@ bool OSDMonitor::prepare_command(MonOpRequestRef op)
   if (!cmdmap_from_json(m->cmd, &cmdmap, ss)) {
     string rs = ss.str();
     mon.reply_command(op, -EINVAL, rs, get_last_committed());
-    return true;
+    return false; /* nothing to propose */
   }
 
   MonSession *session = op->get_session();
   if (!session) {
     derr << __func__ << " no session" << dendl;
     mon.reply_command(op, -EACCES, "access denied", get_last_committed());
-    return true;
+    return false; /* nothing to propose */
   }
 
   return prepare_command_impl(op, cmdmap);
@@ -9991,7 +9991,6 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
 {
   op->mark_osdmon_event(__func__);
   auto m = op->get_req<MMonCommand>();
-  bool ret = false;
   stringstream ss;
   string rs;
   bufferlist rdata;
@@ -10051,8 +10050,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       (prefix == "osd crush set" && !osdid_present)) {
     if (pending_inc.crush.length()) {
       dout(10) << __func__ << " waiting for pending crush update " << dendl;
-      wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-      return true;
+      goto wait;
     }
     dout(10) << "prepare_command setting new crush map" << dendl;
     bufferlist data(m->get_data());
@@ -10064,7 +10062,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     catch (const std::exception &e) {
       err = -EINVAL;
       ss << "Failed to parse crushmap: " << e.what();
-      goto reply;
+      goto reply_no_propose;
     }
   
     int64_t prior_version = 0;
@@ -10082,25 +10080,25 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
                   << dendl;
          err = 0;
          ss << osdmap.get_crush_version();
-         goto reply;
+         goto reply_no_propose;
        }
       }
       if (prior_version != osdmap.get_crush_version()) {
        err = -EPERM;
        ss << "prior_version " << prior_version << " != crush version "
           << osdmap.get_crush_version();
-       goto reply;
+       goto reply_no_propose;
       }
     }
 
     if (!validate_crush_against_features(&crush, ss)) {
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     err = osdmap.validate_crush_rules(&crush, &ss);
     if (err < 0) {
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (g_conf()->mon_osd_crush_smoke_test) {
@@ -10120,7 +10118,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
                 << ": " << ess.str() << dendl;
        ss << "crush smoke test failed with " << r << ": " << ess.str();
        err = r;
-       goto reply;
+       goto reply_no_propose;
       }
       dout(10) << __func__ << " crush somke test duration: "
                << duration << ", result: " << ess.str() << dendl;
@@ -10142,7 +10140,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     }
     if (!validate_crush_against_features(&newcrush, ss)) {
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     pending_inc.crush.clear();
     newcrush.encode(pending_inc.crush, mon.get_quorum_con_features());
@@ -10153,7 +10151,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     string device_class;
     if (!cmd_getval(cmdmap, "class", device_class)) {
       err = -EINVAL; // no value!
-      goto reply;
+      goto reply_no_propose;
     }
 
     bool stop = false;
@@ -10206,7 +10204,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
                 << dendl;
         err = newcrush.update_device_class(osd, device_class, name, &ss);
         if (err < 0) {
-          goto reply;
+          goto reply_no_propose;
         }
         if (err == 0 && !_have_pending_crush()) {
           if (!stop) {
@@ -10250,7 +10248,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           // ss has reason for failure
           ss << ", unable to parse osd id:\"" << idvec[j] << "\". ";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
         osds.insert(osd);
       }
@@ -10273,7 +10271,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         err = newcrush.remove_device_class(cct, osd, &ss);
         if (err < 0) {
           // ss has reason for failure
-          goto reply;
+          goto reply_no_propose;
         }
         updated.insert(osd);
       }
@@ -10291,18 +10289,18 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     string device_class;
     if (!cmd_getval(cmdmap, "class", device_class)) {
       err = -EINVAL; // no value!
-      goto reply;
+      goto reply_no_propose;
     }
     if (osdmap.require_osd_release < ceph_release_t::luminous) {
       ss << "you must complete the upgrade and 'ceph osd require-osd-release "
          << "luminous' before using crush device classes";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if (!_have_pending_crush() &&
         _get_stable_crush().class_exists(device_class)) {
       ss << "class '" << device_class << "' already exists";
-      goto reply;
+      goto reply_no_propose;
     }
      CrushWrapper newcrush = _get_pending_crush();
      if (newcrush.class_exists(device_class)) {
@@ -10319,18 +10317,18 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     string device_class;
     if (!cmd_getval(cmdmap, "class", device_class)) {
        err = -EINVAL; // no value!
-       goto reply;
+       goto reply_no_propose;
      }
     if (osdmap.require_osd_release < ceph_release_t::luminous) {
        ss << "you must complete the upgrade and 'ceph osd require-osd-release "
          << "luminous' before using crush device classes";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
      }
 
      if (!osdmap.crush->class_exists(device_class)) {
        err = 0;
-       goto reply;
+       goto reply_no_propose;
      }
 
      CrushWrapper newcrush = _get_pending_crush();
@@ -10343,7 +10341,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
      if (newcrush.class_is_in_use(class_id, &ts)) {
        err = -EBUSY;
        ss << "class '" << device_class << "' " << ts.str();
-       goto reply;
+       goto reply_no_propose;
      }
 
      // check if class is used by any erasure-code-profiles
@@ -10368,7 +10366,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        err = -EBUSY;
        ss << "class '" << device_class
           << "' is still referenced by erasure-code-profile(s): " << referenced_by;
-       goto reply;
+       goto reply_no_propose;
      }
 
      set<int> osds;
@@ -10377,7 +10375,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        err = newcrush.remove_device_class(cct, p, &ss);
        if (err < 0) {
          // ss has reason for failure
-         goto reply;
+         goto reply_no_propose;
        }
      }
 
@@ -10387,7 +10385,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        if (err < 0) {
          ss << "class '" << device_class << "' cannot be removed '"
             << cpp_strerror(err) << "'";
-         goto reply;
+         goto reply_no_propose;
        }
      }
 
@@ -10400,11 +10398,11 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     string srcname, dstname;
     if (!cmd_getval(cmdmap, "srcname", srcname)) {
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (!cmd_getval(cmdmap, "dstname", dstname)) {
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     CrushWrapper newcrush = _get_pending_crush();
@@ -10413,14 +10411,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       // so command is idempotent
       ss << "already renamed to '" << dstname << "'";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     err = newcrush.rename_class(srcname, dstname);
     if (err < 0) {
       ss << "fail to rename '" << srcname << "' to '" << dstname << "' : "
          << cpp_strerror(err);
-      goto reply;
+      goto reply_no_propose;
     }
 
     pending_inc.crush.clear();
@@ -10444,7 +10442,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!_have_pending_crush() &&
        _get_stable_crush().name_exists(name)) {
       ss << "bucket '" << name << "' already exists";
-      goto reply;
+      goto reply_no_propose;
     }
 
     CrushWrapper newcrush = _get_pending_crush();
@@ -10457,12 +10455,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (type < 0) {
       ss << "type '" << typestr << "' does not exist";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (type == 0) {
       ss << "type '" << typestr << "' is for devices, not buckets";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     int bucketno;
     err = newcrush.add_bucket(0, 0,
@@ -10470,12 +10468,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
                              NULL, &bucketno);
     if (err < 0) {
       ss << "add_bucket error: '" << cpp_strerror(err) << "'";
-      goto reply;
+      goto reply_no_propose;
     }
     err = newcrush.set_item_name(bucketno, name);
     if (err < 0) {
       ss << "error setting bucket name to '" << name << "'";
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (!loc.empty()) {
@@ -10484,7 +10482,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         err = newcrush.move_bucket(cct, bucketno, loc);
         if (err < 0) {
           ss << "error moving bucket '" << name << "' to location " << loc;
-          goto reply;
+          goto reply_no_propose;
         }
       } else {
         ss << "no need to move item id " << bucketno << " name '" << name
@@ -10508,12 +10506,15 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     cmd_getval(cmdmap, "dstname", dstname);
 
     err = crush_rename_bucket(srcname, dstname, &ss);
-    if (err == -EALREADY) // equivalent to success for idempotency
-      err = 0;
-    if (err)
-      goto reply;
-    else
+    if (err) {
+      // equivalent to success for idempotency
+      if (err == -EALREADY) {
+        err = 0;
+      }
+      goto reply_no_propose;
+    } else {
       goto update;
+    }
   } else if (prefix == "osd crush weight-set create" ||
             prefix == "osd crush weight-set create-compat") {
     if (_have_pending_crush()) {
@@ -10526,7 +10527,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (newcrush.has_non_straw2_buckets()) {
       ss << "crush map contains one or more bucket(s) that are not straw2";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if (prefix == "osd crush weight-set create") {
       if (osdmap.require_min_compat_client != ceph_release_t::unknown &&
@@ -10537,7 +10538,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
            << "Try 'ceph osd set-require-min-compat-client luminous' "
            << "before using the new interface";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
       string poolname, mode;
       cmd_getval(cmdmap, "pool", poolname);
@@ -10545,13 +10546,13 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (pool < 0) {
        ss << "pool '" << poolname << "' not found";
        err = -ENOENT;
-       goto reply;
+       goto reply_no_propose;
       }
       cmd_getval(cmdmap, "mode", mode);
       if (mode != "flat" && mode != "positional") {
        ss << "unrecognized weight-set mode '" << mode << "'";
        err = -EINVAL;
-       goto reply;
+       goto reply_no_propose;
       }
       positions = mode == "flat" ? 1 : osdmap.get_pg_pool(pool)->get_size();
     } else {
@@ -10565,7 +10566,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         ss << "weight-set for pool '" << osdmap.get_pool_name(pool)
            << "' already created";
       }
-      goto reply;
+      goto reply_no_propose;
     }
     pending_inc.crush.clear();
     newcrush.encode(pending_inc.crush, mon.get_quorum_con_features());
@@ -10582,7 +10583,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (pool < 0) {
        ss << "pool '" << poolname << "' not found";
        err = -ENOENT;
-       goto reply;
+       goto reply_no_propose;
       }
     } else {
       pool = CrushWrapper::DEFAULT_CHOOSE_ARGS;
@@ -10606,32 +10607,32 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (pool < 0) {
        ss << "pool '" << poolname << "' not found";
        err = -ENOENT;
-       goto reply;
+       goto reply_no_propose;
       }
       if (!newcrush.have_choose_args(pool)) {
        ss << "no weight-set for pool '" << poolname << "'";
        err = -ENOENT;
-       goto reply;
+       goto reply_no_propose;
       }
       auto arg_map = newcrush.choose_args_get(pool);
       int positions = newcrush.get_choose_args_positions(arg_map);
       if (weight.size() != (size_t)positions) {
          ss << "must specify exact " << positions << " weight values";
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
       }
     } else {
       pool = CrushWrapper::DEFAULT_CHOOSE_ARGS;
       if (!newcrush.have_choose_args(pool)) {
        ss << "no backward-compatible weight-set";
        err = -ENOENT;
-       goto reply;
+       goto reply_no_propose;
       }
     }
     if (!newcrush.name_exists(item)) {
       ss << "item '" << item << "' does not exist";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     err = newcrush.choose_args_adjust_item_weightf(
       cct,
@@ -10640,7 +10641,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       weight,
       &ss);
     if (err < 0) {
-      goto reply;
+      goto reply_no_propose;
     }
     err = 0;
     pending_inc.crush.clear();
@@ -10656,7 +10657,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       err = -ENOENT;
       ss << osd_name
         << " does not exist. Create it before updating the crush map";
-      goto reply;
+      goto reply_no_propose;
     }
 
     double weight;
@@ -10664,7 +10665,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "unable to parse weight value '"
          << cmd_vartype_stringify(cmdmap.at("weight")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     string args;
@@ -10679,7 +10680,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "unable to set item id " << osdid << " name '" << osd_name
          << "' weight " << weight << " at location " << loc
          << ": does not exist";
-      goto reply;
+      goto reply_no_propose;
     }
 
     dout(5) << "adding/updating crush item id " << osdid << " name '"
@@ -10700,12 +10701,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     }
 
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
 
     if (err == 0 && !_have_pending_crush()) {
       ss << action << " item id " << osdid << " name '" << osd_name
         << "' weight " << weight << " at location " << loc << ": no change";
-      goto reply;
+      goto reply_no_propose;
     }
 
     pending_inc.crush.clear();
@@ -10724,7 +10725,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        err = -ENOENT;
        ss << osd_name
           << " does not exist.  create it before updating the crush map";
-       goto reply;
+       goto reply_no_propose;
       }
 
       double weight;
@@ -10732,7 +10733,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         ss << "unable to parse weight value '"
            << cmd_vartype_stringify(cmdmap.at("weight")) << "'";
         err = -EINVAL;
-        goto reply;
+        goto reply_no_propose;
       }
 
       string args;
@@ -10822,12 +10823,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!newcrush.name_exists(source)) {
       ss << "source item " << source << " does not exist";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     if (!newcrush.name_exists(dest)) {
       ss << "dest item " << dest << " does not exist";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     int sid = newcrush.get_item_id(source);
     int did = newcrush.get_item_id(dest);
@@ -10835,7 +10836,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (newcrush.get_immediate_parent_id(sid, &sparent) == 0 && !force) {
       ss << "source item " << source << " is not an orphan bucket; pass --yes-i-really-mean-it to proceed anyway";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if (newcrush.get_bucket_alg(sid) != newcrush.get_bucket_alg(did) &&
        !force) {
@@ -10843,13 +10844,13 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         << "dest bucket alg " << crush_alg_name(newcrush.get_bucket_alg(did))
         << "; pass --yes-i-really-mean-it to proceed anyway";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     int r = newcrush.swap_bucket(cct, sid, did);
     if (r < 0) {
       ss << "failed to swap bucket contents: " << cpp_strerror(r);
       err = r;
-      goto reply;
+      goto reply_no_propose;
     }
     ss << "swapped bucket of " << source << " to " << dest;
     pending_inc.crush.clear();
@@ -10873,7 +10874,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!osdmap.crush->name_exists(name)) {
       err = -ENOENT;
       ss << "item " << name << " does not exist";
-      goto reply;
+      goto reply_no_propose;
     } else {
       dout(5) << "resolved crush name '" << name << "' to id " << id << dendl;
     }
@@ -10881,7 +10882,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "no need to move item id " << id << " name '" << name
         << "' to location " << loc << " in crush map";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     dout(5) << "linking crush item name '" << name << "' at location " << loc << dendl;
@@ -10890,7 +10891,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!newcrush.name_exists(name)) {
       err = -ENOENT;
       ss << "item " << name << " does not exist";
-      goto reply;
+      goto reply_no_propose;
     } else {
       int id = newcrush.get_item_id(name);
       if (!newcrush.check_item_loc(cct, id, loc, (int *)NULL)) {
@@ -10903,7 +10904,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        } else {
          ss << "cannot link item id " << id << " name '" << name
              << "' to location " << loc;
-          goto reply;
+          goto reply_no_propose;
        }
       } else {
        ss << "no need to move item id " << id << " name '" << name
@@ -10993,27 +10994,27 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!newcrush.name_exists(name)) {
       err = -ENOENT;
       ss << "device '" << name << "' does not appear in the crush map";
-      goto reply;
+      goto reply_no_propose;
     }
 
     int id = newcrush.get_item_id(name);
     if (id < 0) {
       ss << "device '" << name << "' is not a leaf in the crush map";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     double w;
     if (!cmd_getval(cmdmap, "weight", w)) {
       ss << "unable to parse weight value '"
         << cmd_vartype_stringify(cmdmap.at("weight")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     err = newcrush.adjust_item_weightf(cct, id, w,
                                       g_conf()->osd_crush_update_weight_set);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     pending_inc.crush.clear();
     newcrush.encode(pending_inc.crush, mon.get_quorum_con_features());
     ss << "reweighted item id " << id << " name '" << name << "' to " << w
@@ -11031,27 +11032,27 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!newcrush.name_exists(name)) {
       err = -ENOENT;
       ss << "device '" << name << "' does not appear in the crush map";
-      goto reply;
+      goto reply_no_propose;
     }
 
     int id = newcrush.get_item_id(name);
     if (id >= 0) {
       ss << "device '" << name << "' is not a subtree in the crush map";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     double w;
     if (!cmd_getval(cmdmap, "weight", w)) {
       ss << "unable to parse weight value '"
         << cmd_vartype_stringify(cmdmap.at("weight")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     err = newcrush.adjust_subtree_weightf(cct, id, w,
                                          g_conf()->osd_crush_update_weight_set);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     pending_inc.crush.clear();
     newcrush.encode(pending_inc.crush, mon.get_quorum_con_features());
     ss << "reweighted subtree id " << id << " name '" << name << "' to " << w
@@ -11083,12 +11084,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     } else {
       ss << "unrecognized profile '" << profile << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (!validate_crush_against_features(&newcrush, ss)) {
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     pending_inc.crush.clear();
@@ -11110,25 +11111,25 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       err = -EINVAL;
       ss << "failed to parse integer value "
         << cmd_vartype_stringify(cmdmap.at("value"));
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (tunable == "straw_calc_version") {
       if (value != 0 && value != 1) {
        ss << "value must be 0 or 1; got " << value;
        err = -EINVAL;
-       goto reply;
+       goto reply_no_propose;
       }
       newcrush.set_straw_calc_version(value);
     } else {
       ss << "unrecognized tunable '" << tunable << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (!validate_crush_against_features(&newcrush, ss)) {
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     pending_inc.crush.clear();
@@ -11153,7 +11154,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       // From the user point of view, the rule is more meaningfull.
       ss << "rule " << name << " already exists";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     CrushWrapper newcrush = _get_pending_crush();
@@ -11168,7 +11169,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
                                               pg_pool_t::TYPE_REPLICATED, &ss);
       if (ruleno < 0) {
        err = ruleno;
-       goto reply;
+       goto reply_no_propose;
       }
 
       pending_inc.crush.clear();
@@ -11191,7 +11192,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       // From the user point of view, the rule is more meaningfull.
       ss << "rule " << name << " already exists";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     CrushWrapper newcrush = _get_pending_crush();
@@ -11207,7 +11208,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        "firstn", pg_pool_t::TYPE_REPLICATED, &ss);
       if (ruleno < 0) {
        err = ruleno;
-       goto reply;
+       goto reply_no_propose;
       }
 
       pending_inc.crush.clear();
@@ -11227,7 +11228,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
 
     if (erasure_code_profile_in_use(osdmap.pools, name, &ss)) {
       err = -EBUSY;
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (osdmap.has_erasure_code_profile(name) ||
@@ -11246,7 +11247,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     } else {
       ss << "erasure-code-profile " << name << " does not exist";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
   } else if (prefix == "osd erasure-code-profile set") {
@@ -11261,7 +11262,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     map<string,string> profile_map;
     err = parse_erasure_code_profile(profile, &profile_map, &ss);
     if (err)
-      goto reply;
+      goto reply_no_propose;
     if (auto found = profile_map.find("crush-failure-domain");
        found != profile_map.end()) {
       const auto& failure_domain = found->second;
@@ -11270,7 +11271,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        ss << "erasure-code-profile " << profile_map
          << " contains an invalid failure-domain " << std::quoted(failure_domain);
        err = -EINVAL;
-       goto reply;
+       goto reply_no_propose;
       }
     }
 
@@ -11278,7 +11279,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "erasure-code-profile " << profile_map
         << " must contain a plugin entry" << std::endl;
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     string plugin = profile_map["plugin"];
 
@@ -11288,18 +11289,18 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     } else {
       err = normalize_profile(name, profile_map, force, &ss);
       if (err)
-       goto reply;
+       goto reply_no_propose;
 
       if (osdmap.has_erasure_code_profile(name)) {
        ErasureCodeProfile existing_profile_map =
          osdmap.get_erasure_code_profile(name);
        err = normalize_profile(name, existing_profile_map, force, &ss);
        if (err)
-         goto reply;
+         goto reply_no_propose;
 
        if (existing_profile_map == profile_map) {
          err = 0;
-         goto reply;
+         goto reply_no_propose;
        }
        if (!force) {
          err = -EPERM;
@@ -11308,7 +11309,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
             << existing_profile_map
             << " is different from the proposed profile "
             << profile_map;
-         goto reply;
+         goto reply_no_propose;
        }
       }
 
@@ -11327,7 +11328,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN)
       goto wait;
     if (err)
-      goto reply;
+      goto reply_no_propose;
     string name, poolstr;
     cmd_getval(cmdmap, "name", name);
     string profile;
@@ -11346,10 +11347,10 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
                                                      profile_map,
                                                      &ss);
        if (err)
-         goto reply;
+         goto reply_no_propose;
        err = normalize_profile(name, profile_map, true, &ss);
        if (err)
-         goto reply;
+         goto reply_no_propose;
        dout(20) << "erasure code profile set " << profile << "="
                 << profile_map << dendl;
        pending_inc.set_erasure_code_profile(profile, profile_map);
@@ -11364,15 +11365,13 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       case -EEXIST: // return immediately
        ss << "rule " << name << " already exists";
        err = 0;
-       goto reply;
-       break;
+       goto reply_no_propose;
       case -EALREADY: // wait for pending to be proposed
        ss << "rule " << name << " already exists";
        err = 0;
        break;
       default: // non recoverable error
-       goto reply;
-       break;
+       goto reply_no_propose;
       }
     } else {
       ss << "created rule " << name << " at " << rule;
@@ -11390,7 +11389,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!osdmap.crush->rule_exists(name)) {
       ss << "rule " << name << " does not exist";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     CrushWrapper newcrush = _get_pending_crush();
@@ -11408,12 +11407,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (osdmap.crush_rule_in_use(ruleno)) {
        ss << "crush rule " << name << " (" << ruleno << ") is in use";
        err = -EBUSY;
-       goto reply;
+       goto reply_no_propose;
       }
 
       err = newcrush.remove_rule(ruleno);
       if (err < 0) {
-       goto reply;
+       goto reply_no_propose;
       }
 
       pending_inc.crush.clear();
@@ -11432,12 +11431,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (srcname.empty() || dstname.empty()) {
       ss << "must specify both source rule name and destination rule name";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (srcname == dstname) {
       ss << "destination rule name is equal to source rule name";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     CrushWrapper newcrush = _get_pending_crush();
@@ -11447,13 +11446,13 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       // (so this command is idempotent)
       ss << "already renamed to '" << dstname << "'";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     err = newcrush.rename_rule(srcname, dstname, &ss);
     if (err < 0) {
       // ss has reason for failure
-      goto reply;
+      goto reply_no_propose;
     }
     pending_inc.crush.clear();
     newcrush.encode(pending_inc.crush, mon.get_quorum_con_features());
@@ -11468,14 +11467,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "unable to parse 'newmax' value '"
          << cmd_vartype_stringify(cmdmap.at("newmax")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (newmax > g_conf()->mon_max_osd) {
       err = -ERANGE;
       ss << "cannot set max_osd to " << newmax << " which is > conf.mon_max_osd ("
         << g_conf()->mon_max_osd << ")";
-      goto reply;
+      goto reply_no_propose;
     }
 
     // Don't allow shrinking OSD number as this will cause data loss
@@ -11490,7 +11489,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           err = -EBUSY;
           ss << "cannot shrink max_osd to " << newmax
              << " because osd." << i << " (and possibly others) still in use";
-          goto reply;
+          goto reply_no_propose;
         }
       }
     }
@@ -11510,7 +11509,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "unable to parse 'ratio' value '"
          << cmd_vartype_stringify(cmdmap.at("ratio")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (prefix == "osd set-full-ratio")
       pending_inc.new_full_ratio = n;
@@ -11530,7 +11529,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!vno) {
       ss << "version " << v << " is not recognized";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     OSDMap newmap;
     newmap.deepish_copy_from(osdmap);
@@ -11541,7 +11540,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "osdmap current utilizes features that require " << mvno
         << "; cannot set require_min_compat_client below that to " << vno;
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     bool sure = false;
     cmd_getval(cmdmap, "yes_i_really_mean_it", sure);
@@ -11579,7 +11578,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (!ok) {
        ss << "; add --yes-i-really-mean-it to do it anyway";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
     }
     ss << "set require_min_compat_client to " << vno;
@@ -11629,7 +11628,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         ss << "Not advisable to continue since no OSDs are up. Pass "
            << "--yes-i-really-mean-it if you really wish to continue.";
         err = -EPERM;
-        goto reply;
+        goto reply_no_propose;
       }
       // The release check here is required because for OSD_PGLOG_HARDLIMIT,
       // we are reusing a jewel feature bit that was retired in luminous.
@@ -11640,8 +11639,10 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       } else {
        ss << "not all up OSDs have OSD_PGLOG_HARDLIMIT feature";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
+    } else if (key == "noautoscale") {
+      return prepare_set_flag(op, CEPH_OSDMAP_NOAUTOSCALE);
     } else {
       ss << "unrecognized flag '" << key << "'";
       err = -EINVAL;
@@ -11674,6 +11675,8 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       return prepare_unset_flag(op, CEPH_OSDMAP_NOTIERAGENT);
     else if (key == "nosnaptrim")
       return prepare_unset_flag(op, CEPH_OSDMAP_NOSNAPTRIM);
+    else if (key == "noautoscale")
+      return prepare_unset_flag(op, CEPH_OSDMAP_NOAUTOSCALE);
     else {
       ss << "unrecognized flag '" << key << "'";
       err = -EINVAL;
@@ -11688,74 +11691,74 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!rel) {
       ss << "unrecognized release " << release;
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (rel == osdmap.require_osd_release) {
       // idempotent
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
     if (osdmap.require_osd_release < ceph_release_t::pacific && !sure) {
       ss << "Not advisable to continue since current 'require_osd_release' "
          << "refers to a very old Ceph release. Pass "
         << "--yes-i-really-mean-it if you really wish to continue.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if (!osdmap.get_num_up_osds() && !sure) {
       ss << "Not advisable to continue since no OSDs are up. Pass "
         << "--yes-i-really-mean-it if you really wish to continue.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if (rel == ceph_release_t::pacific) {
       if (!mon.monmap->get_required_features().contains_all(
            ceph::features::mon::FEATURE_PACIFIC)) {
        ss << "not all mons are pacific";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
       if ((!HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_PACIFIC))
            && !sure) {
        ss << "not all up OSDs have CEPH_FEATURE_SERVER_PACIFIC feature";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
     } else if (rel == ceph_release_t::quincy) {
       if (!mon.monmap->get_required_features().contains_all(
            ceph::features::mon::FEATURE_QUINCY)) {
        ss << "not all mons are quincy";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
       if ((!HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_QUINCY))
            && !sure) {
        ss << "not all up OSDs have CEPH_FEATURE_SERVER_QUINCY feature";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
     } else if (rel == ceph_release_t::reef) {
       if (!mon.monmap->get_required_features().contains_all(
            ceph::features::mon::FEATURE_REEF)) {
        ss << "not all mons are reef";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
       if ((!HAVE_FEATURE(osdmap.get_up_osd_features(), SERVER_REEF))
            && !sure) {
        ss << "not all up OSDs have CEPH_FEATURE_SERVER_REEF feature";
        err = -EPERM;
-       goto reply;
+       goto reply_no_propose;
       }
     } else {
       ss << "not supported for this release";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if (rel < osdmap.require_osd_release) {
       ss << "require_osd_release cannot be lowered once it has been set";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     pending_inc.new_require_osd_release = rel;
     goto update;
@@ -11936,7 +11939,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           ss << "unrecognized flag '" << f << "', must be one of "
              << "{noup,nodown,noin,noout}";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
       }
     } else {
@@ -11955,12 +11958,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (flags == 0) {
       ss << "must specify flag(s) {noup,nodwon,noin,noout} to set/unset";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (who.empty()) {
       ss << "must specify at least one or more targets to set/unset";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     set<int> osds;
     set<int> crush_nodes;
@@ -11985,7 +11988,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (osds.empty() && crush_nodes.empty() && device_classes.empty()) {
       // ss has reason for failure
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     bool any = false;
     for (auto osd : osds) {
@@ -12069,11 +12072,10 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     pg_t pgid;
     err = parse_pgid(cmdmap, ss, pgid);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     if (pending_inc.new_pg_temp.count(pgid)) {
       dout(10) << __func__ << " waiting for pending update on " << pgid << dendl;
-      wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-      return true;
+      goto wait;
     }
 
     vector<int64_t> id_vec;
@@ -12088,7 +12090,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (!osdmap.exists(osd)) {
         ss << "osd." << osd << " does not exist";
         err = -ENOENT;
-        goto reply;
+        goto reply_no_propose;
       }
       new_pg_temp.push_back(osd);
     }
@@ -12098,7 +12100,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "num of osds (" << new_pg_temp.size() <<") < pool min size ("
          << pool_min_size << ")";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     int pool_size = osdmap.get_pg_pool_size(pgid);
@@ -12106,7 +12108,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "num of osds (" << new_pg_temp.size() <<") > pool size ("
          << pool_size << ")";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     pending_inc.new_pg_temp[pgid] = mempool::osdmap::vector<int>(
@@ -12118,7 +12120,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     pg_t pgid;
     err = parse_pgid(cmdmap, ss, pgid);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
 
     int64_t osd;
     if (prefix == "osd primary-temp") {
@@ -12126,12 +12128,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         ss << "unable to parse 'id' value '"
            << cmd_vartype_stringify(cmdmap.at("id")) << "'";
         err = -EINVAL;
-        goto reply;
+        goto reply_no_propose;
       }
       if (!osdmap.exists(osd)) {
         ss << "osd." << osd << " does not exist";
         err = -ENOENT;
-        goto reply;
+        goto reply_no_propose;
       }
     }
     else if (prefix == "osd rm-primary-temp") {
@@ -12147,7 +12149,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         << osdmap.require_min_compat_client
         << " < firefly, which is required for primary-temp";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
 
     pending_inc.new_primary_temp[pgid] = osd;
@@ -12157,14 +12159,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     pg_t pgid;
     err = parse_pgid(cmdmap, ss, pgid);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     vector<int> acting;
     int primary;
     osdmap.pg_to_acting_osds(pgid, &acting, &primary);
     if (primary < 0) {
       err = -EAGAIN;
       ss << "pg currently has no primary";
-      goto reply;
+      goto reply_no_propose;
     }
     if (acting.size() > 1) {
       // map to just primary; it will map back to what it wants
@@ -12185,7 +12187,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (!done) {
        err = -EAGAIN;
        ss << "not enough up OSDs in the cluster to force repeer";
-       goto reply;
+       goto reply_no_propose;
       }
     }
     goto update;
@@ -12250,7 +12252,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
          << "Try 'ceph osd set-require-min-compat-client " << min_release_name << "' "
          << "before using the new interface";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
 
     //TODO: Should I add feature and test for upmap-primary?
@@ -12258,11 +12260,11 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN)
       goto wait;
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     pg_t pgid;
     err = parse_pgid(cmdmap, ss, pgid);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     if (pending_inc.old_pools.count(pgid.pool())) {
       ss << "pool of " << pgid << " is pending removal";
       err = -ENOENT;
@@ -12280,8 +12282,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           pending_inc.old_pg_upmap.count(pgid)) {
         dout(10) << __func__ << " waiting for pending update on "
                  << pgid << dendl;
-        wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-        return true;
+        goto wait;
       }
       break;
 
@@ -12292,7 +12293,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         if (! pt->is_replicated()) {
          ss << "pg-upmap-primary is only supported for replicated pools";
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
        }
       }
       // fall through
@@ -12302,8 +12303,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           pending_inc.old_pg_upmap_items.count(pgid)) {
         dout(10) << __func__ << " waiting for pending update on "
                  << pgid << dendl;
-        wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-        return true;
+        goto wait;
       }
       break;
 
@@ -12319,7 +12319,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           ss << "unable to parse 'id' value(s) '"
              << cmd_vartype_stringify(cmdmap.at("id")) << "'";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         int pool_min_size = osdmap.get_pg_pool_min_size(pgid);
@@ -12327,7 +12327,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           ss << "num of osds (" << id_vec.size() <<") < pool min size ("
              << pool_min_size << ")";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         int pool_size = osdmap.get_pg_pool_size(pgid);
@@ -12335,7 +12335,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           ss << "num of osds (" << id_vec.size() <<") > pool size ("
              << pool_size << ")";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         vector<int32_t> new_pg_upmap;
@@ -12343,7 +12343,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           if (osd != CRUSH_ITEM_NONE && !osdmap.exists(osd)) {
             ss << "osd." << osd << " does not exist";
             err = -ENOENT;
-            goto reply;
+            goto reply_no_propose;
           }
           auto it = std::find(new_pg_upmap.begin(), new_pg_upmap.end(), osd);
           if (it != new_pg_upmap.end()) {
@@ -12356,7 +12356,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         if (new_pg_upmap.empty()) {
           ss << "no valid upmap items(pairs) is specified";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         pending_inc.new_pg_upmap[pgid] = mempool::osdmap::vector<int32_t>(
@@ -12379,13 +12379,13 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           ss << "unable to parse 'id' value(s) '"
              << cmd_vartype_stringify(cmdmap.at("id")) << "'";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         if (id_vec.size() % 2) {
           ss << "you must specify pairs of osd ids to be remapped";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         int pool_size = osdmap.get_pg_pool_size(pgid);
@@ -12393,7 +12393,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           ss << "num of osd pairs (" << id_vec.size() / 2 <<") > pool size ("
              << pool_size << ")";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         vector<pair<int32_t,int32_t>> new_pg_upmap_items;
@@ -12409,12 +12409,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           if (!osdmap.exists(from)) {
             ss << "osd." << from << " does not exist";
             err = -ENOENT;
-            goto reply;
+            goto reply_no_propose;
           }
           if (to != CRUSH_ITEM_NONE && !osdmap.exists(to)) {
             ss << "osd." << to << " does not exist";
             err = -ENOENT;
-            goto reply;
+            goto reply_no_propose;
           }
           pair<int32_t,int32_t> entry = make_pair(from, to);
           auto it = std::find(new_pg_upmap_items.begin(),
@@ -12433,7 +12433,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         if (new_pg_upmap_items.empty()) {
           ss << "no valid upmap items(pairs) is specified";
           err = -EINVAL;
-          goto reply;
+          goto reply_no_propose;
         }
 
         pending_inc.new_pg_upmap_items[pgid] =
@@ -12457,12 +12457,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
          ss << "invalid osd id value '"
              << cmd_vartype_stringify(cmdmap.at("id")) << "'";
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
        }
         if (id != CRUSH_ITEM_NONE && !osdmap.exists(id)) {
           ss << "osd." << id << " does not exist";
           err = -ENOENT;
-          goto reply;
+          goto reply_no_propose;
         }
        vector<int> acting;
        int primary;
@@ -12470,7 +12470,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        if (id == primary) {
          ss << "osd." << id << " is already primary for pg " << pgid;
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
        }
        int found_idx = 0;
        for (int i = 1 ; i < (int)acting.size(); i++) {  // skip 0 on purpose
@@ -12482,7 +12482,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        if (found_idx == 0) {
          ss << "osd." << id << " is not in acting set for pg " << pgid;
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
        }
        vector<int> new_acting(acting);
        new_acting[found_idx] = new_acting[0];
@@ -12496,7 +12496,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
          ss << "can't change primary for pg " << pgid << " to osd." << id
             << " - illegal pg after the change";
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
        }
        pending_inc.new_pg_upmap_primary[pgid] = id;
        //TO-REMOVE: 
@@ -12522,20 +12522,20 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "invalid osd id value '"
          << cmd_vartype_stringify(cmdmap.at("id")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     double w;
     if (!cmd_getval(cmdmap, "weight", w)) {
       ss << "unable to parse 'weight' value '"
         << cmd_vartype_stringify(cmdmap.at("weight")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     long ww = (int)((double)CEPH_OSD_MAX_PRIMARY_AFFINITY*w);
     if (ww < 0L) {
       ss << "weight must be >= 0";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (osdmap.require_min_compat_client != ceph_release_t::unknown &&
        osdmap.require_min_compat_client < ceph_release_t::firefly) {
@@ -12543,7 +12543,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         << osdmap.require_min_compat_client
         << " < firefly, which is required for primary-affinity";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if (osdmap.exists(id)) {
       pending_inc.new_primary_affinity[id] = ww;
@@ -12555,7 +12555,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     } else {
       ss << "osd." << id << " does not exist";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
   } else if (prefix == "osd reweight") {
     int64_t id;
@@ -12563,20 +12563,20 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "unable to parse osd id value '"
          << cmd_vartype_stringify(cmdmap.at("id")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     double w;
     if (!cmd_getval(cmdmap, "weight", w)) {
       ss << "unable to parse weight value '"
          << cmd_vartype_stringify(cmdmap.at("weight")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     long ww = (int)((double)CEPH_OSD_IN*w);
     if (ww < 0L) {
       ss << "weight must be >= 0";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (osdmap.exists(id)) {
       pending_inc.new_weight[id] = ww;
@@ -12588,7 +12588,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     } else {
       ss << "osd." << id << " does not exist";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
   } else if (prefix == "osd reweightn") {
     map<int32_t, uint32_t> weights;
@@ -12596,7 +12596,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err) {
       ss << "unable to parse 'weights' value '"
          << cmd_vartype_stringify(cmdmap.at("weights")) << "'";
-      goto reply;
+      goto reply_no_propose;
     }
     pending_inc.new_weight.insert(weights.begin(), weights.end());
     wait_for_finished_proposal(
@@ -12609,7 +12609,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "unable to parse osd id value '"
          << cmd_vartype_stringify(cmdmap.at("id")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     bool sure = false;
     cmd_getval(cmdmap, "yes_i_really_mean_it", sure);
@@ -12617,15 +12617,15 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "are you SURE?  this might mean real, permanent data loss.  pass "
            "--yes-i-really-mean-it if you really do.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     } else if (!osdmap.exists(id)) {
       ss << "osd." << id << " does not exist";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     } else if (!osdmap.is_down(id)) {
       ss << "osd." << id << " is not down";
       err = -EBUSY;
-      goto reply;
+      goto reply_no_propose;
     } else {
       epoch_t e = osdmap.get_info(id).down_at;
       pending_inc.new_lost[id] = e;
@@ -12669,7 +12669,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           << cmd_vartype_stringify(cmdmap.at("id")) << "";
       }
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     bool is_destroy = (prefix == "osd destroy-actual");
@@ -12686,26 +12686,26 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
          << "as deletion of cephx and lockbox keys. "
         << "Pass --yes-i-really-mean-it if you really do.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     } else if (!osdmap.exists(id)) {
       ss << "osd." << id << " does not exist";
       err = 0; // idempotent
-      goto reply;
+      goto reply_no_propose;
     } else if (osdmap.is_up(id)) {
       ss << "osd." << id << " is not `down`.";
       err = -EBUSY;
-      goto reply;
+      goto reply_no_propose;
     } else if (is_destroy && osdmap.is_destroyed(id)) {
       ss << "destroyed osd." << id;
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (prefix == "osd purge-new" &&
        (osdmap.get_state(id) & CEPH_OSD_NEW) == 0) {
       ss << "osd." << id << " is not new";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
 
     bool goto_reply = false;
@@ -12726,7 +12726,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     paxos.unplug();
 
     if (err < 0 || goto_reply) {
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (is_destroy) {
@@ -12767,7 +12767,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
 
     err = get_json_str_map(param_json, ss, &param_map);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
 
     dout(20) << __func__ << " osd new params " << param_map << dendl;
 
@@ -12776,7 +12776,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     paxos.unplug();
 
     if (err < 0) {
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (f) {
@@ -12788,7 +12788,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == EEXIST) {
       // idempotent operation
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     wait_for_finished_proposal(op,
@@ -12805,7 +12805,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (cmd_id < 0) {
        ss << "invalid osd id value '" << cmd_id << "'";
        err = -EINVAL;
-       goto reply;
+       goto reply_no_propose;
       }
       dout(10) << " osd create got id " << cmd_id << dendl;
     }
@@ -12816,7 +12816,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       if (!uuid.parse(uuidstr.c_str())) {
         ss << "invalid uuid value '" << uuidstr << "'";
         err = -EINVAL;
-        goto reply;
+        goto reply_no_propose;
       }
       // we only care about the id if we also have the uuid, to
       // ensure the operation's idempotency.
@@ -12827,11 +12827,10 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     err = prepare_command_osd_create(id, uuid, &new_id, ss);
     if (err < 0) {
       if (err == -EAGAIN) {
-        wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-        return true;
+        goto wait;
       }
       // a check has failed; reply to the user.
-      goto reply;
+      goto reply_no_propose;
 
     } else if (err == EEXIST) {
       // this is an idempotent operation; we can go ahead and reply.
@@ -12845,7 +12844,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         rdata.append(ss);
       }
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     string empty_device_class;
@@ -12893,14 +12892,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       } else {
        ss << "Did you mean to specify \"osd blocklist range\"?";
        err = -EINVAL;
-       goto reply;
+       goto reply_no_propose;
       }
     }
     entity_addr_t addr;
     if (!addr.parse(addrstr)) {
       ss << "unable to parse address " << addrstr;
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     else {
       if (range) {
@@ -12908,18 +12907,18 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
          ss << "You specified a range command, but " << addr
             << " does not parse as a CIDR range";
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
        }
        addr.type = entity_addr_t::TYPE_CIDR;
        err = check_cluster_features(CEPH_FEATUREMASK_RANGE_BLOCKLIST, ss);
        if (err) {
-         goto reply;
+         goto reply_no_propose;
        }
        if ((addr.is_ipv4() && addr.get_nonce() > 32) ||
            (addr.is_ipv6() && addr.get_nonce() > 128)) {
          ss << "Too many bits in range for that protocol!";
          err = -EINVAL;
-         goto reply;
+         goto reply_no_propose;
        }
       } else {
        if (osdmap.require_osd_release >= ceph_release_t::nautilus) {
@@ -12995,7 +12994,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        }
        ss << addr << " isn't blocklisted";
        err = 0;
-       goto reply;
+       goto reply_no_propose;
       }
     }
   } else if (prefix == "osd pool mksnap") {
@@ -13005,7 +13004,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (pool < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     string snapname;
     cmd_getval(cmdmap, "snap", snapname);
@@ -13013,15 +13012,15 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (p->is_unmanaged_snaps_mode()) {
       ss << "pool " << poolstr << " is in unmanaged snaps mode";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     } else if (p->snap_exists(snapname.c_str())) {
       ss << "pool " << poolstr << " snap " << snapname << " already exists";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     } else if (p->is_tier()) {
       ss << "pool " << poolstr << " is a cache tier";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     pg_pool_t *pp = 0;
     if (pending_inc.new_pools.count(pool))
@@ -13037,7 +13036,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        dout(20) << "pool-level snapshots have been disabled for pools "
                    "attached to an fs - poolid:" << pool << dendl;
        err = -EOPNOTSUPP;
-       goto reply;
+        goto reply_no_propose;
       }
       pp->add_snap(snapname.c_str(), ceph_clock_now());
       pp->set_snap_epoch(pending_inc.epoch);
@@ -13054,7 +13053,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (pool < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     string snapname;
     cmd_getval(cmdmap, "snap", snapname);
@@ -13062,11 +13061,11 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (p->is_unmanaged_snaps_mode()) {
       ss << "pool " << poolstr << " is in unmanaged snaps mode";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     } else if (!p->snap_exists(snapname.c_str())) {
       ss << "pool " << poolstr << " snap " << snapname << " does not exist";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
     pg_pool_t *pp = 0;
     if (pending_inc.new_pools.count(pool))
@@ -13105,7 +13104,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (poolstr[0] == '.' && !confirm) {
       ss << "pool names beginning with . are not allowed";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
     if (pool_id >= 0) {
@@ -13117,7 +13116,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        ss << "pool '" << poolstr << "' already exists";
        err = 0;
       }
-      goto reply;
+      goto reply_no_propose;
     }
 
     int pool_type;
@@ -13128,7 +13127,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     } else {
       ss << "unknown pool type '" << pool_type_str << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     bool implicit_rule_creation = false;
@@ -13154,7 +13153,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
                                                      profile_map,
                                                      &ss);
          if (err)
-           goto reply;
+           goto reply_no_propose;
          dout(20) << "erasure code profile " << erasure_code_profile << " set" << dendl;
          pending_inc.set_erasure_code_profile(erasure_code_profile, profile_map);
          goto wait;
@@ -13182,7 +13181,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
           if (interr.length()) {
             ss << "error parsing integer value '" << rule_name << "': " << interr;
             err = -EINVAL;
-            goto reply;
+            goto reply_no_propose;
           }
         }
         rule_name = erasure_code_profile;
@@ -13196,17 +13195,16 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       int rule;
       err = get_crush_rule(rule_name, &rule, &ss);
       if (err == -EAGAIN) {
-       wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-       return true;
+        goto wait;
       }
       if (err)
-       goto reply;
+       goto reply_no_propose;
     }
 
     if (expected_num_objects < 0) {
       ss << "'expected_num_objects' must be non-negative";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     set<int32_t> osds;
@@ -13225,7 +13223,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         cct->_conf->filestore_merge_threshold > 0) {
       ss << "'expected_num_objects' requires 'filestore_merge_threshold < 0'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (has_filestore_osd &&
@@ -13240,7 +13238,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
            << "expected_num_objects parameter when creating the pool."
            << " Pass --yes-i-really-mean-it to ignore it";
         err = -EPERM;
-        goto reply;
+        goto reply_no_propose;
       }
     }
 
@@ -13282,15 +13280,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       switch(err) {
       case -EEXIST:
        ss << "pool '" << poolstr << "' already exists";
-       break;
+        err = 0;
+        goto reply_no_propose;
       case -EAGAIN:
-       wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-       return true;
+        goto wait;
       case -ERANGE:
-        goto reply;
+        goto reply_no_propose;
       default:
-       goto reply;
-       break;
+       goto reply_no_propose;
       }
     } else {
       ss << "pool '" << poolstr << "' created";
@@ -13310,7 +13307,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (pool < 0) {
       ss << "pool '" << poolstr << "' does not exist";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     bool force_no_fake = false;
@@ -13323,15 +13320,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         << ".  If you are *ABSOLUTELY CERTAIN* that is what you want, pass the pool name *twice*, "
         << "followed by --yes-i-really-really-mean-it.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     err = _prepare_remove_pool(pool, &ss, force_no_fake);
     if (err == -EAGAIN) {
-      wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-      return true;
+      goto wait;
     }
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     goto update;
   } else if (prefix == "osd pool rename") {
     string srcpoolstr, destpoolstr;
@@ -13345,7 +13341,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (destpoolstr[0] == '.' && !confirm) {
       ss << "pool names beginning with . are not allowed";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
     if (pool_src < 0) {
       if (pool_dst >= 0) {
@@ -13362,12 +13358,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         ss << "unrecognized pool '" << srcpoolstr << "'";
         err = -ENOENT;
       }
-      goto reply;
+      goto reply_no_propose;
     } else if (pool_dst >= 0) {
       // source pool exists and so does the destination pool
       ss << "pool '" << destpoolstr << "' already exists";
       err = -EEXIST;
-      goto reply;
+      goto reply_no_propose;
     }
 
     int ret = _prepare_rename_pool(pool_src, destpoolstr);
@@ -13387,7 +13383,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN)
       goto wait;
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
 
     getline(ss, rs);
     wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs,
@@ -13398,14 +13394,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN)
       goto wait;
     if (err)
-      goto reply;
+      goto reply_no_propose;
     string poolstr;
     cmd_getval(cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
     if (pool_id < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     string tierpoolstr;
     cmd_getval(cmdmap, "tierpool", tierpoolstr);
@@ -13413,7 +13409,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (tierpool_id < 0) {
       ss << "unrecognized pool '" << tierpoolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     const pg_pool_t *p = osdmap.get_pg_pool(pool_id);
     ceph_assert(p);
@@ -13421,7 +13417,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     ceph_assert(tp);
 
     if (!_check_become_tier(tierpool_id, tp, pool_id, p, &err, &ss)) {
-      goto reply;
+      goto reply_no_propose;
     }
 
     // make sure new tier is empty
@@ -13432,27 +13428,26 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        !force_nonempty) {
       ss << "tier pool '" << tierpoolstr << "' is not empty; --force-nonempty to force";
       err = -ENOTEMPTY;
-      goto reply;
+      goto reply_no_propose;
     }
     if (tp->is_erasure()) {
       ss << "tier pool '" << tierpoolstr
         << "' is an ec pool, which cannot be a tier";
       err = -ENOTSUP;
-      goto reply;
+      goto reply_no_propose;
     }
     if ((!tp->removed_snaps.empty() || !tp->snaps.empty()) &&
        (!force_nonempty ||
         !g_conf()->mon_debug_unsafe_allow_tier_with_nonempty_snaps)) {
       ss << "tier pool '" << tierpoolstr << "' has snapshot state; it cannot be added as a tier without breaking the pool";
       err = -ENOTEMPTY;
-      goto reply;
+      goto reply_no_propose;
     }
     // go
     pg_pool_t *np = pending_inc.get_new_pool(pool_id, p);
     pg_pool_t *ntp = pending_inc.get_new_pool(tierpool_id, tp);
     if (np->tiers.count(tierpool_id) || ntp->is_tier()) {
-      wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-      return true;
+      goto wait;
     }
     np->tiers.insert(tierpool_id);
     np->set_snap_epoch(pending_inc.epoch); // tier will update to our snap info
@@ -13469,7 +13464,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (pool_id < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     string tierpoolstr;
     cmd_getval(cmdmap, "tierpool", tierpoolstr);
@@ -13477,7 +13472,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (tierpool_id < 0) {
       ss << "unrecognized pool '" << tierpoolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     const pg_pool_t *p = osdmap.get_pg_pool(pool_id);
     ceph_assert(p);
@@ -13485,13 +13480,13 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     ceph_assert(tp);
 
     if (!_check_remove_tier(pool_id, p, tp, &err, &ss)) {
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (p->tiers.count(tierpool_id) == 0) {
       ss << "pool '" << tierpoolstr << "' is now (or already was) not a tier of '" << poolstr << "'";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
     if (tp->tier_of != pool_id) {
       ss << "tier pool '" << tierpoolstr << "' is a tier of '"
@@ -13499,12 +13494,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
          // be scary about it; this is an inconsistency and bells must go off
          << "THIS SHOULD NOT HAVE HAPPENED AT ALL";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (p->read_tier == tierpool_id) {
       ss << "tier pool '" << tierpoolstr << "' is the overlay for '" << poolstr << "'; please remove-overlay first";
       err = -EBUSY;
-      goto reply;
+      goto reply_no_propose;
     }
     // go
     pg_pool_t *np = pending_inc.get_new_pool(pool_id, p);
@@ -13512,8 +13507,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (np->tiers.count(tierpool_id) == 0 ||
        ntp->tier_of != pool_id ||
        np->read_tier == tierpool_id) {
-      wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-      return true;
+      goto wait;
     }
     np->tiers.erase(tierpool_id);
     ntp->clear_tier();
@@ -13526,14 +13520,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN)
       goto wait;
     if (err)
-      goto reply;
+      goto reply_no_propose;
     string poolstr;
     cmd_getval(cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
     if (pool_id < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     string overlaypoolstr;
     cmd_getval(cmdmap, "overlaypool", overlaypoolstr);
@@ -13541,7 +13535,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (overlaypool_id < 0) {
       ss << "unrecognized pool '" << overlaypoolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     const pg_pool_t *p = osdmap.get_pg_pool(pool_id);
     ceph_assert(p);
@@ -13550,19 +13544,19 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (p->tiers.count(overlaypool_id) == 0) {
       ss << "tier pool '" << overlaypoolstr << "' is not a tier of '" << poolstr << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if (p->read_tier == overlaypool_id) {
       err = 0;
       ss << "overlay for '" << poolstr << "' is now (or already was) '" << overlaypoolstr << "'";
-      goto reply;
+      goto reply_no_propose;
     }
     if (p->has_read_tier()) {
       ss << "pool '" << poolstr << "' has overlay '"
         << osdmap.get_pool_name(p->read_tier)
         << "'; please remove-overlay first";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     // go
@@ -13586,18 +13580,18 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (pool_id < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     const pg_pool_t *p = osdmap.get_pg_pool(pool_id);
     ceph_assert(p);
     if (!p->has_read_tier()) {
       err = 0;
       ss << "there is now (or already was) no overlay for '" << poolstr << "'";
-      goto reply;
+      goto reply_no_propose;
     }
 
     if (!_check_remove_tier(pool_id, p, NULL, &err, &ss)) {
-      goto reply;
+      goto reply_no_propose;
     }
 
     // go
@@ -13624,21 +13618,21 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN)
       goto wait;
     if (err)
-      goto reply;
+      goto reply_no_propose;
     string poolstr;
     cmd_getval(cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
     if (pool_id < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     const pg_pool_t *p = osdmap.get_pg_pool(pool_id);
     ceph_assert(p);
     if (!p->is_tier()) {
       ss << "pool '" << poolstr << "' is not a tier";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     string modestr;
     cmd_getval(cmdmap, "mode", modestr);
@@ -13646,7 +13640,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (int(mode) < 0) {
       ss << "'" << modestr << "' is not a valid cache mode";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     bool sure = false;
@@ -13656,7 +13650,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        mode == pg_pool_t::CACHEMODE_READFORWARD) {
       ss << "'" << modestr << "' is no longer a supported cache mode";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     if ((mode != pg_pool_t::CACHEMODE_WRITEBACK &&
         mode != pg_pool_t::CACHEMODE_NONE &&
@@ -13666,7 +13660,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "'" << modestr << "' is not a well-supported cache mode and may "
         << "corrupt your data.  pass --yes-i-really-mean-it to force.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
 
     // pool already has this cache-mode set and there are no pending changes
@@ -13676,7 +13670,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "set cache-mode for pool '" << poolstr << "'"
          << " to " << pg_pool_t::get_cache_mode_name(mode);
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
 
     /* Mode description:
@@ -13715,7 +13709,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
          << pg_pool_t::get_cache_mode_name(pg_pool_t::CACHEMODE_READPROXY)
         << "' allowed.";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     if ((p->cache_mode == pg_pool_t::CACHEMODE_READFORWARD &&
         (mode != pg_pool_t::CACHEMODE_WRITEBACK &&
@@ -13743,7 +13737,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
            << pg_pool_t::get_cache_mode_name(mode) << "' on pool '" << poolstr
            << "': dirty objects found";
         err = -EBUSY;
-        goto reply;
+        goto reply_no_propose;
       }
     }
     // go
@@ -13769,14 +13763,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN)
       goto wait;
     if (err)
-      goto reply;
+      goto reply_no_propose;
     string poolstr;
     cmd_getval(cmdmap, "pool", poolstr);
     int64_t pool_id = osdmap.lookup_pg_pool_name(poolstr);
     if (pool_id < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     string tierpoolstr;
     cmd_getval(cmdmap, "tierpool", tierpoolstr);
@@ -13784,7 +13778,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (tierpool_id < 0) {
       ss << "unrecognized pool '" << tierpoolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
     const pg_pool_t *p = osdmap.get_pg_pool(pool_id);
     ceph_assert(p);
@@ -13792,7 +13786,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     ceph_assert(tp);
 
     if (!_check_become_tier(tierpool_id, tp, pool_id, p, &err, &ss)) {
-      goto reply;
+      goto reply_no_propose;
     }
 
     int64_t size = 0;
@@ -13800,7 +13794,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "unable to parse 'size' value '"
          << cmd_vartype_stringify(cmdmap.at("size")) << "'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     // make sure new tier is empty
     const pool_stat_t *pstats =
@@ -13808,14 +13802,14 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (pstats && pstats->stats.sum.num_objects != 0) {
       ss << "tier pool '" << tierpoolstr << "' is not empty";
       err = -ENOTEMPTY;
-      goto reply;
+      goto reply_no_propose;
     }
     auto& modestr = g_conf().get_val<string>("osd_tier_default_cache_mode");
     pg_pool_t::cache_mode_t mode = pg_pool_t::get_cache_mode_from_str(modestr);
     if (int(mode) < 0) {
       ss << "osd tier cache default mode '" << modestr << "' is not a valid cache mode";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     HitSet::Params hsp;
     auto& cache_hit_set_type =
@@ -13832,14 +13826,13 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
       ss << "osd tier cache default hit set type '"
         << cache_hit_set_type << "' is not a known type";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
     // go
     pg_pool_t *np = pending_inc.get_new_pool(pool_id, p);
     pg_pool_t *ntp = pending_inc.get_new_pool(tierpool_id, tp);
     if (np->tiers.count(tierpool_id) || ntp->is_tier()) {
-      wait_for_finished_proposal(op, new C_RetryMessage(this, op));
-      return true;
+      goto wait;
     }
     np->tiers.insert(tierpool_id);
     np->read_tier = np->write_tier = tierpool_id;
@@ -13867,7 +13860,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (pool_id < 0) {
       ss << "unrecognized pool '" << poolstr << "'";
       err = -ENOENT;
-      goto reply;
+      goto reply_no_propose;
     }
 
     string field;
@@ -13875,7 +13868,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (field != "max_objects" && field != "max_bytes") {
       ss << "unrecognized field '" << field << "'; should be 'max_bytes' or 'max_objects'";
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     // val could contain unit designations, so we treat as a string
@@ -13893,7 +13886,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (!tss.empty()) {
       ss << "error parsing value '" << val << "': " << tss;
       err = -EINVAL;
-      goto reply;
+      goto reply_no_propose;
     }
 
     pg_pool_t *pi = pending_inc.get_new_pool(pool_id, osdmap.get_pg_pool(pool_id));
@@ -13917,7 +13910,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     if (err == -EAGAIN) {
       goto wait;
     } else if (err < 0) {
-      goto reply;
+      goto reply_no_propose;
     } else {
       goto update;
     }
@@ -13926,7 +13919,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     string pgidstr;
     err = parse_pgid(cmdmap, ss, pgid, pgidstr);
     if (err < 0)
-      goto reply;
+      goto reply_no_propose;
     bool sure = false;
     cmd_getval(cmdmap, "yes_i_really_mean_it", sure);
     if (!sure) {
@@ -13936,7 +13929,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         << "willing to accept that the data is permanently destroyed.  Pass "
         << "--yes-i-really-mean-it to proceed.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     bool creating_now;
     {
@@ -13961,7 +13954,7 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     } else {
       ss << "pg " << pgid << " already creating";
       err = 0;
-      goto reply;
+      goto reply_no_propose;
     }
   } else if (prefix == "osd force_healthy_stretch_mode") {
     bool sure = false;
@@ -13971,12 +13964,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        "(probably two data centers or availability zones?) and may result in PGs "
        "going inactive until backfilling is complete. Pass --yes-i-really-mean-it to proceed.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     try_end_recovery_stretch_mode(true);
     ss << "Triggering healthy stretch mode";
     err = 0;
-    goto reply;
+    goto reply_no_propose;
   } else if (prefix == "osd force_recovery_stretch_mode") {
     bool sure = false;
     cmd_getval(cmdmap, "yes_i_really_mean_it", sure);
@@ -13986,12 +13979,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
        "availability zones?) and should have happened automatically"
        "Pass --yes-i-really-mean-it to proceed.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
     mon.go_recovery_stretch_mode();
     ss << "Triggering recovery stretch mode";
     err = 0;
-    goto reply;
+    goto reply_no_propose;
   } else if (prefix == "osd set-allow-crimson") {
 
     bool sure = false;
@@ -14007,12 +14000,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
         << "If you are sure, add --yes-i-really-mean-it and add 'crimson' to "
         << "the experimental features config.  This setting is irrevocable.";
       err = -EPERM;
-      goto reply;
+      goto reply_no_propose;
     }
 
     err = 0;
     if (osdmap.get_allow_crimson()) {
-      goto reply;
+      goto reply_no_propose;
     } else {
       pending_inc.set_allow_crimson();
       goto update;
@@ -14021,12 +14014,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
     err = -EINVAL;
   }
 
- reply:
+ reply_no_propose:
   getline(ss, rs);
   if (err < 0 && rs.length() == 0)
     rs = cpp_strerror(err);
   mon.reply_command(op, err, rs, rdata, get_last_committed());
-  return ret;
+  return false; /* nothing to propose */
 
  update:
   getline(ss, rs);
@@ -14035,6 +14028,12 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op,
   return true;
 
  wait:
+  // XXX
+  // Some osd commands split changes across two epochs.
+  // It seems this is mostly for crush rule changes. It doesn't need
+  // to be this way but it's a bit of work to fix that. For now,
+  // trigger a proposal by returning true and then retry the command
+  // to complete the operation.
   wait_for_finished_proposal(op, new C_RetryMessage(this, op));
   return true;
 }