]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: adjust export size after renaming directory into freezing subtree 23088/head
authorYan, Zheng <zyan@redhat.com>
Thu, 9 Aug 2018 03:56:02 +0000 (11:56 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 17 Aug 2018 01:59:54 +0000 (09:59 +0800)
restart exporting the subtree if rename makes export size too large

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/CDir.cc
src/mds/CDir.h
src/mds/MDSRank.h
src/mds/Migrator.cc
src/mds/Migrator.h
src/mds/Server.cc

index b1ad9380619815a1cf628151952b6f83d2ccf32c..978f620e4c4e4c4dcdbb98363c33e76c1bbd118f 100644 (file)
@@ -2978,6 +2978,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());
index 6234327d0501510bca06e532f2b1e61fcb43ef71..6a6b416bee12061932a4cea8bf8075d079b0426c 100644 (file)
@@ -735,6 +735,7 @@ 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;
index b15ccb99ac05ab790c7d1a79f26a8e0f374b2fc7..4af71c0cc7999d8ce8d819459448cea979b40fc8 100644 (file)
@@ -302,6 +302,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(MDSInternalContextBase::vec& ls) {
       MDSInternalContextBase::vec v;
       v.swap(ls);
index 2c751f05ea666dfe5561078694507782684fc8f7..8f4453ed6245fa8d283c5c0a1a4ab01e5ba61c58 100644 (file)
@@ -1101,6 +1101,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.
@@ -1151,6 +1152,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<export_base_t> 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<pair<CDir*, size_t> > 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<CDir*> 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<export_base_t>& parent, bool success)
 {
   if (success)
index f3efebc163aa4154054024fa6a897ceb7cadace2..2065b9bd27df04e533c425fe06bf9856e3a5422e 100644 (file)
@@ -130,6 +130,7 @@ protected:
     map<inodeno_t,map<client_t,Capability::Import> > 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;
@@ -318,7 +319,11 @@ public:
   
   void maybe_split_export(CDir* dir, uint64_t max_size, bool null_okay,
                          vector<pair<CDir*, size_t> >& 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<export_base_t>& parent, bool success);
+
   void get_export_lock_set(CDir *dir, set<SimpleLock*>& locks);
   void get_export_client_set(CDir *dir, set<client_t> &client_set);
   void get_export_client_set(CInode *in, set<client_t> &client_set);
index f1077a78ace9bfc729e0617c2c84b8a2522c82e9..da38dc77ec19536c1f02f6d03cf688676236f537 100644 (file)
@@ -8019,9 +8019,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);