From: Simon Gao Date: Thu, 28 May 2020 08:22:12 +0000 (+0800) Subject: mds: multiple mds scrub support X-Git-Tag: v16.1.0~577^2~12 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=e5c4e8c0b0286004592035f0398660b3fc097ed0;p=ceph.git mds: multiple mds scrub support If a non-auth object is encountered during scrubbing, forward scrub to the object's auth mds. Fixes: https://tracker.ceph.com/issues/12274 Signed-off-by: Simon Gao Signed-off-by: "Yan, Zheng" --- diff --git a/src/include/frag.h b/src/include/frag.h index a4e20bacab22..ec18bddfbb1e 100644 --- a/src/include/frag.h +++ b/src/include/frag.h @@ -570,6 +570,10 @@ public: } } + void clear() { + _set.clear(); + } + void insert_raw(frag_t f){ _set.insert(f); } diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 63f6548b0ae9..3e771e30429a 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -5107,6 +5107,7 @@ void CInode::scrub_initialize(ScrubHeaderRef& header, scrub_info(); scrub_infop->on_finish = f; scrub_infop->scrub_in_progress = true; + scrub_infop->queued_frags.clear(); scrub_infop->header = header; // right now we don't handle remote inodes } diff --git a/src/mds/CInode.h b/src/mds/CInode.h index e38286dbc6ea..470fcfaec8e7 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -306,6 +306,8 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counterqueued_frags; + } + void scrub_set_finisher(MDSContext *c) { ceph_assert(!scrub_infop->on_finish); scrub_infop->on_finish = c; diff --git a/src/mds/MDSRank.cc b/src/mds/MDSRank.cc index 80046d723a65..b6b06a06d61c 100644 --- a/src/mds/MDSRank.cc +++ b/src/mds/MDSRank.cc @@ -1171,6 +1171,7 @@ bool MDSRank::is_valid_message(const cref_t &m) { type == MSG_MDS_TABLE_REQUEST || type == MSG_MDS_LOCK || type == MSG_MDS_INODEFILECAPS || + type == MSG_MDS_SCRUB || type == CEPH_MSG_CLIENT_CAPS || type == CEPH_MSG_CLIENT_CAPRELEASE || type == CEPH_MSG_CLIENT_LEASE) { @@ -1256,6 +1257,11 @@ void MDSRank::handle_message(const cref_t &m) locker->dispatch(m); break; + case MSG_MDS_SCRUB: + ALLOW_MESSAGES_FROM(CEPH_ENTITY_TYPE_MDS); + scrubstack->dispatch(m); + break; + default: derr << "unrecognized message " << *m << dendl; } @@ -2467,13 +2473,8 @@ void MDSRankDispatcher::handle_mds_map( if (mdsmap->get_inline_data_enabled() && !oldmap.get_inline_data_enabled()) dout(0) << "WARNING: inline_data support has been deprecated and will be removed in a future release" << dendl; - if (scrubstack->is_scrubbing()) { - if (mdsmap->get_max_mds() > 1) { - auto c = new C_MDSInternalNoop; - scrubstack->scrub_abort(c); - } - } mdcache->handle_mdsmap(*mdsmap, oldmap); + if (metric_aggregator != nullptr) { metric_aggregator->notify_mdsmap(*mdsmap); } @@ -2504,6 +2505,8 @@ void MDSRank::handle_mds_failure(mds_rank_t who) snapserver->handle_mds_failure_or_stop(who); snapclient->handle_mds_failure(who); + + scrubstack->handle_mds_failure(who); } void MDSRankDispatcher::handle_asok_command( @@ -2612,13 +2615,6 @@ void MDSRankDispatcher::handle_asok_command( cmd_getval(cmdmap, "path", path); cmd_getval(cmdmap, "tag", tag); - /* Multiple MDS scrub is not currently supported. See also: https://tracker.ceph.com/issues/12274 */ - if (mdsmap->get_max_mds() > 1) { - *css << "Scrub is not currently supported for multiple active MDS. Please reduce max_mds to 1 and then scrub."; - r = -EINVAL; - goto out; - } - finisher->queue( new LambdaContext( [this, on_finish, f, path, tag, scrubop_vec](int r) { diff --git a/src/mds/ScrubHeader.h b/src/mds/ScrubHeader.h index a41471fec210..0925c28d6b85 100644 --- a/src/mds/ScrubHeader.h +++ b/src/mds/ScrubHeader.h @@ -37,10 +37,7 @@ public: ScrubHeader(std::string_view tag_, bool is_tag_internal_, bool force_, bool recursive_, bool repair_, ceph::Formatter *f_) : tag(tag_), is_tag_internal(is_tag_internal_), force(force_), - recursive(recursive_), repair(repair_), formatter(f_) - { - ceph_assert(formatter != nullptr); - } + recursive(recursive_), repair(repair_), formatter(f_) {} // Set after construction because it won't be known until we've // started resolving path and locking @@ -51,7 +48,7 @@ public: bool get_force() const { return force; } bool is_internal_tag() const { return is_tag_internal; } CInode *get_origin() const { return origin; } - std::string_view get_tag() const { return tag; } + const std::string& get_tag() const { return tag; } ceph::Formatter& get_formatter() const { return *formatter; } bool get_repaired() const { return repaired; } diff --git a/src/mds/ScrubStack.cc b/src/mds/ScrubStack.cc index c27d8d4a06c5..f454f2334ca4 100644 --- a/src/mds/ScrubStack.cc +++ b/src/mds/ScrubStack.cc @@ -110,13 +110,14 @@ void ScrubStack::add_to_waiting(MDSCacheObject *obj) scrub_waiting.push_back(&obj->item_scrub); } -void ScrubStack::remove_from_waiting(MDSCacheObject *obj) +void ScrubStack::remove_from_waiting(MDSCacheObject *obj, bool kick) { scrubs_in_progress--; if (obj->item_scrub.is_on_list()) { obj->item_scrub.remove_myself(); scrub_stack.push_front(&obj->item_scrub); - kick_off_scrubs(); + if (kick) + kick_off_scrubs(); } } @@ -175,10 +176,13 @@ void ScrubStack::kick_off_scrubs() assert(state == STATE_RUNNING || state == STATE_IDLE); set_state(STATE_RUNNING); - if (CInode *in = dynamic_cast(*it)) { dout(20) << __func__ << " examining " << *in << dendl; ++it; + + if (!validate_inode_auth(in)) + continue; + if (!in->is_dir()) { // it's a regular file, symlink, or hard link dequeue(in); // we only touch it this once, so remove from stack @@ -219,47 +223,125 @@ void ScrubStack::kick_off_scrubs() } } +bool ScrubStack::validate_inode_auth(CInode *in) +{ + if (in->is_auth()) { + if (!in->can_auth_pin()) { + dout(10) << __func__ << " can't auth pin" << dendl; + in->add_waiter(CInode::WAIT_UNFREEZE, new C_RetryScrub(this, in)); + return false; + } + return true; + } else { + MDSRank *mds = mdcache->mds; + if (in->is_ambiguous_auth()) { + dout(10) << __func__ << " ambiguous auth" << dendl; + in->add_waiter(MDSCacheObject::WAIT_SINGLEAUTH, new C_RetryScrub(this, in)); + } else if (mds->is_cluster_degraded()) { + dout(20) << __func__ << " cluster degraded" << dendl; + mds->wait_for_cluster_recovered(new C_RetryScrub(this, in)); + } else { + ScrubHeaderRef header = in->get_scrub_header(); + ceph_assert(header); + + auto ret = remote_scrubs.emplace(std::piecewise_construct, + std::forward_as_tuple(in), + std::forward_as_tuple()); + ceph_assert(ret.second); // FIXME: parallel scrubs? + auto &scrub_r = ret.first->second; + scrub_r.tag = header->get_tag(); + + mds_rank_t auth = in->authority().first; + dout(10) << __func__ << " forward to mds." << auth << dendl; + auto r = make_message(MMDSScrub::OP_QUEUEINO, in->ino(), + std::move(in->scrub_queued_frags()), + header->get_tag(), header->is_internal_tag(), + header->get_force(), header->get_recursive(), + header->get_repair()); + mdcache->mds->send_message_mds(r, auth); + + scrub_r.gather_set.insert(auth); + // wait for ACK + add_to_waiting(in); + } + return false; + } +} + void ScrubStack::scrub_dir_inode(CInode *in, bool *added_children, bool *done) { dout(10) << __func__ << " " << *in << dendl; + ceph_assert(in->is_auth()); + MDSRank *mds = mdcache->mds; ScrubHeaderRef header = in->get_scrub_header(); ceph_assert(header); MDSGatherBuilder gather(g_ceph_context); + auto &queued = in->scrub_queued_frags(); + std::map scrub_remote; + frag_vec_t frags; in->dirfragtree.get_leaves(frags); dout(20) << __func__ << "recursive mode, frags " << frags << dendl; - for (auto &fg : frags) { + if (queued.contains(fg)) + continue; CDir *dir = in->get_or_open_dirfrag(mdcache, fg); if (!dir->is_auth()) { - dout(20) << __func__ << " not auth " << *dir << dendl; - // no-op + if (dir->is_ambiguous_auth()) { + dout(20) << __func__ << " ambiguous auth " << *dir << dendl; + dir->add_waiter(MDSCacheObject::WAIT_SINGLEAUTH, gather.new_sub()); + } else if (mds->is_cluster_degraded()) { + dout(20) << __func__ << " cluster degraded" << dendl; + mds->wait_for_cluster_recovered(gather.new_sub()); + } else { + mds_rank_t auth = dir->authority().first; + scrub_remote[auth].insert_raw(fg); + } } else if (!dir->can_auth_pin()) { dout(20) << __func__ << " freezing/frozen " << *dir << dendl; dir->add_waiter(CDir::WAIT_UNFREEZE, gather.new_sub()); } else if (dir->get_version() == 0) { dout(20) << __func__ << " barebones " << *dir << dendl; dir->fetch(gather.new_sub()); + } else { + _enqueue(dir, header, nullptr, true); + queued.insert_raw(dir->get_frag()); + *added_children = true; } } + + queued.simplify(); + if (gather.has_subs()) { gather.set_finisher(new C_RetryScrub(this, in)); gather.activate(); return; } - std::vector dfs; - in->get_dirfrags(dfs); - for (auto &dir : dfs) { - if (dir->is_auth()){ - _enqueue(dir, header, nullptr, true); - *added_children = true; - } else { - // FIXME: ask auth mds to scrub + if (!scrub_remote.empty()) { + auto ret = remote_scrubs.emplace(std::piecewise_construct, + std::forward_as_tuple(in), + std::forward_as_tuple()); + ceph_assert(ret.second); // FIXME: parallel scrubs? + auto &scrub_r = ret.first->second; + scrub_r.tag = header->get_tag(); + + for (auto& p : scrub_remote) { + p.second.simplify(); + dout(20) << __func__ << " forward " << p.second << " to mds." << p.first << dendl; + auto r = make_message(MMDSScrub::OP_QUEUEDIR, in->ino(), + std::move(p.second), header->get_tag(), + header->is_internal_tag(), header->get_force(), + header->get_recursive(), header->get_repair()); + mds->send_message_mds(r, p.first); + scrub_r.gather_set.insert(p.first); } + // wait for ACKs + add_to_waiting(in); + return; } scrub_dir_inode_final(in); @@ -415,13 +497,13 @@ void ScrubStack::_validate_inode_done(CInode *in, int r, if (in == header->get_origin()) { scrub_origins.erase(in); clog_scrub_summary(in); - if (!header->get_recursive()) { + if (!header->get_recursive() && header->get_formatter()) { if (r >= 0) { // we got into the scrubbing dump it - result.dump(&(header->get_formatter())); + result.dump(header->get_formatter()); } else { // we failed the lookup or something; dump ourselves - header->get_formatter().open_object_section("results"); - header->get_formatter().dump_int("return_code", r); - header->get_formatter().close_section(); // results + header->get_formatter()->open_object_section("results"); + header->get_formatter()->dump_int("return_code", r); + header->get_formatter()->close_section(); // results } } } @@ -612,6 +694,11 @@ void ScrubStack::abort_pending_scrubs() { stack_size = 0; scrub_stack.clear(); scrub_waiting.clear(); + + for (auto& p : remote_scrubs) + remove_from_waiting(p.first, false); + remote_scrubs.clear(); + clear_stack = false; } @@ -696,3 +783,163 @@ void ScrubStack::clog_scrub_summary(CInode *in) { clog->info() << "scrub summary: " << scrub_summary(); } + +void ScrubStack::dispatch(const cref_t &m) +{ + switch (m->get_type()) { + case MSG_MDS_SCRUB: + handle_scrub(ref_cast(m)); + break; + + default: + derr << " scrub stack unknown message " << m->get_type() << dendl_impl; + ceph_abort_msg("scrub stack unknown message"); + } +} + +void ScrubStack::handle_scrub(const cref_t &m) +{ + + mds_rank_t from = mds_rank_t(m->get_source().num()); + dout(10) << __func__ << " " << *m << " from mds." << from << dendl; + + switch (m->get_op()) { + case MMDSScrub::OP_QUEUEDIR: + { + CInode *diri = mdcache->get_inode(m->get_ino()); + ceph_assert(diri); + + std::vector dfs; + MDSGatherBuilder gather(g_ceph_context); + for (const auto& fg : m->get_frags()) { + CDir *dir = diri->get_dirfrag(fg); + if (!dir) { + dout(10) << __func__ << " no frag " << fg << dendl; + continue; + } + if (!dir->is_auth()) { + dout(10) << __func__ << " not auth " << *dir << dendl; + continue; + } + if (!dir->can_auth_pin()) { + dout(10) << __func__ << " can't auth pin " << *dir << dendl; + dir->add_waiter(CDir::WAIT_UNFREEZE, gather.new_sub()); + continue; + } + dfs.push_back(dir); + } + + if (gather.has_subs()) { + gather.set_finisher(new C_MDS_RetryMessage(mdcache->mds, m)); + gather.activate(); + return; + } + + fragset_t queued; + if (!dfs.empty()) { + ScrubHeaderRef header = std::make_shared(m->get_tag(), m->is_internal_tag(), + m->is_force(), m->is_recursive(), + m->is_repair(), nullptr); + for (auto dir : dfs) { + queued.insert_raw(dir->get_frag()); + _enqueue(dir, header, nullptr, true); + } + queued.simplify(); + kick_off_scrubs(); + } + + auto r = make_message(MMDSScrub::OP_QUEUEDIR_ACK, m->get_ino(), + std::move(queued), m->get_tag()); + mdcache->mds->send_message_mds(r, from); + } + break; + case MMDSScrub::OP_QUEUEDIR_ACK: + { + CInode *diri = mdcache->get_inode(m->get_ino()); + ceph_assert(diri); + auto it = remote_scrubs.find(diri); + if (it != remote_scrubs.end() && + m->get_tag() == it->second.tag) { + if (it->second.gather_set.erase(from)) { + auto &queued = diri->scrub_queued_frags(); + for (auto &fg : m->get_frags()) + queued.insert_raw(fg); + queued.simplify(); + + if (it->second.gather_set.empty()) { + remote_scrubs.erase(it); + remove_from_waiting(diri); + } + } + } + } + break; + case MMDSScrub::OP_QUEUEINO: + { + CInode *in = mdcache->get_inode(m->get_ino()); + ceph_assert(in); + + ScrubHeaderRef header = std::make_shared(m->get_tag(), m->is_internal_tag(), + m->is_force(), m->is_recursive(), + m->is_repair(), nullptr); + + _enqueue(in, header, nullptr, true); + in->scrub_queued_frags() = m->get_frags(); + kick_off_scrubs(); + + fragset_t queued; + auto r = make_message(MMDSScrub::OP_QUEUEINO_ACK, m->get_ino(), + std::move(queued), m->get_tag()); + mdcache->mds->send_message_mds(r, from); + } + break; + case MMDSScrub::OP_QUEUEINO_ACK: + { + CInode *in = mdcache->get_inode(m->get_ino()); + ceph_assert(in); + auto it = remote_scrubs.find(in); + if (it != remote_scrubs.end() && + m->get_tag() == it->second.tag && + it->second.gather_set.erase(from)) { + ceph_assert(it->second.gather_set.empty()); + remote_scrubs.erase(it); + + remove_from_waiting(in, false); + dequeue(in); + + if (in == in->scrub_info()->header->get_origin()) { + scrub_origins.erase(in); + clog_scrub_summary(in); + } + MDSContext *c = nullptr; + in->scrub_finished(&c); + if (c) + finisher->queue(new MDSIOContextWrapper(mdcache->mds, c), 0); + + kick_off_scrubs(); + } + } + break; + default: + derr << " scrub stack unknown scrub operation " << m->get_op() << dendl_impl; + ceph_abort_msg("scrub stack unknown scrub operation"); + } +} + +void ScrubStack::handle_mds_failure(mds_rank_t mds) +{ + bool kick = false; + for (auto it = remote_scrubs.begin(); it != remote_scrubs.end(); ) { + if (it->second.gather_set.erase(mds) && + it->second.gather_set.empty()) { + CInode *in = it->first; + remote_scrubs.erase(it++); + remove_from_waiting(in, false); + kick = true; + } else { + ++it; + } + } + if (kick) + kick_off_scrubs(); +} diff --git a/src/mds/ScrubStack.h b/src/mds/ScrubStack.h index a94aeec67666..592b4e9ef643 100644 --- a/src/mds/ScrubStack.h +++ b/src/mds/ScrubStack.h @@ -23,6 +23,7 @@ #include "common/LogClient.h" #include "include/elist.h" +#include "messages/MMDSScrub.h" class MDCache; class Finisher; @@ -95,9 +96,33 @@ public: bool is_scrubbing() const { return !scrub_stack.empty(); } + void handle_mds_failure(mds_rank_t mds); + + void dispatch(const cref_t &m); + MDCache *mdcache; protected: + + // reference to global cluster log client + LogChannelRef &clog; + + /// A finisher needed so that we don't re-enter kick_off_scrubs + Finisher *finisher; + + /// The stack of inodes we want to scrub + elist scrub_stack; + elist scrub_waiting; + /// current number of dentries we're actually scrubbing + int scrubs_in_progress = 0; + int stack_size = 0; + + struct scrub_remote_t { + std::string tag; + std::set gather_set; + }; + std::map remote_scrubs; + class C_KickOffScrubs : public MDSInternalContext { public: C_KickOffScrubs(ScrubStack *s); @@ -114,20 +139,6 @@ protected: private: ScrubStack *stack; }; - - // reference to global cluster log client - LogChannelRef &clog; - - /// A finisher needed so that we don't re-enter kick_off_scrubs - Finisher *finisher; - - /// The stack of inodes we want to scrub - elist scrub_stack; - elist scrub_waiting; - /// current number of dentries we're actually scrubbing - int scrubs_in_progress = 0; - int stack_size = 0; - C_KickOffScrubs scrub_kick; friend class C_RetryScrub; @@ -165,7 +176,12 @@ private: /** * Move the inode/dirfrag back to scrub queue. */ - void remove_from_waiting(MDSCacheObject *obj); + void remove_from_waiting(MDSCacheObject *obj, bool kick=true); + /** + * Validate authority of the inode. If current mds is not auth of the inode, + * forword scrub to auth mds. + */ + bool validate_inode_auth(CInode *in); /** * Scrub a file inode. @@ -245,6 +261,8 @@ private: */ void clog_scrub_summary(CInode *in=nullptr); + void handle_scrub(const cref_t &m); + State state = STATE_IDLE; bool clear_stack = false; diff --git a/src/messages/MMDSScrub.h b/src/messages/MMDSScrub.h new file mode 100644 index 000000000000..f1a7e788b628 --- /dev/null +++ b/src/messages/MMDSScrub.h @@ -0,0 +1,124 @@ +// -*- 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. + * + */ + +#ifndef CEPH_MMDSSCRUB_H +#define CEPH_MMDSSCRUB_H + +#include "messages/MMDSOp.h" + +#include "include/types.h" +#include "include/frag.h" + +class MMDSScrub : public MMDSOp { +public: + static constexpr int OP_QUEUEDIR = 1; + static constexpr int OP_QUEUEDIR_ACK = -1; + static constexpr int OP_QUEUEINO = 2; + static constexpr int OP_QUEUEINO_ACK = -2; + + static const char *get_opname(int o) { + switch (o) { + case OP_QUEUEDIR: return "queue_dir"; + case OP_QUEUEDIR_ACK: return "queue_dir_ack"; + case OP_QUEUEINO: return "queue_ino"; + case OP_QUEUEINO_ACK: return "queue_ino_ack"; + default: ceph_abort(); return nullptr; + } + } + + std::string_view get_type_name() const override { return "mds_scrub"; } + + void print(std::ostream& out) const override { + out << "mds_scrub(" << get_opname(op) << " " + << ino << " " << frags << " " << tag; + if (is_force()) out << " force"; + if (is_recursive()) out << " recursive"; + if (is_repair()) out << " repair"; + out << ")"; + } + void encode_payload(uint64_t features) override { + using ceph::encode; + encode(op, payload); + encode(ino, payload); + encode(frags, payload); + encode(tag, payload); + encode(flags, payload); + } + void decode_payload() override { + using ceph::decode; + auto p = payload.cbegin(); + decode(op, p); + decode(ino, p); + decode(frags, p); + decode(tag, p); + decode(flags, p); + } + inodeno_t get_ino() const { + return ino; + } + const fragset_t& get_frags() const { + return frags; + } + const std::string& get_tag() const { + return tag; + } + int get_op() const { + return op; + } + bool is_internal_tag() const { + return flags & FLAG_INTERNAL_TAG; + } + bool is_force() const { + return flags & FLAG_FORCE; + } + bool is_recursive() const { + return flags & FLAG_RECURSIVE; + } + bool is_repair() const { + return flags & FLAG_REPAIR; + } + +protected: + static constexpr int HEAD_VERSION = 1; + static constexpr int COMPAT_VERSION = 1; + + MMDSScrub() : SafeMessage(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION) {} + MMDSScrub(int o, inodeno_t i, fragset_t&& _frags, std::string_view _tag, + bool internal_tag=false, bool force=false, + bool recursive=false, bool repair=false) + : SafeMessage(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION), + op(o), ino(i), frags(std::move(_frags)), tag(_tag) { + if (internal_tag) flags |= FLAG_INTERNAL_TAG; + if (force) flags |= FLAG_FORCE; + if (recursive) flags |= FLAG_RECURSIVE; + if (repair) flags |= FLAG_REPAIR; + } + + ~MMDSScrub() override {} +private: + template + friend boost::intrusive_ptr ceph::make_message(Args&&... args); + + static constexpr unsigned FLAG_INTERNAL_TAG = 1<<0; + static constexpr unsigned FLAG_FORCE = 1<<1; + static constexpr unsigned FLAG_RECURSIVE = 1<<2; + static constexpr unsigned FLAG_REPAIR = 1<<3; + + int op; + inodeno_t ino; + fragset_t frags; + std::string tag; + unsigned flags = 0; +}; +#endif // CEPH_MMDSSCRUB_H diff --git a/src/msg/Message.cc b/src/msg/Message.cc index 7f79696ca2dd..7b4408bf8ba6 100644 --- a/src/msg/Message.cc +++ b/src/msg/Message.cc @@ -145,6 +145,7 @@ #include "messages/MMDSOpenIno.h" #include "messages/MMDSOpenInoReply.h" #include "messages/MMDSSnapUpdate.h" +#include "messages/MMDSScrub.h" #include "messages/MDirUpdate.h" #include "messages/MDiscover.h" @@ -760,6 +761,10 @@ Message *decode_message(CephContext *cct, m = make_message(); break; + case MSG_MDS_SCRUB: + m = make_message(); + break; + case MSG_MDS_EXPORTDIRDISCOVER: m = make_message(); break; diff --git a/src/msg/Message.h b/src/msg/Message.h index 1c9cb94b1b50..0f1e19a0c00d 100644 --- a/src/msg/Message.h +++ b/src/msg/Message.h @@ -149,6 +149,7 @@ #define MSG_MDS_BEACON 100 // to monitor #define MSG_MDS_PEER_REQUEST 101 #define MSG_MDS_TABLE_REQUEST 102 +#define MSG_MDS_SCRUB 135 // 150 already in use (MSG_OSD_RECOVERY_RESERVE)