return false;
}
- if (diri->scrub_is_in_progress()) {
- dout(7) << "can_fragment: scrub in progress" << dendl;
- return false;
- }
-
for (const auto& dir : dirs) {
+ if (dir->scrub_is_in_progress()) {
+ dout(7) << "can_fragment: scrub in progress " << *dir << dendl;
+ return false;
+ }
+
if (dir->state_test(CDir::STATE_FRAGMENTING)) {
dout(7) << "can_fragment: already fragmenting " << *dir << dendl;
return false;
dout(10) << __func__ << " with {" << *dir << "}"
<< ", on_finish=" << on_finish << ", top=" << top << dendl;
// The edge directory must be in memory
+ dir->auth_pin(this);
dir->scrub_initialize(header, on_finish);
} else {
ceph_assert(0 == "queue dentry to scrub stack");
for (auto &fg : frags) {
CDir *dir = in->get_or_open_dirfrag(mdcache, fg);
- if (dir->get_version() == 0)
+ if (!dir->is_auth()) {
+ dout(20) << __func__ << " not auth " << *dir << dendl;
+ // no-op
+ } else if (!dir->can_auth_pin()) {
+ dout(20) << __func__ << " freezing/frozen " << *dir << dendl;
+ dir->add_waiter(CDir::WAIT_UNFREEZE, gather.new_sub());
+ } else if (dir->get_version() == 0) {
+ dout(20) << __func__ << " barebones " << *dir << dendl;
dir->fetch(gather.new_sub());
+ }
}
if (gather.has_subs()) {
scrubs_in_progress++;
gather.set_finisher(&scrub_kick);
gather.activate();
- dout(10) << __func__ << " barebones dirfrags, fetching" << dendl;
return;
}
}
};
-
void ScrubStack::scrub_dir_inode_final(CInode *in)
{
dout(20) << __func__ << " " << *in << dendl;
MDSContext *c = nullptr;
dir->scrub_finished(&c);
+ dir->auth_unpin(this);
if (c)
finisher->queue(new MDSIOContextWrapper(mdcache->mds, c), 0);
} else if (CDir *dir = dynamic_cast<CDir*>(*it)) {
MDSContext *ctx = nullptr;
dir->scrub_aborted(&ctx);
+ dir->auth_unpin(this);
if (ctx != nullptr) {
ctx->complete(-ECANCELED);
}
* Scrub a dirfrag. It queues child dentries, then does final
* scrub of the dirfrag.
*
- * @param dir The dirfrag to scrub
+ * @param dir The dirfrag to scrub (must be auth)
* @param done set to true if we started to do final scrub
*/
void scrub_dirfrag(CDir *dir, bool *done);