]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: track dirty dentries in separate list 19574/head
authorYan, Zheng <zyan@redhat.com>
Mon, 18 Dec 2017 08:48:51 +0000 (16:48 +0800)
committerYan, Zheng <zyan@redhat.com>
Thu, 21 Dec 2017 09:44:12 +0000 (17:44 +0800)
this should improve performance of large directory

Fixes: http://tracker.ceph.com/issues/19578
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/CDentry.cc
src/mds/CDentry.h
src/mds/CDir.cc
src/mds/CDir.h

index 7d24734931589cdfcf9e01f454adff85fa6927f4..6ab0de1593824fa949795fc8676fd3de45bccb01 100644 (file)
@@ -159,8 +159,9 @@ void CDentry::_mark_dirty(LogSegment *ls)
   // state+pin
   if (!state_test(STATE_DIRTY)) {
     state_set(STATE_DIRTY);
-    dir->inc_num_dirty();
     get(PIN_DIRTY);
+    dir->inc_num_dirty();
+    dir->dirty_dentries.push_back(&item_dir_dirty);
     assert(ls);
   }
   if (ls) 
@@ -189,15 +190,14 @@ void CDentry::mark_clean()
   // not always true for recalc_auth_bits during resolve finish
   //assert(dir->get_version() == 0 || version <= dir->get_version());  // hmm?
 
-  // state+pin
-  state_clear(STATE_DIRTY);
+  state_clear(STATE_DIRTY|STATE_NEW);
   dir->dec_num_dirty();
-  put(PIN_DIRTY);
-  
+
+  item_dir_dirty.remove_myself();
   item_dirty.remove_myself();
 
-  clear_new();
-}    
+  put(PIN_DIRTY);
+}
 
 void CDentry::mark_new() 
 {
index d5c628b699a0ccf3df2f174a3270963563b466d3..1ccc40a66b09d5ad2383db5d98a6099c75c87a93 100644 (file)
@@ -347,7 +347,7 @@ public:
   __u32 hash;
   snapid_t first, last;
 
-  elist<CDentry*>::item item_dirty;
+  elist<CDentry*>::item item_dirty, item_dir_dirty;
   elist<CDentry*>::item item_stray;
 
   // lock
index 1b8d72cc4c0a959e0cbebbf5f67ff12a7a0e0bbf..5f81bd8a4eaecf203a547463fa16ee11476ce682 100644 (file)
@@ -183,7 +183,9 @@ CDir::CDir(CInode *in, frag_t fg, MDCache *mdcache, bool auth) :
   cache(mdcache), inode(in), frag(fg),
   first(2),
   dirty_rstat_inodes(member_offset(CInode, dirty_rstat_item)),
-  projected_version(0),  item_dirty(this), item_new(this),
+  projected_version(0),
+  dirty_dentries(member_offset(CDentry, item_dir_dirty)),
+  item_dirty(this), item_new(this),
   num_head_items(0), num_head_null(0),
   num_snap_items(0), num_snap_null(0),
   num_dirty(0), committing_version(0), committed_version(0),
@@ -863,8 +865,10 @@ void CDir::steal_dentry(CDentry *dn)
     dn->dir->adjust_nested_auth_pins(-ap, -dap, NULL);
   }
 
-  if (dn->is_dirty()) 
+  if (dn->is_dirty()) {
+    dirty_dentries.push_back(&dn->item_dir_dirty);
     num_dirty++;
+  }
 
   dn->dir = this;
 }
@@ -2121,11 +2125,7 @@ void CDir::_omap_commit(int op_prio)
     stale_items.clear();
   }
 
-  for (map_t::iterator p = items.begin();
-      p != items.end(); ) {
-    CDentry *dn = p->second;
-    ++p;
-
+  auto write_one = [&](CDentry *dn) {
     string key;
     dn->key().encode(key);
 
@@ -2134,13 +2134,9 @@ void CDir::_omap_commit(int op_prio)
       dout(10) << " rm " << key << dendl;
       write_size += key.length();
       to_remove.insert(key);
-      continue;
+      return;
     }
 
-    if (!dn->is_dirty() &&
-       (!dn->state_test(CDentry::STATE_FRAGMENTING) || dn->get_linkage()->is_null()))
-      continue;  // skip clean dentries
-
     if (dn->get_linkage()->is_null()) {
       dout(10) << " rm " << dn->name << " " << *dn << dendl;
       write_size += key.length();
@@ -2174,6 +2170,22 @@ void CDir::_omap_commit(int op_prio)
       to_set.clear();
       to_remove.clear();
     }
+  };
+
+  if (state_test(CDir::STATE_FRAGMENTING)) {
+    for (auto p = items.begin(); p != items.end(); ) {
+      CDentry *dn = p->second;
+      ++p;
+      if (!dn->is_dirty() && dn->get_linkage()->is_null())
+       continue;
+      write_one(dn);
+    }
+  } else {
+    for (auto p = dirty_dentries.begin(); !p.end(); ) {
+      CDentry *dn = *p;
+      ++p;
+      write_one(dn);
+    }
   }
 
   ObjectOperation op;
@@ -2342,10 +2354,9 @@ void CDir::_committed(int r, version_t v)
     mark_clean();
 
   // dentries clean?
-  for (map_t::iterator it = items.begin();
-       it != items.end(); ) {
-    CDentry *dn = it->second;
-    ++it;
+  for (auto p = dirty_dentries.begin(); !p.end(); ) {
+    CDentry *dn = *p;
+    ++p;
     
     // inode?
     if (dn->linkage.is_primary()) {
@@ -2366,19 +2377,18 @@ void CDir::_committed(int r, version_t v)
 
     // dentry
     if (committed_version >= dn->get_version()) {
-      if (dn->is_dirty()) {
-       dout(15) << " dir " << committed_version << " >= dn " << dn->get_version() << " now clean " << *dn << dendl;
-       dn->mark_clean();
+      dout(15) << " dir " << committed_version << " >= dn " << dn->get_version() << " now clean " << *dn << dendl;
+      dn->mark_clean();
 
-       // drop clean null stray dentries immediately
-       if (stray && 
-           dn->get_num_ref() == 0 &&
-           !dn->is_projected() &&
-           dn->get_linkage()->is_null())
-         remove_dentry(dn);
-      } 
+      // drop clean null stray dentries immediately
+      if (stray &&
+         dn->get_num_ref() == 0 &&
+         !dn->is_projected() &&
+         dn->get_linkage()->is_null())
+       remove_dentry(dn);
     } else {
       dout(15) << " dir " << committed_version << " < dn " << dn->get_version() << " still dirty " << *dn << dendl;
+      assert(dn->is_dirty());
     }
   }
 
index b73dfeba069767492ad5b9b1dff9ffa290c3cc8b..7c0b7d445549442509183d99688bd494f5075dd5 100644 (file)
@@ -174,9 +174,9 @@ protected:
   std::list<fnode_t*> projected_fnode;
 
 public:
+  elist<CDentry*> dirty_dentries;
   elist<CDir*>::item item_dirty, item_new;
 
-
 public:
   version_t get_version() const { return fnode.version; }
   void set_version(version_t v) {