]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: add version to anchor; avoid looping in open_remote_ino
authorSage Weil <sage@newdream.net>
Fri, 21 Nov 2008 22:34:40 +0000 (14:34 -0800)
committerSage Weil <sage@newdream.net>
Fri, 21 Nov 2008 22:34:40 +0000 (14:34 -0800)
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
src/mds/AnchorServer.cc
src/mds/CDentry.cc
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/Server.cc

index b07ee6ffa7280ca123db5ba98568186045c4255d..ceaa54ea13c1526b4625eff91afdf5d9cdf62bb6 100644 (file)
@@ -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
index 74ceb22b2664d065ff759c4aca0b63428a919d89..67c9660c95df39e05fbadd4a5729259c1882928e 100644 (file)
@@ -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;
index aecd9c82a9eb43deb26a671e037811e50885b0c2..7a56e4984fa08d8700619a8fdfcb56f228a089a3 100644 (file)
@@ -250,7 +250,7 @@ void CDentry::make_anchor_trace(vector<Anchor>& 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;
 }
 
index 1967d1de3b2eb4bfed70cd19e6e5adf6d5f4a9d2..a0ac89504d03b8b1d05efe7347a4e348c3a3615e 100644 (file)
@@ -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<Anchor> 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<Anchor>& 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<Anchor>& 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<Anchor>& 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
index c29b9906fd0f732c33040004f00ba63ea195b67b..ee1b9b3821a15ba4aa77bba6ea723938f202c383 100644 (file)
@@ -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<Anchor>& anchortrace,
+                        inodeno_t hadino, version_t hadv,
                          Context *onfinish);
 
   C_Gather *parallel_fetch(map<inodeno_t,string>& pathmap);
index 5afcac63fd4443c4a3bbb2f8fe761a228ca6cc8d..185ba27dfa12257d71d4f57fc88d030743199385 100644 (file)
@@ -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));