]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: avoid traversing all dirfrags when trying to get wrlocks 22884/head
authorXuehan Xu <xuxuehan@360.cn>
Fri, 8 Jun 2018 14:29:30 +0000 (22:29 +0800)
committerNathan Cutler <ncutler@suse.com>
Thu, 5 Jul 2018 19:50:11 +0000 (21:50 +0200)
Fixes: http://tracker.ceph.com/issues/24467
Signed-off-by: Xuehan Xu <xuxuehan@360.cn>
(cherry picked from commit da02fbcb0afd1b72d6c030f06613d8b18028a13c)

src/mds/CDir.cc
src/mds/CDir.h
src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDCache.cc
src/mds/Migrator.cc

index e6796ee37c8e7b815b975455b4bf62880fcac8df..bce25b1fd7c7e3ae56b3458e9f453aa963dfd296 100644 (file)
@@ -1017,10 +1017,7 @@ void CDir::split(int bits, list<CDir*>& subs, list<MDSInternalContextBase*>& wai
     CDir *f = new CDir(inode, *p, cache, is_auth());
     f->state_set(state & (MASK_STATE_FRAGMENT_KEPT | STATE_COMPLETE));
     f->get_replicas() = get_replicas();
-    f->dir_auth = dir_auth;
-    f->init_fragment_pins();
     f->set_version(get_version());
-
     f->pop_me = pop_me;
     f->pop_me.scale(fac);
 
@@ -1038,6 +1035,7 @@ void CDir::split(int bits, list<CDir*>& subs, list<MDSInternalContextBase*>& wai
 
     f->set_dir_auth(get_dir_auth());
     f->prepare_new_fragment(replay);
+    f->init_fragment_pins();
   }
   
   // repartition dentries
@@ -2657,7 +2655,9 @@ void CDir::set_dir_auth(const mds_authority_t &a)
   // new subtree root?
   if (!was_subtree && is_subtree_root()) {
     dout(10) << " new subtree root, adjusting auth_pins" << dendl;
-    
+
+    inode->num_subtree_roots++;   
+
     // adjust nested auth pins
     if (get_cum_auth_pins())
       inode->adjust_nested_auth_pins(-1, NULL);
@@ -2671,7 +2671,9 @@ void CDir::set_dir_auth(const mds_authority_t &a)
   } 
   if (was_subtree && !is_subtree_root()) {
     dout(10) << " old subtree root, adjusting auth_pins" << dendl;
-    
+
+    inode->num_subtree_roots--;
+  
     // adjust nested auth pins
     if (get_cum_auth_pins())
       inode->adjust_nested_auth_pins(1, NULL);
index 5739e907ba5d23b2b00df5498f8cc2b564b83164..4597b7ddb5016064cee5f7f5d89ca3104f3a82dc 100644 (file)
@@ -181,6 +181,15 @@ public:
   void assimilate_dirty_rstat_inodes();
   void assimilate_dirty_rstat_inodes_finish(MutationRef& mut, EMetaBlob *blob);
 
+  void mark_exporting() {
+    state_set(CDir::STATE_EXPORTING);
+    inode->num_exporting_dirs++;
+  }
+  void clear_exporting() {
+    state_clear(CDir::STATE_EXPORTING);
+    inode->num_exporting_dirs--;
+  }
+
 protected:
   version_t projected_version;
   mempool::mds_co::list<fnode_t> projected_fnode;
index 4b9379cc781d34bc52b1e79188b323f07056dc1a..3ca0f4f4fefb6aa9c5673f72b5f6c1f0990c98fe 100644 (file)
@@ -769,6 +769,9 @@ void CInode::close_dirfrag(frag_t fg)
     dir->state_clear(CDir::STATE_STICKY);
     dir->put(CDir::PIN_STICKY);
   }
+
+  if (dir->is_subtree_root())
+    num_subtree_roots--;
   
   // dump any remaining dentries, for debugging purposes
   for (const auto &p : dir->items)
@@ -787,21 +790,22 @@ void CInode::close_dirfrags()
 
 bool CInode::has_subtree_root_dirfrag(int auth)
 {
-  for (const auto &p : dirfrags) {
-    if (p.second->is_subtree_root() &&
-       (auth == -1 || p.second->dir_auth.first == auth))
+  if (num_subtree_roots > 0) {
+    if (auth == -1)
       return true;
+    for (const auto &p : dirfrags) {
+      if (p.second->is_subtree_root() &&
+         p.second->dir_auth.first == auth)
+       return true;
+    }
   }
   return false;
 }
 
 bool CInode::has_subtree_or_exporting_dirfrag()
 {
-  for (const auto &p : dirfrags) {
-    if (p.second->is_subtree_root() ||
-       p.second->state_test(CDir::STATE_EXPORTING))
-      return true;
-  }
+  if (num_subtree_roots > 0 || num_exporting_dirs > 0)
+    return true;
   return false;
 }
 
index ddf2c4bd46dbb71c7fbee668709533ad36ffd472..e0e37e9644c9f916813195f29aa7b8f3e31135c0 100644 (file)
@@ -538,6 +538,11 @@ public:
   // -- cache infrastructure --
 private:
   mempool::mds_co::compact_map<frag_t,CDir*> dirfrags; // cached dir fragments under this Inode
+
+  //for the purpose of quickly determining whether there's a subtree root or exporting dir
+  int num_subtree_roots = 0;
+  int num_exporting_dirs = 0;
+
   int stickydir_ref = 0;
   scrub_info_t *scrub_infop = nullptr;
 
@@ -712,6 +717,8 @@ public:
     assert(num_projected_xattrs == 0);
     assert(num_projected_srnodes == 0);
     assert(num_caps_wanted == 0);
+    assert(num_subtree_roots == 0);
+    assert(num_exporting_dirs == 0);
   }
   
 
index d82da8741d67829c861fc29ee3cd816ac89ba2dc..64b442b9d58b19c4a87bcbe9126f0d1a55f0aed6 100644 (file)
@@ -10997,9 +10997,6 @@ void MDCache::adjust_dir_fragments(CInode *diri,
       }
 
       show_subtrees(10);
-
-      // dir has no PIN_SUBTREE; CDir::purge_stolen() drops it.
-      dir->dir_auth = CDIR_AUTH_DEFAULT;
     }
     
     diri->close_dirfrag(dir->get_frag());
