++p) {
CDir *dir = *p;
+ bool ready = true;
if (!dir->is_complete()) {
dout(15) << " fetching incomplete " << *dir << dendl;
- dir->fetch(gather.new_sub(),
- true); // ignore authpinnability
- }
- else if (!dir->state_test(CDir::STATE_DNPINNEDFRAG)) {
+ dir->fetch(gather.new_sub(), true); // ignore authpinnability
+ ready = false;
+ }
+ if (dir->get_frag() == frag_t() && dir->is_new()) {
+ // 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 (!ready)
+ continue;
+
+ if (!dir->state_test(CDir::STATE_DNPINNEDFRAG)) {
dout(15) << " marking " << *dir << dendl;
for (CDir::map_t::iterator p = dir->items.begin();
p != dir->items.end();
}
dir->state_set(CDir::STATE_DNPINNEDFRAG);
dir->auth_unpin(dir);
- }
- else {
+ } else {
dout(15) << " already marked " << *dir << dendl;
}
}
uf.bits = bits;
uf.ls = ls;
ls->uncommitted_fragments.insert(basedirfrag);
- if (rollback) {
+ if (rollback)
uf.rollback.swap(*rollback);
- // preserve COMPLETE flag for newly created dirfrag
- if (bits > 0 && basedirfrag.frag == frag_t()) {
- CDir *dir = get_dirfrag(basedirfrag);
- if (dir && dir->is_complete())
- uf.complete = true;
- }
- }
}
void MDCache::finish_uncommitted_fragment(dirfrag_t basedirfrag, int op)
dir->set_version(rollback.fnode.version);
dir->fnode = rollback.fnode;
- if (uf.complete)
- dir->mark_complete();
dir->_mark_dirty(ls);
if (!(dir->fnode.rstat == dir->fnode.accounted_rstat)) {
struct ufragment {
int bits;
bool committed;
- bool complete;
LogSegment *ls;
list<Context*> waiters;
list<frag_t> old_frags;
bufferlist rollback;
- ufragment() : bits(0), committed(false), complete(false), ls(NULL) {}
+ ufragment() : bits(0), committed(false), ls(NULL) {}
};
map<dirfrag_t, ufragment> uncommitted_fragments;