if (!daemon_state.is_updating(key) &&
(key.type == "osd" || key.type == "mds" || key.type == "mon")) {
std::ostringstream oss;
- auto c = new MetadataUpdate(daemon_state, key);
+ auto c = new MetadataUpdate(daemon_state, cluster_state, key);
if (key.type == "osd") {
oss << "{\"prefix\": \"osd metadata\", \"id\": "
<< key.name<< "}";
cluster_state.with_mgrmap([&](const MgrMap& mgrmap) {
auto md_update = [&] (DaemonKey key) {
std::ostringstream oss;
- auto c = new MetadataUpdate(daemon_state, key);
+ auto c = new MetadataUpdate(daemon_state, cluster_state, key);
// FIXME remove post-nautilus: include 'id' for luminous mons
oss << "{\"prefix\": \"mgr metadata\", \"who\": \""
<< key.name << "\", \"id\": \"" << key.name << "\"}";
{
}
+static std::string crush_hostname_for_osd(ClusterState& cluster_state, int osd_id)
+{
+ std::string hostname;
+ cluster_state.with_osdmap([&](const OSDMap& osdmap) {
+ if (osdmap.crush) {
+ auto loc = osdmap.crush->get_full_location(osd_id);
+ auto it = loc.find("host");
+ if (it != loc.end()) {
+ hostname = it->second;
+ }
+ }
+ });
+ return hostname;
+}
+
void MetadataUpdate::finish(int r)
{
daemon_state.clear_updating(key);
if (daemon_state.exists(key)) {
DaemonStatePtr state = daemon_state.get(key);
+ // Resolve CRUSH host before taking state->lock to preserve lock ordering
+ // (Objecter::rwlock must not be acquired under state->lock)
+ std::string crush_host;
+ if (key.type == "osd") {
+ try {
+ crush_host = crush_hostname_for_osd(cluster_state, std::stoi(key.name));
+ } catch (const std::exception& e) {
+ dout(5) << "cannot derive CRUSH hostname for " << key
+ << ": " << e.what() << dendl;
+ }
+ }
std::map<string,string> m;
{
std::lock_guard l(state->lock);
- state->hostname = daemon_meta.at("hostname").get_str();
-
if (key.type == "mds" || key.type == "mgr" || key.type == "mon") {
daemon_meta.erase("name");
} else if (key.type == "osd") {
for (const auto &[key, val] : daemon_meta) {
m.emplace(key, val.get_str());
}
+ // prefer CRUSH physical host over container/pod hostname (tracker.ceph.com/issues/73080)
+ if (!crush_host.empty()) {
+ m["hostname"] = crush_host;
+ }
}
+ // update_metadata calls _rm then _insert using state->hostname read from
+ // the map via set_metadata, so hostname must be set through m, not
+ // directly on state->hostname before the call (that would corrupt by_server)
daemon_state.update_metadata(state, m);
} else {
auto state = std::make_shared<DaemonState>(daemon_state.types);
for (const auto &[key, val] : daemon_meta) {
m.emplace(key, val.get_str());
}
+ // prefer CRUSH physical host over container/pod hostname (tracker.ceph.com/issues/73080)
+ if (key.type == "osd") {
+ try {
+ std::string crush_host = crush_hostname_for_osd(cluster_state,
+ std::stoi(key.name));
+ if (!crush_host.empty()) {
+ state->hostname = crush_host;
+ m["hostname"] = crush_host;
+ }
+ } catch (const std::exception& e) {
+ dout(5) << "cannot derive CRUSH hostname for " << key
+ << ": " << e.what() << dendl;
+ }
+ }
state->set_metadata(m);
daemon_state.insert(state);
dout(1) << "Skipping incomplete metadata entry" << dendl;
continue;
}
- dout(4) << osd_metadata.at("hostname").get_str() << dendl;
DaemonStatePtr dm = std::make_shared<DaemonState>(daemon_state.types);
- dm->key = DaemonKey{"osd",
- stringify(osd_metadata.at("id").get_int())};
+ int osd_id = osd_metadata.at("id").get_int();
+ dm->key = DaemonKey{"osd", stringify(osd_id)};
dm->hostname = osd_metadata.at("hostname").get_str();
+ // prefer CRUSH physical host over container/pod hostname (tracker.ceph.com/issues/73080)
+ std::string crush_host = crush_hostname_for_osd(cluster_state, osd_id);
+ if (!crush_host.empty()) {
+ dm->hostname = crush_host;
+ }
+ dout(4) << dm->hostname << dendl;
+
osd_metadata.erase("id");
osd_metadata.erase("hostname");
update_meta = true;
}
if (update_meta) {
- auto c = new MetadataUpdate(daemon_state, k);
+ auto c = new MetadataUpdate(daemon_state, cluster_state, k);
std::ostringstream cmd;
cmd << "{\"prefix\": \"osd metadata\", \"id\": "
<< osd_id << "}";
if (daemon_state.is_updating(k)) {
continue;
}
- auto c = new MetadataUpdate(daemon_state, k);
+ auto c = new MetadataUpdate(daemon_state, cluster_state, k);
constexpr std::string_view cmd = R"({{"prefix": "mon metadata", "id": "{}"}})";
monc->start_mon_command({fmt::format(cmd, name)}, {},
&c->outbl, &c->outs, c);
}
if (update) {
- auto c = new MetadataUpdate(daemon_state, k);
+ auto c = new MetadataUpdate(daemon_state, cluster_state, k);
// Older MDS daemons don't have addr in the metadata, so
// fake it if the returned metadata doesn't have the field.