]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: touch missed dentry when fetching dir on path traverse
authorSage Weil <sage@newdream.net>
Fri, 17 Sep 2010 16:46:29 +0000 (09:46 -0700)
committerSage Weil <sage@newdream.net>
Fri, 17 Sep 2010 16:46:29 +0000 (09:46 -0700)
We can get into a loop when doing a path traverse if we miss on a large
directory and then end up trimming the result we need before handling the
original request.  To avoid this, we simply put the wanted dentry at the
top of the LRU (instead of midpoint).

Signed-off-by: Sage Weil <sage@newdream.net>
src/mds/CDir.cc
src/mds/CDir.h
src/mds/MDCache.cc
src/mds/MDCache.h

index a4fb5fb944a382fa0cd49686fca1e1935a1ac862..4d3be3c0ed97c877c189b006250e41a60266b5fb 100644 (file)
@@ -1032,16 +1032,23 @@ void CDir::last_put()
 class C_Dir_Fetch : public Context {
  protected:
   CDir *dir;
+  string want_dn;
  public:
   bufferlist bl;
 
-  C_Dir_Fetch(CDir *d) : dir(d) { }
+  C_Dir_Fetch(CDir *d, const string& w) : dir(d), want_dn(w) { }
   void finish(int result) {
-    dir->_fetched(bl);
+    dir->_fetched(bl, want_dn);
   }
 };
 
 void CDir::fetch(Context *c, bool ignore_authpinnability)
+{
+  string want;
+  return fetch(c, want, ignore_authpinnability);
+}
+
+void CDir::fetch(Context *c, const string& want_dn, bool ignore_authpinnability)
 {
   dout(10) << "fetch on " << *this << dendl;
   
@@ -1068,7 +1075,7 @@ void CDir::fetch(Context *c, bool ignore_authpinnability)
   if (cache->mds->logger) cache->mds->logger->inc(l_mds_dir_f);
 
   // start by reading the first hunk of it
-  C_Dir_Fetch *fin = new C_Dir_Fetch(this);
+  C_Dir_Fetch *fin = new C_Dir_Fetch(this, want_dn);
   object_t oid = get_ondisk_object();
   OSDMap *osdmap = cache->mds->objecter->osdmap;
   ceph_object_layout ol = osdmap->make_object_layout(oid,
@@ -1078,10 +1085,11 @@ void CDir::fetch(Context *c, bool ignore_authpinnability)
   cache->mds->objecter->read(oid, ol, rd, CEPH_NOSNAP, &fin->bl, 0, fin);
 }
 
-void CDir::_fetched(bufferlist &bl)
+void CDir::_fetched(bufferlist &bl, const string& want_dn)
 {
   dout(10) << "_fetched " << bl.length() 
           << " bytes for " << *this
+          << " want_dn=" << want_dn
           << dendl;
   
   assert(is_auth());
@@ -1300,6 +1308,11 @@ void CDir::_fetched(bufferlist &bl)
       assert(0);
     }
     
+    if (dn && want_dn.length() && want_dn == dname) {
+      dout(10) << " touching wanted dn " << *dn << dendl;
+      inode->mdcache->touch_dentry(dn);
+    }
+
     /** clean underwater item?
      * Underwater item is something that is dirty in our cache from
      * journal replay, but was previously flushed to disk before the
index a01e57311e62c7ff79e1f2447e578d737d2c36f5..fca55b095a4d938dcb6c2f52031ea78be652421f 100644 (file)
@@ -438,7 +438,8 @@ private:
     return file_object_t(ino(), frag);
   }
   void fetch(Context *c, bool ignore_authpinnability=false);
-  void _fetched(bufferlist &bl);
+  void fetch(Context *c, const string& want_dn, bool ignore_authpinnability=false);
+  void _fetched(bufferlist &bl, const string& want_dn);
 
   // -- commit --
   map<version_t, list<Context*> > waiting_for_commit;
index e5b61d8f5335a9247b471580ab0a355f17c151a1..0141c7b73850a830b09d91e4fc8fd8528e9150dc 100644 (file)
@@ -6023,7 +6023,7 @@ int MDCache::path_traverse(MDRequest *mdr, Message *req,     // who
        // directory isn't complete; reload
         dout(7) << "traverse: incomplete dir contents for " << *cur << ", fetching" << dendl;
         touch_inode(cur);
-        curdir->fetch(_get_waiter(mdr, req));
+        curdir->fetch(_get_waiter(mdr, req), path[depth]);
        if (mds->logger) mds->logger->inc(l_mds_tdirf);
         return 1;
       }
index c80815d75c76404838a39d4cbca740e56af894d9..9cd96115ea561fbbcef0037dd94ad43a58738eda 100644 (file)
@@ -879,6 +879,7 @@ public:
     if (in->get_parent_dn())
       touch_dentry(in->get_projected_parent_dn());
   }
+public:
   void touch_dentry(CDentry *dn) {
     // touch ancestors
     if (dn->get_dir()->get_inode()->get_projected_parent_dn())
@@ -890,7 +891,6 @@ public:
     else
       lru.lru_midtouch(dn);
   }
-public:
   void touch_dentry_bottom(CDentry *dn) {
     lru.lru_bottouch(dn);
   }