From: Yan, Zheng Date: Fri, 19 Dec 2014 07:29:32 +0000 (+0800) Subject: mds: check multiversion inode when purging stray X-Git-Tag: v0.93~87^2~24 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5f58c4ccfc6c9bd02c50388f28e252df45a711d5;p=ceph.git mds: check multiversion inode when purging stray we can't purge a multiversion directory inode when it is still referenced by some snapshots. For regular files that are still referenced by some snapshots, we need to keep the backtrace object. Signed-off-by: Yan, Zheng --- diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 3e2203e021ce..2a9d5f0a1575 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -8944,19 +8944,19 @@ void MDCache::eval_stray(CDentry *dn, bool delay) // purge? if (in->inode.nlink == 0) { - if (in->is_dir()) { // past snaprealm parents imply snapped dentry remote links. // only important for directories. normal file data snaps are handled // by the object store. + if (in->snaprealm && in->snaprealm->has_past_parents()) { + if (!in->snaprealm->have_past_parents_open() && + !in->snaprealm->open_parents(new C_MDC_EvalStray(this, dn))) + return; + in->snaprealm->prune_past_parents(); + } + if (in->is_dir()) { if (in->snaprealm && in->snaprealm->has_past_parents()) { - if (!in->snaprealm->have_past_parents_open() && - !in->snaprealm->open_parents(new C_MDC_EvalStray(this, dn))) - return; - in->snaprealm->prune_past_parents(); - if (in->snaprealm->has_past_parents()) { - dout(20) << " has past parents " << in->snaprealm->srnode.past_parents << dendl; - return; // not until some snaps are deleted. - } + dout(20) << " directory has past parents " << in->snaprealm->srnode.past_parents << dendl; + return; // not until some snaps are deleted. } if (in->has_dirfrags()) { list ls; @@ -8996,6 +8996,11 @@ void MDCache::eval_stray(CDentry *dn, bool delay) num_strays_delayed++; logger->set(l_mdc_num_strays_delayed, num_strays_delayed); } + } else if (in->snaprealm && in->snaprealm->has_past_parents()) { + assert(!in->is_dir()); + dout(20) << " file has past parents " << in->snaprealm->srnode.past_parents << dendl; + if (in->is_file() && in->get_projected_inode()->size > 0) + truncate_stray(dn); // truncate head objects } else { if (in->is_dir()) in->close_dirfrags(); @@ -9048,15 +9053,68 @@ void MDCache::fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Conte class C_IO_MDC_PurgeStrayPurged : public MDCacheIOContext { CDentry *dn; + bool only_head; public: - C_IO_MDC_PurgeStrayPurged(MDCache *c, CDentry *d) : - MDCacheIOContext(c), dn(d) { } + C_IO_MDC_PurgeStrayPurged(MDCache *c, CDentry *d, bool oh) : + MDCacheIOContext(c), dn(d), only_head(oh) { } void finish(int r) { assert(r == 0 || r == -ENOENT); - mdcache->_purge_stray_purged(dn, r); + mdcache->_purge_stray_purged(dn, only_head); } }; +void MDCache::truncate_stray(CDentry *dn) +{ + CDentry::linkage_t *dnl = dn->get_projected_linkage(); + CInode *in = dnl->get_inode(); + dout(10) << "truncate_stray " << *dn << " " << *in << dendl; + assert(!dn->is_replicated()); + + dn->state_set(CDentry::STATE_PURGING); + dn->get(CDentry::PIN_PURGING); + in->state_set(CInode::STATE_PURGING); + + if (dn->item_stray.is_on_list()) + dn->item_stray.remove_myself(); + + C_GatherBuilder gather( + g_ceph_context, + new C_OnFinisher(new C_IO_MDC_PurgeStrayPurged(this, dn, true), + &mds->finisher)); + + SnapRealm *realm = in->find_snaprealm(); + assert(realm); + dout(10) << " realm " << *realm << dendl; + const SnapContext *snapc = &realm->get_snap_context(); + + uint64_t period = (uint64_t)in->inode.layout.fl_object_size * + (uint64_t)in->inode.layout.fl_stripe_count; + uint64_t to = in->inode.get_max_size(); + to = MAX(in->inode.size, to); + // when truncating a file, the filer does not delete stripe objects that are + // truncated to zero. so we need to purge stripe objects up to the max size + // the file has ever been. + to = MAX(in->inode.max_size_ever, to); + if (period && to > period) { + uint64_t num = (to - 1) / period; + dout(10) << "purge_stray 0~" << to << " objects 0~" << num + << " snapc " << snapc << " on " << *in << dendl; + mds->filer->purge_range(in->ino(), &in->inode.layout, *snapc, + 1, num, ceph_clock_now(g_ceph_context), + 0, gather.new_sub()); + } + + // keep backtrace object + if (period && to > 0) { + mds->filer->zero(in->ino(), &in->inode.layout, *snapc, + 0, period, ceph_clock_now(g_ceph_context), + 0, true, NULL, gather.new_sub()); + } + + assert(gather.has_subs()); + gather.activate(); +} + void MDCache::purge_stray(CDentry *dn) { CDentry::linkage_t *dnl = dn->get_projected_linkage(); @@ -9087,7 +9145,8 @@ void MDCache::purge_stray(CDentry *dn) SnapContext nullsnapc; C_GatherBuilder gather( g_ceph_context, - new C_OnFinisher(new C_IO_MDC_PurgeStrayPurged(this, dn), &mds->finisher)); + new C_OnFinisher(new C_IO_MDC_PurgeStrayPurged(this, dn, false), + &mds->finisher)); if (in->is_dir()) { object_locator_t oloc(mds->mdsmap->get_metadata_pool()); @@ -9184,13 +9243,13 @@ public: } }; -void MDCache::_purge_stray_purged(CDentry *dn, int r) +void MDCache::_purge_stray_purged(CDentry *dn, bool only_head) { - assert (r == 0 || r == -ENOENT); CInode *in = dn->get_projected_linkage()->get_inode(); dout(10) << "_purge_stray_purged " << *dn << " " << *in << dendl; - if (in->get_num_ref() == (int)in->is_dirty() && + if (!only_head && + in->get_num_ref() == (int)in->is_dirty() && dn->get_num_ref() == (int)dn->is_dirty() + !!in->get_num_ref() + 1/*PIN_PURGING*/) { // kill dentry. version_t pdv = dn->pre_dirty(); @@ -9228,6 +9287,7 @@ void MDCache::_purge_stray_purged(CDentry *dn, int r) inode_t *pi = in->project_inode(); pi->size = 0; + pi->max_size_ever = 0; pi->client_ranges.clear(); pi->truncate_size = 0; pi->truncate_from = 0; @@ -9287,8 +9347,6 @@ void MDCache::_purge_stray_logged_truncate(CDentry *dn, LogSegment *ls) eval_stray(dn); } - - void MDCache::reintegrate_stray(CDentry *straydn, CDentry *rdn) { dout(10) << "reintegrate_stray " << *straydn << " into " << *rdn << dendl; diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index b1459cb97b94..c28cc9d397dd 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -912,8 +912,9 @@ public: protected: void scan_stray_dir(dirfrag_t next=dirfrag_t()); + void truncate_stray(CDentry *dn); void purge_stray(CDentry *dn); - void _purge_stray_purged(CDentry *dn, int r=0); + void _purge_stray_purged(CDentry *dn, bool only_head); void _purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls); void _purge_stray_logged_truncate(CDentry *dn, LogSegment *ls); friend struct C_MDC_RetryScanStray;