log_master_commit(r);
}
+void MDCache::logged_master_update(metareqid_t reqid)
+{
+ dout(10) << "logged_master_update " << reqid << dendl;
+ assert(uncommitted_masters.count(reqid));
+ uncommitted_masters[reqid].safe = true;
+ if (pending_masters.count(reqid)) {
+ pending_masters.erase(reqid);
+ if (pending_masters.empty())
+ process_delayed_resolve();
+ }
+}
/*
* The mds could crash after receiving all slaves' commit acknowledgement,
return;
}
+ discard_delayed_resolve(from);
+
// ambiguous slave requests?
if (!m->slave_requests.empty()) {
+ for (vector<metareqid_t>::iterator p = m->slave_requests.begin();
+ p != m->slave_requests.end();
+ ++p) {
+ if (uncommitted_masters.count(*p) && !uncommitted_masters[*p].safe)
+ pending_masters.insert(*p);
+ }
+
+ if (!pending_masters.empty()) {
+ dout(10) << " still have pending updates, delay processing slave resolve" << dendl;
+ delayed_resolve[from] = m;
+ return;
+ }
+
MMDSResolveAck *ack = new MMDSResolveAck;
for (vector<metareqid_t>::iterator p = m->slave_requests.begin();
p != m->slave_requests.end();
if (!resolve_ack_gather.empty() || !need_resolve_rollback.empty()) {
dout(10) << "delay processing subtree resolve" << dendl;
- discard_delayed_resolve(from);
delayed_resolve[from] = m;
return;
}
void MDCache::process_delayed_resolve()
{
dout(10) << "process_delayed_resolve" << dendl;
- for (map<int, MMDSResolve *>::iterator p = delayed_resolve.begin();
- p != delayed_resolve.end(); ++p)
+ map<int, MMDSResolve*> tmp;
+ tmp.swap(delayed_resolve);
+ for (map<int, MMDSResolve*>::iterator p = tmp.begin(); p != tmp.end(); ++p)
handle_resolve(p->second);
- delayed_resolve.clear();
}
void MDCache::discard_delayed_resolve(int who)
snapid_t follows=CEPH_NOSNAP);
// slaves
- void add_uncommitted_master(metareqid_t reqid, LogSegment *ls, set<int> &slaves) {
+ void add_uncommitted_master(metareqid_t reqid, LogSegment *ls, set<int> &slaves, bool safe=false) {
uncommitted_masters[reqid].ls = ls;
uncommitted_masters[reqid].slaves = slaves;
+ uncommitted_masters[reqid].safe = safe;
}
void wait_for_uncommitted_master(metareqid_t reqid, Context *c) {
uncommitted_masters[reqid].waiters.push_back(c);
}
void log_master_commit(metareqid_t reqid);
+ void logged_master_update(metareqid_t reqid);
void _logged_master_commit(metareqid_t reqid, LogSegment *ls, list<Context*> &waiters);
void committed_master_slave(metareqid_t r, int from);
void finish_committed_masters();
set<int> slaves;
LogSegment *ls;
list<Context*> waiters;
+ bool safe;
};
map<metareqid_t, umaster> uncommitted_masters; // master: req -> slave set
+ set<metareqid_t> pending_masters;
+
//map<metareqid_t, bool> ambiguous_slave_updates; // for log trimming.
//map<metareqid_t, Context*> waiting_for_slave_update_commit;
friend class ESlaveUpdate;
assert(g_conf->mds_kill_link_at != 3);
+ if (!mdr->more()->witnessed.empty())
+ mdcache->logged_master_update(mdr->reqid);
+
if (inc) {
// link the new dentry
dn->pop_projected_linkage();
{
dout(10) << "_unlink_local_finish " << *dn << dendl;
+ if (!mdr->more()->witnessed.empty())
+ mdcache->logged_master_update(mdr->reqid);
+
// unlink main dentry
dn->get_dir()->unlink_inode(dn);
dn->pop_projected_linkage();
{
dout(10) << "_rename_finish " << *mdr << dendl;
+ if (!mdr->more()->witnessed.empty())
+ mdcache->logged_master_update(mdr->reqid);
+
// apply
_rename_apply(mdr, srcdn, destdn, straydn);
dout(10) << "EUpdate.replay " << reqid << " had slaves, expecting a matching ECommitted" << dendl;
_segment->uncommitted_masters.insert(reqid);
set<int> slaves;
- mds->mdcache->add_uncommitted_master(reqid, _segment, slaves);
+ mds->mdcache->add_uncommitted_master(reqid, _segment, slaves, true);
}
if (client_map.length()) {