this, dn, mds->mdlog->get_current_segment()));
} else {
if (in->get_num_ref() != (int)in->is_dirty() ||
- dn->get_num_ref() != (int)dn->is_dirty() + !!in->get_num_ref() + 1/*PIN_PURGING*/) {
+ dn->get_num_ref() !=
+ (int)dn->is_dirty() +
+ !!dn->state_test(CDentry::STATE_FRAGMENTING) +
+ !!in->get_num_ref() + 1 /* PIN_PURGING */) {
// Nobody should be taking new references to an inode when it
// is being purged (aside from it were
void StrayManager::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls)
{
CInode *in = dn->get_linkage()->get_inode();
+ CDir *dir = dn->get_dir();
dout(10) << "_purge_stray_logged " << *dn << " " << *in << dendl;
ceph_assert(!in->state_test(CInode::STATE_RECOVERING));
+ ceph_assert(!dir->is_frozen_dir());
bool new_dn = dn->is_new();
// unlink
ceph_assert(dn->get_projected_linkage()->is_null());
- dn->dir->unlink_inode(dn, !new_dn);
+ dir->unlink_inode(dn, !new_dn);
dn->pop_projected_linkage();
dn->mark_dirty(pdv, ls);
- dn->dir->pop_and_dirty_projected_fnode(ls);
+ dir->pop_and_dirty_projected_fnode(ls);
in->state_clear(CInode::STATE_ORPHAN);
dn->state_clear(CDentry::STATE_PURGING | CDentry::STATE_PURGINGPINNED);
dn->put(CDentry::PIN_PURGING);
+
// drop dentry?
if (new_dn) {
dout(20) << " dn is new, removing" << dendl;
dn->mark_clean();
- dn->dir->remove_dentry(dn);
+ dir->remove_dentry(dn);
}
// drop inode
in->mark_clean();
mds->mdcache->remove_inode(in);
+ dir->auth_unpin(this);
+
if (mds->is_stopping())
mds->mdcache->shutdown_export_stray_finish(ino);
}
<< *dn << dendl;
}
-class C_OpenSnapParents : public StrayManagerContext {
+class C_RetryEnqueue : public StrayManagerContext {
CDentry *dn;
bool trunc;
public:
- C_OpenSnapParents(StrayManager *sm_, CDentry *dn_, bool t) :
+ C_RetryEnqueue(StrayManager *sm_, CDentry *dn_, bool t) :
StrayManagerContext(sm_), dn(dn_), trunc(t) { }
void finish(int r) override {
sm->_enqueue(dn, trunc);
{
ceph_assert(started);
+ CDir *dir = dn->get_dir();
+ if (!dir->can_auth_pin()) {
+ dout(10) << " can't auth_pin (freezing?) " << *dir << ", waiting" << dendl;
+ dir->add_waiter(CDir::WAIT_UNFREEZE, new C_RetryEnqueue(this, dn, trunc));
+ return;
+ }
+
CInode *in = dn->get_linkage()->get_inode();
if (in->snaprealm &&
!in->snaprealm->have_past_parents_open() &&
- !in->snaprealm->open_parents(new C_OpenSnapParents(this, dn, trunc))) {
+ !in->snaprealm->open_parents(new C_RetryEnqueue(this, dn, trunc))) {
// this can happen if the dentry had been trimmed from cache.
return;
}
+ dn->get_dir()->auth_pin(this);
+
if (trunc) {
truncate(dn);
} else {
dn->state_clear(CDentry::STATE_PURGING | CDentry::STATE_PURGINGPINNED);
dn->put(CDentry::PIN_PURGING);
+ dn->get_dir()->auth_unpin(this);
+
eval_stray(dn);
if (!dn->state_test(CDentry::STATE_PURGING) && mds->is_stopping())