Skip to content

Commit 5f5bf82

Browse files
committed
mds: Mark the scrub passed if dirfrag is dirty
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 <[email protected]> Fixes: https://tracker.ceph.com/issues/65020
1 parent 983134d commit 5f5bf82

File tree

4 files changed

+44
-5
lines changed

4 files changed

+44
-5
lines changed

src/mds/CInode.cc

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5086,6 +5086,7 @@ void CInode::validate_disk_state(CInode::validated_data *results,
50865086
results->raw_stats.memory_value.rstat = in->get_inode()->rstat;
50875087
frag_info_t& dir_info = results->raw_stats.ondisk_value.dirstat;
50885088
nest_info_t& nest_info = results->raw_stats.ondisk_value.rstat;
5089+
bool has_local_dirty_dirfrag = false;
50895090

50905091
if (rval != 0) {
50915092
results->raw_stats.error_str << "Failed to read dirfrags off disk";
@@ -5103,6 +5104,8 @@ void CInode::validate_disk_state(CInode::validated_data *results,
51035104
ceph_assert(dir->get_version() > 0);
51045105
nest_info.add(dir->get_fnode()->accounted_rstat);
51055106
dir_info.add(dir->get_fnode()->accounted_fragstat);
5107+
if (dir->is_auth() && dir->is_dirty())
5108+
has_local_dirty_dirfrag = true;
51065109
}
51075110
}
51085111
nest_info.rsubdirs++; // it gets one to account for self
@@ -5128,7 +5131,17 @@ void CInode::validate_disk_state(CInode::validated_data *results,
51285131
"please rerun scrub when system is stable; "
51295132
"assuming passed for now;" << dendl;
51305133
results->raw_stats.passed = true;
5131-
}
5134+
} else if (has_local_dirty_dirfrag || in->has_dirty_remote_dirfrag_scrubbed()) {
5135+
MDCache *mdcache = in->mdcache; // for dout()
5136+
auto ino = [this]() { return in->ino(); }; // for dout()
5137+
dout(20) << (has_local_dirty_dirfrag ? "local": "remote") << " dirfrag : "
5138+
"raw stats most likely wont match since it's a directory "
5139+
"inode and a dirfrag is dirty; please rerun scrub when "
5140+
"system is stable; assuming passed for now;" << dendl;
5141+
results->raw_stats.passed = true;
5142+
if (in->has_dirty_remote_dirfrag_scrubbed())
5143+
in->clear_dirty_remote_dirfrag_scrubbed();
5144+
}
51325145
goto next;
51335146
}
51345147

src/mds/CInode.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,16 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
467467
return scrub_infop->queued_frags;
468468
}
469469

470+
bool has_dirty_remote_dirfrag_scrubbed() {
471+
return dirty_remote_dirfrag_scrubbed;
472+
}
473+
void mark_dirty_remote_dirfrag_scrubbed() {
474+
dirty_remote_dirfrag_scrubbed = true;
475+
}
476+
void clear_dirty_remote_dirfrag_scrubbed() {
477+
dirty_remote_dirfrag_scrubbed = false;
478+
}
479+
470480
bool is_multiversion() const {
471481
return snaprealm || // other snaprealms will link to me
472482
get_inode()->is_dir() || // links to me in other snaps
@@ -1255,6 +1265,7 @@ class CInode : public MDSCacheObject, public InodeStoreBase, public Counter<CIno
12551265

12561266
int stickydir_ref = 0;
12571267
std::unique_ptr<scrub_info_t> scrub_infop;
1268+
bool dirty_remote_dirfrag_scrubbed = false;
12581269
/** @} Scrubbing and fsck */
12591270
};
12601271

src/mds/ScrubStack.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,6 +1001,7 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
10011001
ceph_assert(diri);
10021002

