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 <zyan@redhat.com>
(cherry picked from commit
bc50e0309280c08c3ca79dfa5514ac3a15f81a23)
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;
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";
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");
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;
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.
}