* merge with parent and/or child subtrees, if is it appropriate.
* merge can ONLY happen if both parent and child have unambiguous auth.
*/
-void MDCache::adjust_subtree_auth(CDir *dir, mds_authority_t auth, bool do_eval)
+void MDCache::adjust_subtree_auth(CDir *dir, mds_authority_t auth)
{
dout(7) << "adjust_subtree_auth " << dir->get_dir_auth() << " -> " << auth
<< " on " << *dir << dendl;
- if (mds->is_any_replay() || mds->is_resolve())
- do_eval = false;
-
show_subtrees();
CDir *root;
p = p->inode->get_parent_dir();
}
}
-
- if (do_eval)
- eval_subtree_root(dir->get_inode());
}
show_subtrees();
assert(subtrees.count(dir));
set<CDir*> oldbounds = subtrees[dir];
+ set<CInode*> to_eval;
// try merge at my root
- try_subtree_merge_at(dir);
+ try_subtree_merge_at(dir, &to_eval);
// try merge at my old bounds
- for (set<CDir*>::iterator p = oldbounds.begin();
- p != oldbounds.end();
- ++p)
- try_subtree_merge_at(*p);
+ for (auto bound : oldbounds)
+ try_subtree_merge_at(bound, &to_eval);
+
+ if (!(mds->is_any_replay() || mds->is_resolve())) {
+ for(auto in : to_eval)
+ eval_subtree_root(in);
+ }
}
class C_MDC_SubtreeMergeWB : public MDCacheLogContext {
}
};
-void MDCache::try_subtree_merge_at(CDir *dir, bool do_eval)
+void MDCache::try_subtree_merge_at(CDir *dir, set<CInode*> *to_eval)
{
dout(10) << "try_subtree_merge_at " << *dir << dendl;
assert(subtrees.count(dir));
- if (mds->is_any_replay() || mds->is_resolve())
- do_eval = false;
-
// merge with parent?
CDir *parent = dir;
if (!dir->inode->is_base())
}
}
- if (do_eval)
- eval_subtree_root(dir->get_inode());
+ if (to_eval && dir->get_inode()->is_auth())
+ to_eval->insert(dir->get_inode());
}
show_subtrees(15);
{
// evaluate subtree inode filelock?
// (we should scatter the filelock on subtree bounds)
- if (diri->is_auth())
- mds->locker->try_eval(diri, CEPH_LOCK_IFILE | CEPH_LOCK_INEST);
+ assert(diri->is_auth());
+ mds->locker->try_eval(diri, CEPH_LOCK_IFILE | CEPH_LOCK_INEST);
}
root = dir;
}
+ set<CInode*> to_eval;
+
// verify/adjust bounds.
// - these may be new, or
// - beneath existing ambiguous bounds (which will be collapsed),
t = get_subtree_root(t->get_parent_dir());
dout(10) << " swallowing intervening subtree at " << *t << dendl;
adjust_subtree_auth(t, auth);
- try_subtree_merge_at(t);
+ try_subtree_merge_at(t, &to_eval);
t = get_subtree_root(bound->get_parent_dir());
if (t == dir) break;
}
CDir *stray = *p;
dout(10) << " swallowing extra subtree at " << *stray << dendl;
adjust_subtree_auth(stray, auth);
- try_subtree_merge_at(stray);
+ try_subtree_merge_at(stray, &to_eval);
}
}
// swallowing subtree may add new subtree bounds
verify_subtree_bounds(dir, bounds);
show_subtrees();
+
+ if (!(mds->is_any_replay() || mds->is_resolve())) {
+ for(auto in : to_eval)
+ eval_subtree_root(in);
+ }
}
projected_subtree_renames[diri].push_back(pair<CDir*,CDir*>(olddir, newdir));
}
-void MDCache::adjust_subtree_after_rename(CInode *diri, CDir *olddir,
- bool pop, bool imported)
+void MDCache::adjust_subtree_after_rename(CInode *diri, CDir *olddir, bool pop)
{
dout(10) << "adjust_subtree_after_rename " << *diri << " from " << *olddir << dendl;
subtrees[oldparent].erase(dir);
assert(subtrees.count(newparent));
subtrees[newparent].insert(dir);
- try_subtree_merge_at(dir, !imported);
+ // caller is responsible for 'eval diri'
+ try_subtree_merge_at(dir, NULL);
} else {
// mid-subtree.
// did auth change?
if (oldparent->authority() != newparent->authority()) {
- adjust_subtree_auth(dir, oldparent->authority(), !imported); // caller is responsible for *diri.
- try_subtree_merge_at(dir, !imported);
+ adjust_subtree_auth(dir, oldparent->authority());
+ // caller is responsible for 'eval diri'
+ try_subtree_merge_at(dir, NULL);
}
}
}
public:
bool is_subtrees() { return !subtrees.empty(); }
void list_subtrees(list<CDir*>& ls);
- void adjust_subtree_auth(CDir *root, mds_authority_t auth, bool do_eval=true);
- void adjust_subtree_auth(CDir *root, mds_rank_t a, mds_rank_t b=CDIR_AUTH_UNKNOWN, bool do_eval=true) {
- adjust_subtree_auth(root, mds_authority_t(a,b), do_eval);
+ void adjust_subtree_auth(CDir *root, mds_authority_t auth);
+ void adjust_subtree_auth(CDir *root, mds_rank_t a, mds_rank_t b=CDIR_AUTH_UNKNOWN) {
+ adjust_subtree_auth(root, mds_authority_t(a,b));
}
void adjust_bounded_subtree_auth(CDir *dir, set<CDir*>& bounds, mds_authority_t auth);
void adjust_bounded_subtree_auth(CDir *dir, set<CDir*>& bounds, mds_rank_t a) {
}
void map_dirfrag_set(list<dirfrag_t>& dfs, set<CDir*>& result);
void try_subtree_merge(CDir *root);
- void try_subtree_merge_at(CDir *root, bool do_eval=true);
+ void try_subtree_merge_at(CDir *root, set<CInode*> *to_eval);
void subtree_merge_writebehind_finish(CInode *in, MutationRef& mut);
void eval_subtree_root(CInode *diri);
CDir *get_subtree_root(CDir *dir);
void verify_subtree_bounds(CDir *root, const list<dirfrag_t>& bounds);
void project_subtree_rename(CInode *diri, CDir *olddir, CDir *newdir);
- void adjust_subtree_after_rename(CInode *diri, CDir *olddir,
- bool pop, bool imported = false);
+ void adjust_subtree_after_rename(CInode *diri, CDir *olddir, bool pop);
void get_auth_subtrees(set<CDir*>& s);
void get_fullauth_subtrees(set<CDir*>& s);
CDentry::linkage_t *destdnl = destdn->get_linkage();
CInode *oldin = destdnl->get_inode();
-
- bool imported_inode = false;
// primary+remote link merge?
bool linkmerge = (srcdnl->get_inode() == destdnl->get_inode() &&
// hack: fix auth bit
in->state_set(CInode::STATE_AUTH);
- imported_inode = true;
mdr->clear_ambiguous_auth();
}
// update subtree map?
if (destdnl->is_primary() && in->is_dir())
- mdcache->adjust_subtree_after_rename(in, srcdn->get_dir(), true, imported_inode);
+ mdcache->adjust_subtree_after_rename(in, srcdn->get_dir(), true);
if (straydn && oldin->is_dir())
mdcache->adjust_subtree_after_rename(oldin, destdn->get_dir(), true);