summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@inktank.com>2013-09-23 16:16:48 -0700
committerSage Weil <sage@inktank.com>2013-09-23 16:16:48 -0700
commit286a6991900fdfc66e1c44a0299f3de8d30e7785 (patch)
tree746fcd386938cf04b1c0c04de09b47eb21c832a4
parent6200eeca5970163a883e6105a4e40508ea4a5e87 (diff)
parent945eb3cbfc5d9e4578305b937bc9eb6097de1b1d (diff)
downloadceph-286a6991900fdfc66e1c44a0299f3de8d30e7785.tar.gz
Merge pull request #566 from ceph/wip-purge-stray
Fixes for purging stray Reviewed-by: Sage Weil <sage@inktank.com>
-rw-r--r--src/mds/CDentry.cc12
-rw-r--r--src/mds/CDentry.h4
-rw-r--r--src/mds/CDir.cc15
-rw-r--r--src/mds/CDir.h1
-rw-r--r--src/mds/CInode.cc7
-rw-r--r--src/mds/CInode.h3
-rw-r--r--src/mds/Locker.cc5
-rw-r--r--src/mds/MDCache.cc256
-rw-r--r--src/mds/MDCache.h31
-rw-r--r--src/mds/Server.cc8
-rw-r--r--src/mds/mdstypes.h8
11 files changed, 193 insertions, 157 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 0d2445a525f..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
@@ -146,6 +148,7 @@ protected:
public:
elist<CDentry*>::item item_dirty;
+ elist<CDentry*>::item item_stray;
protected:
int auth_pins, nested_auth_pins;
@@ -254,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 2b991d78fde..c77ca180a6f 100644
--- a/src/mds/CDir.cc
+++ b/src/mds/CDir.cc
@@ -655,6 +655,14 @@ void CDir::remove_null_dentries() {
assert(get_num_any() == items.size());
}
+void CDir::touch_dentries_bottom() {
+ dout(12) << "touch_dentries_bottom " << *this << dendl;
+
+ for (CDir::map_t::iterator p = items.begin();
+ p != items.end();
+ ++p)
+ inode->mdcache->touch_dentry_bottom(p->second);
+}
bool CDir::try_trim_snap_dentry(CDentry *dn, const set<snapid_t>& snaps)
{
@@ -1461,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();
@@ -1605,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/CDir.h b/src/mds/CDir.h
index 7cf2b6a43d7..86da4e5dfd3 100644
--- a/src/mds/CDir.h
+++ b/src/mds/CDir.h
@@ -357,6 +357,7 @@ private:
void remove_null_dentries();
void purge_stale_snap_data(const set<snapid_t>& snaps);
public:
+ void touch_dentries_bottom();
bool try_trim_snap_dentry(CDentry *dn, const set<snapid_t>& snaps);
diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc
index 46f8d33cfd8..7accc5a4dba 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())
@@ -1073,7 +1079,6 @@ void CInode::_stored_backtrace(version_t v, Context *fin)
clear_dirty_parent();
if (fin)
fin->complete(0);
- mdcache->maybe_eval_stray(this);
}
void CInode::_mark_dirty_parent(LogSegment *ls, bool dirty_pool)
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/Locker.cc b/src/mds/Locker.cc
index 99bd761e0f7..19c9176f414 100644
--- a/src/mds/Locker.cc
+++ b/src/mds/Locker.cc
@@ -1640,9 +1640,6 @@ void Locker::file_update_finish(CInode *in, Mutation *mut, bool share, client_t
share_inode_max_size(in);
}
issue_caps_set(need_issue);
-
- // unlinked stray? may need to purge (e.g., after all caps are released)
- mdcache->maybe_eval_stray(in);
}
Capability* Locker::issue_new_caps(CInode *in,
@@ -3011,8 +3008,6 @@ void Locker::remove_client_cap(CInode *in, client_t client)
}
try_eval(in, CEPH_CAP_LOCKS);
-
- mds->mdcache->maybe_eval_stray(in);
}
diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc
index 86b380f2827..9dc1229fbb9 100644
--- a/src/mds/MDCache.cc
+++ b/src/mds/MDCache.cc
@@ -127,7 +127,8 @@ long g_num_caps = 0;
set<int> SimpleLock::empty_gather_set;
-MDCache::MDCache(MDS *m)
+MDCache::MDCache(MDS *m) :
+ delayed_eval_stray(member_offset(CDentry, item_stray))
{
mds = m;
migrator = new Migrator(mds, this);
@@ -676,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;
}
@@ -5934,8 +5936,9 @@ void MDCache::truncate_inode_finish(CInode *in, LogSegment *ls)
EUpdate *le = new EUpdate(mds->mdlog, "truncate finish");
mds->mdlog->start_entry(le);
- le->metablob.add_dir_context(in->get_parent_dir());
- le->metablob.add_primary_dentry(in->get_projected_parent_dn(), in, true);
+ CDentry *dn = in->get_projected_parent_dn();
+ le->metablob.add_dir_context(dn->get_dir());
+ le->metablob.add_primary_dentry(dn, in, true);
le->metablob.add_truncate_finish(in->ino(), ls->offset);
journal_dirty_inode(mut, &le->metablob, in);
@@ -6017,8 +6020,15 @@ bool MDCache::trim(int max)
}
dout(7) << "trim max=" << max << " cur=" << lru.lru_get_size() << dendl;
- map<int, MCacheExpire*> expiremap;
+ // process delayed eval_stray()
+ for (elist<CDentry*>::iterator p = delayed_eval_stray.begin(); !p.end(); ) {
+ CDentry *dn = *p;
+ ++p;
+ dn->item_stray.remove_myself();
+ eval_stray(dn);
+ }
+ map<int, MCacheExpire*> expiremap;
bool is_standby_replay = mds->is_standby_replay();
int unexpirable = 0;
list<CDentry*> unexpirables;
@@ -6026,13 +6036,12 @@ bool MDCache::trim(int max)
while (lru.lru_get_size() + unexpirable > (unsigned)max) {
CDentry *dn = static_cast<CDentry*>(lru.lru_expire());
if (!dn) break;
- if (is_standby_replay && dn->get_linkage() &&
- dn->get_linkage()->inode->item_open_file.is_on_list()) {
+ if ((is_standby_replay && dn->get_linkage() &&
+ dn->get_linkage()->inode->item_open_file.is_on_list()) ||
+ trim_dentry(dn, expiremap)) {
unexpirables.push_back(dn);
++unexpirable;
- continue;
}
- trim_dentry(dn, expiremap);
}
for(list<CDentry*>::iterator i = unexpirables.begin();
i != unexpirables.end();
@@ -6087,7 +6096,7 @@ void MDCache::send_expire_messages(map<int, MCacheExpire*>& expiremap)
}
-void MDCache::trim_dentry(CDentry *dn, map<int, MCacheExpire*>& expiremap)
+bool MDCache::trim_dentry(CDentry *dn, map<int, MCacheExpire*>& expiremap)
{
dout(12) << "trim_dentry " << *dn << dendl;
@@ -6142,6 +6151,9 @@ void MDCache::trim_dentry(CDentry *dn, map<int, MCacheExpire*>& expiremap)
CInode *in = dnl->get_inode();
assert(in);
trim_inode(dn, in, con, expiremap);
+ // purging stray instead of trimming ?
+ if (dn->get_num_ref() > 0)
+ return true;
}
else {
assert(dnl->is_null());
@@ -6160,6 +6172,7 @@ void MDCache::trim_dentry(CDentry *dn, map<int, MCacheExpire*>& expiremap)
migrator->export_empty_import(dir);
if (mds->logger) mds->logger->inc(l_mds_iex);
+ return false;
}
@@ -6222,7 +6235,14 @@ void MDCache::trim_inode(CDentry *dn, CInode *in, CDir *con, map<int, MCacheExpi
trim_dirfrag(*p, con ? con:*p, expiremap); // if no container (e.g. root dirfrag), use *p
// INODE
- if (!in->is_auth()) {
+ if (in->is_auth()) {
+ // eval stray after closing dirfrags
+ if (dn) {
+ maybe_eval_stray(in);
+ if (dn->get_num_ref() > 0)
+ return;
+ }
+ } else {
pair<int,int> auth = in->authority();
dirfrag_t df;
@@ -6305,6 +6325,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 {
@@ -6725,9 +6751,6 @@ void MDCache::inode_remove_replica(CInode *in, int from, set<SimpleLock *>& gath
if (in->nestlock.remove_replica(from)) gather_locks.insert(&in->nestlock);
if (in->flocklock.remove_replica(from)) gather_locks.insert(&in->flocklock);
if (in->policylock.remove_replica(from)) gather_locks.insert(&in->policylock);
-
- // trim?
- maybe_eval_stray(in);
}
void MDCache::dentry_remove_replica(CDentry *dn, int from, set<SimpleLock *>& gather_locks)
@@ -6737,10 +6760,6 @@ void MDCache::dentry_remove_replica(CDentry *dn, int from, set<SimpleLock *>& ga
// fix lock
if (dn->lock.remove_replica(from))
gather_locks.insert(&dn->lock);
-
- CDentry::linkage_t *dnl = dn->get_projected_linkage();
- if (dnl->is_primary())
- maybe_eval_stray(dnl->get_inode());
}
void MDCache::trim_client_leases()
@@ -9147,7 +9166,7 @@ struct C_MDC_EvalStray : public Context {
}
};
-void MDCache::eval_stray(CDentry *dn)
+void MDCache::eval_stray(CDentry *dn, bool delay)
{
dout(10) << "eval_stray " << *dn << dendl;
CDentry::linkage_t *dnl = dn->get_projected_linkage();
@@ -9211,9 +9230,13 @@ void MDCache::eval_stray(CDentry *dn)
dout(20) << " too many dn refs" << dendl;
return;
}
- purge_stray(dn);
+ if (delay) {
+ if (!dn->item_stray.is_on_list())
+ delayed_eval_stray.push_back(&dn->item_stray);
+ } else
+ purge_stray(dn);
}
- else if (in->inode.nlink == 1) {
+ else if (in->inode.nlink >= 1) {
// trivial reintegrate?
if (!in->remote_parents.empty()) {
CDentry *rlink = *in->remote_parents.begin();
@@ -9257,14 +9280,6 @@ void MDCache::fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Conte
mds->objecter->getxattr(oid, object_locator_t(pool), "parent", CEPH_NOSNAP, &bl, 0, fin);
}
-void MDCache::remove_backtrace(inodeno_t ino, int64_t pool, Context *fin)
-{
- SnapContext snapc;
- object_t oid = CInode::get_object_name(ino, frag_t(), "");
- mds->objecter->removexattr(oid, object_locator_t(pool), "parent", snapc,
- ceph_clock_now(g_ceph_context), 0, NULL, fin);
-}
-
class C_MDC_PurgeStrayPurged : public Context {
MDCache *cache;
CDentry *dn;
@@ -9276,94 +9291,6 @@ public:
}
};
-class C_MDC_PurgeForwardingPointers : public Context {
- MDCache *cache;
- CDentry *dn;
-public:
- bufferlist bl;
- C_MDC_PurgeForwardingPointers(MDCache *c, CDentry *d) :
- cache(c), dn(d) {}
- void finish(int r) {
- cache->_purge_forwarding_pointers(bl, dn, r);
- }
-};
-
-class C_MDC_PurgeStray : public Context {
- MDCache *cache;
- CDentry *dn;
-public:
- C_MDC_PurgeStray(MDCache *c, CDentry *d) :
- cache(c), dn(d) {}
- void finish(int r) {
- cache->_purge_stray(dn, r);
- }
-};
-
-void MDCache::_purge_forwarding_pointers(bufferlist& bl, CDentry *dn, int r)
-{
- assert(r == 0 || r == -ENOENT || r == -ENODATA);
- inode_backtrace_t backtrace;
- if (r == 0)
- ::decode(backtrace, bl);
-
- // setup gathering context
- C_GatherBuilder gather_bld(g_ceph_context);
-
- // remove all the objects with forwarding pointer backtraces (aka sentinels)
- for (set<int64_t>::const_iterator i = backtrace.old_pools.begin();
- i != backtrace.old_pools.end();
- ++i) {
- SnapContext snapc;
- object_t oid = CInode::get_object_name(backtrace.ino, frag_t(), "");
- object_locator_t oloc(*i);
-
- mds->objecter->remove(oid, oloc, snapc, ceph_clock_now(g_ceph_context), 0,
- NULL, gather_bld.new_sub());
- }
-
- if (gather_bld.has_subs()) {
- gather_bld.set_finisher(new C_MDC_PurgeStray(this, dn));
- gather_bld.activate();
- } else {
- _purge_stray(dn, r);
- }
-}
-
-void MDCache::_purge_stray(CDentry *dn, int r)
-{
- // purge the strays
- CDentry::linkage_t *dnl = dn->get_projected_linkage();
- CInode *in = dnl->get_inode();
- dout(10) << "_purge_stray " << *dn << " " << *in << dendl;
-
- SnapRealm *realm = in->find_snaprealm();
- SnapContext nullsnap;
- const SnapContext *snapc;
- if (realm) {
- dout(10) << " realm " << *realm << dendl;
- snapc = &realm->get_snap_context();
- } else {
- dout(10) << " NO realm, using null context" << dendl;
- snapc = &nullsnap;
- assert(in->last == CEPH_NOSNAP);
- }
-
- uint64_t period = (uint64_t)in->inode.layout.fl_object_size * (uint64_t)in->inode.layout.fl_stripe_count;
- uint64_t cur_max_size = in->inode.get_max_size();
- uint64_t to = MAX(in->inode.size, cur_max_size);
- if (to && period) {
- uint64_t num = (to + period - 1) / period;
- dout(10) << "purge_stray 0~" << to << " objects 0~" << num << " snapc " << snapc << " on " << *in << dendl;
- mds->filer->purge_range(in->inode.ino, &in->inode.layout, *snapc,
- 0, num, ceph_clock_now(g_ceph_context), 0,
- new C_MDC_PurgeStrayPurged(this, dn));
-
- } else {
- dout(10) << "purge_stray 0 objects snapc " << snapc << " on " << *in << dendl;
- _purge_stray_purged(dn);
- }
-}
-
void MDCache::purge_stray(CDentry *dn)
{
CDentry::linkage_t *dnl = dn->get_projected_linkage();
@@ -9381,24 +9308,86 @@ void MDCache::purge_stray(CDentry *dn)
dn->get(CDentry::PIN_PURGING);
in->state_set(CInode::STATE_PURGING);
-
+ if (dn->item_stray.is_on_list())
+ dn->item_stray.remove_myself();
+
+ if (in->is_dirty_parent())
+ in->clear_dirty_parent();
+
// CHEAT. there's no real need to journal our intent to purge, since
// that is implicit in the dentry's presence and non-use in the stray
// dir. on recovery, we'll need to re-eval all strays anyway.
+ SnapContext nullsnapc;
+ C_GatherBuilder gather(g_ceph_context, new C_MDC_PurgeStrayPurged(this, dn));
+
if (in->is_dir()) {
- dout(10) << "purge_stray dir ... implement me!" << dendl; // FIXME XXX
- // remove the backtrace
- remove_backtrace(in->ino(), mds->mdsmap->get_metadata_pool(),
- new C_MDC_PurgeStrayPurged(this, dn));
- } else if (in->is_file()) {
- // get the backtrace before blowing away the object
- C_MDC_PurgeForwardingPointers *fin = new C_MDC_PurgeForwardingPointers(this, dn);
- fetch_backtrace(in->ino(), in->get_inode().layout.fl_pg_pool, fin->bl, fin);
+ object_locator_t oloc(mds->mdsmap->get_metadata_pool());
+ list<frag_t> ls;
+ if (!in->dirfragtree.is_leaf(frag_t()))
+ in->dirfragtree.get_leaves(ls);
+ ls.push_back(frag_t());
+ for (list<frag_t>::iterator p = ls.begin();
+ p != ls.end();
+ ++p) {
+ object_t oid = CInode::get_object_name(in->inode.ino, *p, "");
+ dout(10) << "purge_stray remove dirfrag " << oid << dendl;
+ mds->objecter->remove(oid, oloc, nullsnapc, ceph_clock_now(g_ceph_context),
+ 0, NULL, gather.new_sub());
+ }
+ assert(gather.has_subs());
+ gather.activate();
+ return;
+ }
+
+ const SnapContext *snapc;
+ SnapRealm *realm = in->find_snaprealm();
+ if (realm) {
+ dout(10) << " realm " << *realm << dendl;
+ snapc = &realm->get_snap_context();
} else {
- // not a dir or file; purged!
- _purge_stray_purged(dn);
+ dout(10) << " NO realm, using null context" << dendl;
+ snapc = &nullsnapc;
+ assert(in->last == CEPH_NOSNAP);
+ }
+
+ if (in->is_file()) {
+ uint64_t period = (uint64_t)in->inode.layout.fl_object_size *
+ (uint64_t)in->inode.layout.fl_stripe_count;
+ uint64_t cur_max_size = in->inode.get_max_size();
+ uint64_t to = MAX(in->inode.size, cur_max_size);
+ if (to && period) {
+ uint64_t num = (to + period - 1) / period;
+ dout(10) << "purge_stray 0~" << to << " objects 0~" << num
+ << " snapc " << snapc << " on " << *in << dendl;
+ mds->filer->purge_range(in->inode.ino, &in->inode.layout, *snapc,
+ 0, num, ceph_clock_now(g_ceph_context), 0,
+ gather.new_sub());
+ }
}
+
+ inode_t *pi = in->get_projected_inode();
+ object_t oid = CInode::get_object_name(pi->ino, frag_t(), "");
+ // remove the backtrace object if it was not purged
+ if (!gather.has_subs()) {
+ object_locator_t oloc(pi->layout.fl_pg_pool);
+ dout(10) << "purge_stray remove backtrace object " << oid
+ << " pool " << oloc.pool << " snapc " << snapc << dendl;
+ mds->objecter->remove(oid, oloc, *snapc, ceph_clock_now(g_ceph_context), 0,
+ NULL, gather.new_sub());
+ }
+ // remove old backtrace objects
+ for (vector<int64_t>::iterator p = pi->old_pools.begin();
+ p != pi->old_pools.end();
+ ++p) {
+ object_locator_t oloc(*p);
+ dout(10) << "purge_stray remove backtrace object " << oid
+ << " old pool " << *p << " snapc " << snapc << dendl;
+ mds->objecter->remove(oid, oloc, *snapc, ceph_clock_now(g_ceph_context), 0,
+ NULL, gather.new_sub());
+ }
+ assert(gather.has_subs());
+ gather.activate();
}
class C_MDC_PurgeStrayLogged : public Context {
@@ -9480,9 +9469,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
@@ -9493,11 +9479,13 @@ 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();
- if (in->is_dirty_parent())
- in->clear_dirty_parent();
remove_inode(in);
@@ -10639,7 +10627,7 @@ void MDCache::handle_dentry_unlink(MDentryUnlink *m)
!in->state_test(CInode::STATE_EXPORTINGCAPS))
migrator->export_caps(in);
- lru.lru_bottouch(straydn); // move stray to end of lru
+ touch_dentry_bottom(straydn); // move stray to end of lru
straydn = NULL;
} else {
assert(!straydn);
@@ -10649,7 +10637,7 @@ void MDCache::handle_dentry_unlink(MDentryUnlink *m)
assert(dnl->is_null());
// move to bottom of lru
- lru.lru_bottouch(dn);
+ touch_dentry_bottom(dn);
}
}
diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h
index b4b57da84b2..d8f2a9486fb 100644
--- a/src/mds/MDCache.h
+++ b/src/mds/MDCache.h
@@ -19,6 +19,7 @@
#include "include/types.h"
#include "include/filepath.h"
+#include "include/elist.h"
#include "CInode.h"
#include "CDentry.h"
@@ -564,7 +565,7 @@ public:
// trimming
bool trim(int max = -1); // trim cache
- void trim_dentry(CDentry *dn, map<int, MCacheExpire*>& expiremap);
+ bool trim_dentry(CDentry *dn, map<int, MCacheExpire*>& expiremap);
void trim_dirfrag(CDir *dir, CDir *con,
map<int, MCacheExpire*>& expiremap);
void trim_inode(CDentry *dn, CInode *in, CDir *con,
@@ -646,6 +647,15 @@ public:
}
void touch_dentry_bottom(CDentry *dn) {
lru.lru_bottouch(dn);
+ if (dn->get_projected_linkage()->is_primary()) {
+ CInode *in = dn->get_projected_linkage()->get_inode();
+ if (in->has_dirfrags()) {
+ list<CDir*> ls;
+ in->get_dirfrags(ls);
+ for (list<CDir*>::iterator p = ls.begin(); p != ls.end(); ++p)
+ (*p)->touch_dentries_bottom();
+ }
+ }
}
protected:
@@ -858,31 +868,28 @@ public:
// -- stray --
public:
+ elist<CDentry*> delayed_eval_stray;
+
void scan_stray_dir();
- void eval_stray(CDentry *dn);
+ void eval_stray(CDentry *dn, bool delay=false);
void eval_remote(CDentry *dn);
- void maybe_eval_stray(CInode *in) {
+ void maybe_eval_stray(CInode *in, bool delay=false) {
if (in->inode.nlink > 0 || in->is_base())
return;
CDentry *dn = in->get_projected_parent_dn();
- if (dn->get_projected_linkage()->is_primary() &&
- dn->get_dir()->get_inode()->is_stray() &&
- !dn->is_replicated())
- eval_stray(dn);
+ if (!dn->state_test(CDentry::STATE_PURGING) &&
+ dn->get_projected_linkage()->is_primary() &&
+ dn->get_dir()->get_inode()->is_stray())
+ eval_stray(dn, delay);
}
protected:
void fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Context *fin);
- void remove_backtrace(inodeno_t ino, int64_t pool, Context *fin);
- void _purge_forwarding_pointers(bufferlist& bl, CDentry *dn, int r);
- void _purge_stray(CDentry *dn, int r);
void purge_stray(CDentry *dn);
void _purge_stray_purged(CDentry *dn, int r=0);
void _purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls);
void _purge_stray_logged_truncate(CDentry *dn, LogSegment *ls);
friend class C_MDC_FetchedBacktrace;
- friend class C_MDC_PurgeForwardingPointers;
- friend class C_MDC_PurgeStray;
friend class C_MDC_PurgeStrayLogged;
friend class C_MDC_PurgeStrayLoggedTruncate;
friend class C_MDC_PurgeStrayPurged;
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();
}
}