]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: keep import/export subtree_map state in sync with journal
authorSage Weil <sage@newdream.net>
Fri, 15 Apr 2011 22:51:50 +0000 (15:51 -0700)
committerSage Weil <sage@newdream.net>
Fri, 15 Apr 2011 23:32:55 +0000 (16:32 -0700)
We were being sloppy before with the ESubtreeMap vs import/export events.
Fix that by doing a few things:

 - add an ambig flag to the subtree map items, and set it for in-progress
   imports.  That means an ESubtreeMap followed by EImportFinish will do
   the right thing now.
 - adjust the dir_auth on EExport journaling (handle_export_dir_ack) so
   that our journaled subtree_map state is always in sync with what we
   see during replay.

Also document clearly what the dir_auth variations actually mean.

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

index d5e474ffc49f7e893af8b8acf604f950b854d5a8..bae2a70ae8dfd5d15143a08885873485e8f9a49f 100644 (file)
@@ -2198,9 +2198,25 @@ ESubtreeMap *MDCache::create_subtree_map()
        p != subtrees.end();
        ++p) {
     CDir *dir = p->first;
-    if (!dir->is_auth()) continue;
 
-    dout(15) << " subtree " << *dir << dendl;
+    // journal subtree as "ours" if we are
+    //   me, -2
+    //   me, me
+    //   me, !me (may be importing and ambiguous!)
+
+    // so not
+    //   !me, *
+    if (dir->get_dir_auth().first != mds->whoami)
+      continue;
+
+    if (dir->is_ambiguous_dir_auth() &&
+       migrator->is_importing(dir->dirfrag())) {
+      dout(15) << " ambig subtree " << *dir << dendl;
+      le->ambiguous_subtrees.insert(dir->dirfrag());
+    } else {
+      dout(15) << " subtree " << *dir << dendl;
+    }
+
     le->subtrees[dir->dirfrag()].clear();
     le->metablob.add_dir_context(dir, EMetaBlob::TO_ROOT);
     le->metablob.add_dir(dir, false);
@@ -2479,7 +2495,8 @@ void MDCache::handle_mds_recovery(int who)
        ++p) {
     CDir *dir = p->first;
 
-    if (dir->authority().first != who)
+    if (dir->authority().first != who ||
+       dir->authority().second == mds->whoami)
       continue;
     assert(!dir->is_auth());
    
index 25349ae93b4f1ff3df0fd1baf2042419d554b425..67603e9faf1d40ff5f42f12c86cf49e8a14b707f 100644 (file)
 #include "messages/MExportCapsAck.h"
 
 
-
-
+/*
+ * this is what the dir->dir_auth values look like
+ *
+ *   dir_auth  authbits  
+ * export
+ *   me         me      - before
+ *   me, me     me      - still me, but preparing for export
+ *   me, them   me      - send MExportDir (peer is preparing)
+ *   them, me   me      - journaled EExport
+ *   them       them    - done
+ *
+ * import:
+ *   them       them    - before
+ *   me, them   me      - journaled EImportStart
+ *   me         me      - done
+ *
+ * which implies:
+ *  - auth bit is set if i am listed as first _or_ second dir_auth.
+ */
 
 #include "common/config.h"
 
@@ -1217,6 +1234,11 @@ void Migrator::handle_export_ack(MExportDirAck *m)
   set<CDir*> bounds;
   cache->get_subtree_bounds(dir, bounds);
 
+  // list us second, them first.
+  // this keeps authority().first in sync with subtree auth state in the journal.
+  int target = export_peer[dir];
+  cache->adjust_subtree_auth(dir, target, mds->get_nodeid());
+
   // log completion. 
   //  include export bounds, to ensure they're in the journal.
   EExport *le = new EExport(mds->mdlog, dir);
index f7f4090fd063eabd518b0a783e0701b0a22ad19c..0230de1a59ef87ba368c05659b8bdc5caf39dd51 100644 (file)
@@ -22,21 +22,24 @@ class ESubtreeMap : public LogEvent {
 public:
   EMetaBlob metablob;
   map<dirfrag_t, vector<dirfrag_t> > subtrees;
+  set<dirfrag_t> ambiguous_subtrees;
   uint64_t expire_pos;
 
   ESubtreeMap() : LogEvent(EVENT_SUBTREEMAP), expire_pos(0) { }
   
   void print(ostream& out) {
-    out << "subtree_map " << subtrees.size() << " subtrees " 
+    out << "ESubtreeMap " << subtrees.size() << " subtrees " 
+       << ", " << ambiguous_subtrees.size() << " ambiguous "
        << metablob;
   }
 
   void encode(bufferlist& bl) const {
-    __u8 struct_v = 3;
+    __u8 struct_v = 4;
     ::encode(struct_v, bl);
     ::encode(stamp, bl);
     ::encode(metablob, bl);
     ::encode(subtrees, bl);
+    ::encode(ambiguous_subtrees, bl);
     ::encode(expire_pos, bl);
   } 
   void decode(bufferlist::iterator &bl) {
@@ -46,6 +49,8 @@ public:
       ::decode(stamp, bl);
     ::decode(metablob, bl);
     ::decode(subtrees, bl);
+    if (struct_v >= 4)
+      ::decode(ambiguous_subtrees, bl);
     if (struct_v >= 3)
       ::decode(expire_pos, bl);
   }
index 7e77443f9b5a6699bc4bec8180498257ddb54011..814fd8d2cad4812ca7e0724ff7137bb755878aaa 100644 (file)
@@ -1067,7 +1067,15 @@ void ESubtreeMap::replay(MDS *mds)
        p != subtrees.end();
        ++p) {
     CDir *dir = mds->mdcache->get_dirfrag(p->first);
-    mds->mdcache->adjust_bounded_subtree_auth(dir, p->second, mds->get_nodeid());
+    if (ambiguous_subtrees.count(p->first)) {
+      // ambiguous!
+      mds->mdcache->add_ambiguous_import(p->first, p->second);
+      mds->mdcache->adjust_bounded_subtree_auth(dir, p->second,
+                                               pair<int,int>(mds->get_nodeid(), mds->get_nodeid()));
+    } else {
+      // not ambiguous
+      mds->mdcache->adjust_bounded_subtree_auth(dir, p->second, mds->get_nodeid());
+    }
   }
   
   mds->mdcache->show_subtrees();
@@ -1201,9 +1209,9 @@ void EImportFinish::replay(MDS *mds)
     }
   } else {
     dout(10) << "EImportFinish.replay " << base << " success=" << success
-            << ", predates my subtree_map start point, ignoring
+            << " on subtree not marked as ambiguous
             << dendl;
-    // verify that?
+    assert(0 == "this shouldn't happen unless this is an old journal");
   }
 }