]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mds: Mark the scrub passed if dirfrag is dirty
authorKotresh HR <khiremat@redhat.com>
Thu, 15 May 2025 16:15:29 +0000 (21:45 +0530)
committerKotresh HR <khiremat@redhat.com>
Wed, 9 Jul 2025 13:59:40 +0000 (13:59 +0000)
The in-memory and on-disk stats might not match on a
directory inode if any of the local or remote dirfrag
is dirty.  So don't fail the scrub and mark it as
passed if the local or remote dirfrag is dirty.

Signed-off-by: Kotresh HR <khiremat@redhat.com>
Fixes: https://tracker.ceph.com/issues/65020
src/mds/CInode.cc
src/mds/CInode.h
src/mds/ScrubStack.cc
src/messages/MMDSScrub.h

index e538a759f952901570e106ec28877fa25dda2bcf..c0209e9cab8a302330456c541c78f1abcb26e189 100644 (file)
@@ -5086,6 +5086,7 @@ next:
       results->raw_stats.memory_value.rstat = in->get_inode()->rstat;
       frag_info_t& dir_info = results->raw_stats.ondisk_value.dirstat;
       nest_info_t& nest_info = results->raw_stats.ondisk_value.rstat;
+      bool has_local_dirty_dirfrag = false;
 
       if (rval != 0) {
         results->raw_stats.error_str << "Failed to read dirfrags off disk";
@@ -5103,6 +5104,8 @@ next:
          ceph_assert(dir->get_version() > 0);
          nest_info.add(dir->get_fnode()->accounted_rstat);
          dir_info.add(dir->get_fnode()->accounted_fragstat);
+          if (dir->is_auth() && dir->is_dirty())
+              has_local_dirty_dirfrag = true;
         }
       }
       nest_info.rsubdirs++; // it gets one to account for self
@@ -5128,7 +5131,17 @@ next:
                       "please rerun scrub when system is stable; "
                       "assuming passed for now;" << dendl;
           results->raw_stats.passed = true;
-        }
+        } else if (has_local_dirty_dirfrag || in->has_dirty_remote_dirfrag_scrubbed()) {
+          MDCache *mdcache = in->mdcache; // for dout()
+          auto ino = [this]() { return in->ino(); }; // for dout()
+          dout(20) << (has_local_dirty_dirfrag ? "local": "remote") << " dirfrag : "
+                     "raw stats most likely wont match since it's a directory "
+                     "inode and a dirfrag is dirty; please rerun scrub when "
+                     "system is stable; assuming passed for now;" << dendl;
+          results->raw_stats.passed = true;
+         if (in->has_dirty_remote_dirfrag_scrubbed())
+           in->clear_dirty_remote_dirfrag_scrubbed();
+       }
        goto next;
       }
 
index bddba4c7f1990596376169cb980139e6d560fa00..1337cbfc2795381cd2335efa00a020d2ad2ae857 100644 (file)
@@ -467,6 +467,16 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
     return scrub_infop->queued_frags;
   }
 
+  bool has_dirty_remote_dirfrag_scrubbed() {
+    return dirty_remote_dirfrag_scrubbed;
+  }
+  void mark_dirty_remote_dirfrag_scrubbed() {
+    dirty_remote_dirfrag_scrubbed = true;
+  }
+  void clear_dirty_remote_dirfrag_scrubbed() {
+    dirty_remote_dirfrag_scrubbed = false;
+  }
+
   bool is_multiversion() const {
     return snaprealm ||  // other snaprealms will link to me
       get_inode()->is_dir() ||  // links to me in other snaps
@@ -1255,6 +1265,7 @@ private:
 
   int stickydir_ref = 0;
   std::unique_ptr<scrub_info_t> scrub_infop;
+  bool dirty_remote_dirfrag_scrubbed = false;
   /** @} Scrubbing and fsck */
 };
 