index b7e1b03ea885f09b070ce4ecf8ff727d63f7ae12..770451eab878c6abdcb6531e97b79b6d9e05727c 100644 (file)
@@ -370,7 +370,7 @@ void Migrator::export_try_cancel(CDir *dir, bool notify_peer)
 
     if (it->second.state == EXPORT_CANCELLED) {
       export_state.erase(it);
-      dir->state_clear(CDir::STATE_EXPORTING);
+      dir->clear_exporting();
       // send pending import_maps?
       cache->maybe_send_pending_resolves();
     }
@@ -395,7 +395,7 @@ void Migrator::export_try_cancel(CDir *dir, bool notify_peer)
 void Migrator::export_cancel_finish(CDir *dir)
 {
   assert(dir->state_test(CDir::STATE_EXPORTING));
-  dir->state_clear(CDir::STATE_EXPORTING);
+  dir->clear_exporting();
 
   // pinned by Migrator::export_notify_abort()
   dir->auth_unpin(this);
@@ -860,7 +860,7 @@ void Migrator::export_dir(CDir *dir, mds_rank_t dest)
   mds->hit_export_target(ceph_clock_now(), dest, -1);
 
   dir->auth_pin(this);
-  dir->state_set(CDir::STATE_EXPORTING);
+  dir->mark_exporting();
 
   MDRequestRef mdr = mds->mdcache->request_start_internal(CEPH_MDS_OP_EXPORTDIR);
   mdr->more()->export_dir = dir;
@@ -1074,7 +1074,7 @@ void Migrator::export_frozen(CDir *dir, uint64_t tid)
     mds->send_message_mds(new MExportDirCancel(dir->dirfrag(), it->second.tid), it->second.peer);
     export_state.erase(it);
 
-    dir->state_clear(CDir::STATE_EXPORTING);
+    dir->clear_exporting();
     cache->maybe_send_pending_resolves();
     return;
   }
@@ -2071,7 +2071,7 @@ void Migrator::export_finish(CDir *dir)
   MutationRef mut = it->second.mut;
   // remove from exporting list, clean up state
   export_state.erase(it);
-  dir->state_clear(CDir::STATE_EXPORTING);
+  dir->clear_exporting();
 
   cache->show_subtrees();
   audit();