// -------------------------------------------------------------------------------
// STRAYS
+struct C_MDC_EvalStray : public Context {
+ MDCache *mdcache;
+ CDentry *dn;
+ C_MDC_EvalStray(MDCache *c, CDentry *d) : mdcache(c), dn(d) {}
+ void finish(int r) {
+ mdcache->eval_stray(dn);
+ }
+};
+
void MDCache::eval_stray(CDentry *dn)
{
dout(10) << "eval_stray " << *dn << dendl;
// purge?
if (in->inode.nlink == 0) {
+ // past snaprealm parents imply snapped dentry remote links
+ 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()) return; // not until some snaps are deleted.
+ }
if (dn->is_replicated() || in->is_any_caps()) return; // wait
if (!in->dirfrags.empty()) return; // wait for dirs to close/trim
_purge_stray(dn);
invalidate_cached_snaps();
}
+
+void SnapRealm::prune_past_parents()
+{
+ dout(10) << "prune_past_parents" << dendl;
+ check_cache();
+ assert(open);
+
+ map<snapid_t, snaplink_t>::iterator p = past_parents.begin();
+ while (p != past_parents.end()) {
+ set<snapid_t>::iterator q = cached_snaps.lower_bound(p->second.first);
+ if (q == cached_snaps.end() ||
+ *q > p->first) {
+ dout(10) << "prune_past_parents pruning [" << p->second.first << "," << p->first
+ << "] " << p->second.ino << dendl;
+ past_parents.erase(p++);
+ } else {
+ dout(10) << "prune_past_parents keeping [" << p->second.first << "," << p->first
+ << "] " << p->second.ino << dendl;
+ p++;
+ }
+ }
+}
void project_past_parent(SnapRealm *newparent, bufferlist& snapbl);
void add_past_parent(SnapRealm *oldparent);
+ void prune_past_parents();
+ bool has_past_parents() { return !past_parents.empty(); }
void build_snap_set(set<snapid_t>& s,
snapid_t& max_seq, snapid_t& max_last_created, snapid_t& max_last_destroyed,