diff options
author | Yan, Zheng <zheng.z.yan@intel.com> | 2013-09-04 11:13:57 +0800 |
---|---|---|
committer | Yan, Zheng <zheng.z.yan@intel.com> | 2013-09-22 14:14:15 +0800 |
commit | cbf1f3ca1e6e0b38c9f37a44983c10654380e1d1 (patch) | |
tree | 4386efe26b7c5656f76edc7ae72aefb7a5dba500 | |
parent | c63b4edcdc252fe960cfd8d9442df313c0ab12ce (diff) | |
download | ceph-cbf1f3ca1e6e0b38c9f37a44983c10654380e1d1.tar.gz |
mds: evaluate stray when releasing inode/dentry's reference
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>
-rw-r--r-- | src/mds/CDentry.cc | 12 | ||||
-rw-r--r-- | src/mds/CDentry.h | 3 | ||||
-rw-r--r-- | src/mds/CDir.cc | 7 | ||||
-rw-r--r-- | src/mds/CInode.cc | 6 | ||||
-rw-r--r-- | src/mds/CInode.h | 3 | ||||
-rw-r--r-- | src/mds/MDCache.cc | 14 | ||||
-rw-r--r-- | src/mds/Server.cc | 8 | ||||
-rw-r--r-- | src/mds/mdstypes.h | 8 |
8 files changed, 53 insertions, 8 deletions
diff --git a/src/mds/CDentry.cc b/src/mds/CDentry.cc index 5ff6e61fbe0..05766587930 100644 --- a/src/mds/CDentry.cc +++ b/src/mds/CDentry.cc @@ -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); + } + } +} diff --git a/src/mds/CDentry.h b/src/mds/CDentry.h index c540a810456..e40854adfaa 100644 --- a/src/mds/CDentry.h +++ b/src/mds/CDentry.h @@ -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(); diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index c7527419e47..c77ca180a6f 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -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++; diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index 46f8d33cfd8..bcc7cc674ed 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -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()) diff --git a/src/mds/CInode.h b/src/mds/CInode.h index 8e760220c14..1c2a9339c1c 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -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 -- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 4773e113dad..d6562e39b7f 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -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(); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 466d4818456..c6f48c2a1f7 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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); } } diff --git a/src/mds/mdstypes.h b/src/mds/mdstypes.h index 902e3104aa8..2a3874818b7 100644 --- a/src/mds/mdstypes.h +++ b/src/mds/mdstypes.h @@ -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(); } } |