diff options
Diffstat (limited to 'src/mds/MDBalancer.cc')
-rw-r--r-- | src/mds/MDBalancer.cc | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/src/mds/MDBalancer.cc b/src/mds/MDBalancer.cc index baa43bb43..da785179e 100644 --- a/src/mds/MDBalancer.cc +++ b/src/mds/MDBalancer.cc @@ -230,6 +230,7 @@ void MDBalancer::handle_export_pins(void) void MDBalancer::tick() { static int num_bal_times = g_conf()->mds_bal_max; + bool balance_automate = mds->mdsmap->allows_balance_automate(); auto bal_interval = g_conf().get_val<int64_t>("mds_bal_interval"); auto bal_max_until = g_conf().get_val<int64_t>("mds_bal_max_until"); time now = clock::now(); @@ -248,7 +249,8 @@ void MDBalancer::tick() // We can use duration_cast below, although the result is an int, // because the values from g_conf are also integers. // balance? - if (mds->get_nodeid() == 0 + if (balance_automate + && mds->get_nodeid() == 0 && mds->is_active() && bal_interval > 0 && chrono::duration_cast<chrono::seconds>(now - last_heartbeat).count() >= bal_interval @@ -565,7 +567,8 @@ double MDBalancer::try_match(balance_state_t& state, mds_rank_t ex, double& maxe void MDBalancer::queue_split(const CDir *dir, bool fast) { - dout(10) << __func__ << " enqueuing " << *dir + constexpr const auto &_func_ = __func__; + dout(10) << _func_ << " enqueuing " << *dir << " (fast=" << fast << ")" << dendl; const dirfrag_t df = dir->dirfrag(); @@ -579,6 +582,16 @@ void MDBalancer::queue_split(const CDir *dir, bool fast) return; } + if (mds->is_stopping()) { + // not a good time. This could have been (!mds->is_active()) + // or at least (mds->is_stopping() || mds->is_stopped()), but + // is_stopped() is never true because an MDS respawns as soon as it's removed from the map; + // the narrow is_stopping check is to avoid potential regressions + // due to unknown coupling with other parts of the MDS (especially multiple ranks). + dout(5) << "ignoring the " << _func_ << " callback because the MDS state is '" << ceph_mds_state_name(mds->get_state()) << "'" << dendl; + return; + } + auto mdcache = mds->mdcache; CDir *dir = mdcache->get_dirfrag(df); @@ -593,7 +606,7 @@ void MDBalancer::queue_split(const CDir *dir, bool fast) // Pass on to MDCache: note that the split might still not // happen if the checks in MDCache::can_fragment fail. - dout(10) << __func__ << " splitting " << *dir << dendl; + dout(10) << _func_ << " splitting " << *dir << dendl; int bits = g_conf()->mds_bal_split_bits; if (dir->inode->is_ephemeral_dist()) { unsigned min_frag_bits = mdcache->get_ephemeral_dist_frag_bits(); @@ -623,6 +636,7 @@ void MDBalancer::queue_split(const CDir *dir, bool fast) void MDBalancer::queue_merge(CDir *dir) { const auto frag = dir->dirfrag(); + constexpr const auto &_func_ = __func__; auto callback = [this, frag](int r) { ceph_assert(frag.frag != frag_t()); @@ -631,6 +645,16 @@ void MDBalancer::queue_merge(CDir *dir) // starting one), and this context is the only one that erases it. merge_pending.erase(frag); + if (mds->is_stopping()) { + // not a good time. This could have been (!mds->is_active()) + // or at least (mds->is_stopping() || mds->is_stopped()), but + // is_stopped() is never true because an MDS respawns as soon as it's removed from the map; + // the narrow is_stopping check is to avoid potential regressions + // due to unknown coupling with other parts of the MDS (especially multiple ranks). + dout(5) << "ignoring the " << _func_ << " callback because the MDS state is '" << ceph_mds_state_name(mds->get_state()) << "'" << dendl; + return; + } + auto mdcache = mds->mdcache; CDir *dir = mdcache->get_dirfrag(frag); if (!dir) { @@ -662,7 +686,12 @@ void MDBalancer::queue_merge(CDir *dir) } bool all = true; for (auto& sib : sibs) { - if (!sib->is_auth() || !sib->should_merge()) { + auto is_auth = sib->is_auth(); + auto should_merge = sib->should_merge(); + + dout(20) << ": sib=" << *sib << ", is_auth=" << is_auth << ", should_merge=" + << should_merge << dendl; + if (!is_auth || !should_merge) { all = false; break; } |