ceph_assert(r == 0);
in->mdcache->logger->inc(l_mdc_uninline_succeeded);
+ auto h = in->get_scrub_header();
+ h->record_uninline_passed();
in->uninline_finished();
mdr->apply();
mds->server->respond_to_request(mdr, r);
<< " (" << cpp_strerror(r) << ") for " << *in << dendl;
in->mdcache->logger->inc(l_mdc_uninline_write_failed);
ceph_assert(in->get_scrub_header());
+ auto h = in->get_scrub_header();
+ h->record_uninline_failed();
std::string path;
in->make_path_string(path);
- in->get_scrub_header()->record_uninline_status(in->ino(), r, path);
+ h->record_uninline_status(in->ino(), r, path);
in->uninline_finished();
mds->server->respond_to_request(mdr, r);
return;
}
logger->inc(l_mdc_uninline_started);
+ auto h = in->get_scrub_header();
+ h->record_uninline_started();
in->uninline_initialize();
auto ino = [&]() { return in->ino(); };
return paths;
}
+ void record_uninline_started() {
+ uninline_started++;
+ }
+ void record_uninline_passed() {
+ uninline_passed++;
+ }
+ void record_uninline_failed() {
+ uninline_failed++;
+ }
+ uint64_t get_uninline_started() const {
+ return uninline_started;
+ }
+ uint64_t get_uninline_passed() const {
+ return uninline_passed;
+ }
+ uint64_t get_uninline_failed() const {
+ return uninline_failed;
+ }
+
protected:
const std::string tag;
bool is_tag_internal;
// errno -> [ino1, ino2, ino3, ...]
std::unordered_map<int, std::vector<_inodeno_t>> uninline_failed_info;
std::unordered_map<_inodeno_t, std::string> paths;
+
+ // scrub counters
+ uint64_t uninline_started = 0;
+ uint64_t uninline_passed = 0;
+ uint64_t uninline_failed = 0;
};
typedef std::shared_ptr<ScrubHeader> ScrubHeaderRef;
return 0;
}
+void ScrubStack::init_scrub_counters(std::string_view path, std::string_view tag)
+{
+ scrub_counters_t sc{real_clock::now(), std::string(path), 0, 0, 0};
+ for (auto& stat : mds_scrub_stats) {
+ stat.counters[std::string(tag)] = sc;
+ }
+}
+
int ScrubStack::enqueue(CInode *in, ScrubHeaderRef& header, bool top)
{
// abort in progress
//to make sure mdsdir is always on the top
top = false;
}
+
+ std::string path;
+ in->make_path_string(path);
+ init_scrub_counters(path, header->get_tag());
int r = _enqueue(in, header, top);
if (r < 0)
return r;
header->set_origin(m->get_origin());
scrubbing_map.emplace(header->get_tag(), header);
}
+
for (auto dir : dfs) {
queued.insert_raw(dir->get_frag());
_enqueue(dir, header, true);
std::set<std::string> scrubbing_tags;
std::unordered_map<std::string, unordered_map<int, std::vector<_inodeno_t>>> uninline_failed_meta_info;
std::unordered_map<_inodeno_t, std::string> paths;
+ std::unordered_map<std::string, std::vector<uint64_t>> counters;
for (auto it = scrubbing_map.begin(); it != scrubbing_map.end(); ) {
auto& header = it->second;
ufi.clear();
paths.merge(header->get_paths());
ceph_assert(header->get_paths().size() == 0);
+ std::vector<uint64_t> c{header->get_uninline_started(),
+ header->get_uninline_passed(),
+ header->get_uninline_failed()
+ };
+ counters[header->get_tag()] = c;
scrubbing_map.erase(it++);
} else {
++it;
std::move(scrubbing_tags),
std::move(uninline_failed_meta_info),
std::move(paths),
+ std::move(counters),
clear_stack);
mdcache->mds->send_message_mds(ack, 0);
stat.uninline_failed_meta_info[scrub_tag] = errno_map;
}
stat.paths.insert(m->get_paths().begin(), m->get_paths().end());;
+ for (auto& [tag, v] : m->get_counters()) {
+ stat.counters[tag].uninline_started = v[0];
+ stat.counters[tag].uninline_passed = v[1];
+ stat.counters[tag].uninline_failed = v[2];
+ }
}
}
}
}
ufmi.clear();
paths.clear();
+ // do not clear the counters map; we'll clear them later:
+ // - on user request or
+ // - after a grace period
}
}
ufmi[it->first] = header->get_uninline_failed_info();
mds_scrub_stats[0].paths.merge(header->get_paths());
move_uninline_failures_to_damage_table();
+
+ auto& c = mds_scrub_stats[0].counters;
+ auto& sc = c[header->get_tag()];
+ sc.uninline_started = header->get_uninline_started();
+ sc.uninline_passed = header->get_uninline_passed();
+ sc.uninline_failed = header->get_uninline_failed();
+
scrubbing_map.erase(it++);
} else {
++it;
#include "common/LogClient.h"
#include "common/Cond.h"
+#include "common/ceph_time.h"
#include "include/elist.h"
#include "messages/MMDSScrub.h"
#include "messages/MMDSScrubStats.h"
void move_uninline_failures_to_damage_table();
+ void init_scrub_counters(std::string_view path, std::string_view tag);
+
MDCache *mdcache;
protected:
// check if any mds is aborting scrub after mds.0 starts
bool scrub_any_peer_aborting = true;
+ struct scrub_counters_t {
+ ceph::real_clock::time_point start_time;
+ std::string origin_path;
+ uint64_t uninline_started;
+ uint64_t uninline_passed;
+ uint64_t uninline_failed;
+ };
struct scrub_stat_t {
unsigned epoch_acked = 0;
std::set<std::string> scrubbing_tags;
bool aborting = false;
std::unordered_map<std::string, std::unordered_map<int, std::vector<_inodeno_t>>> uninline_failed_meta_info;
std::unordered_map<_inodeno_t, std::string> paths;
+ std::unordered_map<std::string, scrub_counters_t> counters; // map(scrub_tag -> counters)
};
std::vector<scrub_stat_t> mds_scrub_stats;
const std::unordered_map<_inodeno_t, std::string>& get_paths() const {
return paths;
}
+ const std::unordered_map<std::string, std::vector<uint64_t>>& get_counters() const {
+ return counters;
+ }
void encode_payload(uint64_t features) override {
using ceph::encode;
encode(ino, payload);
encode(path, payload);
}
+ count = (int)counters.size();
+ encode(count, payload);
+ for (auto& [tag, v] : counters) {
+ encode(tag, payload);
+ uint64_t started = v[0];
+ uint64_t passed = v[1];
+ uint64_t failed = v[2];
+
+ encode(started, payload);
+ encode(passed, payload);
+ encode(failed, payload);
+ }
}
void decode_uninline_failed_info(ceph::bufferlist::const_iterator& p) {
using ceph::decode;
decode(path, p);
paths[ino] = path;
}
+ count = 0;
+ decode(count, p);
+ while (count--) {
+ std::string tag;
+ decode(tag, p);
+ uint64_t started = 0;
+ uint64_t passed = 0;
+ uint64_t failed = 0;
+
+ decode(started, p);
+ decode(passed, p);
+ decode(failed, p);
+ std::vector<uint64_t> c{started, passed, failed};
+ counters[tag] = c;
+ }
}
protected:
epoch(e), scrubbing_tags(tags), update_scrubbing(true), aborting(abrt) {}
MMDSScrubStats(unsigned e, const std::set<std::string>& tags,
std::unordered_map<std::string, std::unordered_map<int, std::vector<_inodeno_t>>>&& ufmi,
- std::unordered_map<_inodeno_t, std::string>&& paths_, bool abrt = false) :
+ std::unordered_map<_inodeno_t, std::string>&& paths_,
+ std::unordered_map<std::string, std::vector<uint64_t>>&& counters_,
+ bool abrt = false) :
MMDSOp(MSG_MDS_SCRUB_STATS, HEAD_VERSION, COMPAT_VERSION),
epoch(e), scrubbing_tags(tags), update_scrubbing(true), aborting(abrt),
- uninline_failed_meta_info(std::move(ufmi)), paths(std::move(paths_)) {}
+ uninline_failed_meta_info(std::move(ufmi)), paths(std::move(paths_)),
+ counters(std::move(counters_)) {}
~MMDSScrubStats() override {}
private:
// <tag, <error_code, [ino1, ino2, ...]>>
std::unordered_map<std::string, std::unordered_map<int, std::vector<_inodeno_t>>> uninline_failed_meta_info;
std::unordered_map<_inodeno_t, std::string> paths;
+ std::unordered_map<std::string, std::vector<uint64_t>> counters;
template<class T, typename... Args>
friend boost::intrusive_ptr<T> ceph::make_message(Args&&... args);