From: Jason Dillaman Date: Thu, 30 Jul 2020 17:00:22 +0000 (-0400) Subject: mon/MonClient: apply MON config before finishing bootstrap X-Git-Tag: v15.2.14~31^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bb220fd6ecd1a6924b078aa343ec51030d65da22;p=ceph.git mon/MonClient: apply MON config before finishing bootstrap In general, non-primitive config options cannot be updated after the service threads have been marked as running. In librados, this happens after the MonClient bootstrap process. However, the configs received from the MON were applied in a separate thread which can race with librados marking the service threads as running. Now the received MON configs will be applied within the context of the bootstrap function call instead of deferring to a separate thread. Signed-off-by: Jason Dillaman (cherry picked from commit 313aeaa55d67089e0a2e173718899e603e51ce2e) Conflicts: src/mon/MonClient.cc (trivial) --- diff --git a/src/mon/MonClient.cc b/src/mon/MonClient.cc index b94b4d9a9ea..23030db686c 100644 --- a/src/mon/MonClient.cc +++ b/src/mon/MonClient.cc @@ -137,6 +137,14 @@ int MonClient::get_monmap_and_config() } }); + want_bootstrap_config = true; + auto shutdown_config = make_scope_guard([this] { + std::unique_lock l(monc_lock); + want_bootstrap_config = false; + bootstrap_config.reset(); + }); + + ceph::ref_t config; while (tries-- > 0) { r = init(); if (r < 0) { @@ -160,7 +168,7 @@ int MonClient::get_monmap_and_config() r = 0; break; } - while ((!got_config || monmap.get_epoch() == 0) && r == 0) { + while ((!bootstrap_config || monmap.get_epoch() == 0) && r == 0) { ldout(cct,20) << __func__ << " waiting for monmap|config" << dendl; auto status = map_cond.wait_for(l, ceph::make_timespan( cct->_conf->mon_client_hunt_interval)); @@ -168,8 +176,10 @@ int MonClient::get_monmap_and_config() r = -ETIMEDOUT; } } - if (got_config) { + + if (bootstrap_config) { ldout(cct,10) << __func__ << " success" << dendl; + config = std::move(bootstrap_config); r = 0; break; } @@ -179,6 +189,12 @@ int MonClient::get_monmap_and_config() continue; } + if (config) { + // apply the bootstrap config to ensure its applied prior to completing + // the bootstrap + cct->_conf.set_mon_vals(cct, config->config, config_cb); + } + shutdown(); return r; } @@ -437,6 +453,15 @@ void MonClient::handle_monmap(MMonMap *m) void MonClient::handle_config(MConfig *m) { ldout(cct,10) << __func__ << " " << *m << dendl; + + if (want_bootstrap_config) { + // get_monmap_and_config is waiting for config which it will apply + // synchronously + bootstrap_config = ceph::ref_t(m, false); + map_cond.notify_all(); + return; + } + finisher.queue(new LambdaContext([this, m](int r) { cct->_conf.set_mon_vals(cct, m->config, config_cb); if (config_notify_cb) { @@ -444,8 +469,6 @@ void MonClient::handle_config(MConfig *m) } m->put(); })); - got_config = true; - map_cond.notify_all(); } // ---------------------- diff --git a/src/mon/MonClient.h b/src/mon/MonClient.h index 80262200b61..f10b447a6e2 100644 --- a/src/mon/MonClient.h +++ b/src/mon/MonClient.h @@ -290,7 +290,9 @@ private: bool want_monmap; ceph::condition_variable map_cond; bool passthrough_monmap = false; - bool got_config = false; + + bool want_bootstrap_config = false; + ceph::ref_t bootstrap_config; // authenticate std::unique_ptr auth;