/* This function DOES put the passed message before returning */
void MDCache::handle_dir_update(MDirUpdate *m)
{
- CDir *dir = get_dirfrag(m->get_dirfrag());
+ dirfrag_t df = m->get_dirfrag();
+ CDir *dir = get_dirfrag(df);
if (!dir) {
- dout(5) << "dir_update on " << m->get_dirfrag() << ", don't have it" << dendl;
+ dout(5) << "dir_update on " << df << ", don't have it" << dendl;
// discover it?
if (m->should_discover()) {
// only try once!
// this is key to avoid a fragtree update race, among other things.
- m->tried_discover();
+ m->inc_tried_discover();
vector<CDentry*> trace;
CInode *in;
filepath path = m->get_path();
int r = path_traverse(null_ref, m, NULL, path, &trace, &in, MDS_TRAVERSE_DISCOVER);
if (r > 0)
return;
- assert(r == 0);
- open_remote_dirfrag(in, m->get_dirfrag().frag,
- new C_MDS_RetryMessage(mds, m));
- return;
+ if (r == 0 &&
+ in->ino() == df.ino &&
+ in->get_approx_dirfrag(df.frag) == NULL) {
+ open_remote_dirfrag(in, df.frag, new C_MDS_RetryMessage(mds, m));
+ return;
+ }
}
m->put();
return;
}
- // update
- dout(5) << "dir_update on " << *dir << dendl;
- dir->dir_rep = m->get_dir_rep();
- dir->dir_rep_by = m->get_dir_rep_by();
-
+ if (!m->has_tried_discover()) {
+ // Update if it already exists. Othwerwise it got updated by discover reply.
+ dout(5) << "dir_update on " << *dir << dendl;
+ dir->dir_rep = m->get_dir_rep();
+ dir->dir_rep_by = m->get_dir_rep_by();
+ }
+
// done
m->put();
}
int32_t discover;
compact_set<int32_t> dir_rep_by;
filepath path;
+ int tried_discover;
public:
mds_rank_t get_source_mds() const { return from_mds; }
dirfrag_t get_dirfrag() const { return dirfrag; }
int get_dir_rep() const { return dir_rep; }
const compact_set<int>& get_dir_rep_by() const { return dir_rep_by; }
- bool should_discover() const { return discover > 0; }
+ bool should_discover() const { return discover > tried_discover; }
const filepath& get_path() const { return path; }
- void tried_discover() {
- if (discover) discover--;
- }
+ bool has_tried_discover() const { return tried_discover > 0; }
+ void inc_tried_discover() { ++tried_discover; }
- MDirUpdate() : Message(MSG_MDS_DIRUPDATE) {}
+ MDirUpdate() : Message(MSG_MDS_DIRUPDATE), tried_discover(0) {}
MDirUpdate(mds_rank_t f,
dirfrag_t dirfrag,
int dir_rep,
compact_set<int>& dir_rep_by,
filepath& path,
bool discover = false) :
- Message(MSG_MDS_DIRUPDATE) {
+ Message(MSG_MDS_DIRUPDATE), tried_discover(0) {
this->from_mds = f;
this->dirfrag = dirfrag;
this->dir_rep = dir_rep;
this->dir_rep_by = dir_rep_by;
- if (discover) this->discover = 5;
- else this->discover = 0;
+ this->discover = discover ? 5 : 0;
this->path = path;
}
private: