}
}
+ if (tag & WAIT_CREATED) {
+ assert(state_test(STATE_CREATING));
+ assert(state_test(STATE_FRAGMENTING));
+ }
+
MDSCacheObject::add_waiter(tag, c);
}
void CDir::mark_new(LogSegment *ls)
{
ls->new_dirfrags.push_back(&item_new);
+ state_clear(STATE_CREATING);
+
+ if (state_test(CDir::STATE_FRAGMENTING)) {
+ list<MDSInternalContextBase*> ls;
+ take_waiting(CDir::WAIT_CREATED, ls);
+ cache->mds->queue_waiters(ls);
+ }
}
void CDir::mark_clean()
static const unsigned STATE_FREEZINGDIR = (1<< 5);
static const unsigned STATE_COMMITTING = (1<< 6); // mid-commit
static const unsigned STATE_FETCHING = (1<< 7); // currenting fetching
+ static const unsigned STATE_CREATING = (1<< 8);
static const unsigned STATE_IMPORTBOUND = (1<<10);
static const unsigned STATE_EXPORTBOUND = (1<<11);
static const unsigned STATE_EXPORTING = (1<<12);
static const uint64_t WAIT_DENTRY = (1<<0); // wait for item to be in cache
static const uint64_t WAIT_COMPLETE = (1<<1); // wait for complete dir contents
static const uint64_t WAIT_FROZEN = (1<<2); // auth pins removed
+ static const uint64_t WAIT_CREATED = (1<<3); // new dirfrag is logged
static const int WAIT_DNLOCK_OFFSET = 4;
dout(15) << " fetching incomplete " << *dir << dendl;
dir->fetch(gather.new_sub(), true); // ignore authpinnability
ready = false;
- }
- if (dir->get_frag() == frag_t() && dir->is_new()) {
+ } else if (dir->get_frag() == frag_t()) {
// The COMPLETE flag gets lost if we fragment a new dirfrag, then rollback
// the operation. To avoid CDir::fetch() complaining about missing object,
// we commit new dirfrag first.
- dout(15) << " committing new " << *dir << dendl;
- assert(dir->is_dirty());
- dir->commit(0, gather.new_sub(), true);
- ready = false;
+ if (dir->state_test(CDir::STATE_CREATING)) {
+ dout(15) << " waiting until new dir gets journaled " << *dir << dendl;
+ dir->add_waiter(CDir::WAIT_CREATED, gather.new_sub());
+ ready = false;
+ } else if (dir->is_new()) {
+ dout(15) << " committing new " << *dir << dendl;
+ assert(dir->is_dirty());
+ dir->commit(0, gather.new_sub(), true);
+ ready = false;
+ }
}
if (!ready)
continue;
// ...and that new dir is empty.
CDir *newdir = newi->get_or_open_dirfrag(mdcache, frag_t());
+ newdir->state_set(CDir::STATE_CREATING);
newdir->mark_complete();
newdir->fnode.version = newdir->pre_dirty();