]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: auth pin stray dir when purging stray inode
authorYan, Zheng <zyan@redhat.com>
Tue, 3 Mar 2020 03:30:45 +0000 (11:30 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 20 Apr 2020 10:11:15 +0000 (18:11 +0800)
After stray inode gets added to purge queue, mds deletes stray dentry.
MDS needs to make sure stray dir is not being fragmented.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/StrayManager.cc
src/mds/StrayManager.h

index a093dd73fb004fe338a976a5ee16ce3eba9b1d7e..aab044ca68b7115829be7a32b113f2d5c3741959 100644 (file)
@@ -198,7 +198,10 @@ void StrayManager::_purge_stray_purged(
           this, dn, mds->mdlog->get_current_segment()));
   } else {
     if (in->get_num_ref() != (int)in->is_dirty() ||
-        dn->get_num_ref() != (int)dn->is_dirty() + !!in->get_num_ref() + 1/*PIN_PURGING*/) {
+        dn->get_num_ref() !=
+         (int)dn->is_dirty() +
+         !!dn->state_test(CDentry::STATE_FRAGMENTING) +
+         !!in->get_num_ref() + 1 /* PIN_PURGING */) {
       // Nobody should be taking new references to an inode when it
       // is being purged (aside from it were 
 
@@ -236,29 +239,32 @@ void StrayManager::_purge_stray_purged(
 void StrayManager::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls)
 {
   CInode *in = dn->get_linkage()->get_inode();
+  CDir *dir = dn->get_dir();
   dout(10) << "_purge_stray_logged " << *dn << " " << *in << dendl;
 
   ceph_assert(!in->state_test(CInode::STATE_RECOVERING));
+  ceph_assert(!dir->is_frozen_dir());
 
   bool new_dn = dn->is_new();
 
   // unlink
   ceph_assert(dn->get_projected_linkage()->is_null());
-  dn->dir->unlink_inode(dn, !new_dn);
+  dir->unlink_inode(dn, !new_dn);
   dn->pop_projected_linkage();
   dn->mark_dirty(pdv, ls);
 
-  dn->dir->pop_and_dirty_projected_fnode(ls);
+  dir->pop_and_dirty_projected_fnode(ls);
 
   in->state_clear(CInode::STATE_ORPHAN);
   dn->state_clear(CDentry::STATE_PURGING | CDentry::STATE_PURGINGPINNED);
   dn->put(CDentry::PIN_PURGING);
 
+
   // drop dentry?
   if (new_dn) {
     dout(20) << " dn is new, removing" << dendl;
     dn->mark_clean();
-    dn->dir->remove_dentry(dn);
+    dir->remove_dentry(dn);
   }
 
   // drop inode
@@ -267,6 +273,8 @@ void StrayManager::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *l
     in->mark_clean();
   mds->mdcache->remove_inode(in);
 
+  dir->auth_unpin(this);
+
   if (mds->is_stopping())
     mds->mdcache->shutdown_export_stray_finish(ino);
 }
@@ -308,11 +316,11 @@ void StrayManager::enqueue(CDentry *dn, bool trunc)
     << *dn << dendl;
 }
 
-class C_OpenSnapParents : public StrayManagerContext {
+class C_RetryEnqueue : public StrayManagerContext {
   CDentry *dn;
   bool trunc;
   public:
-    C_OpenSnapParents(StrayManager *sm_, CDentry *dn_, bool t) :
+    C_RetryEnqueue(StrayManager *sm_, CDentry *dn_, bool t) :
       StrayManagerContext(sm_), dn(dn_), trunc(t) { }
     void finish(int r) override {
       sm->_enqueue(dn, trunc);
@@ -323,14 +331,23 @@ void StrayManager::_enqueue(CDentry *dn, bool trunc)
 {
   ceph_assert(started);
 
+  CDir *dir = dn->get_dir();
+  if (!dir->can_auth_pin()) {
+    dout(10) << " can't auth_pin (freezing?) " << *dir << ", waiting" << dendl;
+    dir->add_waiter(CDir::WAIT_UNFREEZE, new C_RetryEnqueue(this, dn, trunc));
+    return;
+  }
+
   CInode *in = dn->get_linkage()->get_inode();
   if (in->snaprealm &&
       !in->snaprealm->have_past_parents_open() &&
-      !in->snaprealm->open_parents(new C_OpenSnapParents(this, dn, trunc))) {
+      !in->snaprealm->open_parents(new C_RetryEnqueue(this, dn, trunc))) {
     // this can happen if the dentry had been trimmed from cache.
     return;
   }
 
+  dn->get_dir()->auth_pin(this);
+
   if (trunc) {
     truncate(dn);
   } else {
@@ -739,6 +756,8 @@ void StrayManager::_truncate_stray_logged(CDentry *dn, LogSegment *ls)
   dn->state_clear(CDentry::STATE_PURGING | CDentry::STATE_PURGINGPINNED);
   dn->put(CDentry::PIN_PURGING);
 
+  dn->get_dir()->auth_unpin(this);
+
   eval_stray(dn);
 
   if (!dn->state_test(CDentry::STATE_PURGING) &&  mds->is_stopping())
index 46335e1d472019c256d15f71a584beeff5b3b49d..0ad8a53f0cad6d01526cccdbd7e31d43bc204c55 100644 (file)
@@ -103,7 +103,7 @@ protected:
   friend class StrayManagerContext;
 
   friend class C_StraysFetched;
-  friend class C_OpenSnapParents;
+  friend class C_RetryEnqueue;
   friend class C_PurgeStrayLogged;
   friend class C_TruncateStrayLogged;
   friend class C_IO_PurgeStrayPurged;