From 33910a7142328f4524de6fec2bb622c7f39fe8dd Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 9 Aug 2018 11:56:02 +0800 Subject: [PATCH] mds: adjust export size after renaming directory into freezing subtree restart exporting the subtree if rename makes export size too large Signed-off-by: "Yan, Zheng" --- src/mds/CDir.cc | 17 +++++++++ src/mds/CDir.h | 5 +-- src/mds/MDSRank.h | 4 ++ src/mds/Migrator.cc | 90 +++++++++++++++++++++++++++++++++++++++++++++ src/mds/Migrator.h | 5 +++ src/mds/Server.cc | 6 ++- 6 files changed, 123 insertions(+), 4 deletions(-) diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index ae43b20f7fa59..1cefd1d6b471a 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -2908,6 +2908,23 @@ bool CDir::is_frozen_tree() const } } +CDir *CDir::get_freezing_tree_root() +{ + if (num_freezing_trees == 0) + return nullptr; + CDir *dir = this; + while (true) { + if (dir->is_freezing_tree_root()) + return dir; + if (dir->is_subtree_root()) + return nullptr; + if (dir->inode->parent) + dir = dir->inode->parent->dir; + else + return nullptr; + } +} + CDir *CDir::get_frozen_tree_root() { assert(is_frozen()); diff --git a/src/mds/CDir.h b/src/mds/CDir.h index ea5879a703da8..e92bea480398f 100644 --- a/src/mds/CDir.h +++ b/src/mds/CDir.h @@ -723,11 +723,13 @@ public: bool is_freezing_tree() const; bool is_freezing_tree_root() const { return state & STATE_FREEZINGTREE; } bool is_freezing_dir() const { return state & STATE_FREEZINGDIR; } + CDir *get_freezing_tree_root(); bool is_frozen() const override { return is_frozen_dir() || is_frozen_tree(); } bool is_frozen_tree() const; bool is_frozen_tree_root() const { return state & STATE_FROZENTREE; } bool is_frozen_dir() const { return state & STATE_FROZENDIR; } + CDir *get_frozen_tree_root(); bool is_freezeable(bool freezing=false) const { // no nested auth pins. @@ -751,9 +753,6 @@ public: return true; } - CDir *get_frozen_tree_root(); - - ostream& print_db_line_prefix(ostream& out) override; void print(ostream& out) override; void dump(Formatter *f) const; diff --git a/src/mds/MDSRank.h b/src/mds/MDSRank.h index d26627e8e0c2f..ffc6aeb4e2f8c 100644 --- a/src/mds/MDSRank.h +++ b/src/mds/MDSRank.h @@ -297,6 +297,10 @@ class MDSRank { finished_queue.push_back(c); progress_thread.signal(); } + void queue_waiter_front(MDSInternalContextBase *c) { + finished_queue.push_back(c); + progress_thread.signal(); + } void queue_waiters(std::list& ls) { finished_queue.splice( finished_queue.end(), ls ); progress_thread.signal(); diff --git a/src/mds/Migrator.cc b/src/mds/Migrator.cc index 73db73f868844..a4a62ac6c6ca1 100644 --- a/src/mds/Migrator.cc +++ b/src/mds/Migrator.cc @@ -1126,6 +1126,7 @@ void Migrator::dispatch_export_dir(MDRequestRef& mdr, int count) it->second.last_cum_auth_pins_change = ceph_clock_now(); it->second.approx_size = results.front().second; + it->second.orig_size = it->second.approx_size; total_exporting_size += it->second.approx_size; // start the freeze, but hold it up with an auth_pin. @@ -1176,6 +1177,95 @@ void Migrator::dispatch_export_dir(MDRequestRef& mdr, int count) export_try_cancel(dir); } +void Migrator::restart_export_dir(CDir *dir, uint64_t tid) +{ + auto it = export_state.find(dir); + if (it == export_state.end() || it->second.tid != tid) + return; + if (it->second.state != EXPORT_DISCOVERING && + it->second.state != EXPORT_FREEZING) + return; + + dout(7) << "restart_export_dir " << *dir << dendl; + + std::shared_ptr parent; + parent.swap(it->second.parent); + if (!parent) + export_queue.emplace_front(dir->dirfrag(), it->second.peer); + + export_try_cancel(dir); + + if (parent) + child_export_finish(parent, true); +} + +class C_MDC_RestartExportDir : public MigratorContext { + CDir *dir; + uint64_t tid; +public: + C_MDC_RestartExportDir(Migrator *m, CDir *d, uint64_t t) : + MigratorContext(m), dir(d), tid(t) {} + void finish(int r) override { + mig->restart_export_dir(dir, tid); + } +}; + +bool Migrator::adjust_export_size(export_state_t &stat, CDir *dir) +{ + if (dir->state_test(CDir::STATE_EXPORTING) || + dir->is_freezing_dir() || dir->is_frozen_dir()) + return false; + + if (stat.approx_size >= max_export_size && + stat.approx_size >= stat.orig_size * 2) + return false; + + vector > results; + maybe_split_export(dir, max_export_size, true, results); + if (results.size() == 1 && results.front().first == dir) { + auto size = results.front().second; + stat.approx_size += size; + total_exporting_size += size; + return true; + } + + return false; +} + +void Migrator::adjust_export_after_rename(CInode* diri, CDir *olddir) +{ + CDir *newdir = diri->get_parent_dir(); + if (newdir == olddir) + return; + + CDir *freezing_dir = newdir->get_freezing_tree_root(); + CDir *old_freezing_dir = olddir->get_freezing_tree_root(); + if (!freezing_dir || freezing_dir == old_freezing_dir) + return; + + dout(7) << "adjust_export_after_rename " << *diri << dendl; + + auto &stat = export_state.at(freezing_dir); + assert(stat.state == EXPORT_DISCOVERING || + stat.state == EXPORT_FREEZING); + + if (g_conf->mds_thrash_exports) { + if (rand() % 3 == 0) { + mds->queue_waiter_front(new C_MDC_RestartExportDir(this, freezing_dir, stat.tid)); + return; + } + } + + vector ls; + diri->get_nested_dirfrags(ls); + for (auto d : ls) { + if (!adjust_export_size(stat, d)) { + mds->queue_waiter_front(new C_MDC_RestartExportDir(this, freezing_dir, stat.tid)); + return; + } + } +} + void Migrator::child_export_finish(std::shared_ptr& parent, bool success) { if (success) diff --git a/src/mds/Migrator.h b/src/mds/Migrator.h index ce9dcb53a7e7c..d718a7ac48fac 100644 --- a/src/mds/Migrator.h +++ b/src/mds/Migrator.h @@ -129,6 +129,7 @@ protected: map > peer_imported; MutationRef mut; size_t approx_size = 0; + size_t orig_size = 0; // for freeze tree deadlock detection utime_t last_cum_auth_pins_change; int last_cum_auth_pins = 0; @@ -315,7 +316,11 @@ public: void maybe_split_export(CDir* dir, uint64_t max_size, bool null_okay, vector >& results); + void restart_export_dir(CDir *dir, uint64_t tid); + bool adjust_export_size(export_state_t &stat, CDir *dir); + void adjust_export_after_rename(CInode* diri, CDir *olddir); void child_export_finish(std::shared_ptr& parent, bool success); + void get_export_lock_set(CDir *dir, set& locks); void get_export_client_set(CDir *dir, set &client_set); void get_export_client_set(CInode *in, set &client_set); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index fd48bea191883..1708b41b4f9ba 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -7529,9 +7529,13 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C mdr->apply(); // update subtree map? - if (destdnl->is_primary() && in->is_dir()) + if (destdnl->is_primary() && in->is_dir()) { mdcache->adjust_subtree_after_rename(in, srcdn->get_dir(), true); + if (destdn->is_auth()) + mdcache->migrator->adjust_export_after_rename(in, srcdn->get_dir()); + } + if (straydn && oldin->is_dir()) mdcache->adjust_subtree_after_rename(oldin, destdn->get_dir(), true); -- 2.39.5