From: Yan, Zheng Date: Wed, 29 Jun 2016 09:15:01 +0000 (+0800) Subject: mds: handle partly purged directory X-Git-Tag: ses5-milestone5~375^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bc50e0309280c08c3ca79dfa5514ac3a15f81a23;p=ceph.git mds: handle partly purged directory For a snapshoted direcotry whose snaprealm parents are being opened, MDS does not know if the directory is purgeable. So MDS can't skip committing dirfrags of the directory. But if the direcotry is purgeale, some dirfrags could have already been deleted during MDS failover. Committing them could return -ENOENT. Signed-off-by: Yan, Zheng --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 20243ed9c058..bcb93f6155b5 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -2211,11 +2211,19 @@ void CDir::_commit(version_t want, int op_prio) void CDir::_committed(int r, version_t v) { if (r < 0) { - dout(1) << "commit error " << r << " v " << v << dendl; - cache->mds->clog->error() << "failed to commit dir " << dirfrag() << " object," - << " errno " << r << "\n"; - cache->mds->handle_write_error(r); - return; + // the directory could be partly purged during MDS failover + if (r == -ENOENT && committed_version == 0 && + inode->inode.nlink == 0 && inode->snaprealm) { + inode->state_set(CInode::STATE_MISSINGOBJS); + r = 0; + } + if (r < 0) { + dout(1) << "commit error " << r << " v " << v << dendl; + cache->mds->clog->error() << "failed to commit dir " << dirfrag() << " object," + << " errno " << r << "\n"; + cache->mds->handle_write_error(r); + return; + } } dout(10) << "_committed v " << v << " on " << *this << dendl; diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index aea56906bfcd..3736f1641663 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -143,6 +143,7 @@ ostream& operator<<(ostream& out, const CInode& in) if (in.state_test(CInode::STATE_NEEDSRECOVER)) out << " needsrecover"; if (in.state_test(CInode::STATE_RECOVERING)) out << " recovering"; if (in.state_test(CInode::STATE_DIRTYPARENT)) out << " dirtyparent"; + if (in.state_test(CInode::STATE_MISSINGOBJS)) out << " missingobjs"; if (in.is_freezing_inode()) out << " FREEZING=" << in.auth_pin_freeze_allowance; if (in.is_frozen_inode()) out << " FROZEN"; if (in.is_frozen_auth_pin()) out << " FROZEN_AUTHPIN"; @@ -4116,6 +4117,8 @@ void CInode::dump(Formatter *f) const f->dump_string("state", "dirtypool"); if (state_test(STATE_ORPHAN)) f->dump_string("state", "orphan"); + if (state_test(STATE_MISSINGOBJS)) + f->dump_string("state", "missingobjs"); f->close_section(); f->open_array_section("client_caps"); diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 7892031a960d..eb70325c9d92 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -217,6 +217,7 @@ public: static const int STATE_FROZENAUTHPIN = (1<<17); static const int STATE_DIRTYPOOL = (1<<18); static const int STATE_REPAIRSTATS = (1<<19); + static const int STATE_MISSINGOBJS = (1<<20); // orphan inode needs notification of releasing reference static const int STATE_ORPHAN = STATE_NOTIFYREF; diff --git a/src/mds/StrayManager.cc b/src/mds/StrayManager.cc index 22c2fa67b57c..4ba8572c8100 100644 --- a/src/mds/StrayManager.cc +++ b/src/mds/StrayManager.cc @@ -634,7 +634,12 @@ bool StrayManager::__eval_stray(CDentry *dn, bool delay) if (in->is_dir()) { if (in->snaprealm && in->snaprealm->has_past_parents()) { dout(20) << " directory has past parents " - << in->snaprealm->srnode.past_parents << dendl; + << in->snaprealm->srnode.past_parents << dendl; + if (in->state_test(CInode::STATE_MISSINGOBJS)) { + mds->clog->error() << "previous attempt at committing dirfrag of ino " + << in->ino() << " has failed, missing object\n"; + mds->handle_write_error(-ENOENT); + } return false; // not until some snaps are deleted. }