From 455b8423e6898f053a92eb3dd8d8acaa128625c0 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 21 Nov 2008 14:34:40 -0800 Subject: [PATCH] mds: add version to anchor; avoid looping in open_remote_ino If we do not find the item referenced by teh anchor trace, we try again, but keep track of the anchor version we ended on. If we hit a dead end at the same point next time and the anchor hasn't changed, we give up. --- src/mds/Anchor.h | 15 +++++++++------ src/mds/AnchorServer.cc | 6 ++++-- src/mds/CDentry.cc | 2 +- src/mds/MDCache.cc | 39 +++++++++++++++++++++++++-------------- src/mds/MDCache.h | 3 ++- src/mds/Server.cc | 1 + 6 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/mds/Anchor.h b/src/mds/Anchor.h index b07ee6ffa7280..ceaa54ea13c15 100644 --- a/src/mds/Anchor.h +++ b/src/mds/Anchor.h @@ -35,33 +35,36 @@ public: inodeno_t dirino; __u32 dn_hash; int nref; // reference count + version_t updated; - Anchor() : dn_hash(0), nref(0) {} - Anchor(inodeno_t i, inodeno_t di, __u32 hash, int nr=0) : - ino(i), dirino(di), dn_hash(hash), nref(nr) { } - Anchor(inodeno_t i, inodeno_t di, const nstring &dname, int nr=0) : + Anchor() : dn_hash(0), nref(0), updated(0) {} + Anchor(inodeno_t i, inodeno_t di, __u32 hash, int nr, version_t u) : + ino(i), dirino(di), dn_hash(hash), nref(nr), updated(u) { } + Anchor(inodeno_t i, inodeno_t di, const nstring &dname, int nr, version_t u) : ino(i), dirino(di), dn_hash(ceph_full_name_hash(dname.data(), dname.length())), - nref(nr) { } + nref(nr), updated(u) { } void encode(bufferlist &bl) const { ::encode(ino, bl); ::encode(dirino, bl); ::encode(dn_hash, bl); ::encode(nref, bl); + ::encode(updated, bl); } void decode(bufferlist::iterator &bl) { ::decode(ino, bl); ::decode(dirino, bl); ::decode(dn_hash, bl); ::decode(nref, bl); + ::decode(updated, bl); } }; WRITE_CLASS_ENCODER(Anchor) inline ostream& operator<<(ostream& out, const Anchor &a) { - return out << "a(" << a.ino << " " << a.dirino << "/" << a.dn_hash << " " << a.nref << ")"; + return out << "a(" << a.ino << " " << a.dirino << "/" << a.dn_hash << " " << a.nref << " v" << a.updated << ")"; } #endif diff --git a/src/mds/AnchorServer.cc b/src/mds/AnchorServer.cc index 74ceb22b2664d..67c9660c95df3 100644 --- a/src/mds/AnchorServer.cc +++ b/src/mds/AnchorServer.cc @@ -63,7 +63,7 @@ bool AnchorServer::add(inodeno_t ino, inodeno_t dirino, __u32 dn_hash) if (anchor_map.count(ino) == 0) { // new item - anchor_map[ino] = Anchor(ino, dirino, dn_hash); + anchor_map[ino] = Anchor(ino, dirino, dn_hash, 0, version); dout(7) << "add added " << anchor_map[ino] << dendl; return true; } else { @@ -81,6 +81,7 @@ void AnchorServer::inc(inodeno_t ino) while (1) { Anchor &anchor = anchor_map[ino]; anchor.nref++; + anchor.updated = version; dout(10) << "inc now " << anchor << dendl; ino = anchor.dirino; @@ -98,7 +99,8 @@ void AnchorServer::dec(inodeno_t ino) while (true) { Anchor &anchor = anchor_map[ino]; anchor.nref--; - + anchor.updated = version; + if (anchor.nref == 0) { dout(10) << "dec removing " << anchor << dendl; inodeno_t dirino = anchor.dirino; diff --git a/src/mds/CDentry.cc b/src/mds/CDentry.cc index aecd9c82a9eb4..7a56e4984fa08 100644 --- a/src/mds/CDentry.cc +++ b/src/mds/CDentry.cc @@ -250,7 +250,7 @@ void CDentry::make_anchor_trace(vector& trace, CInode *in) dir->inode->make_anchor_trace(trace); // add this inode (in my dirfrag) to the end - trace.push_back(Anchor(in->ino(), dir->ino(), name)); + trace.push_back(Anchor(in->ino(), dir->ino(), name, 0, 0)); dout(10) << "make_anchor_trace added " << trace.back() << dendl; } diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 1967d1de3b2eb..a0ac89504d03b 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -5625,20 +5625,21 @@ public: class C_MDC_OpenRemoteIno : public Context { MDCache *mdcache; inodeno_t ino; + inodeno_t hadino; + version_t hadv; Context *onfinish; public: vector anchortrace; - C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, Context *c) : - mdcache(mdc), ino(i), onfinish(c) {} - C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, vector& at, - Context *c) : - mdcache(mdc), ino(i), onfinish(c), anchortrace(at) {} + C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, inodeno_t hi, version_t hv, Context *c) : + mdcache(mdc), ino(i), hadino(hi), hadv(hv), onfinish(c) {} + C_MDC_OpenRemoteIno(MDCache *mdc, inodeno_t i, vector& at, Context *c) : + mdcache(mdc), ino(i), hadino(0), hadv(0), onfinish(c), anchortrace(at) {} void finish(int r) { assert(r == 0); if (r == 0) - mdcache->open_remote_ino_2(ino, anchortrace, onfinish); + mdcache->open_remote_ino_2(ino, anchortrace, hadino, hadv, onfinish); else { onfinish->finish(r); delete onfinish; @@ -5646,16 +5647,17 @@ public: } }; -void MDCache::open_remote_ino(inodeno_t ino, Context *onfinish) +void MDCache::open_remote_ino(inodeno_t ino, Context *onfinish, inodeno_t hadino, version_t hadv) { dout(7) << "open_remote_ino on " << ino << dendl; - C_MDC_OpenRemoteIno *c = new C_MDC_OpenRemoteIno(this, ino, onfinish); + C_MDC_OpenRemoteIno *c = new C_MDC_OpenRemoteIno(this, ino, hadino, hadv, onfinish); mds->anchorclient->lookup(ino, c->anchortrace, c); } void MDCache::open_remote_ino_2(inodeno_t ino, vector& anchortrace, + inodeno_t hadino, version_t hadv, Context *onfinish) { dout(7) << "open_remote_ino_2 on " << ino @@ -5729,12 +5731,21 @@ void MDCache::open_remote_ino_2(inodeno_t ino, if (dir->is_auth()) { if (dir->is_complete()) { - // hrm. requery anchor table. - dout(10) << "expected ino " << anchortrace[i].ino - << " in complete dir " << *dir - << ", requerying anchortable" - << dendl; - open_remote_ino(ino, onfinish); + // make sure we didn't get to the same version anchor 2x in a row + if (hadv && hadino == anchortrace[i].ino && hadv == anchortrace[i].updated) { + dout(10) << "expected ino " << anchortrace[i].ino + << " in complete dir " << *dir + << ", got same anchor " << anchortrace[i] << " 2x in a row" << dendl; + onfinish->finish(-ENOENT); + delete onfinish; + } else { + // hrm. requery anchor table. + dout(10) << "expected ino " << anchortrace[i].ino + << " in complete dir " << *dir + << ", requerying anchortable" + << dendl; + open_remote_ino(ino, onfinish, anchortrace[i].ino, anchortrace[i].updated); + } } else { dout(10) << "need ino " << anchortrace[i].ino << ", fetching incomplete dir " << *dir diff --git a/src/mds/MDCache.h b/src/mds/MDCache.h index c29b9906fd0f7..ee1b9b3821a15 100644 --- a/src/mds/MDCache.h +++ b/src/mds/MDCache.h @@ -855,9 +855,10 @@ public: void open_remote_dirfrag(CInode *diri, frag_t fg, Context *fin); CInode *get_dentry_inode(CDentry *dn, MDRequest *mdr); - void open_remote_ino(inodeno_t ino, Context *fin); + void open_remote_ino(inodeno_t ino, Context *fin, inodeno_t hadino=0, version_t hadv=0); void open_remote_ino_2(inodeno_t ino, vector& anchortrace, + inodeno_t hadino, version_t hadv, Context *onfinish); C_Gather *parallel_fetch(map& pathmap); diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 5afcac63fd444..185ba27dfa122 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -2038,6 +2038,7 @@ void Server::handle_client_readdir(MDRequest *mdr) if (in) { dn->link_remote(in); } else { + dout(10) << "opening remote ino for " << *dn << dendl; mdcache->open_remote_ino(dn->get_remote_ino(), new C_MDS_RetryRequest(mdcache, mdr)); -- 2.39.5