diff options
Diffstat (limited to 'src/mds/MDCache.cc')
-rw-r--r-- | src/mds/MDCache.cc | 256 |
1 files changed, 122 insertions, 134 deletions
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); } } |