index 785bd3c34d80ab321fe1c2e22fef693f37aa02a5..9c401f14aab72b327df6c61e44565cf4d6bc1a6b 100644 (file)
@@ -1001,6 +1001,7 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
       ceph_assert(diri);
 
       std::vector<CDir*> dfs;
+      bool has_dirty_dirfrag = false;
       MDSGatherBuilder gather(g_ceph_context);
       frag_vec_t frags;
       diri->dirfragtree.get_leaves(frags);
@@ -1024,6 +1025,10 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
            dir->add_waiter(CDir::WAIT_UNFREEZE, gather.new_sub());
            continue;
          }
+          if (dir->is_dirty()) {
+            dout(10) << __func__ << " found dirty remote dirfrag " << *dir <<  dendl;
+            has_dirty_dirfrag = true;
+         }
          dfs.push_back(dir);
        }
       }
@@ -1056,7 +1061,8 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
       }
 
       auto r = make_message<MMDSScrub>(MMDSScrub::OP_QUEUEDIR_ACK, m->get_ino(),
-                                      std::move(queued), m->get_tag());
+                                      std::move(queued), m->get_tag(),
+                                      inodeno_t(), false, false, false, false, has_dirty_dirfrag);
       mdcache->mds->send_message_mds(r, from);
     }
     break;
@@ -1078,6 +1084,8 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
 
            const auto& header = diri->get_scrub_header();
            header->set_epoch_last_forwarded(scrub_epoch);
+           if (m->is_remote_dirfrag_dirty())
+             diri->mark_dirty_remote_dirfrag_scrubbed();
            remove_from_waiting(diri);
          }
        }
index 7714b377608ee73bb35883e3b4b371cb34d0d882..41fc8788aefd12bc2dabd8d1cdac3ab5b959aaff 100644 (file)
@@ -51,6 +51,7 @@ public:
     if (is_force()) out << " force";
     if (is_recursive()) out << " recursive";
     if (is_repair()) out << " repair";
+    if (is_remote_dirfrag_dirty()) out << " dirty_remote_dirfrag";
     out << ")";
   }
   void encode_payload(uint64_t features) override {
@@ -99,23 +100,28 @@ public:
   bool is_repair() const {
     return flags & FLAG_REPAIR;
   }
+  bool is_remote_dirfrag_dirty() const {
+    return flags & FLAG_DIRTY_REMOTE_DIRFRAG;
+  }
 
 protected:
-  static constexpr int HEAD_VERSION = 1;
-  static constexpr int COMPAT_VERSION = 1;
+  static constexpr int HEAD_VERSION = 2;
+  static constexpr int COMPAT_VERSION = 2;
 
   MMDSScrub() : MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION) {}
   MMDSScrub(int o)
     : MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION), op(o) {}
   MMDSScrub(int o, inodeno_t i, fragset_t&& _frags, std::string_view _tag,
            inodeno_t _origin=inodeno_t(), bool internal_tag=false,
-           bool force=false, bool recursive=false, bool repair=false)
+           bool force=false, bool recursive=false, bool repair=false,
+           bool remote_dirfrag_dirty=false)
     : MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION),
     op(o), ino(i), frags(std::move(_frags)), tag(_tag), origin(_origin) {
     if (internal_tag) flags |= FLAG_INTERNAL_TAG;
     if (force) flags |= FLAG_FORCE;
     if (recursive) flags |= FLAG_RECURSIVE;
     if (repair) flags |= FLAG_REPAIR;
+    if (remote_dirfrag_dirty) flags |= FLAG_DIRTY_REMOTE_DIRFRAG;
   }
 
   ~MMDSScrub() override {}
@@ -129,6 +135,7 @@ private:
   static constexpr unsigned FLAG_FORCE         = 1<<1;
   static constexpr unsigned FLAG_RECURSIVE     = 1<<2;
   static constexpr unsigned FLAG_REPAIR                = 1<<3;
+  static constexpr unsigned FLAG_DIRTY_REMOTE_DIRFRAG  = 1<<4;
 
   int32_t op;
   inodeno_t ino;