summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2013-09-04 11:13:57 +0800
committerYan, Zheng <zheng.z.yan@intel.com>2013-09-22 14:14:15 +0800
commitcbf1f3ca1e6e0b38c9f37a44983c10654380e1d1 (patch)
tree4386efe26b7c5656f76edc7ae72aefb7a5dba500
parentc63b4edcdc252fe960cfd8d9442df313c0ab12ce (diff)
downloadceph-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.cc12
-rw-r--r--src/mds/CDentry.h3
-rw-r--r--src/mds/CDir.cc7
-rw-r--r--src/mds/CInode.cc6
-rw-r--r--src/mds/CInode.h3
-rw-r--r--src/mds/MDCache.cc14
-rw-r--r--src/mds/Server.cc8
-rw-r--r--src/mds/mdstypes.h8
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();
}
}