From 7432adb36ef6c2112fcbcf34d3b13c5d4d202d42 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 19 Jun 2017 16:28:41 +0800 Subject: [PATCH] mds: handle MDirUpdate race mds may try discover several times for MDirUpdate, rename may kick in and cause MDCache::path_traverse() to return error. Signed-off-by: "Yan, Zheng" --- src/mds/MDCache.cc | 29 +++++++++++++++++------------ src/messages/MDirUpdate.h | 15 +++++++-------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index ebecf6583110c..8ed3a72002081 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -10302,15 +10302,16 @@ int MDCache::send_dir_updates(CDir *dir, bool bcast) /* 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 trace; CInode *in; filepath path = m->get_path(); @@ -10319,21 +10320,25 @@ void MDCache::handle_dir_update(MDirUpdate *m) 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(); } diff --git a/src/messages/MDirUpdate.h b/src/messages/MDirUpdate.h index e282b04d386d0..5752d34c68f74 100644 --- a/src/messages/MDirUpdate.h +++ b/src/messages/MDirUpdate.h @@ -25,33 +25,32 @@ class MDirUpdate : public Message { int32_t discover; compact_set 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& 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& 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: -- 2.39.5