10031003
std::vector<CDir*> dfs;
1004+
bool has_dirty_dirfrag = false;
10041005
MDSGatherBuilder gather(g_ceph_context);
10051006
frag_vec_t frags;
10061007
diri->dirfragtree.get_leaves(frags);
@@ -1024,6 +1025,10 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
10241025
dir->add_waiter(CDir::WAIT_UNFREEZE, gather.new_sub());
10251026
continue;
10261027
}
1028+
if (dir->is_dirty()) {
1029+
dout(10) << __func__ << " found dirty remote dirfrag " << *dir << dendl;
1030+
has_dirty_dirfrag = true;
1031+
}
10271032
dfs.push_back(dir);
10281033
}
10291034
}
@@ -1056,7 +1061,8 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
10561061
}
10571062

10581063
auto r = make_message<MMDSScrub>(MMDSScrub::OP_QUEUEDIR_ACK, m->get_ino(),
1059-
std::move(queued), m->get_tag());
1064+
std::move(queued), m->get_tag(),
1065+
inodeno_t(), false, false, false, false, has_dirty_dirfrag);
10601066
mdcache->mds->send_message_mds(r, from);
10611067
}
10621068
break;
@@ -1078,6 +1084,8 @@ void ScrubStack::handle_scrub(const cref_t<MMDSScrub> &m)
10781084

10791085
const auto& header = diri->get_scrub_header();
10801086
header->set_epoch_last_forwarded(scrub_epoch);
1087+
if (m->is_remote_dirfrag_dirty())
1088+
diri->mark_dirty_remote_dirfrag_scrubbed();
10811089
remove_from_waiting(diri);
10821090
}
10831091
}

src/messages/MMDSScrub.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class MMDSScrub : public MMDSOp {
5151
if (is_force()) out << " force";
5252
if (is_recursive()) out << " recursive";
5353
if (is_repair()) out << " repair";
54+
if (is_remote_dirfrag_dirty()) out << " dirty_remote_dirfrag";
5455
out << ")";
5556
}
5657
void encode_payload(uint64_t features) override {
@@ -99,23 +100,28 @@ class MMDSScrub : public MMDSOp {
99100
bool is_repair() const {
100101
return flags & FLAG_REPAIR;
101102
}
103+
bool is_remote_dirfrag_dirty() const {
104+
return flags & FLAG_DIRTY_REMOTE_DIRFRAG;
105+
}
102106

103107
protected:
104-
static constexpr int HEAD_VERSION = 1;
105-
static constexpr int COMPAT_VERSION = 1;
108+
static constexpr int HEAD_VERSION = 2;
109+
static constexpr int COMPAT_VERSION = 2;
106110

107111
MMDSScrub() : MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION) {}
108112
MMDSScrub(int o)
109113
: MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION), op(o) {}
110114
MMDSScrub(int o, inodeno_t i, fragset_t&& _frags, std::string_view _tag,
111115
inodeno_t _origin=inodeno_t(), bool internal_tag=false,
112-
bool force=false, bool recursive=false, bool repair=false)
116+
bool force=false, bool recursive=false, bool repair=false,
117+
bool remote_dirfrag_dirty=false)
113118
: MMDSOp(MSG_MDS_SCRUB, HEAD_VERSION, COMPAT_VERSION),
114119
op(o), ino(i), frags(std::move(_frags)), tag(_tag), origin(_origin) {
115120
if (internal_tag) flags |= FLAG_INTERNAL_TAG;
116121
if (force) flags |= FLAG_FORCE;
117122
if (recursive) flags |= FLAG_RECURSIVE;
118123
if (repair) flags |= FLAG_REPAIR;
124+
if (remote_dirfrag_dirty) flags |= FLAG_DIRTY_REMOTE_DIRFRAG;
119125
}
120126

121127
~MMDSScrub() override {}
@@ -129,6 +135,7 @@ class MMDSScrub : public MMDSOp {
129135
static constexpr unsigned FLAG_FORCE = 1<<1;
130136
static constexpr unsigned FLAG_RECURSIVE = 1<<2;
131137
static constexpr unsigned FLAG_REPAIR = 1<<3;
138+
static constexpr unsigned FLAG_DIRTY_REMOTE_DIRFRAG = 1<<4;
132139

133140
int32_t op;
134141
inodeno_t ino;

0 commit comments

Comments
 (0)