-void CInode::maybe_export_pin()
-{
- if (g_conf->mds_bal_export_pin && is_dir() && is_normal()) {
- mds_rank_t pin = get_export_pin(false);
- dout(20) << "maybe_export_pin export_pin=" << pin << " on " << *this << dendl;
- if (pin == mdcache->mds->get_nodeid()) {
- for (auto it = dirfrags.begin(); it != dirfrags.end(); it++) {
- CDir *cd = it->second;
- dout(20) << "dirfrag: " << *cd << dendl;
- if (cd->state_test(CDir::STATE_CREATING)) {
- /* inode is not journaled yet */
- cd->add_waiter(CDir::WAIT_CREATED, new C_CInode_ExportPin(this));
- dout(15) << "aux subtree pin of " << *cd << " delayed for finished creation" << dendl;
- continue;
- }
- if (cd->state_test(CDir::STATE_AUXSUBTREE)) continue;
- CDir *subtree = mdcache->get_subtree_root(cd);
- assert(subtree);
- if (subtree->is_ambiguous_auth()) {
- subtree->add_waiter(MDSCacheObject::WAIT_SINGLEAUTH, new C_CInode_ExportPin(this));
- dout(15) << "aux subtree pin of " << *cd << " delayed for single auth on subtree " << *subtree << dendl;
- } else if (subtree->is_auth()) {
- assert(cd->is_auth());
- if (subtree->is_frozen() || subtree->is_freezing()) {
- subtree->add_waiter(MDSCacheObject::WAIT_UNFREEZE, new C_CInode_ExportPin(this));
- dout(15) << "aux subtree pin of " << *cd << " delayed for unfreeze on subtree " << *subtree << dendl;
- } else {
- cd->state_set(CDir::STATE_AUXSUBTREE);
- mdcache->adjust_subtree_auth(cd, mdcache->mds->get_nodeid());
- dout(15) << "aux subtree pinned " << *cd << dendl;
- }
- } else {
- assert(!cd->is_auth());
- dout(15) << "not setting aux subtree pin for " << *cd << " because not auth" << dendl;
- }
- }
- } else if (pin != MDS_RANK_NONE) {
- for (auto it = dirfrags.begin(); it != dirfrags.end(); it++) {
- CDir *cd = it->second;
- if (cd->is_auth() && cd->state_test(CDir::STATE_AUXSUBTREE)) {
- assert(!(cd->is_frozen() || cd->is_freezing()));
- assert(!cd->state_test(CDir::STATE_EXPORTBOUND));
- cd->state_clear(CDir::STATE_AUXSUBTREE); /* merge will happen eventually */
- dout(15) << "cleared aux subtree pin " << *cd << dendl;
- }
+ if (state_test(CInode::STATE_QUEUEDEXPORTPIN))
+ return;
+
+ bool queue = false;
+ for (auto p = dirfrags.begin(); p != dirfrags.end(); p++) {
+ CDir *dir = p->second;
+ if (!dir->is_auth())
+ continue;
+ if (export_pin != MDS_RANK_NONE) {
+ if (dir->is_subtree_root()) {
+ // set auxsubtree bit or export it
+ if (!dir->state_test(CDir::STATE_AUXSUBTREE) ||
+ export_pin != dir->get_dir_auth().first)
+ queue = true;
+ } else {
+ // create aux subtree or export it
+ queue = true;