export_ephemeral_random_max = g_conf().get_val<double>("mds_export_ephemeral_random_max");
symlink_recovery = g_conf().get_val<bool>("mds_symlink_recovery");
+ kill_dirfrag_at = static_cast<enum dirfrag_killpoint>(g_conf().get_val<int64_t>("mds_kill_dirfrag_at"));
kill_shutdown_at = g_conf().get_val<uint64_t>("mds_kill_shutdown_at");
if (changed.count("mds_export_ephemeral_random_max")) {
export_ephemeral_random_max = g_conf().get_val<double>("mds_export_ephemeral_random_max");
}
+
+ if (changed.count("mds_kill_dirfrag_at")) {
+ kill_dirfrag_at = static_cast<enum dirfrag_killpoint>(g_conf().get_val<int64_t>("mds_kill_dirfrag_at"));
+ }
+
if (changed.count("mds_health_cache_threshold"))
cache_health_threshold = g_conf().get_val<double>("mds_health_cache_threshold");
if (changed.count("mds_cache_mid"))
void MDCache::fragment_freeze_dirs(const std::vector<CDir*>& dirs)
{
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_FREEZE);
bool any_subtree = false, any_non_subtree = false;
for (const auto& dir : dirs) {
dir->auth_pin(dir); // until we mark and complete them
dout(10) << "fragment_logged " << basedirfrag << " bits " << info.bits
<< " on " << *diri << dendl;
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_LOGGED);
+
mdr->mark_event("prepare logged");
mdr->apply(); // mark scatterlock
// tell peers
mds_rank_t diri_auth = (first->is_subtree_root() && !diri->is_auth()) ?
diri->authority().first : CDIR_AUTH_UNKNOWN;
+ dout(20) << " first dirfrag " << *first << " diri_auth=" << diri_auth << dendl;
for (const auto &p : first->get_replicas()) {
if (mds->mdsmap->get_state(p.first) < MDSMap::STATE_REJOIN ||
(mds->mdsmap->get_state(p.first) == MDSMap::STATE_REJOIN &&
* So we need to ensure replicas have received the notify, then unlock
* the dirfragtreelock.
*/
+ dout(20) << " ack wanted" << dendl;
notify->mark_ack_wanted();
info.notify_ack_waiting.insert(p.first);
}
}
mds->send_message_mds(notify, p.first);
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_STORED_POST_NOTIFY);
}
// journal commit
dir->unfreeze_dir();
}
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_STORED_POST_JOURNAL);
+
if (info.notify_ack_waiting.empty()) {
fragment_drop_locks(info);
} else {
void MDCache::_fragment_committed(dirfrag_t basedirfrag, const MDRequestRef& mdr)
{
dout(10) << "fragment_committed " << basedirfrag << dendl;
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_COMMITTED);
+
if (mdr)
mdr->mark_event("commit logged");
void MDCache::_fragment_old_purged(dirfrag_t basedirfrag, int bits, const MDRequestRef& mdr)
{
dout(10) << "fragment_old_purged " << basedirfrag << dendl;
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_OLD_PURGED);
+
if (mdr)
mdr->mark_event("old frags purged");
void MDCache::fragment_maybe_finish(const fragment_info_iterator& it)
{
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_MAYBE_FINISH);
+
if (!it->second.finishing)
return;
void MDCache::handle_fragment_notify_ack(const cref_t<MMDSFragmentNotifyAck> &ack)
{
dout(10) << "handle_fragment_notify_ack " << *ack << " from " << ack->get_source() << dendl;
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_HANDLE_NOTIFY_ACK);
mds_rank_t from = mds_rank_t(ack->get_source().num());
if (mds->get_state() < MDSMap::STATE_ACTIVE) {
void MDCache::handle_fragment_notify(const cref_t<MMDSFragmentNotify> ¬ify)
{
dout(10) << "handle_fragment_notify " << *notify << " from " << notify->get_source() << dendl;
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_HANDLE_NOTIFY);
mds_rank_t from = mds_rank_t(notify->get_source().num());
if (mds->get_state() < MDSMap::STATE_REJOIN) {
auto ack = make_message<MMDSFragmentNotifyAck>(notify->get_base_dirfrag(),
notify->get_bits(), notify->get_tid());
mds->send_message_mds(ack, from);
+ ceph_assert(kill_dirfrag_at != dirfrag_killpoint::FRAGMENT_HANDLE_NOTIFY_POSTACK);
}
}
StrayManager stray_manager;
private:
+ enum dirfrag_killpoint : std::int8_t {
+ FRAGMENT_FREEZE = 1,
+ FRAGMENT_HANDLE_NOTIFY,
+ FRAGMENT_HANDLE_NOTIFY_POSTACK,
+ FRAGMENT_STORED_POST_NOTIFY,
+ FRAGMENT_STORED_POST_JOURNAL,
+ FRAGMENT_HANDLE_NOTIFY_ACK,
+ FRAGMENT_MAYBE_FINISH,
+ FRAGMENT_LOGGED,
+ FRAGMENT_COMMITTED,
+ FRAGMENT_OLD_PURGED,
+ };
+
std::set<inodeno_t> replay_taken_inos; // the inos have been taken when replaying
// -- fragmenting --
// Stores the symlink target on the file object's head
bool symlink_recovery;
+ enum dirfrag_killpoint kill_dirfrag_at;
// File size recovery
RecoveryQueue recovery_queue;