From: Sage Weil Date: Thu, 17 Mar 2011 22:09:15 +0000 (-0700) Subject: mds: close exported dirfrag X-Git-Tag: v0.27~178 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6fcecbc129da19c4fadf67fb6ad25f7af479d2d8;p=ceph.git mds: close exported dirfrag 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 --- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 0bae0eb8758..72182468d0d 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -1060,6 +1060,8 @@ void MDCache::adjust_bounded_subtree_auth(CDir *dir, vector& bound_df void MDCache::map_dirfrag_set(list& dfs, set& result) { + dout(10) << "map_dirfrag_set " << dfs << dendl; + // group by inode map ino_fragset; for (list::iterator p = dfs.begin(); p != dfs.end(); ++p) @@ -1070,7 +1072,8 @@ void MDCache::map_dirfrag_set(list& dfs, set& result) p != ino_fragset.end(); ++p) { CInode *in = get_inode(p->first); - if (!in) continue; + if (!in) + continue; list fglist; for (set::iterator q = p->second.begin(); q != p->second.end(); ++q) @@ -1081,7 +1084,8 @@ void MDCache::map_dirfrag_set(list& dfs, set& result) for (list::iterator q = fglist.begin(); q != fglist.end(); ++q) { CDir *dir = in->get_dirfrag(*q); - if (dir) result.insert(dir); + if (dir) + result.insert(dir); } } } diff --git a/src/mds/journal.cc b/src/mds/journal.cc index 99fafdc13c6..d9c203c0af6 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -1061,8 +1061,42 @@ void EExport::replay(MDS *mds) // adjust auth away mds->mdcache->adjust_bounded_subtree_auth(dir, realbounds, pair(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 bounds; + mds->mdcache->get_subtree_bounds(dir, bounds); + for (set::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()); + } + } }