]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: close exported dirfrag
authorSage Weil <sage@newdream.net>
Thu, 17 Mar 2011 22:09:15 +0000 (15:09 -0700)
committerSage Weil <sage.weil@dreamhost.com>
Fri, 1 Apr 2011 21:34:32 +0000 (14:34 -0700)
We have to keep export bounds open for auth subtrees.  After we export a
subtree, though, there are two opportunities to drop empty dirfrags from
our cache:

 - The children of the exported subtree may now be trimmable, if they are
   also non-auth and empty.
 - The exported subtree may be trimmable if it is empty and the parent is
   also non-auth.  This may be true for ancestors further up the hierarchy
   as well.

This helps ensure that when we get to rejoin, the only non-auth subtrees we
have are there because they are non-empty or because they are bounds on our
own subtrees.

Signed-off-by: Sage Weil <sage@newdream.net>
src/mds/MDCache.cc
src/mds/journal.cc

index 0bae0eb87582e5641b4098e80b7eb545188ca06a..72182468d0d58ea09b72d48c3d1f696c94512672 100644 (file)
@@ -1060,6 +1060,8 @@ void MDCache::adjust_bounded_subtree_auth(CDir *dir, vector<dirfrag_t>& bound_df
 
 void MDCache::map_dirfrag_set(list<dirfrag_t>& dfs, set<CDir*>& result)
 {
+  dout(10) << "map_dirfrag_set " << dfs << dendl;
+
   // group by inode
   map<inodeno_t, fragset_t> ino_fragset;
   for (list<dirfrag_t>::iterator p = dfs.begin(); p != dfs.end(); ++p)
@@ -1070,7 +1072,8 @@ void MDCache::map_dirfrag_set(list<dirfrag_t>& dfs, set<CDir*>& result)
        p != ino_fragset.end();
        ++p) {
     CInode *in = get_inode(p->first);
-    if (!in) continue;
+    if (!in)
+      continue;
 
     list<frag_t> fglist;
     for (set<frag_t>::iterator q = p->second.begin(); q != p->second.end(); ++q)
@@ -1081,7 +1084,8 @@ void MDCache::map_dirfrag_set(list<dirfrag_t>& dfs, set<CDir*>& result)
 
     for (list<frag_t>::iterator q = fglist.begin(); q != fglist.end(); ++q) {
       CDir *dir = in->get_dirfrag(*q);
-      if (dir) result.insert(dir);
+      if (dir)
+       result.insert(dir);
     }
   }
 }
index 99fafdc13c63ff804dd05093aee768265f3a20ed..d9c203c0af6c6e97ebb736ef2b08234c683791dd 100644 (file)
@@ -1061,8 +1061,42 @@ void EExport::replay(MDS *mds)
 
   // adjust auth away
   mds->mdcache->adjust_bounded_subtree_auth(dir, realbounds, pair<int,int>(CDIR_AUTH_UNKNOWN, CDIR_AUTH_UNKNOWN));
-  mds->mdcache->trim_non_auth_subtree(dir);
-  mds->mdcache->try_subtree_merge(dir);
+
+  // can we now trim child subtrees?
+  set<CDir*> bounds;
+  mds->mdcache->get_subtree_bounds(dir, bounds);
+  for (set<CDir*>::iterator p = bounds.begin(); p != bounds.end(); p++) {
+    CDir *bd = *p;
+    if (bd->get_dir_auth().first != mds->whoami &&  // we are not auth
+       bd->get_num_any() == 0) {                   // and empty
+      CInode *bi = bd->get_inode();
+      dout(10) << "EExport.replay " << base << " closing empty non-auth child subtree " << *bd << dendl;
+      mds->mdcache->remove_subtree(bd);
+      bd->mark_clean();
+      bi->close_dirfrag(bd->get_frag());
+    }
+  }
+
+  if (mds->mdcache->trim_non_auth_subtree(dir)) {
+    // keep
+    mds->mdcache->try_subtree_merge(dir);
+  } else {
+    // can we trim this subtree (and possibly our ancestors) too?
+    CInode *diri = dir->get_inode();
+    while (!diri->is_base()) {
+      dir = mds->mdcache->get_subtree_root(diri->get_parent_dir());
+      if (dir->get_dir_auth().first == mds->whoami)
+       break;  // we are auth, keep.
+      dout(10) << "EExport.replay " << base << " parent subtree also non-auth: " << *dir << dendl;
+      if (mds->mdcache->trim_non_auth_subtree(dir))
+       break;
+      dout(10) << "EExport.replay " << base << " closing empty parent subtree " << *dir << dendl;
+      mds->mdcache->remove_subtree(dir);
+      dir->mark_clean();
+      diri = dir->get_inode();
+      diri->close_dirfrag(dir->get_frag());
+    }
+  }
 }