From: Yan, Zheng Date: Wed, 29 Jun 2016 09:15:01 +0000 (+0800) Subject: mds: handle partly purged directory X-Git-Tag: v10.2.3~114^2~7 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5c2ff04061cc686c8ece37cee3393365769d2bf1;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 (cherry picked from commit bc50e0309280c08c3ca79dfa5514ac3a15f81a23) --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index d99c896f79527..fcae684f677fd 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -2229,11 +2229,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 3242355ed0c0d..d94e0e2fb0804 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"; @@ -4095,6 +4096,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 4181191341e20..3404d9189c16d 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 e6f4959262390..38e7f11b1e248 100644 --- a/src/mds/StrayManager.cc +++ b/src/mds/StrayManager.cc @@ -564,7 +564,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. }