diff options
author | Sage Weil <sage@inktank.com> | 2013-09-23 16:16:48 -0700 |
---|---|---|
committer | Sage Weil <sage@inktank.com> | 2013-09-23 16:16:48 -0700 |
commit | 286a6991900fdfc66e1c44a0299f3de8d30e7785 (patch) | |
tree | 746fcd386938cf04b1c0c04de09b47eb21c832a4 | |
parent | 6200eeca5970163a883e6105a4e40508ea4a5e87 (diff) | |
parent | 945eb3cbfc5d9e4578305b937bc9eb6097de1b1d (diff) | |
download | ceph-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.cc | 12 | ||||
-rw-r--r-- | src/mds/CDentry.h | 4 | ||||
-rw-r--r-- | src/mds/CDir.cc | 15 | ||||
-rw-r--r-- | src/mds/CDir.h | 1 | ||||
-rw-r--r-- | src/mds/CInode.cc | 7 | ||||
-rw-r--r-- | src/mds/CInode.h | 3 | ||||
-rw-r--r-- | src/mds/Locker.cc | 5 | ||||
-rw-r--r-- | src/mds/MDCache.cc | 256 | ||||
-rw-r--r-- | src/mds/MDCache.h | 31 | ||||
-rw-r--r-- | src/mds/Server.cc | 8 | ||||
-rw-r--r-- | src/mds/mdstypes.h | 8 |
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(); } } |