From: Yan, Zheng Date: Wed, 19 Jul 2017 06:31:52 +0000 (+0800) Subject: mds: refuse 'export dir' request when mds is stopping X-Git-Tag: v12.1.2~44^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=58623d781da1189d2e88cf4875294353db78cea9;p=ceph.git mds: refuse 'export dir' request when mds is stopping Fixes: http://tracker.ceph.com/issues/20677 Signed-off-by: "Yan, Zheng" --- diff --git a/src/mds/Migrator.cc b/src/mds/Migrator.cc index 779a87dc2f9..ad32f6d3464 100644 --- a/src/mds/Migrator.cc +++ b/src/mds/Migrator.cc @@ -977,15 +977,22 @@ void Migrator::handle_export_discover_ack(MExportDirDiscoverAck *m) dout(7) << "must have aborted" << dendl; } else { assert(it->second.state == EXPORT_DISCOVERING); - // release locks to avoid deadlock - MDRequestRef mdr = static_cast(it->second.mut.get()); - assert(mdr); - mds->mdcache->request_finish(mdr); - it->second.mut.reset(); - // freeze the subtree - it->second.state = EXPORT_FREEZING; - dir->auth_unpin(this); - assert(g_conf->mds_kill_export_at != 3); + + if (m->is_success()) { + // release locks to avoid deadlock + MDRequestRef mdr = static_cast(it->second.mut.get()); + assert(mdr); + mds->mdcache->request_finish(mdr); + it->second.mut.reset(); + // freeze the subtree + it->second.state = EXPORT_FREEZING; + dir->auth_unpin(this); + assert(g_conf->mds_kill_export_at != 3); + + } else { + dout(7) << "peer failed to discover (not active?), canceling" << dendl; + export_try_cancel(dir, false); + } } m->put(); // done @@ -1249,7 +1256,7 @@ void Migrator::handle_export_prep_ack(MExportDirPrepAck *m) assert(it->second.state == EXPORT_PREPPING); if (!m->is_success()) { - dout(7) << "peer couldn't acquire all needed locks, canceling" << dendl; + dout(7) << "peer couldn't acquire all needed locks or wasn't active, canceling" << dendl; export_try_cancel(dir, false); m->put(); return; @@ -2037,6 +2044,14 @@ void Migrator::handle_export_discover(MExportDirDiscover *m) // note import state dirfrag_t df = m->get_dirfrag(); + + if (!mds->is_active()) { + dout(7) << " not active, send NACK " << dendl; + mds->send_message_mds(new MExportDirDiscoverAck(df, m->get_tid(), false), from); + m->put(); + return; + } + // only start discovering on this message once. map::iterator it = import_state.find(df); if (!m->started) { @@ -2278,68 +2293,75 @@ void Migrator::handle_export_prep(MExportDirPrep *m) mds->queue_waiters(finished); - // open all bounds - set import_bounds; - for (map::iterator p = import_bound_fragset.begin(); - p != import_bound_fragset.end(); - ++p) { - CInode *in = cache->get_inode(p->first); - assert(in); + bool success = true; + if (mds->is_active()) { + // open all bounds + set import_bounds; + for (map::iterator p = import_bound_fragset.begin(); + p != import_bound_fragset.end(); + ++p) { + CInode *in = cache->get_inode(p->first); + assert(in); - // map fragset into a frag_t list, based on the inode fragtree - list fglist; - for (set::iterator q = p->second.begin(); q != p->second.end(); ++q) - in->dirfragtree.get_leaves_under(*q, fglist); - dout(10) << " bound inode " << p->first << " fragset " << p->second << " maps to " << fglist << dendl; - - for (list::iterator q = fglist.begin(); - q != fglist.end(); - ++q) { - CDir *bound = cache->get_dirfrag(dirfrag_t(p->first, *q)); - if (!bound) { - dout(7) << " opening bounding dirfrag " << *q << " on " << *in << dendl; - cache->open_remote_dirfrag(in, *q, - new C_MDS_RetryMessage(mds, m)); - return; - } + // map fragset into a frag_t list, based on the inode fragtree + list fglist; + for (set::iterator q = p->second.begin(); q != p->second.end(); ++q) + in->dirfragtree.get_leaves_under(*q, fglist); + dout(10) << " bound inode " << p->first << " fragset " << p->second << " maps to " << fglist << dendl; + + for (list::iterator q = fglist.begin(); + q != fglist.end(); + ++q) { + CDir *bound = cache->get_dirfrag(dirfrag_t(p->first, *q)); + if (!bound) { + dout(7) << " opening bounding dirfrag " << *q << " on " << *in << dendl; + cache->open_remote_dirfrag(in, *q, + new C_MDS_RetryMessage(mds, m)); + return; + } - if (!bound->state_test(CDir::STATE_IMPORTBOUND)) { - dout(7) << " pinning import bound " << *bound << dendl; - bound->get(CDir::PIN_IMPORTBOUND); - bound->state_set(CDir::STATE_IMPORTBOUND); - } else { - dout(7) << " already pinned import bound " << *bound << dendl; + if (!bound->state_test(CDir::STATE_IMPORTBOUND)) { + dout(7) << " pinning import bound " << *bound << dendl; + bound->get(CDir::PIN_IMPORTBOUND); + bound->state_set(CDir::STATE_IMPORTBOUND); + } else { + dout(7) << " already pinned import bound " << *bound << dendl; + } + import_bounds.insert(bound); } - import_bounds.insert(bound); } - } - - dout(7) << " all ready, noting auth and freezing import region" << dendl; - bool success = true; - if (!mds->mdcache->is_readonly() && - dir->get_inode()->filelock.can_wrlock(-1) && - dir->get_inode()->nestlock.can_wrlock(-1)) { - it->second.mut = new MutationImpl(); - // force some locks. hacky. - mds->locker->wrlock_force(&dir->inode->filelock, it->second.mut); - mds->locker->wrlock_force(&dir->inode->nestlock, it->second.mut); - - // note that i am an ambiguous auth for this subtree. - // specify bounds, since the exporter explicitly defines the region. - cache->adjust_bounded_subtree_auth(dir, import_bounds, - pair(oldauth, mds->get_nodeid())); - cache->verify_subtree_bounds(dir, import_bounds); - // freeze. - dir->_freeze_tree(); - // note new state - it->second.state = IMPORT_PREPPED; + dout(7) << " all ready, noting auth and freezing import region" << dendl; + + if (!mds->mdcache->is_readonly() && + dir->get_inode()->filelock.can_wrlock(-1) && + dir->get_inode()->nestlock.can_wrlock(-1)) { + it->second.mut = new MutationImpl(); + // force some locks. hacky. + mds->locker->wrlock_force(&dir->inode->filelock, it->second.mut); + mds->locker->wrlock_force(&dir->inode->nestlock, it->second.mut); + + // note that i am an ambiguous auth for this subtree. + // specify bounds, since the exporter explicitly defines the region. + cache->adjust_bounded_subtree_auth(dir, import_bounds, + pair(oldauth, mds->get_nodeid())); + cache->verify_subtree_bounds(dir, import_bounds); + // freeze. + dir->_freeze_tree(); + // note new state + it->second.state = IMPORT_PREPPED; + } else { + dout(7) << " couldn't acquire all needed locks, failing. " << *dir << dendl; + success = false; + } } else { - dout(7) << " couldn't acquire all needed locks, failing. " << *dir << dendl; + dout(7) << " not active, failing. " << *dir << dendl; success = false; - import_reverse_prepping(dir); } + if (!success) + import_reverse_prepping(dir); + // ok! dout(7) << " sending export_prep_ack on " << *dir << dendl; mds->send_message(new MExportDirPrepAck(dir->dirfrag(), success, m->get_tid()), m->get_connection());