]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix infinite loop of MDCache::populate_mydir().
authorYan, Zheng <zheng.z.yan@intel.com>
Thu, 10 Oct 2013 02:35:48 +0000 (10:35 +0800)
committerGreg Farnum <greg@inktank.com>
Wed, 16 Oct 2013 23:08:09 +0000 (16:08 -0700)
make MDCache::populate_mydir() only fetch bare-bone stray dirs.
After all stray dirs are populated, call MDCache::scan_stray_dir(),
it fetches incomplete stray dirs.

Fixes: #4405
Signed-off-by: Yan, Zheng <zheng.z.yan@intel.com>
Reviewed-by: Greg Farnum <greg@inktank.com>
Reviewed-by: Sage Weil <sage@inktank.com>
(cherry picked from commit 007f06ec174d4ee5cfb578c8b3f1c96b2bb0c238)

Conflicts:

src/mds/MDCache.h

Reviewed-by: Greg Farnum <greg@inktank.com>
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/MDS.cc

index b6c37aec53f67cdbfa68b06e793db8124789b040..992730d3c0ab2d46ffc67512ac9ddf66e670a768 100644 (file)
@@ -632,7 +632,7 @@ void MDCache::populate_mydir()
       CDir *dir = strays[i]->get_dirfrag(fg);
       if (!dir)
        dir = strays[i]->get_or_open_dirfrag(this, fg);
-      if (!dir->is_complete()) {
+      if (dir->get_version() == 0) {
        dir->fetch(new C_MDS_RetryOpenRoot(this));
        return;
       }
@@ -653,6 +653,8 @@ void MDCache::populate_mydir()
   assert(!open);    
   open = true;
   mds->queue_waiters(waiting_for_open);
+
+  scan_stray_dir();
 }
 
 void MDCache::open_foreign_mdsdir(inodeno_t ino, Context *fin)
@@ -9125,19 +9127,34 @@ void MDCache::_snaprealm_create_finish(MDRequest *mdr, Mutation *mut, CInode *in
 // -------------------------------------------------------------------------------
 // STRAYS
 
-void MDCache::scan_stray_dir()
+struct C_MDC_RetryScanStray : public Context {
+  MDCache *cache;
+  dirfrag_t next;
+  C_MDC_RetryScanStray(MDCache *c,  dirfrag_t n) : cache(c), next(n) { }
+  void finish(int r) {
+    cache->scan_stray_dir(next);
+  }
+};
+
+void MDCache::scan_stray_dir(dirfrag_t next)
 {
-  dout(10) << "scan_stray_dir" << dendl;
-  
+  dout(10) << "scan_stray_dir " << next << dendl;
+
   list<CDir*> ls;
   for (int i = 0; i < NUM_STRAY; ++i) {
-    if (strays[i]) {
-      strays[i]->get_dirfrags(ls);
-    }
+    if (strays[i]->ino() < next.ino)
+      continue;
+    strays[i]->get_dirfrags(ls);
   }
 
   for (list<CDir*>::iterator p = ls.begin(); p != ls.end(); ++p) {
     CDir *dir = *p;
+    if (dir->dirfrag() < next)
+      continue;
+    if (!dir->is_complete()) {
+      dir->fetch(new C_MDC_RetryScanStray(this, dir->dirfrag()));
+      return;
+    }
     for (CDir::map_t::iterator q = dir->items.begin(); q != dir->items.end(); ++q) {
       CDentry *dn = q->second;
       CDentry::linkage_t *dnl = dn->get_projected_linkage();
index 36a322c6324a2005871d6cd8f18bdd8e824d723a..2574e755c9b7163c37821132be002d44c5a856fd 100644 (file)
@@ -858,7 +858,6 @@ public:
 
   // -- stray --
 public:
-  void scan_stray_dir();
   void eval_stray(CDentry *dn);
   void eval_remote(CDentry *dn);
 
@@ -872,6 +871,7 @@ public:
       eval_stray(dn);
   }
 protected:
+  void scan_stray_dir(dirfrag_t next=dirfrag_t());
   void fetch_backtrace(inodeno_t ino, int64_t pool, bufferlist& bl, Context *fin);
   void remove_backtrace(inodeno_t ino, int64_t pool, Context *fin);
   void _purge_forwarding_pointers(bufferlist& bl, CDentry *dn, int r);
@@ -880,6 +880,7 @@ protected:
   void _purge_stray_purged(CDentry *dn, int r=0);
   void _purge_stray_logged(CDentry *dn, version_t pdv, LogSegment *ls);
   void _purge_stray_logged_truncate(CDentry *dn, LogSegment *ls);
+  friend class C_MDC_RetryScanStray;
   friend class C_MDC_FetchedBacktrace;
   friend class C_MDC_PurgeForwardingPointers;
   friend class C_MDC_PurgeStray;
index 70c5efbec585c027c7e1118c2c51668b6d363389..3a7f7b9339bddc6681c6e12aea38a0e2c88dd83f 100644 (file)
@@ -1520,7 +1520,6 @@ void MDS::active_start()
     mdcache->open_root();
 
   mdcache->clean_open_file_lists();
-  mdcache->scan_stray_dir();
   mdcache->export_remaining_imported_caps();
   finish_contexts(g_ceph_context, waiting_for_replay);  // kick waiters
   finish_contexts(g_ceph_context, waiting_for_active);  // kick waiters