From 4a0545bc5064e50de4214fdc69d1f51a57fa0815 Mon Sep 17 00:00:00 2001 From: Leonid Usov Date: Thu, 8 Feb 2024 14:07:28 +0200 Subject: [PATCH] mds,messages: quiesce db inter-rank messaging Fixes: https://tracker.ceph.com/issues/63708 Signed-off-by: Leonid Usov (cherry picked from commit 82f3dbc3ef7b577219f8e1cfaeae4009a809029e) --- src/mds/MDSRank.cc | 12 ++ src/mds/MDSRank.h | 1 + src/mds/MDSRankQuiesce.cc | 286 ++++++++++++++++++++++++---- src/mds/QuiesceDbEncoding.h | 157 +++++++++++++++ src/mds/QuiesceDbManager.cc | 4 +- src/messages/MMDSQuiesceDbAck.h | 63 ++++++ src/messages/MMDSQuiesceDbListing.h | 63 ++++++ src/msg/Message.cc | 10 + src/msg/Message.h | 2 + 9 files changed, 557 insertions(+), 41 deletions(-) create mode 100644 src/mds/QuiesceDbEncoding.h create mode 100644 src/messages/MMDSQuiesceDbAck.h create mode 100644 src/messages/MMDSQuiesceDbListing.h diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc index 7d3f9cda9a226..12f6865b2bc19 100644 --- a/src/mds/MDSRank.cc +++ b/src/mds/MDSRank.cc @@ -1065,6 +1065,10 @@ bool MDSRankDispatcher::ms_dispatch(const cref_t &m) bool MDSRank::_dispatch(const cref_t &m, bool new_msg) { + if (quiesce_dispatch(m)) { + return true; + } + if (is_stale_message(m)) { return true; } @@ -1216,6 +1220,7 @@ bool MDSRank::is_valid_message(const cref_t &m) { return true; } + dout(10) << "invalid message type: " << std::hex << type << std::dec << dendl; return false; } @@ -1283,6 +1288,13 @@ void MDSRank::handle_message(const cref_t &m) } break; + case MSG_MDS_QUIESCE_DB_LISTING: + case MSG_MDS_QUIESCE_DB_ACK: + ALLOW_MESSAGES_FROM(CEPH_ENTITY_TYPE_MDS); + quiesce_dispatch(m); + break; + + case MSG_MDS_LOCK: case MSG_MDS_INODEFILECAPS: ALLOW_MESSAGES_FROM(CEPH_ENTITY_TYPE_MDS); diff --git a/src/mds/MDSRank.h b/src/mds/MDSRank.h index 02512be7916b5..41c45cd7d391a 100644 --- a/src/mds/MDSRank.h +++ b/src/mds/MDSRank.h @@ -570,6 +570,7 @@ class MDSRank { void quiesce_cluster_update(); void quiesce_agent_setup(); + bool quiesce_dispatch(const cref_t &m); /* Update MDSMap export_targets for this rank. Called on ::tick(). */ void update_targets(); diff --git a/src/mds/MDSRankQuiesce.cc b/src/mds/MDSRankQuiesce.cc index 49e6f39522533..27425497b14c3 100644 --- a/src/mds/MDSRankQuiesce.cc +++ b/src/mds/MDSRankQuiesce.cc @@ -3,10 +3,15 @@ #include "QuiesceDbManager.h" #include "QuiesceAgent.h" + +#include "messages/MMDSQuiesceDbListing.h" +#include "messages/MMDSQuiesceDbAck.h" + #include #include #include #include +#include #define dout_context g_ceph_context #define dout_subsys ceph_subsys_mds_quiesce @@ -203,46 +208,203 @@ void MDSRank::command_quiesce_db(const cmdmap_t& cmdmap, std::functionrequest.op_string() << dendl; + dout(20) << "Submitting " << ctx->request << dendl; int rc = quiesce_db_manager->submit_request(ctx); if (rc != 0) { bufferlist bl; + // on_finish was moved there, so should only call via the ctx. + ctx->on_finish(rc, "Error submitting the command to the local db manager", bl); delete ctx; - on_finish(rc, "Error submitting the command to the local db manager", bl); } } +static void rebind_agent_callback(std::shared_ptr agt, std::shared_ptr mgr) { + if (!agt || !mgr) { + return; + } + std::weak_ptr weak_agent = agt; + mgr->reset_agent_callback([weak_agent](QuiesceMap& update) { + if (auto agent = weak_agent.lock()) { + return agent->db_update(update); + } else { + return false; + } + }); +} + void MDSRank::quiesce_cluster_update() { + // the quiesce leader is the lowest rank with the highest state up to ACTIVE + auto less_leader = [](MDSMap::mds_info_t const* l, MDSMap::mds_info_t const* r) { + ceph_assert(l->rank != MDS_RANK_NONE); + ceph_assert(r->rank != MDS_RANK_NONE); + ceph_assert(l->state <= MDSMap::STATE_ACTIVE); + ceph_assert(r->state <= MDSMap::STATE_ACTIVE); + if (l->rank == r->rank) { + return l->state < r->state; + } else { + return l->rank > r->rank; + } + }; + + std::priority_queue, decltype(less_leader)> member_info(less_leader); QuiesceClusterMembership membership; - mds_rank_t leader = 0; // MAYBE LATER: initialize this from the map + QuiesceInterface::PeerId me = mds_gid_t(monc->get_global_id()); + + for (auto&& [gid, info] : mdsmap->get_mds_info()) { + // if it has a rank and state <= ACTIVE, it's good enough + if (info.rank != MDS_RANK_NONE && info.state <= MDSMap::STATE_ACTIVE) { + member_info.push(&info); + membership.members.insert(info.global_id); + } + } + + QuiesceInterface::PeerId leader = + member_info.empty() + ? QuiesceClusterMembership::INVALID_MEMBER + : member_info.top()->global_id; membership.epoch = mdsmap->get_epoch(); membership.leader = leader; - membership.me = whoami; - membership.fs_id = mdsmap->get_info(whoami).join_fscid; + membership.me = me; membership.fs_name = mdsmap->get_fs_name(); - mdsmap->get_mds_set(membership.members); - dout(5) << "epoch:" << membership.epoch << " leader:" << membership.leader << " members:" << membership.members << dendl; + dout(5) << "epoch:" << membership.epoch << " me:" << me << " leader:" << leader << " members:" << membership.members + << (mdsmap->is_degraded() ? " (degraded)" : "") << dendl; - membership.send_ack = [=,this](QuiesceMap&& ack) { - if (whoami == leader) { - // loopback - quiesce_db_manager->submit_ack_from(whoami, std::move(ack)); - return 0; - } else { - // TODO: implement messaging - return -ENOTSUP; + if (leader != QuiesceClusterMembership::INVALID_MEMBER) { + membership.send_ack = [=, this](QuiesceMap&& ack) { + if (me == leader) { + // loopback + quiesce_db_manager->submit_ack_from(me, std::move(ack)); + return 0; + } else { + std::lock_guard guard(mds_lock); + + if (mdsmap->get_state_gid(leader) == MDSMap::STATE_NULL) { + dout(5) << "couldn't find the leader " << leader << " in the map" << dendl; + return -ENOENT; + } + auto addrs = mdsmap->get_info_gid(leader).addrs; + + auto ack_msg = make_message(me); + dout(10) << "sending ack " << ack << " to the leader " << leader << dendl; + ack_msg->diff_map = std::move(ack); + return send_message_mds(ack_msg, addrs); + } + }; + + membership.send_listing_to = [=, this](QuiesceInterface::PeerId to, QuiesceDbListing&& db) { + std::lock_guard guard(mds_lock); + if (mdsmap->get_state_gid(to) == MDSMap::STATE_NULL) { + dout(5) << "couldn't find the peer " << to << " in the map" << dendl; + return -ENOENT; + } + auto addrs = mdsmap->get_info_gid(to).addrs; + auto listing_msg = make_message(me); + dout(10) << "sending listing " << db << " to the peer " << to << dendl; + listing_msg->db_listing = std::move(db); + return send_message_mds(listing_msg, addrs); + }; + } + + QuiesceDbManager::RequestContext* inject_request = nullptr; + + bool degraded = mdsmap->is_degraded(); + + if (degraded && membership.is_leader()) { + dout(5) << "WARNING: injecting a cancel all request" + << " members: " << membership.members + << " in: " << mdsmap->get_num_in_mds() + << " up: " << mdsmap->get_num_up_mds() + << " sr: " << mdsmap->get_num_standby_replay_mds() + << dendl; + + struct CancelAll: public QuiesceDbManager::RequestContext { + mds_rank_t whoami; + CancelAll(mds_rank_t whoami) : whoami(whoami) { + request.cancel_roots(); + } + void finish(int rc) override { + dout(rc == 0 ? 15 : 3) << "injected cancel all completed with rc: " << rc << dendl; + } + }; + + inject_request = new CancelAll(whoami); + } + + if (!is_active()) { + quiesce_db_manager->reset_agent_callback([whoami = whoami, degraded, is_sr = is_standby_replay()](QuiesceMap& quiesce_map) { + for (auto it = quiesce_map.roots.begin(); it != quiesce_map.roots.end();) { + switch (it->second.state) { + case QS_QUIESCING: + if (degraded) { + it->second.state = QS_FAILED; + dout(3) << "DEGRADED RESPONDER: reporting '" << it->first << "' as " << it->second.state << dendl; + ++it; + } else if (is_sr) { + it->second.state = QS_QUIESCED; + dout(15) << "STANDBY REPLAY RESPONDER: reporting '" << it->first << "' as " << it->second.state << dendl; + ++it; + } else { + // just ack. + dout(20) << "INTACTIVE RESPONDER: reporting '" << it->first << "' as " << it->second.state << dendl; + it = quiesce_map.roots.erase(it); + } + break; + default: + it = quiesce_map.roots.erase(it); + break; + } + } + return true; + }); + + if (quiesce_agent) { + // reset the agent if it's present + // because it won't receive any more callbacks + quiesce_agent->reset_async(); } - }; + } else { + rebind_agent_callback(quiesce_agent, quiesce_db_manager); + } - membership.send_listing_to = [=](mds_rank_t to, QuiesceDbListing&& db) { - // TODO: implement messaging - return -ENOTSUP; - }; + quiesce_db_manager->update_membership(membership, inject_request); +} - quiesce_db_manager->update_membership(membership); +bool MDSRank::quiesce_dispatch(const cref_t &m) { + switch(m->get_type()) { + case MSG_MDS_QUIESCE_DB_LISTING: + { + const auto& req = ref_cast(m); + if (quiesce_db_manager) { + dout(10) << "got " << req->db_listing << " from peer " << req->gid << dendl; + int result = quiesce_db_manager->submit_listing_from(req->gid, std::move(req->db_listing)); + if (result != 0) { + dout(3) << "error (" << result << ") submitting " << req->db_listing << " from peer " << req->gid << dendl; + } + } else { + dout(5) << "no db manager to process " << req->db_listing << dendl; + } + return true; + } + case MSG_MDS_QUIESCE_DB_ACK: + { + const auto& req = ref_cast(m); + if (quiesce_db_manager) { + dout(10) << "got ack " << req->diff_map << " from peer " << req->gid << dendl; + int result = quiesce_db_manager->submit_ack_from(req->gid, std::move(req->diff_map)); + if (result != 0) { + dout(3) << "error (" << result << ") submitting an ack from peer " << req->gid << dendl; + } + } else { + dout(5) << "no db manager to process an ack: " << req->diff_map << dendl; + } + return true; + } + default: + return false; + } } void MDSRank::quiesce_agent_setup() { @@ -278,29 +440,62 @@ void MDSRank::quiesce_agent_setup() { return std::nullopt; } } - std::optional dummy_quiesce_after; + std::optional debug_quiesce_after; if (auto pit = uri->params().find("q"); pit != uri->params().end()) { try { - dummy_quiesce_after = (*pit).has_value ? std::stod((*pit).value) : 1 /*second*/; + debug_quiesce_after = (*pit).has_value ? std::stod((*pit).value) : 1 /*second*/; } catch (...) { dout(5) << "error parsing the time for debug quiesce for query: " << uri->query() << dendl; c->complete(-EINVAL); return std::nullopt; } } + std::optional debug_fail_after; + if (auto pit = uri->params().find("f"); pit != uri->params().end()) { + try { + debug_fail_after = (*pit).has_value ? std::stod((*pit).value) : 1 /*second*/; + } catch (...) { + dout(5) << "error parsing the time for debug fail for query: " << uri->query() << dendl; + c->complete(-EINVAL); + return std::nullopt; + } + } + std::optional debug_rank; + if (auto pit = uri->params().find("r"); pit != uri->params().end()) { + try { + if ((*pit).has_value) { + debug_rank = (mds_rank_t)std::stoul((*pit).value); + } + } catch (...) { + dout(5) << "error parsing the rank for debug pin for query: " << uri->query() << dendl; + c->complete(-EINVAL); + return std::nullopt; + } + } + + if (debug_rank && (debug_rank >= mdsmap->get_max_mds())) { + dout(5) << "invalid rank: " << uri->query() << dendl; + c->complete(-EINVAL); + return std::nullopt; + } auto path = uri->path(); dout(20) << "got request to quiesce '" << path << "'" << dendl; std::lock_guard l(mds_lock); - if (!dummy_quiesce_after) { + if (!debug_quiesce_after && !debug_fail_after && !debug_rank) { // the real deal! + if (mdsmap->is_degraded()) { + dout(3) << "DEGRADED: refusing to quiesce" << dendl; + c->complete(EPERM); + return std::nullopt; + } auto qc = new MDCache::C_MDS_QuiescePath(mdcache, c); auto mdr = mdcache->quiesce_path(filepath(path), qc, nullptr, quiesce_delay_ms); return mdr ? mdr->reqid : std::optional(); } else { - /* dummy quiesce */ + /* dummy quiesce/fail */ // always create a new request id auto req_id = metareqid_t(entity_name_t::MDS(whoami), issue_tid()); auto [it, inserted] = quiesce_requests->try_emplace(path, req_id, c); @@ -317,25 +512,44 @@ void MDSRank::quiesce_agent_setup() { // since we weren't inserted, we must have successfully quiesced c->complete(0); } + } else if (debug_rank && (debug_rank != whoami)) { + // the root was pinned to a different rank + // we should acknowledge the quiesce regardless of the other flags + it->second.second->complete(0); + it->second.second = nullptr; } else { - // do quiesce if needed + // do quiesce or fail + + bool do_fail = false; + double delay; + if (debug_quiesce_after.has_value() && debug_fail_after.has_value()) { + do_fail = debug_fail_after < debug_quiesce_after; + } else { + do_fail = debug_fail_after.has_value(); + } + + if (do_fail) { + delay = debug_fail_after.value(); + } else { + delay = debug_quiesce_after.value(); + } - auto quiesce_task = new LambdaContext([quiesce_requests, req_id, this](int) { + auto quiesce_task = new LambdaContext([quiesce_requests, req_id, do_fail, this](int) { // the mds lock should be held by the timer dout(20) << "quiesce_task: callback by the timer" << dendl; auto it = std::ranges::find(*quiesce_requests, req_id, [](auto x) { return x.second.first; }); if (it != quiesce_requests->end() && it->second.second != nullptr) { - dout(20) << "quiesce_task: completing the root '" << it->first << "'" << dendl; - it->second.second->complete(0); + dout(20) << "quiesce_task: completing the root '" << it->first << "' as failed: " << do_fail << dendl; + it->second.second->complete(do_fail ? -EBADF : 0); it->second.second = nullptr; } dout(20) << "quiesce_task: done" << dendl; }); dout(20) << "scheduling a quiesce_task (" << quiesce_task - << ") to fire after " << *dummy_quiesce_after + << ") to fire after " << delay << " seconds on timer " << &timer << dendl; - timer.add_event_after(*dummy_quiesce_after, quiesce_task); + timer.add_event_after(delay, quiesce_task); } return it->second.first; } @@ -373,13 +587,5 @@ void MDSRank::quiesce_agent_setup() { }; quiesce_agent.reset(new QuiesceAgent(ci)); - - std::weak_ptr weak_agent = quiesce_agent; - quiesce_db_manager->reset_agent_callback([weak_agent](QuiesceMap& update) { - if (auto agent = weak_agent.lock()) { - return agent->db_update(update); - } else { - return false; - } - }); + rebind_agent_callback(quiesce_agent, quiesce_db_manager); }; diff --git a/src/mds/QuiesceDbEncoding.h b/src/mds/QuiesceDbEncoding.h new file mode 100644 index 0000000000000..756e63cf9e3e9 --- /dev/null +++ b/src/mds/QuiesceDbEncoding.h @@ -0,0 +1,157 @@ +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2023 IBM, Red Hat + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#pragma once +#include "QuiesceDb.h" +#include "include/encoding.h" +#include + +void encode(QuiesceDbVersion const& v, bufferlist& bl, uint64_t features = 0) +{ + encode(v.epoch, bl, features); + encode(v.set_version, bl, features); +} + +void decode(QuiesceDbVersion& v, bufferlist::const_iterator& p) +{ + decode(v.epoch, p); + decode(v.set_version, p); +} + +void encode(QuiesceState const & state, bufferlist& bl, uint64_t features=0) +{ + static_assert(QuiesceState::QS__MAX <= UINT8_MAX); + uint8_t v = (uint8_t)state; + encode(v, bl, features); +} + +void decode(QuiesceState & state, bufferlist::const_iterator& p) +{ + uint8_t v = 0; + decode(v, p); + state = (QuiesceState)v; +} + +void encode(QuiesceTimeInterval const & interval, bufferlist& bl, uint64_t features=0) +{ + encode(interval.count(), bl, features); +} + +void decode(QuiesceTimeInterval & interval, bufferlist::const_iterator& p) +{ + QuiesceClock::rep count; + decode(count, p); + interval = QuiesceTimeInterval { count }; +} + +void encode(RecordedQuiesceState const& rstate, bufferlist& bl, uint64_t features = 0) +{ + encode(rstate.state, bl, features); + encode(rstate.at_age.count(), bl, features); +} + +void decode(RecordedQuiesceState& rstate, bufferlist::const_iterator& p) +{ + decode(rstate.state, p); + decode(rstate.at_age, p); +} + +void encode(QuiesceSet::MemberInfo const& member, bufferlist& bl, uint64_t features = 0) +{ + encode(member.rstate, bl, features); + encode(member.excluded, bl, features); +} + +void decode(QuiesceSet::MemberInfo& member, bufferlist::const_iterator& p) +{ + decode(member.rstate, p); + decode(member.excluded, p); +} + +void encode(QuiesceSet const& set, bufferlist& bl, uint64_t features = 0) +{ + encode(set.version, bl, features); + encode(set.rstate, bl, features); + encode(set.timeout, bl, features); + encode(set.expiration, bl, features); + encode(set.members, bl, features); +} + +void decode(QuiesceSet& set, bufferlist::const_iterator& p) +{ + decode(set.version, p); + decode(set.rstate, p); + decode(set.timeout, p); + decode(set.expiration, p); + decode(set.members, p); +} + +void encode(QuiesceDbRequest const& req, bufferlist& bl, uint64_t features = 0) +{ + encode(req.control.raw, bl, features); + encode(req.set_id, bl); + encode(req.if_version, bl); + encode(req.timeout, bl); + encode(req.expiration, bl); + encode(req.await, bl); + encode(req.roots, bl); +} + +void decode(QuiesceDbRequest& req, bufferlist::const_iterator& p) +{ + decode(req.control.raw, p); + decode(req.set_id, p); + decode(req.if_version, p); + decode(req.timeout, p); + decode(req.expiration, p); + decode(req.await, p); + decode(req.roots, p); +} + +void encode(QuiesceDbListing const& listing, bufferlist& bl, uint64_t features = 0) +{ + encode(listing.db_version, bl, features); + encode(listing.db_age, bl, features); + encode(listing.sets, bl, features); +} + +void decode(QuiesceDbListing& listing, bufferlist::const_iterator& p) +{ + decode(listing.db_version, p); + decode(listing.db_age, p); + decode(listing.sets, p); +} + +void encode(QuiesceMap::RootInfo const& root, bufferlist& bl, uint64_t features = 0) +{ + encode(root.state, bl, features); + encode(root.ttl, bl, features); +} + +void decode(QuiesceMap::RootInfo& root, bufferlist::const_iterator& p) +{ + decode(root.state, p); + decode(root.ttl, p); +} + +void encode(QuiesceMap const& map, bufferlist& bl, uint64_t features = 0) +{ + encode(map.db_version, bl, features); + encode(map.roots, bl, features); +} + +void decode(QuiesceMap& map, bufferlist::const_iterator& p) +{ + decode(map.db_version, p); + decode(map.roots, p); +} + diff --git a/src/mds/QuiesceDbManager.cc b/src/mds/QuiesceDbManager.cc index 3eb9009f86b0b..1ff998f606868 100644 --- a/src/mds/QuiesceDbManager.cc +++ b/src/mds/QuiesceDbManager.cc @@ -202,7 +202,9 @@ bool QuiesceDbManager::membership_upkeep() bool was_leader = membership.epoch > 0 && membership.leader == membership.me; bool is_leader = cluster_membership && cluster_membership->leader == cluster_membership->me; if (cluster_membership) { - dout(10) << "epoch: " << cluster_membership->epoch << " is_leader: " << is_leader << " was_leader: " << was_leader << dendl; + dout(10) << "epoch:" << cluster_membership->epoch << " leader:" + << std::boolalpha << was_leader << "->" << is_leader << std::noboolalpha + << " members:" << cluster_membership->members << dendl; } else { dout(10) << "shutdown! was_leader: " << was_leader << dendl; } diff --git a/src/messages/MMDSQuiesceDbAck.h b/src/messages/MMDSQuiesceDbAck.h new file mode 100644 index 0000000000000..907db239bd18f --- /dev/null +++ b/src/messages/MMDSQuiesceDbAck.h @@ -0,0 +1,63 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#pragma once + +#include "messages/MMDSOp.h" +#include "mds/QuiesceDbEncoding.h" + +class MMDSQuiesceDbAck final : public MMDSOp { +public: + mds_gid_t gid; + mutable QuiesceMap diff_map; + +protected: + MMDSQuiesceDbAck(mds_gid_t gid) : MMDSOp{MSG_MDS_QUIESCE_DB_ACK}, gid(gid) {} + MMDSQuiesceDbAck() : MMDSQuiesceDbAck(MDS_GID_NONE) {} + ~MMDSQuiesceDbAck() final {} + +public: + std::string_view get_type_name() const override { return "mds_quiesce_db_ack"; } + void print(std::ostream& o) const override { + + } + + void encode_payload(uint64_t features) override + { + using ceph::encode; + + ceph_assert(gid != MDS_GID_NONE); + + ENCODE_START(1, 1, payload); + encode(gid, payload); + encode(diff_map, payload); + ENCODE_FINISH(payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + DECODE_START(1, p); + decode(gid, p); + decode(diff_map, p); + DECODE_FINISH(p); + } + +private: + template + friend boost::intrusive_ptr ceph::make_message(Args&&... args); + template + friend MURef crimson::make_message(Args&&... args); +}; diff --git a/src/messages/MMDSQuiesceDbListing.h b/src/messages/MMDSQuiesceDbListing.h new file mode 100644 index 0000000000000..9d3ce20fdab48 --- /dev/null +++ b/src/messages/MMDSQuiesceDbListing.h @@ -0,0 +1,63 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2004-2006 Sage Weil + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + + +#pragma once + +#include "messages/MMDSOp.h" +#include "mds/QuiesceDbEncoding.h" + +class MMDSQuiesceDbListing final : public MMDSOp { +public: + mds_gid_t gid; + mutable QuiesceDbListing db_listing; + +protected: + MMDSQuiesceDbListing(mds_gid_t gid) : MMDSOp{MSG_MDS_QUIESCE_DB_LISTING}, gid(gid) {} + MMDSQuiesceDbListing() : MMDSQuiesceDbListing(MDS_GID_NONE) {} + ~MMDSQuiesceDbListing() final {} + +public: + std::string_view get_type_name() const override { return "mds_quiesce_db_listing"; } + void print(std::ostream& o) const override { + + } + + void encode_payload(uint64_t features) override + { + using ceph::encode; + + ceph_assert(gid != MDS_GID_NONE); + + ENCODE_START(1, 1, payload); + encode(gid, payload); + encode(db_listing, payload); + ENCODE_FINISH(payload); + } + + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + DECODE_START(1, p); + decode(gid, p); + decode(db_listing, p); + DECODE_FINISH(p); + } + +private: + template + friend boost::intrusive_ptr ceph::make_message(Args&&... args); + template + friend MURef crimson::make_message(Args&&... args); +}; diff --git a/src/msg/Message.cc b/src/msg/Message.cc index 70ac4ad133894..7f209f9022348 100644 --- a/src/msg/Message.cc +++ b/src/msg/Message.cc @@ -131,6 +131,8 @@ #include "messages/MClientMetrics.h" #include "messages/MMDSPeerRequest.h" +#include "messages/MMDSQuiesceDbListing.h" +#include "messages/MMDSQuiesceDbAck.h" #include "messages/MMDSMap.h" #include "messages/MFSMap.h" @@ -848,6 +850,14 @@ Message *decode_message(CephContext *cct, case MSG_MDS_TABLE_REQUEST: m = make_message(); + break; + + case MSG_MDS_QUIESCE_DB_LISTING: + m = make_message(); + break; + + case MSG_MDS_QUIESCE_DB_ACK: + m = make_message(); break; /* case MSG_MDS_INODEUPDATE: diff --git a/src/msg/Message.h b/src/msg/Message.h index 40833744b67d1..cabefe6556b53 100644 --- a/src/msg/Message.h +++ b/src/msg/Message.h @@ -198,6 +198,8 @@ #define MSG_MDS_METRICS 0x501 // for mds metric aggregator #define MSG_MDS_PING 0x502 // for mds pinger #define MSG_MDS_SCRUB_STATS 0x503 // for mds scrub stack +#define MSG_MDS_QUIESCE_DB_LISTING 0x505 // quiesce db replication +#define MSG_MDS_QUIESCE_DB_ACK 0x506 // quiesce agent ack back to the db // *** generic *** #define MSG_TIMECHECK 0x600 -- 2.39.5