]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: evaluate stray when releasing inode/dentry's reference
authorYan, Zheng <zheng.z.yan@intel.com>
Wed, 4 Sep 2013 03:13:57 +0000 (11:13 +0800)
committerYan, Zheng <zheng.z.yan@intel.com>
Sun, 22 Sep 2013 06:14:15 +0000 (14:14 +0800)
Current method to purge stray inode is call MDCache::maybe_eval_stray()
after releasing a reference to the stray inode/dentry. It's difficult
to make this method work correct, because there are so many places that
can release reference.

This patch solves the issue by calling MDCache::maybe_eval_stray()
in MDSCacheObject::put(). This avoids adding code that calls
MDCache::maybe_eval_stray() to each place that releases reference.

Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
src/mds/CDentry.cc
src/mds/CDentry.h
src/mds/CDir.cc
src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDCache.cc
src/mds/Server.cc
src/mds/mdstypes.h

index 5ff6e61fbe03f0e6b48c68ff18f19e5ecca624c9..0576658793000129490edd82750cd561712cdca9 100644 (file)
@@ -567,4 +567,14 @@ void CDentry::remove_client_lease(ClientLease *l, Locker *locker)
     locker->eval_gather(&lock);
 }
 
-
+void CDentry::_put()
+{
+  if (get_num_ref() <= (int)is_dirty() + 1) {
+    CDentry::linkage_t *dnl = get_projected_linkage();
+    if (dnl->is_primary()) {
+      CInode *in = dnl->get_inode();
+      if (get_num_ref() == (int)is_dirty() + !!in->get_num_ref())
+       in->mdcache->maybe_eval_stray(in, true);
+    }
+  }
+}
index c540a8104564db51d5ea8a39de2b20a273895b26..e40854adfaa951f855de74948feb5db2abc19a6b 100644 (file)
@@ -76,6 +76,8 @@ public:
   static const int STATE_FRAGMENTING =  (1<<1);
   static const int STATE_PURGING =      (1<<2);
   static const int STATE_BADREMOTEINO = (1<<3);
+  // stray dentry needs notification of releasing reference
+  static const int STATE_STRAY =       STATE_NOTIFYREF;
 
   // -- pins --
   static const int PIN_INODEPIN =     1;  // linked inode is pinned
@@ -255,6 +257,7 @@ public:
   void last_put() {
     lru_unpin();
   }
+  void _put();
 
   // auth pins
   bool can_auth_pin();
index c7527419e4771f20763bf7994393d824a5ba3f1a..c77ca180a6fe4d95d80415f6fae783ab90cfdf5e 100644 (file)
@@ -1469,6 +1469,7 @@ void CDir::_fetched(bufferlist &bl, const string& want_dn)
   }
   bool purged_any = false;
 
+  bool stray = inode->is_stray();
 
   //int num_new_inodes_loaded = 0;
   loff_t baseoff = p.get_off();
@@ -1613,6 +1614,12 @@ void CDir::_fetched(bufferlist &bl, const string& want_dn)
          if (in->inode.is_dirty_rstat())
            in->mark_dirty_rstat();
 
+         if (stray) {
+           dn->state_set(CDentry::STATE_STRAY);
+           if (in->inode.nlink == 0)
+             in->state_set(CInode::STATE_ORPHAN);
+         }
+
          //in->hack_accessed = false;
          //in->hack_load_stamp = ceph_clock_now(g_ceph_context);
          //num_new_inodes_loaded++;
index 46f8d33cfd89e9da60c42fbfc56b54773a6c2bfd..bcc7cc674edcf40986e02ff2206ad17c6fcf654b 100644 (file)
@@ -682,6 +682,12 @@ void CInode::last_put()
     parent->put(CDentry::PIN_INODEPIN);
 }
 
+void CInode::_put()
+{
+  if (get_num_ref() == (int)is_dirty() + (int)is_dirty_parent())
+    mdcache->maybe_eval_stray(this, true);
+}
+
 void CInode::add_remote_parent(CDentry *p) 
 {
   if (remote_parents.empty())
index 8e760220c1482339e9be19af1f5bc316e68b5e4d..1c2a9339c1cdd8f17a0060ff561a293cc9523326 100644 (file)
@@ -156,6 +156,8 @@ public:
   static const int STATE_STRAYPINNED = (1<<16);
   static const int STATE_FROZENAUTHPIN = (1<<17);
   static const int STATE_DIRTYPOOL =   (1<<18);
+  // orphan inode needs notification of releasing reference
+  static const int STATE_ORPHAN =      STATE_NOTIFYREF;
 
   static const int MASK_STATE_EXPORTED =
     (STATE_DIRTY|STATE_NEEDSRECOVER|STATE_DIRTYPARENT|STATE_DIRTYPOOL);
@@ -812,6 +814,7 @@ public:
   }
   void first_get();
   void last_put();
