]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: adjust export size after renaming directory into freezing subtree 23952/head
authorYan, Zheng <zyan@redhat.com>
Thu, 9 Aug 2018 03:56:02 +0000 (11:56 +0800)
committerYan, Zheng <zyan@redhat.com>
Thu, 6 Sep 2018 06:57:33 +0000 (14:57 +0800)
restart exporting the subtree if rename makes export size too large

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
(cherry picked from commit a7076fae36fe085faed2f4a7eeade7cfcd1a2f2e)

 Conflicts:
src/mds/MDSRank.h

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 3487b10cc98840a81bbbfb28dbf3edc1ca3a095a..49b5cef52dfdb09303409654dc3190e77645c93c 100644 (file)
@@ -2964,6 +2964,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 4597b7ddb5016064cee5f7f5d89ca3104f3a82dc..42c7c89aa1031b46b5e337302aaccc2288f5f04f 100644 (file)
@@ -743,6 +743,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 96e0b1c8bec451351bbfc4bd515ba5a68b1b5c04..5c64ad7552d4327889a8a663174ac3457c2a25d1 100644 (file)
@@ -300,10 +300,18 @@ class MDSRank {
       finished_queue.push_back(c);
       progress_thread.signal();
     }
+    void queue_waiter_front(MDSInternalContextBase *c) {
+      finished_queue.push_front(c);
+      progress_thread.signal();
+    }
     void queue_waiters(std::list<MDSInternalContextBase*>& ls) {
       finished_queue.splice( finished_queue.end(), ls );
       progress_thread.signal();
     }
+    void queue_waiters_front(std::list<MDSInternalContextBase*>& ls) {
+      finished_queue.splice(finished_queue.begin(), ls);
+      progress_thread.signal();
+    }
 
     MDSRank(
         mds_rank_t whoami_,
index 0a6f06e19b601e4241e206eb85c54e5ce2a2da1c..8dbcc6bdcbc9499d9b0b8229e7ba8923c616228a 100644 (file)
@@ -1119,6 +1119,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.
@@ -1169,6 +1170,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 caee7f074c0aec084b7f746398e22629575fe0ca..99c0ae2740933c3cf606f98c75c50682caf1a141 100644 (file)
@@ -129,6 +129,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;
@@ -315,7 +316,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 ceabf8f9b44e56896e05107474d41b5313b38d81..afec5edce4d7254a21d310a03b07687d3a6993c1 100644 (file)
@@ -7960,9 +7960,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);