]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
reef: mds/MDBalancer: ignore queued callbacks if MDS is not active 54493/head
authorLeonid Usov <leonid.usov@ibm.com>
Wed, 25 Oct 2023 10:04:14 +0000 (13:04 +0300)
committerLeonid Usov <leonid.usov@ibm.com>
Tue, 14 Nov 2023 12:01:18 +0000 (14:01 +0200)
Signed-off-by: Leonid Usov <leonid.usov@ibm.com>
Fixes: https://tracker.ceph.com/issues/63479
Original-Issue: https://tracker.ceph.com/issues/63281
Original-PR: https://github.com/ceph/ceph/pull/54178
(cherry picked from commit 41406dc3ec5940ec8b9db8dcbf8e4640ce5c3eae)

src/mds/MDBalancer.cc

index baa43bb43412cee90c7a659d48ff3098f7d65405..1cf0d441b1cd4a4bff83a64673978b27c7f89335 100644 (file)
@@ -565,7 +565,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 +580,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 +604,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 +634,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 +643,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) {