From: Sage Weil Date: Tue, 16 Mar 2010 19:35:28 +0000 (-0700) Subject: mds: remove unlinked metadata after replay X-Git-Tag: v0.20~276 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=389e313d89d38a276b33b905c9c841d122fce87f;p=ceph.git mds: remove unlinked metadata after replay 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. --- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 224ff5a653ae..0e83314292b1 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -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 ls; + in->get_dirfrags(ls); + for (list::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::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 diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index 536800fc51e7..babe436b673b 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -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);