mds: auth pin stray dir when purging stray inode

After stray inode gets added to purge queue, mds deletes stray dentry.
MDS needs to make sure stray dir is not being fragmented.

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
This commit is contained in:
Yan, Zheng 2020-03-03 11:30:45 +08:00
parent 02e15a20d9
commit 72dab35bd0
2 changed files with 27 additions and 8 deletions

View File

@ -198,7 +198,10 @@ void StrayManager::_purge_stray_purged(
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
@ -236,29 +239,32 @@ void StrayManager::_purge_stray_purged(
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
@ -267,6 +273,8 @@ void StrayManager::_purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *l
in->mark_clean();
mds->mdcache->remove_inode(in);
dir->auth_unpin(this);
if (mds->is_stopping())
mds->mdcache->shutdown_export_stray_finish(ino);
}
@ -308,11 +316,11 @@ void StrayManager::enqueue(CDentry *dn, bool trunc)
<< *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);
@ -323,14 +331,23 @@ void StrayManager::_enqueue(CDentry *dn, bool 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 {
@ -739,6 +756,8 @@ void StrayManager::_truncate_stray_logged(CDentry *dn, LogSegment *ls)
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())

View File

@ -103,7 +103,7 @@ protected:
friend class StrayManagerContext;
friend class C_StraysFetched;
friend class C_OpenSnapParents;
friend class C_RetryEnqueue;
friend class C_PurgeStrayLogged;
friend class C_TruncateStrayLogged;
friend class C_IO_PurgeStrayPurged;