]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mds: handle partly purged directory
authorYan, Zheng <zyan@redhat.com>
Wed, 29 Jun 2016 09:15:01 +0000 (17:15 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 15 Jul 2016 01:11:49 +0000 (09:11 +0800)
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>
src/mds/CDir.cc
src/mds/CInode.cc
src/mds/CInode.h
src/mds/StrayManager.cc

index 20243ed9c058b8957b49ff9edcba19e76af6199b..bcb93f6155b533612e2aef26c606921c27426106 100644 (file)
@@ -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;
index aea56906bfcda0c076b8ea22b71d40bd780d1839..3736f1641663d5e47d8b70c1e75bd88541842b1b 100644 (file)
@@ -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");
index 7892031a960dc79f581070fad44056b8f9451f56..eb70325c9d926e2b4c35fb31568ac072bc20ca55 100644 (file)
@@ -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;
 
index 22c2fa67b57cd37ed8de9a6dd1e30304a58453f6..4ba8572c81005ba419435faf03f21cb93d948806 100644 (file)
@@ -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.
       }