]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: don't finish dentry waiters when splitting/merging dirfrags
authorYan, Zheng <zyan@redhat.com>
Fri, 28 Apr 2017 10:08:51 +0000 (18:08 +0800)
committerYan, Zheng <zyan@redhat.com>
Thu, 11 May 2017 06:13:24 +0000 (14:13 +0800)
move dentry waiters to the new dirfrags instead

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

index 3bc939b43cf2ef2948b65dabfc9b1c506ebdc914..86ba961be1bbf03324d9e5f56d1253817fe589b4 100644 (file)
@@ -869,12 +869,19 @@ void CDir::steal_dentry(CDentry *dn)
   dn->dir = this;
 }
 
-void CDir::prepare_old_fragment(bool replay)
+void CDir::prepare_old_fragment(map<string_snap_t, std::list<MDSInternalContextBase*> >& dentry_waiters, bool replay)
 {
   // auth_pin old fragment for duration so that any auth_pinning
   // during the dentry migration doesn't trigger side effects
   if (!replay && is_auth())
     auth_pin(this);
+
+  if (!waiting_on_dentry.empty()) {
+    for (auto p = waiting_on_dentry.begin(); p != waiting_on_dentry.end(); ++p)
+      dentry_waiters[p->first].swap(p->second);
+    waiting_on_dentry.clear();
+    put(PIN_DNWAITER);
+  }
 }
 
 void CDir::prepare_new_fragment(bool replay)
@@ -960,7 +967,8 @@ void CDir::split(int bits, list<CDir*>& subs, list<MDSInternalContextBase*>& wai
     fragstatdiff.add_delta(fnode.accounted_fragstat, fnode.fragstat);
   dout(10) << " rstatdiff " << rstatdiff << " fragstatdiff " << fragstatdiff << dendl;
 
-  prepare_old_fragment(replay);
+  map<string_snap_t, std::list<MDSInternalContextBase*> > dentry_waiters;
+  prepare_old_fragment(dentry_waiters, replay);
 
   // create subfrag dirs
   int n = 0;
@@ -1004,6 +1012,16 @@ void CDir::split(int bits, list<CDir*>& subs, list<MDSInternalContextBase*>& wai
     f->steal_dentry(dn);
   }
 
+  for (auto& p : dentry_waiters) {
+    frag_t subfrag = inode->pick_dirfrag(p.first.name);
+    int n = (subfrag.value() & (subfrag.mask() ^ frag.mask())) >> subfrag.mask_shift();
+    CDir *f = subfrags[n];
+
+    if (f->waiting_on_dentry.empty())
+      f->get(PIN_DNWAITER);
+    f->waiting_on_dentry[p.first].swap(p.second);
+  }
+
   // FIXME: handle dirty old rstat
 
   // fix up new frag fragstats
@@ -1048,6 +1066,8 @@ void CDir::merge(list<CDir*>& subs, list<MDSInternalContextBase*>& waiters, bool
   version_t rstat_version = inode->get_projected_inode()->rstat.version;
   version_t dirstat_version = inode->get_projected_inode()->dirstat.version;
 
+  map<string_snap_t, std::list<MDSInternalContextBase*> > dentry_waiters;
+
   for (auto dir : subs) {
     dout(10) << " subfrag " << dir->get_frag() << " " << *dir << dendl;
     assert(!dir->is_auth() || dir->is_complete() || replay);
@@ -1058,7 +1078,7 @@ void CDir::merge(list<CDir*>& subs, list<MDSInternalContextBase*>& waiters, bool
       fragstatdiff.add_delta(dir->fnode.accounted_fragstat, dir->fnode.fragstat,
                             &touched_mtime, &touched_chattr);
 
-    dir->prepare_old_fragment(replay);
+    dir->prepare_old_fragment(dentry_waiters, replay);
 
     // steal dentries
     while (!dir->items.empty()) 
@@ -1085,6 +1105,13 @@ void CDir::merge(list<CDir*>& subs, list<MDSInternalContextBase*>& waiters, bool
     inode->close_dirfrag(dir->get_frag());
   }
 
+  if (!dentry_waiters.empty()) {
+    get(PIN_DNWAITER);
+    for (auto& p : dentry_waiters) {
+      waiting_on_dentry[p.first].swap(p.second);
+    }
+  }
+
   if (is_auth() && !replay)
     mark_complete();
 
index 4c90292df33b7fe99eb6219969a5ff7ad9ebf9f9..5b0079a74de4dda79950314ecd01afba8556ac6f 100644 (file)
@@ -483,7 +483,7 @@ public:
 
 private:
   void prepare_new_fragment(bool replay);
-  void prepare_old_fragment(bool replay);
+  void prepare_old_fragment(map<string_snap_t, std::list<MDSInternalContextBase*> >& dentry_waiters, bool replay);
   void steal_dentry(CDentry *dn);  // from another dir.  used by merge/split.
   void finish_old_fragment(list<MDSInternalContextBase*>& waiters, bool replay);
   void init_fragment_pins();
index a407a8769d9b58fbb6ea71b413a3f341c1b819c0..9a0208014bec8e181db632e1846a640772fa2bb5 100644 (file)
@@ -10101,10 +10101,11 @@ void MDCache::handle_discover_reply(MDiscoverReply *m)
     if (who >= 0)
       dout(7) << " dir_auth_hint is " << m->get_dir_auth_hint() << dendl;
 
-    frag_t fg = m->get_base_dir_frag();
-    CDir *dir = cur->get_dirfrag(fg);
 
     if (m->get_wanted_base_dir()) {
+      frag_t fg = m->get_base_dir_frag();
+      CDir *dir = cur->get_dirfrag(fg);
+
       if (cur->is_waiting_for_dir(fg)) {
        if (cur->is_auth())
          cur->take_waiting(CInode::WAIT_DIR, finished);
@@ -10118,6 +10119,8 @@ void MDCache::handle_discover_reply(MDiscoverReply *m)
 
     // try again?
     if (m->get_error_dentry().length()) {
+      frag_t fg = cur->pick_dirfrag(m->get_error_dentry());
+      CDir *dir = cur->get_dirfrag(fg);
       // wanted a dentry
       if (dir && dir->is_waiting_for_dentry(m->get_error_dentry(), m->get_wanted_snapid())) {
        if (dir->is_auth() || dir->lookup(m->get_error_dentry())) {