if (dir.state_test(CDir::STATE_COMPLETE)) out << "|complete";
if (dir.state_test(CDir::STATE_FREEZINGTREE)) out << "|freezingtree";
if (dir.state_test(CDir::STATE_FROZENTREE)) out << "|frozentree";
+ if (dir.state_test(CDir::STATE_AUXSUBTREE)) out << "|auxsubtree";
//if (dir.state_test(CDir::STATE_FROZENTREELEAF)) out << "|frozentreeleaf";
if (dir.state_test(CDir::STATE_FROZENDIR)) out << "|frozendir";
if (dir.state_test(CDir::STATE_FREEZINGDIR)) out << "|freezingdir";
static const unsigned STATE_ASSIMRSTAT = (1<<17); // assimilating inode->frag rstats
static const unsigned STATE_DIRTYDFT = (1<<18); // dirty dirfragtree
static const unsigned STATE_BADFRAG = (1<<19); // bad dirfrag
+ static const unsigned STATE_AUXSUBTREE = (1<<20); // no subtree merge
// common states
static const unsigned STATE_CLEAN = 0;
if (parent != dir && // we have a parent,
parent->dir_auth == dir->dir_auth && // auth matches,
dir->dir_auth.second == CDIR_AUTH_UNKNOWN && // auth is unambiguous,
- !dir->state_test(CDir::STATE_EXPORTBOUND)) { // not an exportbound,
+ !dir->state_test(CDir::STATE_EXPORTBOUND) && // not an exportbound,
+ !dir->state_test(CDir::STATE_AUXSUBTREE)) { // not aux subtree
// merge with parent.
dout(10) << " subtree merge at " << *dir << dendl;
dir->set_dir_auth(CDIR_AUTH_DEFAULT);
return;
}
+ if (g_conf->mds_thrash_exports) {
+ // create random subtree bound (which will not be exported)
+ list<CDir*> ls;
+ for (auto p = dir->begin(); p != dir->end(); ++p) {
+ auto dn = p->second;
+ CDentry::linkage_t *dnl= dn->get_linkage();
+ if (dnl->is_primary()) {
+ CInode *in = dnl->get_inode();
+ if (in->is_dir())
+ in->get_nested_dirfrags(ls);
+ }
+ }
+ if (ls.size() > 0) {
+ int n = rand() % ls.size();
+ auto p = ls.begin();
+ while (n--) ++p;
+ CDir *bd = *p;
+ if (!(bd->is_frozen() || bd->is_freezing())) {
+ assert(bd->is_auth());
+ dir->state_set(CDir::STATE_AUXSUBTREE);
+ mds->mdcache->adjust_subtree_auth(dir, mds->get_nodeid());
+ dout(0) << "export_dir: create aux subtree " << *bd << " under " << *dir << dendl;
+ }
+ }
+ }
+
mds->hit_export_target(ceph_clock_now(), dest, -1);
dir->auth_pin(this);
bd->state_clear(CDir::STATE_EXPORTBOUND);
}
+ if (dir->state_test(CDir::STATE_AUXSUBTREE))
+ dir->state_clear(CDir::STATE_AUXSUBTREE);
+
// adjust auth, with possible subtree merge.
// (we do this _after_ removing EXPORTBOUND pins, to allow merges)
cache->adjust_subtree_auth(dir, it->second.peer);
if (mode == TO_AUTH_SUBTREE_ROOT) {
// subtree root?
- if (dir->is_subtree_root() && !dir->state_test(CDir::STATE_EXPORTBOUND)) {
- if (dir->is_auth() && !dir->is_ambiguous_auth()) {
- // it's an auth subtree, we don't need maybe (if any), and we're done.
- dout(20) << "EMetaBlob::add_dir_context(" << dir << ") reached unambig auth subtree, don't need " << maybe
- << " at " << *dir << dendl;
- maybe.clear();
- break;
+ if (dir->is_subtree_root() &&
+ !dir->state_test(CDir::STATE_EXPORTBOUND)) {
+ if (dir->is_auth() && !dir->is_ambiguous_auth() ) {
+ if (dir->state_test(CDir::STATE_AUXSUBTREE) &&
+ dir->get_dir_auth().first == diri->authority().first) {
+ // auxiliary subtree. treat it as normal dirfrag
+ dout(20) << "EMetaBlob::add_dir_context(" << dir << ") auxiliary subtree " << dendl;
+ } else {
+ // it's an auth subtree, we don't need maybe (if any), and we're done.
+ dout(20) << "EMetaBlob::add_dir_context(" << dir << ") reached unambig auth subtree, don't need " << maybe
+ << " at " << *dir << dendl;
+ maybe.clear();
+ break;
+ }
} else {
dout(20) << "EMetaBlob::add_dir_context(" << dir << ") reached ambig or !auth subtree, need " << maybe
<< " at " << *dir << dendl;