]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: adjust export size after renaming directory into freezing subtree
authorYan, Zheng <zyan@redhat.com>
Thu, 9 Aug 2018 03:56:02 +0000 (11:56 +0800)
committerYan, Zheng <zyan@redhat.com>
Tue, 28 Aug 2018 23:12:42 +0000 (07:12 +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 ae43b20f7fa59b6785a4fd193af3f007296bbc59..1cefd1d6b471ae725ed7b09ce270d540390580ad 100644 (file)
@@ -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());
index ea5879a703da82db1542297870d0e55441c64f75..e92bea480398f149f63b95334c0c49d806785684 100644 (file)
@@ -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;
index d26627e8e0c2f7075e11f99b98c31145ae97eaeb..ffc6aeb4e2f8c54958ee4e7095be32adb1dd42da 100644 (file)
@@ -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<MDSInternalContextBase*>& ls) {
       finished_queue.splice( finished_queue.end(), ls );
       progress_thread.signal();
index 73db73f8688444112f6648567b1899fcfbdf71e6..a4a62ac6c6ca1ee8983ead7a1173e16233ee229e 100644 (file)
@@ -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<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 ce9dcb53a7e7caee9ca2d723d7c2ff69cec1e4e2..d718a7ac48fac450e60f201d61341c50b000e591 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 fd48bea1918839a484920ffcbd5d4e18e2951803..1708b41b4f9ba33a4cb414b92dafa2439ef78550 100644 (file)
@@ -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);