]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
cephfs: Reset scrub data when inodes move
authorDouglas Fuller <dfuller@redhat.com>
Thu, 30 Nov 2017 16:13:36 +0000 (11:13 -0500)
committerDouglas Fuller <dfuller@redhat.com>
Wed, 24 Jan 2018 16:14:47 +0000 (11:14 -0500)
If an inode currently on the ScrubStack is moved, it may be
initialized again, causing an assert. Instead, remove the inode
from its parent scrub list and reinitialize it.

Fixes: http://tracker.ceph.com/issues/22288
Signed-off-by: Douglas Fuller <dfuller@redhat.com>
src/mds/CDir.cc
src/mds/CInode.cc

index 97d9c3fe85f69bffd1bee374063138263ff69c4e..5d530603fdb25c3d6833fe50833aaf328bd6f500 100644 (file)
@@ -3185,6 +3185,12 @@ int CDir::_next_dentry_on_set(set<dentry_key_t>& dns, bool missing_okay,
       continue;
     }
 
+    if (!dn->get_linkage()->is_primary()) {
+      dout(15) << " skip dentry " << dnkey.name
+              << ", no longer primary" << dendl;
+      continue;
+    }
+
     *dnout = dn;
     return 0;
   }
index 412a4f3d59e9a19d1be675b744632f1e4a54f277..829572587825f67a1541e975e40998552aa73963 100644 (file)
@@ -4417,7 +4417,17 @@ void CInode::scrub_initialize(CDentry *scrub_parent,
                              MDSInternalContextBase *f)
 {
   dout(20) << __func__ << " with scrub_version " << get_version() << dendl;
-  assert(!scrub_is_in_progress());
+  if (scrub_is_in_progress()) {
+    dout(20) << __func__ << " inode moved during scrub, reinitializing "
+            << dendl;
+    assert(scrub_infop->scrub_parent);
+    CDentry *dn = scrub_infop->scrub_parent;
+    CDir *dir = dn->dir;
+    dn->put(CDentry::PIN_SCRUBPARENT);
+    assert(dir->scrub_infop && dir->scrub_infop->directory_scrubbing);
+    dir->scrub_infop->directories_scrubbing.erase(dn->key());
+    dir->scrub_infop->others_scrubbing.erase(dn->key());
+  }
   scrub_info();
   if (!scrub_infop)
     scrub_infop = new scrub_info_t();