+  void _put();
 
 
   // -- hierarchy stuff --
index 4773e113dad60c8843a0a0cad0f5a69cfcb0686f..d6562e39b7fd9051bb8116cff098912b6d0cda5e 100644 (file)
@@ -677,6 +677,7 @@ CDentry *MDCache::get_or_create_stray_dentry(CInode *in)
   } else 
     assert(straydn->get_projected_linkage()->is_null());
 
+  straydn->state_set(CDentry::STATE_STRAY);
   return straydn;
 }
 
@@ -6314,6 +6315,12 @@ void MDCache::trim_non_auth()
       // add back into lru (at the top)
       lru.lru_insert_top(dn);
 
+      if (dn->get_dir()->get_inode()->is_stray()) {
+       dn->state_set(CDentry::STATE_STRAY);
+       if (dnl->is_primary() && dnl->get_inode()->inode.nlink == 0)
+         dnl->get_inode()->state_set(CInode::STATE_ORPHAN);
+      }
+
       if (!first_auth) {
        first_auth = dn;
       } else {
@@ -9495,9 +9502,6 @@ void MDCache::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls)
   CInode *in = dn->get_linkage()->get_inode();
   dout(10) << "_purge_stray_logged " << *dn << " " << *in << dendl;
 
-  dn->state_clear(CDentry::STATE_PURGING);
-  dn->put(CDentry::PIN_PURGING);
-
   assert(!in->state_test(CInode::STATE_RECOVERING));
 
   // unlink
@@ -9508,6 +9512,10 @@ void MDCache::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls)
 
   dn->dir->pop_and_dirty_projected_fnode(ls);
 
+  in->state_clear(CInode::STATE_ORPHAN);
+  dn->state_clear(CDentry::STATE_PURGING);
+  dn->put(CDentry::PIN_PURGING);
+
   // drop inode
   if (in->is_dirty())
     in->mark_clean();
index 466d48184565964b61b8b8faaec73b8ca1c95eb2..c6f48c2a1f7ae2d92fdb816116ebb50006f05d73 100644 (file)
@@ -4909,8 +4909,10 @@ void Server::_unlink_local(MDRequest *mdr, CDentry *dn, CDentry *straydn)
   inode_t *pi = in->project_inode();
   mdr->add_projected_inode(in); // do this _after_ my dn->pre_dirty().. we apply that one manually.
   pi->version = in->pre_dirty();
-  pi->nlink--;
   pi->ctime = mdr->now;
+  pi->nlink--;
+  if (pi->nlink == 0)
+    in->state_set(CInode::STATE_ORPHAN);
 
   if (dnl->is_primary()) {
     // primary link.  add stray dentry.
@@ -6054,8 +6056,10 @@ void Server::_rename_prepare(MDRequest *mdr,
        pi->nlink--;
     }
     if (tpi) {
-      tpi->nlink--;
       tpi->ctime = mdr->now;
+      tpi->nlink--;
+      if (tpi->nlink == 0)
+       oldin->state_set(CInode::STATE_ORPHAN);
     }
   }
 
index 902e3104aa8963785b822ca38db5dce064ee2009..2a3874818b7ae8869cd7cb9b6c51dd0afac64f27 100644 (file)
@@ -1134,8 +1134,9 @@ class MDSCacheObject {
   // -- state --
   const static int STATE_AUTH      = (1<<30);
   const static int STATE_DIRTY     = (1<<29);
-  const static int STATE_REJOINING = (1<<28);  // replica has not joined w/ primary copy
-  const static int STATE_REJOINUNDEF = (1<<27);  // contents undefined.
+  const static int STATE_NOTIFYREF = (1<<28); // notify dropping ref drop through _put()
+  const static int STATE_REJOINING = (1<<27);  // replica has not joined w/ primary copy
+  const static int STATE_REJOINUNDEF = (1<<26);  // contents undefined.
 
 
   // -- wait --
@@ -1221,6 +1222,7 @@ protected:
 #endif
     assert(ref > 0);
   }
+  virtual void _put() {}
   void put(int by) {
 #ifdef MDS_REF_SET
     if (ref == 0 || ref_map[by] == 0) {
@@ -1236,6 +1238,8 @@ protected:
 #endif
       if (ref == 0)
        last_put();
+      if (state_test(STATE_NOTIFYREF))
+       _put();
     }
   }