]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: remove unlinked metadata after replay
authorSage Weil <sage@newdream.net>
Tue, 16 Mar 2010 19:35:28 +0000 (12:35 -0700)
committerSage Weil <sage@newdream.net>
Tue, 16 Mar 2010 19:35:28 +0000 (12:35 -0700)
We can get unlink metadata after replay:

 create some auth metadata (possibly a whole tree)
 export to another mds
 other mds deletes it
 reimport tree, original link to root is broken by EImportStart
-> entire tree is unlinked

Find any unlinked metadata (that's not a base inode) and remove
it (recursively) after journal replay.

src/mds/MDCache.cc
src/mds/MDCache.h

index 224ff5a653ae559e10d618b42c3da139e4e99111..0e83314292b115ff376b08869b4b4162d5eedf4c 100644 (file)
@@ -2426,6 +2426,7 @@ void MDCache::maybe_resolve_finish()
     dout(10) << "maybe_resolve_finish got all resolves+resolve_acks, done." << dendl;
     disambiguate_imports();
     if (mds->is_resolve()) {
+      trim_unlinked_inodes();
       recalc_auth_bits();
       trim_non_auth(); 
       mds->resolve_done();
@@ -2631,6 +2632,49 @@ void MDCache::finish_ambiguous_import(dirfrag_t df)
   try_subtree_merge(dir);
 }
 
+void MDCache::remove_inode_recursive(CInode *in)
+{
+  dout(10) << "remove_inode_resurcive " << *in << dendl;
+  list<CDir*> ls;
+  in->get_dirfrags(ls);
+  for (list<CDir*>::iterator p = ls.begin(); p != ls.end(); ++p) {
+    CDir *subdir = *p;
+
+    dout(10) << " removing dirfrag " << subdir << dendl;
+    CDir::map_t::iterator p = subdir->items.begin();
+    while (p != subdir->items.end()) {
+      CDentry *dn = p->second;
+      ++p;
+      CDentry::linkage_t *dnl = dn->get_linkage();
+      if (dnl->is_primary()) {
+       CInode *in = dnl->get_inode();
+       subdir->unlink_inode(dn);
+       remove_inode_recursive(in);
+      }
+      subdir->remove_dentry(dn);
+    }
+    
+    if (subdir->is_subtree_root()) 
+      remove_subtree(subdir);
+    in->close_dirfrag(subdir->dirfrag().frag);
+  }
+  remove_inode(in);
+}
+
+void MDCache::trim_unlinked_inodes()
+{
+  dout(7) << "trim_unlinked_inodes" << dendl;
+
+  hash_map<vinodeno_t,CInode*>::iterator p = inode_map.begin();
+  while (p != inode_map.end()) {
+    CInode *in = p->second;
+    ++p;
+    if (in->get_parent_dn() == NULL && !in->is_base()) {
+      dout(7) << " trimming unlinked " << *in << dendl;
+      remove_inode_recursive(in);
+    }
+  }
+}
 
 /** recalc_auth_bits()
  * once subtree auth is disambiguated, we need to adjust all the 
index 536800fc51e76586178d0775584cf608311d19fc..babe436b673b5a1578f11f3a77a690eb7dc37ffb 100644 (file)
@@ -653,6 +653,8 @@ protected:
   void maybe_resolve_finish();
   void disambiguate_imports();
   void recalc_auth_bits();
+  void trim_unlinked_inodes();
+  void remove_inode_recursive(CInode *in);
 public:
   void add_rollback(metareqid_t reqid) {
     need_resolve_rollback.insert(reqid);