default: false
services:
- mds
- with_legacy: true
- name: mds_log_skip_corrupt_events
type: bool
level: dev
default: -1
services:
- mds
- with_legacy: true
- name: mds_log_events_per_segment
- type: int
+ type: uint
level: advanced
desc: maximum number of events in an MDS journal segment
default: 1024
min: 1
services:
- mds
- with_legacy: true
# segment size for mds log, default to default file_layout_t
- name: mds_log_segment_size
type: size
min: 8
services:
- mds
- with_legacy: true
- name: mds_log_warn_factor
type: float
level: advanced
// Detect MDS_HEALTH_TRIM condition
// Indicates MDS is not trimming promptly
{
- if (mds->mdlog->get_num_segments() > (size_t)(g_conf()->mds_log_max_segments * g_conf().get_val<double>("mds_log_warn_factor"))) {
+ const auto log_max_segments = mds->mdlog->get_max_segments();
+ const auto log_warn_factor = g_conf().get_val<double>("mds_log_warn_factor");
+ if (mds->mdlog->get_num_segments() > (size_t)(log_max_segments * log_warn_factor)) {
CachedStackStringStream css;
*css << "Behind on trimming (" << mds->mdlog->get_num_segments()
- << "/" << g_conf()->mds_log_max_segments << ")";
+ << "/" << log_max_segments << ")";
MDSHealthMetric m(MDS_HEALTH_TRIM, HEALTH_WARN, css->strv());
m.metadata["num_segments"] = stringify(mds->mdlog->get_num_segments());
- m.metadata["max_segments"] = stringify(g_conf()->mds_log_max_segments);
+ m.metadata["max_segments"] = stringify(log_max_segments);
health.metrics.push_back(m);
}
}
using namespace std;
+MDLog::MDLog(MDSRank* m)
+ :
+ mds(m),
+ replay_thread(this),
+ recovery_thread(this),
+ submit_thread(this)
+{
+ debug_subtrees = g_conf().get_val<bool>("mds_debug_subtrees");
+ events_per_segment = g_conf().get_val<uint64_t>("mds_log_events_per_segment");
+ pause = g_conf().get_val<bool>("mds_log_pause");
+ max_segments = g_conf().get_val<uint64_t>("mds_log_max_segments");
+ max_events = g_conf().get_val<int64_t>("mds_log_max_events");
+}
+
MDLog::~MDLog()
{
if (journaler) { delete journaler; journaler = 0; }
// disambiguate imports. Because the ESubtreeMap reflects the subtree
// state when all EImportFinish events are replayed.
} else if (ls->end/period != ls->offset/period ||
- ls->num_events >= g_conf()->mds_log_events_per_segment) {
+ ls->num_events >= events_per_segment) {
dout(10) << "submit_entry also starting new segment: last = "
<< ls->seq << "/" << ls->offset << ", event seq = " << event_seq << dendl;
_start_new_segment();
- } else if (g_conf()->mds_debug_subtrees &&
+ } else if (debug_subtrees &&
le->get_type() != EVENT_SUBTREEMAP_TEST) {
// debug: journal this every time to catch subtree replay bugs.
// use a different event id so it doesn't get interpreted as a
std::unique_lock locker{submit_mutex};
while (!mds->is_daemon_stopping()) {
- if (g_conf()->mds_log_pause) {
+ if (pause) {
submit_cond.wait(locker);
continue;
}
void MDLog::trim(int m)
{
- unsigned max_segments = g_conf()->mds_log_max_segments;
- int max_events = g_conf()->mds_log_max_events;
+ int max_ev = max_events;
if (m >= 0)
- max_events = m;
+ max_ev = m;
if (mds->mdcache->is_readonly()) {
dout(10) << "trim, ignoring read-only FS" << dendl;
return;
}
- // Clamp max_events to not be smaller than events per segment
- if (max_events > 0 && max_events <= g_conf()->mds_log_events_per_segment) {
- max_events = g_conf()->mds_log_events_per_segment + 1;
+ // Clamp max_ev to not be smaller than events per segment
+ if (max_ev > 0 && (uint64_t)max_ev <= events_per_segment) {
+ max_ev = events_per_segment + 1;
}
submit_mutex.lock();
// trim!
dout(10) << "trim "
<< segments.size() << " / " << max_segments << " segments, "
- << num_events << " / " << max_events << " events"
+ << num_events << " / " << max_ev << " events"
<< ", " << expiring_segments.size() << " (" << expiring_events << ") expiring"
<< ", " << expired_segments.size() << " (" << expired_events << ") expired"
<< dendl;
unsigned num_remaining_segments = (segments.size() - expired_segments.size() - expiring_segments.size());
if ((num_remaining_segments <= max_segments) &&
- (max_events < 0 || num_events - expiring_events - expired_events <= max_events))
+ (max_ev < 0 || num_events - expiring_events - expired_events <= max_ev))
break;
// Do not trim too many segments at once for peak workload. If mds keeps creating N segments each tick,
f->dump_unsigned("num_segments", get_num_segments());
f->close_section();
}
+
+
+void MDLog::handle_conf_change(const std::set<std::string>& changed, const MDSMap& mdsmap)
+{
+ if (changed.count("mds_debug_subtrees")) {
+ debug_subtrees = g_conf().get_val<bool>("mds_debug_subtrees");
+ }
+ if (changed.count("mds_log_events_per_segment")) {
+ events_per_segment = g_conf().get_val<uint64_t>("mds_log_events_per_segment");
+ }
+ if (changed.count("mds_log_max_events")) {
+ max_events = g_conf().get_val<int64_t>("mds_log_max_events");
+ }
+ if (changed.count("mds_log_max_segments")) {
+ max_segments = g_conf().get_val<uint64_t>("mds_log_max_segments");
+ }
+ if (changed.count("mds_log_pause")) {
+ pause = g_conf().get_val<bool>("mds_log_pause");
+ if (!pause) {
+ kick_submitter();
+ }
+ }
+}
#include "common/Thread.h"
#include "LogSegment.h"
+#include "MDSMap.h"
#include <list>
#include <map>
class MDLog {
public:
- explicit MDLog(MDSRank *m) : mds(m),
- replay_thread(this),
- recovery_thread(this),
- submit_thread(this) {}
+ MDLog(MDSRank *m);
~MDLog();
const std::set<LogSegment*> &get_expiring_segments() const
size_t get_num_events() const { return num_events; }
size_t get_num_segments() const { return segments.size(); }
+ auto get_debug_subtrees() const {
+ return events_per_segment;
+ }
+ auto get_max_segments() const {
+ return max_segments;
+ }
+
uint64_t get_read_pos() const;
uint64_t get_write_pos() const;
uint64_t get_safe_pos() const;
void standby_trim_segments();
+ void handle_conf_change(const std::set<std::string>& changed, const MDSMap& mds_map);
+
void dump_replay_status(Formatter *f) const;
MDSRank *mds;
// -- events --
LogEvent *cur_event = nullptr;
+
+ bool debug_subtrees;
+ uint64_t events_per_segment;
+ int64_t max_events;
+ uint64_t max_segments;
+ bool pause;
};
#endif
"mds_cache_trim_decay_rate",
"mds_cap_acquisition_throttle_retry_request_time",
"mds_cap_revoke_eviction_timeout",
+ "mds_debug_subtrees",
"mds_dir_max_entries",
"mds_dump_cache_threshold_file",
"mds_dump_cache_threshold_formatter",
"mds_inject_journal_corrupt_dentry_first",
"mds_inject_migrator_session_race",
"mds_inject_rename_corrupt_dentry_first",
+ "mds_log_events_per_segment",
+ "mds_log_max_events",
+ "mds_log_max_segments",
"mds_log_pause",
"mds_max_caps_per_client",
"mds_max_export_size",
dout(10) << "flushing conf change to components: " << changed << dendl;
- if (changed.count("mds_log_pause") && !g_conf()->mds_log_pause) {
- mdlog->kick_submitter();
- }
sessionmap.handle_conf_change(changed);
server->handle_conf_change(changed);
mdcache->handle_conf_change(changed, *mdsmap);
+ mdlog->handle_conf_change(changed, *mdsmap);
purge_queue.handle_conf_change(changed, *mdsmap);
}));
}
dout(0) << "journal subtrees: " << subtrees << dendl;
dout(0) << "journal ambig_subtrees: " << ambiguous_subtrees << dendl;
mds->mdcache->show_subtrees();
- ceph_assert(!g_conf()->mds_debug_subtrees || errors == 0);
+ ceph_assert(!mds->mdlog->get_debug_subtrees() || errors == 0);
}
return;
}