]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
import/export stable with new subtree infrastructure. now to fix recovery.
authorsageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Mon, 26 Feb 2007 18:13:44 +0000 (18:13 +0000)
committersageweil <sageweil@29311d96-e01e-0410-9327-a35deaab8ce9>
Mon, 26 Feb 2007 18:13:44 +0000 (18:13 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@1132 29311d96-e01e-0410-9327-a35deaab8ce9

16 files changed:
branches/sage/cephmds2/client/Client.cc
branches/sage/cephmds2/mds/CDir.cc
branches/sage/cephmds2/mds/CDir.h
branches/sage/cephmds2/mds/Locker.cc
branches/sage/cephmds2/mds/MDBalancer.cc
branches/sage/cephmds2/mds/MDCache.cc
branches/sage/cephmds2/mds/MDCache.h
branches/sage/cephmds2/mds/MDS.cc
branches/sage/cephmds2/mds/MDSMap.h
branches/sage/cephmds2/mds/MDStore.cc
branches/sage/cephmds2/mds/Migrator.cc
branches/sage/cephmds2/mds/Migrator.h
branches/sage/cephmds2/mds/Renamer.cc
branches/sage/cephmds2/mds/journal.cc
branches/sage/cephmds2/messages/MExportDirNotify.h
branches/sage/cephmds2/messages/MOSDOpReply.h

index f2f8f07432d4d32f7773ab6169c4ac70124c4c4a..60497b4e8862032a90393d911323ff2387236ab9 100644 (file)
@@ -1787,12 +1787,10 @@ int Client::getdir(const char *relpath, map<string,inode_t>& contents)
         contents[*pdn] = in->inode;
       }
     }
-    
+
     // add .. too?
-    if (diri != root && diri->dn && diri->dn->dir) {
-      Inode *parent = diri->dn->dir->parent_inode;
-      contents[".."] = parent->inode;
-    }    
+    if (diri != root) 
+      contents[".."] = diri->inode;
 
     // FIXME: remove items in cache that weren't in my readdir?
     // ***
index dd996edcdd0ea4ba7ca6e7913a7dda8b80328916..03ff1b6f809c4292349163f64230056619cf13a7 100644 (file)
@@ -59,14 +59,19 @@ ostream& operator<<(ostream& out, CDir& dir)
   if (dir.get_dir_auth() != CDIR_AUTH_DEFAULT) 
     out << " dir_auth=" << dir.get_dir_auth();
   
+  if (dir.get_cum_auth_pins())
+    out << " ap=" << dir.get_auth_pins() << "+" << dir.get_nested_auth_pins();
+
   out << " state=" << dir.get_state();
-  if (dir.state_test(CDIR_STATE_PROXY)) out << "|proxy";
-  if (dir.state_test(CDIR_STATE_COMPLETE)) out << "|complete";
-  if (dir.state_test(CDIR_STATE_FREEZINGTREE)) out << "|freezingtree";
-  if (dir.state_test(CDIR_STATE_FROZENTREE)) out << "|frozentree";
-  //if (dir.state_test(CDIR_STATE_FROZENTREELEAF)) out << "|frozentreeleaf";
-  if (dir.state_test(CDIR_STATE_FROZENDIR)) out << "|frozendir";
-  if (dir.state_test(CDIR_STATE_FREEZINGDIR)) out << "|freezingdir";
+  if (dir.state_test(CDir::STATE_PROXY)) out << "|proxy";
+  if (dir.state_test(CDir::STATE_COMPLETE)) out << "|complete";
+  if (dir.state_test(CDir::STATE_FREEZINGTREE)) out << "|freezingtree";
+  if (dir.state_test(CDir::STATE_FROZENTREE)) out << "|frozentree";
+  //if (dir.state_test(CDir::STATE_FROZENTREELEAF)) out << "|frozentreeleaf";
+  if (dir.state_test(CDir::STATE_FROZENDIR)) out << "|frozendir";
+  if (dir.state_test(CDir::STATE_FREEZINGDIR)) out << "|freezingdir";
+  if (dir.state_test(CDir::STATE_EXPORTBOUND)) out << "|exportbound";
+  if (dir.state_test(CDir::STATE_IMPORTBOUND)) out << "|importbound";
 
   out << " sz=" << dir.get_nitems() << "+" << dir.get_nnull();
   
@@ -93,7 +98,7 @@ CDir::CDir(CInode *in, MDCache *mdcache, bool auth)
   
   nitems = 0;
   nnull = 0;
-  state = CDIR_STATE_INITIAL;
+  state = STATE_INITIAL;
 
   projected_version = version = 0;
   committing_version = 0;
@@ -107,11 +112,11 @@ CDir::CDir(CInode *in, MDCache *mdcache, bool auth)
   // auth
   assert(in->is_dir());
   if (auth) 
-    state |= CDIR_STATE_AUTH;
+    state |= STATE_AUTH;
   /*
   if (in->dir_is_hashed()) {
     assert(0);                      // when does this happen?  
-    state |= CDIR_STATE_HASHED;
+    state |= STATE_HASHED;
   }
   */
  
@@ -119,8 +124,8 @@ CDir::CDir(CInode *in, MDCache *mdcache, bool auth)
   nested_auth_pins = 0;
   request_pins = 0;
   
-  //dir_rep = CDIR_REP_NONE;
-  dir_rep = CDIR_REP_ALL;      // hack: to wring out some bugs! FIXME FIXME
+  //dir_rep = REP_NONE;
+  dir_rep = REP_ALL;      // hack: to wring out some bugs! FIXME FIXME
 }
 
 
@@ -476,7 +481,8 @@ void CDir::finish_waiting(int mask, int result)
 
   list<Context*> finished;
   take_waiting(mask, finished);
-  finish_contexts(finished, result);
+  //finish_contexts(finished, result);
+  cache->mds->queue_finished(finished);
 }
 
 void CDir::finish_waiting(int mask, const string& dn, int result) 
@@ -485,7 +491,8 @@ void CDir::finish_waiting(int mask, const string& dn, int result)
 
   list<Context*> finished;
   take_waiting(mask, dn, finished);
-  finish_contexts(finished, result);
+  //finish_contexts(finished, result);
+  cache->mds->queue_finished(finished);
 }
 
 
@@ -500,8 +507,8 @@ version_t CDir::pre_dirty()
 
 void CDir::_mark_dirty()
 {
-  if (!state_test(CDIR_STATE_DIRTY)) {
-    state_set(CDIR_STATE_DIRTY);
+  if (!state_test(STATE_DIRTY)) {
+    state_set(STATE_DIRTY);
     dout(10) << "mark_dirty (was clean) " << *this << " version " << version << endl;
     get(PIN_DIRTY);
   } else {
@@ -519,8 +526,8 @@ void CDir::mark_dirty(version_t pv)
 void CDir::mark_clean()
 {
   dout(10) << "mark_clean " << *this << " version " << version << endl;
-  if (state_test(CDIR_STATE_DIRTY)) {
-    state_clear(CDIR_STATE_DIRTY);
+  if (state_test(STATE_DIRTY)) {
+    state_clear(STATE_DIRTY);
     put(PIN_DIRTY);
   }
 }
@@ -550,6 +557,12 @@ void CDir::last_put()
  */
 pair<int,int> CDir::authority() 
 {
+  if (is_subtree_root()) 
+    return dir_auth;
+
+  return inode->authority();
+}
+/*
   pair<int,int> a = dir_auth;
   
   // look at parent?
@@ -561,6 +574,7 @@ pair<int,int> CDir::authority()
   else 
     return pair<int,int>(a.first, dir_auth.second);
 }
+*/
 
 /** is_subtree_root()
  * true if this is an auth delegation point.  
@@ -574,10 +588,15 @@ pair<int,int> CDir::authority()
  */
 bool CDir::is_subtree_root()
 {
-  if (dir_auth == CDIR_AUTH_DEFAULT)
+  if (dir_auth == CDIR_AUTH_DEFAULT) {
+    //dout(10) << "is_subtree_root false " << dir_auth << " != " << CDIR_AUTH_DEFAULT
+    //<< " on " << ino() << endl;
     return false;
-  else
+  } else {
+    //dout(10) << "is_subtree_root true " << dir_auth << " != " << CDIR_AUTH_DEFAULT
+    //<< " on " << ino() << endl;
     return true;
+  }
 }
 
 
@@ -613,6 +632,8 @@ pair<int,int> CDir::dentry_authority(const string& dn)
 
 
 /** set_dir_auth
+ *
+ * always list ourselves first.
  *
  * accept 'iamauth' param so that i can intelligently adjust freeze auth_pins
  * even when the auth bit isn't correct.  
@@ -631,17 +652,17 @@ void CDir::set_dir_auth(pair<int,int> a, bool iamauth)
 
   // new subtree root?
   if (!was_subtree && is_subtree_root()) {
-    dout(10) << "new subtree root, adjusting auth_pins" << endl;
+    dout(10) << " new subtree root, adjusting auth_pins" << endl;
     
     // adjust nested auth pins
-    inode->adjust_nested_auth_pins(get_cum_auth_pins());
+    inode->adjust_nested_auth_pins(-get_cum_auth_pins());
     
-    // pin parent of frozen dir/tree?
-    if (iamauth && (is_frozen_tree_root() || is_frozen_dir()))
-      inode->auth_pin();
+    // unpin parent of frozen dir/tree?
+    if (inode->is_auth() && (is_frozen_tree_root() || is_frozen_dir()))
+      inode->auth_unpin();
   } 
   if (was_subtree && !is_subtree_root()) {
-    dout(10) << "old subtree root, adjusting auth_pins" << endl;
+    dout(10) << " old subtree root, adjusting auth_pins" << endl;
     
     // adjust nested auth pins
     inode->adjust_nested_auth_pins(get_cum_auth_pins());
@@ -692,7 +713,7 @@ void CDir::auth_unpin()
   assert(auth_pins >= 0);
   
   // pending freeze?
-  if (auth_pins + nested_auth_pins == 0)
+  if (auth_pins + nested_auth_pins == 0) 
     on_freezeable();
   
   // nest?
@@ -711,7 +732,7 @@ void CDir::adjust_nested_auth_pins(int inc)
   // dir
   dir->nested_auth_pins += inc;
   
-  dout(10) << "adjust_nested_auth_pins on " << *dir << " count now " << dir->auth_pins << " + " << dir->nested_auth_pins << endl;
+  dout(10) << "adjust_nested_auth_pins " << inc << " on " << *dir << " count now " << dir->auth_pins << " + " << dir->nested_auth_pins << endl;
   assert(dir->nested_auth_pins >= 0);
   
   // pending freeze?
@@ -772,7 +793,7 @@ void CDir::freeze_tree(Context *c)
     dout(10) << "freeze_tree " << *this << endl;
     _freeze_tree(c);
   } else {
-    state_set(CDIR_STATE_FREEZINGTREE);
+    state_set(STATE_FREEZINGTREE);
     dout(10) << "freeze_tree + wait " << *this << endl;
     
     // need to wait for auth pins to expire
@@ -786,7 +807,7 @@ void CDir::freeze_tree_finish(Context *c)
   if (!is_freezeable()) {
     // wait again!
     dout(10) << "freeze_tree_finish still waiting " << *this << endl;
-    state_set(CDIR_STATE_FREEZINGTREE);
+    state_set(STATE_FREEZINGTREE);
     add_waiter(CDIR_WAIT_FREEZEABLE, new C_MDS_FreezeTree(this, c));
     return;
   }
@@ -803,8 +824,8 @@ void CDir::_freeze_tree(Context *c)
   assert(is_freezeable_dir());
 
   // twiddle state
-  state_clear(CDIR_STATE_FREEZINGTREE);   // actually, this may get set again by next context?
-  state_set(CDIR_STATE_FROZENTREE);
+  state_clear(STATE_FREEZINGTREE);   // actually, this may get set again by next context?
+  state_set(STATE_FROZENTREE);
 
   // auth_pin inode for duration of freeze, if we are not a subtree root.
   if (is_auth() && !is_subtree_root())
@@ -821,9 +842,9 @@ void CDir::unfreeze_tree()
 {
   dout(10) << "unfreeze_tree " << *this << endl;
 
-  if (state_test(CDIR_STATE_FROZENTREE)) {
+  if (state_test(STATE_FROZENTREE)) {
     // frozen.  unfreeze.
-    state_clear(CDIR_STATE_FROZENTREE);
+    state_clear(STATE_FROZENTREE);
 
     // unpin  (may => FREEZEABLE)   FIXME: is this order good?
     if (is_auth() && !is_subtree_root())
@@ -833,8 +854,8 @@ void CDir::unfreeze_tree()
     finish_waiting(CDIR_WAIT_UNFREEZE);
   } else {
     // freezing.  stop it.
-    assert(state_test(CDIR_STATE_FREEZINGTREE));
-    state_clear(CDIR_STATE_FREEZINGTREE);
+    assert(state_test(STATE_FREEZINGTREE));
+    state_clear(STATE_FREEZINGTREE);
     
     // cancel freeze waiters
     finish_waiting(CDIR_WAIT_FREEZEABLE, -1);
@@ -908,7 +929,7 @@ void CDir::freeze_dir(Context *c)
     dout(10) << "freeze_dir " << *this << endl;
     _freeze_dir(c);
   } else {
-    state_set(CDIR_STATE_FREEZINGDIR);
+    state_set(STATE_FREEZINGDIR);
     dout(10) << "freeze_dir + wait " << *this << endl;
     
     // need to wait for auth pins to expire
@@ -920,7 +941,7 @@ void CDir::_freeze_dir(Context *c)
 {  
   dout(10) << "_freeze_dir " << *this << endl;
 
-  state_set(CDIR_STATE_FROZENDIR);
+  state_set(STATE_FROZENDIR);
 
   if (is_auth() && !is_subtree_root())
     inode->auth_pin();  // auth_pin for duration of freeze
@@ -940,7 +961,7 @@ void CDir::freeze_dir_finish(Context *c)
   } else {
     // wait again!
     dout(10) << "freeze_dir_finish still waiting " << *this << endl;
-    state_set(CDIR_STATE_FREEZINGDIR);
+    state_set(STATE_FREEZINGDIR);
     add_waiter(CDIR_WAIT_FREEZEABLE, new C_MDS_FreezeDir(this, c));
   }
 }
@@ -948,7 +969,7 @@ void CDir::freeze_dir_finish(Context *c)
 void CDir::unfreeze_dir()
 {
   dout(10) << "unfreeze_dir " << *this << endl;
-  state_clear(CDIR_STATE_FROZENDIR);
+  state_clear(STATE_FROZENDIR);
   
   // unpin  (may => FREEZEABLE)   FIXME: is this order good?
   if (is_auth() && !is_subtree_root())
@@ -989,9 +1010,9 @@ void CDir::dump(int depth) {
     iter++;
   }
 
-  if (!(state_test(CDIR_STATE_COMPLETE)))
+  if (!(state_test(STATE_COMPLETE)))
     dout(10) << ind << "..." << endl;
-  if (state_test(CDIR_STATE_DIRTY))
+  if (state_test(STATE_DIRTY))
     dout(10) << ind << "[dirty]" << endl;
 
 }
index 9dfd6d46f5071a661e4d7c0558ffa2aff66a8be5..4673ab246963c2fda634de0c786ee3baecdb9018 100644 (file)
@@ -53,61 +53,8 @@ class Context;
 #define CDIR_NONCE_EXPORT   1
 
 
-// state bits
-#define CDIR_STATE_AUTH          (1<<0)   // auth for this dir (hashing doesn't count)
-#define CDIR_STATE_PROXY         (1<<1)   // proxy auth
 
-#define CDIR_STATE_COMPLETE      (1<<2)   // the complete contents are in cache
-#define CDIR_STATE_DIRTY         (1<<3)   // has been modified since last commit
 
-#define CDIR_STATE_FROZENTREE     (1<<4)   // root of tree (bounded by exports)
-#define CDIR_STATE_FREEZINGTREE   (1<<5)   // in process of freezing 
-//#define CDIR_STATE_FROZENTREELEAF (1<<6)   // outer bound of frozen region (on import)
-#define CDIR_STATE_FROZENDIR      (1<<7)
-#define CDIR_STATE_FREEZINGDIR    (1<<8)
-
-#define CDIR_STATE_COMMITTING     (1<<9)   // mid-commit
-#define CDIR_STATE_FETCHING       (1<<10)   // currenting fetching
-
-#define CDIR_STATE_DELETED        (1<<11)
-
-#define CDIR_STATE_IMPORT       (1<<12)   // flag set if this is an import.
-#define CDIR_STATE_EXPORT       (1<<13)
-#define CDIR_STATE_IMPORTBOUND  (1<<14)
-#define CDIR_STATE_EXPORTBOUND  (1<<15)
-
-#define CDIR_STATE_HASHED           (1<<16)   // if hashed
-#define CDIR_STATE_HASHING          (1<<17)
-#define CDIR_STATE_UNHASHING        (1<<18)
-
-
-
-
-
-// these state bits are preserved by an import/export
-// ...except if the directory is hashed, in which case none of them are!
-#define CDIR_MASK_STATE_EXPORTED    (CDIR_STATE_COMPLETE\
-                                    |CDIR_STATE_DIRTY)  
-#define CDIR_MASK_STATE_IMPORT_KEPT (CDIR_STATE_IMPORT\
-                                    |CDIR_STATE_EXPORT\
-                                    |CDIR_STATE_IMPORTBOUND\
-                                    |CDIR_STATE_FROZENTREE\
-                                    |CDIR_STATE_PROXY)
-
-#define CDIR_MASK_STATE_EXPORT_KEPT (CDIR_STATE_HASHED\
-                                    |CDIR_STATE_FROZENTREE\
-                                    |CDIR_STATE_FROZENDIR\
-                                    |CDIR_STATE_EXPORT\
-                                    |CDIR_STATE_PROXY)
-
-// common states
-#define CDIR_STATE_CLEAN   0
-#define CDIR_STATE_INITIAL 0  
-
-// directory replication
-#define CDIR_REP_ALL       1
-#define CDIR_REP_NONE      0
-#define CDIR_REP_LIST      2
 
 
 
@@ -218,6 +165,52 @@ class CDir : public MDSCacheObject {
     }
   }
 
+  // -- state --
+  static const unsigned STATE_AUTH =          (1<< 0);   // auth for this dir (hashing doesn't count)
+  static const unsigned STATE_PROXY =         (1<< 1);   // proxy auth
+  static const unsigned STATE_COMPLETE =      (1<< 2);   // the complete contents are in cache
+  static const unsigned STATE_DIRTY =         (1<< 3);   // has been modified since last commit
+  static const unsigned STATE_FROZENTREE =    (1<< 4);   // root of tree (bounded by exports)
+  static const unsigned STATE_FREEZINGTREE =  (1<< 5);   // in process of freezing 
+  static const unsigned STATE_FROZENDIR =     (1<< 6);
+  static const unsigned STATE_FREEZINGDIR =   (1<< 7);
+  static const unsigned STATE_COMMITTING =    (1<< 8);   // mid-commit
+  static const unsigned STATE_FETCHING =      (1<< 9);   // currenting fetching
+  static const unsigned STATE_DELETED =       (1<<10);
+  static const unsigned STATE_IMPORT =        (1<<11);   // flag set if this is an import.
+  static const unsigned STATE_EXPORT =        (1<<12);
+  static const unsigned STATE_IMPORTBOUND =   (1<<13);
+  static const unsigned STATE_EXPORTBOUND =   (1<<14);
+  static const unsigned STATE_HASHED =        (1<<15);   // if hashed
+  static const unsigned STATE_HASHING =       (1<<16);
+  static const unsigned STATE_UNHASHING =     (1<<17);
+
+  // common states
+  static const unsigned STATE_CLEAN =  0;
+  static const unsigned STATE_INITIAL = 0;
+
+  // these state bits are preserved by an import/export
+  // ...except if the directory is hashed, in which case none of them are!
+  static const unsigned MASK_STATE_EXPORTED = 
+  STATE_COMPLETE|STATE_DIRTY;
+  static const unsigned MASK_STATE_IMPORT_KEPT = 
+  STATE_IMPORT|STATE_EXPORT
+  |STATE_IMPORTBOUND|STATE_EXPORTBOUND
+  |STATE_FROZENTREE|STATE_PROXY;
+  static const unsigned MASK_STATE_EXPORT_KEPT = 
+  STATE_HASHED 
+  |STATE_IMPORTBOUND|STATE_EXPORTBOUND
+  |STATE_FROZENTREE
+  |STATE_FROZENDIR
+  |STATE_EXPORT
+  |STATE_PROXY;
+
+  // -- rep spec --
+  static const int REP_NONE =     0;
+  static const int REP_ALL =      1;
+  static const int REP_LIST =     2;
+
+
 
  public:
   // context
@@ -260,7 +253,7 @@ class CDir : public MDSCacheObject {
 
   // cache control  (defined for authority; hints for replicas)
   int              dir_rep;
-  set<int>         dir_rep_by;      // if dir_rep == CDIR_REP_LIST
+  set<int>         dir_rep_by;      // if dir_rep == REP_LIST
 
   // popularity
   meta_load_t popularity[MDS_NPOP];
@@ -335,18 +328,22 @@ class CDir : public MDSCacheObject {
   pair<int,int> authority();
   pair<int,int> dentry_authority(const string& d);
   pair<int,int> get_dir_auth() { return dir_auth; }
-  //int get_dir_auth_pending() { return dir_auth->second; }
   void set_dir_auth(pair<int,int> a, bool iamauth=false);
-  void set_dir_auth(int a, bool iamauth=false) { 
-    set_dir_auth(pair<int,int>(a, dir_auth.second), iamauth); 
+  void set_dir_auth(int a) { 
+    set_dir_auth(pair<int,int>(a, CDIR_AUTH_UNKNOWN), false); 
   }
-  void set_dir_auth_pending(int b) { 
-    set_dir_auth(pair<int,int>(dir_auth.first, b)); 
+  bool auth_is_ambiguous() {
+    return dir_auth.second != CDIR_AUTH_UNKNOWN;
   }
-
+  bool is_fullauth() {
+    return is_auth() && !auth_is_ambiguous();
+  }
+  bool is_fullnonauth() {
+    return !is_auth() && !auth_is_ambiguous();
+  }
+  
   bool is_subtree_root();
 
-
  
 
   // for giving to clients
@@ -364,20 +361,20 @@ class CDir : public MDSCacheObject {
 
 
   // -- state --
-  bool is_complete() { return state & CDIR_STATE_COMPLETE; }
-  bool is_dirty() { return state_test(CDIR_STATE_DIRTY); }
+  bool is_complete() { return state & STATE_COMPLETE; }
+  bool is_dirty() { return state_test(STATE_DIRTY); }
 
-  bool is_auth() { return state & CDIR_STATE_AUTH; }
-  bool is_proxy() { return state & CDIR_STATE_PROXY; }
-  bool is_import() { return state & CDIR_STATE_IMPORT; }
-  bool is_export() { return state & CDIR_STATE_EXPORT; }
+  bool is_auth() { return state & STATE_AUTH; }
+  bool is_proxy() { return state & STATE_PROXY; }
+  bool is_import() { return state & STATE_IMPORT; }
+  bool is_export() { return state & STATE_EXPORT; }
 
-  bool is_hashed() { return state & CDIR_STATE_HASHED; }
-  bool is_hashing() { return state & CDIR_STATE_HASHING; }
-  bool is_unhashing() { return state & CDIR_STATE_UNHASHING; }
+  bool is_hashed() { return state & STATE_HASHED; }
+  bool is_hashing() { return state & STATE_HASHING; }
+  bool is_unhashing() { return state & STATE_UNHASHING; }
 
   bool is_rep() { 
-    if (dir_rep == CDIR_REP_NONE) return false;
+    if (dir_rep == REP_NONE) return false;
     return true;
   }
  
@@ -398,8 +395,8 @@ class CDir : public MDSCacheObject {
   void _mark_dirty();
   void mark_dirty(version_t pv);
   void mark_clean();
-  void mark_complete() { state_set(CDIR_STATE_COMPLETE); }
-  bool is_clean() { return !state_test(CDIR_STATE_DIRTY); }
+  void mark_complete() { state_set(STATE_COMPLETE); }
+  bool is_clean() { return !state_test(STATE_DIRTY); }
 
 
 
@@ -438,6 +435,8 @@ class CDir : public MDSCacheObject {
   bool can_auth_pin() { return !(is_frozen() || is_freezing()); }
   int is_auth_pinned() { return auth_pins; }
   int get_cum_auth_pins() { return auth_pins + nested_auth_pins; }
+  int get_auth_pins() { return auth_pins; }
+  int get_nested_auth_pins() { return nested_auth_pins; }
   void auth_pin();
   void auth_unpin();
   void adjust_nested_auth_pins(int inc);
@@ -456,13 +455,13 @@ class CDir : public MDSCacheObject {
 
   bool is_freezing() { return is_freezing_tree() || is_freezing_dir(); }
   bool is_freezing_tree();
-  bool is_freezing_tree_root() { return state & CDIR_STATE_FREEZINGTREE; }
-  bool is_freezing_dir() { return state & CDIR_STATE_FREEZINGDIR; }
+  bool is_freezing_tree_root() { return state & STATE_FREEZINGTREE; }
+  bool is_freezing_dir() { return state & STATE_FREEZINGDIR; }
 
   bool is_frozen() { return is_frozen_dir() || is_frozen_tree(); }
   bool is_frozen_tree();
-  bool is_frozen_tree_root() { return state & CDIR_STATE_FROZENTREE; }
-  bool is_frozen_dir() { return state & CDIR_STATE_FROZENDIR; }
+  bool is_frozen_tree_root() { return state & STATE_FROZENTREE; }
+  bool is_frozen_dir() { return state & STATE_FROZENDIR; }
   
   bool is_freezeable() {
     // no nested auth pins.
@@ -470,7 +469,7 @@ class CDir : public MDSCacheObject {
       return false;
 
     // inode must not be frozen.
-    if (inode->is_frozen())
+    if (!is_subtree_root() && inode->is_frozen())
       return false;
 
     return true;
@@ -479,8 +478,8 @@ class CDir : public MDSCacheObject {
     if (auth_pins > 0) 
       return false;
 
-    // inode must not be frozen.
-    if (inode->is_frozen())
+    // if not subtree root, inode must not be frozen.
+    if (!is_subtree_root() && inode->is_frozen())
       return false;
 
     return true;
@@ -511,7 +510,7 @@ class CDirDiscover {
   CDirDiscover(CDir *dir, int nonce) {
     ino = dir->ino();
     this->nonce = nonce;
-    dir_auth = dir->dir_auth.first;
+    //dir_auth = dir->dir_auth.first;
     dir_rep = dir->dir_rep;
     rep_by = dir->dir_rep_by;
   }
@@ -521,7 +520,7 @@ class CDirDiscover {
     assert(!dir->is_auth());
 
     dir->replica_nonce = nonce;
-    dir->set_dir_auth( dir_auth );
+    //dir->set_dir_auth( dir_auth );
     dir->dir_rep = dir_rep;
     dir->dir_rep_by = rep_by;
   }
@@ -604,11 +603,11 @@ class CDirExport {
     dir->projected_version = dir->version = st.version;    // this is bumped, below, if dirty
 
     // twiddle state
-    if (dir->state & CDIR_STATE_HASHED) 
-      dir->state_set( CDIR_STATE_AUTH );         // just inherit auth flag when hashed
+    if (dir->state & CDir::STATE_HASHED) 
+      dir->state_set( CDir::STATE_AUTH );         // just inherit auth flag when hashed
     else
-      dir->state = (dir->state & CDIR_MASK_STATE_IMPORT_KEPT) |   // remember import flag, etc.
-        (st.state & CDIR_MASK_STATE_EXPORTED);
+      dir->state = (dir->state & CDir::MASK_STATE_IMPORT_KEPT) |   // remember import flag, etc.
+        (st.state & CDir::MASK_STATE_EXPORTED);
     dir->dir_rep = st.dir_rep;
 
     dir->popularity[MDS_POP_JUSTME] += st.popularity_justme;
index 0c87276c543d4c6ac1f80bf2f64cd097cd1fe0ca..a99a4672448d8a862d820c75deaabdb0e3aa4c68 100644 (file)
@@ -1998,7 +1998,7 @@ void Locker::handle_lock_dn(MLock *m)
 
       case LOCK_AC_REQXLOCK:
         // send nak
-        if (dir->state_test(CDIR_STATE_DELETED)) {
+        if (dir->state_test(CDir::STATE_DELETED)) {
           dout(7) << "handle_lock_dn reqxlock on deleted dir " << *dir << ", nak" << endl;
         } else {
           dout(7) << "handle_lock_dn reqxlock on " << dname << " in " << *dir << " dne, nak" << endl;
index 5ca8401993e30a3b9237ccfcbd1b61f7a6b6bb56..071cc0638642245dde9b7184b2f0604734ab73b7 100644 (file)
@@ -70,6 +70,7 @@ void MDBalancer::tick()
   // balance?
   if (true && 
       mds->get_nodeid() == 0 &&
+      g_conf.mds_bal_interval > 0 &&
       (num_bal_times || 
        (g_conf.mds_bal_max_until >= 0 && 
        elapsed.sec() > g_conf.mds_bal_max_until)) && 
@@ -133,19 +134,20 @@ void MDBalancer::send_heartbeat()
   mds_load_t load = get_load();
   mds_load[ mds->get_nodeid() ] = load;
 
-  // import_map
+  // import_map -- how much do i import from whom
   map<int, float> import_map;
-
-  for (set<CDir*>::iterator it = mds->mdcache->imports.begin();
-       it != mds->mdcache->imports.end();
+  set<CDir*> authsubs;
+  mds->mdcache->get_auth_subtrees(authsubs);
+  for (set<CDir*>::iterator it = authsubs.begin();
+       it != authsubs.end();
        it++) {
     CDir *im = *it;
-    if (im->inode->is_root()) continue;
     int from = im->inode->authority().first;
+    if (from == mds->get_nodeid()) continue;
     import_map[from] += im->popularity[MDS_POP_CURDOM].meta_load();
   }
   mds_import_map[ mds->get_nodeid() ] = import_map;
-
+  
   
   dout(5) << "mds" << mds->get_nodeid() << " sending heartbeat " << beat_epoch << " " << load << endl;
   for (map<int, float>::iterator it = import_map.begin();
@@ -207,15 +209,17 @@ void MDBalancer::handle_heartbeat(MHeartbeat *m)
 void MDBalancer::export_empties() 
 {
   dout(5) << "export_empties checking for empty imports" << endl;
-
-  for (set<CDir*>::iterator it = mds->mdcache->imports.begin();
-       it != mds->mdcache->imports.end();
+  dout(0) << "IMPLEMENT ME" << endl;
+  /*
+  for (set<CDir*>::iterator it = mds->mdcache->subtrees.begin();
+       it != mds->mdcache->subtrees.end();
        it++) {
     CDir *dir = *it;
     
     if (!dir->inode->is_root() && dir->get_size() == 0) 
       mds->mdcache->migrator->export_empty_import(dir);
   }
+  */
 }
 
 
@@ -288,7 +292,8 @@ void MDBalancer::do_rebalance(int beat)
   if (mds_load[whoami].mds_load() > 0) {
     load_fac = mds_load[whoami].root.meta_load() / mds_load[whoami].mds_load();
     dout(7) << " load_fac is " << load_fac 
-             << " <- " << mds_load[whoami].root.meta_load() << " / " << mds_load[whoami].mds_load()
+             << " <- " << mds_load[whoami].root.meta_load()
+           << " / " << mds_load[whoami].mds_load()
              << endl;
   }
   
@@ -417,23 +422,27 @@ void MDBalancer::do_rebalance(int beat)
   // make a sorted list of my imports
   map<double,CDir*>    import_pop_map;
   multimap<int,CDir*>  import_from_map;
-  for (set<CDir*>::iterator it = mds->mdcache->imports.begin();
-       it != mds->mdcache->imports.end();
+  set<CDir*> fullauthsubs;
+
+  mds->mdcache->get_fullauth_subtrees(fullauthsubs);
+  for (set<CDir*>::iterator it = fullauthsubs.begin();
+       it != fullauthsubs.end();
        it++) {
-    if ((*it)->is_hashed()) continue;
-    double pop = (*it)->popularity[MDS_POP_CURDOM].meta_load();
+    CDir *im = *it;
+
+    double pop = im->popularity[MDS_POP_CURDOM].meta_load();
     if (pop < g_conf.mds_bal_idle_threshold &&
-        (*it)->inode != mds->mdcache->get_root()) {
-      dout(-5) << " exporting idle import " << **it 
-               << " back to mds" << (*it)->inode->authority()
+        im->inode != mds->mdcache->get_root()) {
+      dout(-5) << " exporting idle import " << *im
+               << " back to mds" << im->inode->authority().first
                << endl;
-      mds->mdcache->migrator->export_dir(*it, (*it)->inode->authority().first);
+      mds->mdcache->migrator->export_dir(im, im->inode->authority().first);
       continue;
     }
-    import_pop_map[ pop ] = *it;
-    int from = (*it)->inode->authority().first;
-    dout(15) << "  map: i imported " << **it << " from " << from << endl;
-    import_from_map.insert(pair<int,CDir*>(from, *it));
+    import_pop_map[ pop ] = im;
+    int from = im->inode->authority().first;
+    dout(15) << "  map: i imported " << *im << " from " << from << endl;
+    import_from_map.insert(pair<int,CDir*>(from, im));
   }
   
 
@@ -532,7 +541,8 @@ void MDBalancer::do_rebalance(int beat)
     }
 
     // okay, search for fragments of my workload
-    set<CDir*> candidates = mds->mdcache->imports;
+    set<CDir*> candidates;
+    mds->mdcache->get_fullauth_subtrees(candidates);
 
     list<CDir*> exports;
     
@@ -595,7 +605,7 @@ void MDBalancer::find_exports(CDir *dir,
     if (!in->is_dir()) continue;
     if (!in->dir) continue;       // clearly not popular
     
-    if (in->dir->is_export()) continue;
+    if (!in->dir->is_auth()) continue;
     if (in->dir->is_hashed()) continue;
     if (already_exporting.count(in->dir)) continue;
 
@@ -746,7 +756,7 @@ void MDBalancer::hit_recursive(CDir *dir, int type)
 
       dout(1) << "replicating dir " << *dir << " pop " << dir_pop << " .. rdp " << rdp << " adj " << rd_adj << endl;
           
-      dir->dir_rep = CDIR_REP_ALL;
+      dir->dir_rep = CDir::REP_ALL;
       mds->mdcache->send_dir_updates(dir, true);
 
       dir->popularity[MDS_POP_JUSTME].pop[META_POP_IRD].adjust(rd_adj);
@@ -759,7 +769,7 @@ void MDBalancer::hit_recursive(CDir *dir, int type)
       // unreplicate
       dout(1) << "unreplicating dir " << *dir << " pop " << dir_pop << endl;
       
-      dir->dir_rep = CDIR_REP_NONE;
+      dir->dir_rep = CDir::REP_NONE;
       mds->mdcache->send_dir_updates(dir);
     }
   }
@@ -783,7 +793,7 @@ void MDBalancer::hit_recursive(CDir *dir, int type)
       in->popularity[MDS_POP_CURDOM].pop[type].hit();
     }
     
-    if (dir->is_import()) 
+    if (dir->is_subtree_root()) 
       curdom = false;   // end of auth domain, stop hitting auth counters.
     dir = dir->inode->get_parent_dir();
   }
@@ -797,7 +807,7 @@ void MDBalancer::subtract_export(CDir *dir)
 {
   meta_load_t curdom = dir->popularity[MDS_POP_CURDOM];
   
-  bool in_domain = !dir->is_import();
+  bool in_domain = !dir->is_subtree_root();
   
   while (true) {
     CInode *in = dir->inode;
@@ -808,7 +818,7 @@ void MDBalancer::subtract_export(CDir *dir)
     dir = in->get_parent_dir();
     if (!dir) break;
     
-    if (dir->is_import()) in_domain = false;
+    if (dir->is_subtree_root()) in_domain = false;
     
     dir->popularity[MDS_POP_ANYDOM] -= curdom;
     if (in_domain) dir->popularity[MDS_POP_CURDOM] -= curdom;
@@ -820,7 +830,7 @@ void MDBalancer::add_import(CDir *dir)
 {
   meta_load_t curdom = dir->popularity[MDS_POP_CURDOM];
 
-  bool in_domain = !dir->is_import();
+  bool in_domain = !dir->is_subtree_root();
   
   while (true) {
     CInode *in = dir->inode;
@@ -831,7 +841,7 @@ void MDBalancer::add_import(CDir *dir)
     dir = in->get_parent_dir();
     if (!dir) break;
     
-    if (dir->is_import()) in_domain = false;
+    if (dir->is_subtree_root()) in_domain = false;
     
     dir->popularity[MDS_POP_ANYDOM] += curdom;
     if (in_domain) dir->popularity[MDS_POP_CURDOM] += curdom;
index a0fcf789d550e047a737f9aeab96364ea2ec30e7..0b1736a5089ef47475c429fe6ba8872ac454f3c5 100644 (file)
@@ -208,13 +208,15 @@ public:
 
 void MDCache::log_import_map(Context *onsync)
 {
-  dout(10) << "log_import_map " << imports.size() << " imports, "
-          << exports.size() << " exports" << endl;
+  dout(10) << "log_import_map " << num_subtrees() << " subtrees" 
+          << num_subtrees_fullauth() << " fullauth"
+          << endl;
   
   EImportMap *le = new EImportMap;
-
+  
   // include import/export inodes,
   // and a spanning tree to tie it to the root of the fs
+  /*
   for (set<CDir*>::iterator p = imports.begin();
        p != imports.end();
        p++) {
@@ -235,6 +237,7 @@ void MDCache::log_import_map(Context *onsync)
       }
     }
   }
+  */
 
   mds->mdlog->writing_import_map = true;
   mds->mdlog->submit_entry(le);
@@ -281,28 +284,34 @@ void MDCache::send_import_map_now(int who)
 {
   dout(10) << "send_import_map to mds" << who << endl;
 
+  /*
   MMDSImportMap *m = new MMDSImportMap;
 
   // known
-  for (set<CDir*>::iterator p = imports.begin();
-       p != imports.end();
+  for (map<CDir*,set<CDir*> >::iterator p = subtrees.begin();
+       p != subtrees.end();
        p++) {
-    CDir *im = *p;
+    CDir *dir = p->first;
 
-    if (migrator->is_importing(im->ino())) {
+    // only our subtrees
+    if (dir->authority().first != mds->get_nodeid()) 
+      continue;
+
+    if (migrator->is_importing(dir->ino())) {
       // ambiguous (mid-import)
-      m->add_ambiguous_import(im->ino(), 
-                             migrator->get_import_bound_inos(im->ino()));
+      m->add_ambiguous_import(dir->ino(), 
+                             migrator->get_import_bound_inos(dir->ino()));
     } else {
       // not ambiguous.
-      m->add_import(im->ino());
+      m->add_import(dir->ino());
       
-      if (nested_exports.count(im)) {
-       for (set<CDir*>::iterator q = nested_exports[im].begin();
-            q != nested_exports[im].end();
+      // bounds too
+      if (nested_exports.count(dir)) {
+       for (set<CDir*>::iterator q = p->second.begin();
+            q != p->second.end();
             ++q) {
-         CDir *ex = *q;
-         m->add_import_export(im->ino(), ex->ino());
+         CDir *bound = *q;
+         m->add_import_export(dir->ino(), bound->ino());
        }
       }
     }
@@ -316,6 +325,8 @@ void MDCache::send_import_map_now(int who)
   
   // second
   mds->send_message_mds(m, who, MDS_PORT_CACHE);
+
+  */
 }
 
 
@@ -485,7 +496,7 @@ void MDCache::finish_ambiguous_import(inodeno_t dirino)
   }
 
   // adjust dir_auth, import maps
-  import_subtree(dir, bounds);
+  adjust_subtree_auth(dir, mds->get_nodeid());
 }
 
 void MDCache::finish_ambiguous_export(inodeno_t dirino, set<inodeno_t>& bounds)
@@ -499,6 +510,7 @@ void MDCache::finish_ambiguous_export(inodeno_t dirino, set<inodeno_t>& bounds)
           << " bounds " << bounds
           << endl;
   
+  /*
   // adjust dir_auth
   CDir *im = get_auth_container(dir);
   if (dir->get_inode()->authority().first == CDIR_AUTH_UNKNOWN) { 
@@ -507,14 +519,14 @@ void MDCache::finish_ambiguous_export(inodeno_t dirino, set<inodeno_t>& bounds)
     assert(imports.count(dir));
     imports.erase(dir);
     dir->set_dir_auth( CDIR_AUTH_PARENT );
-    dir->state_clear(CDIR_STATE_IMPORT);
+    dir->state_clear(CDir::STATE_IMPORT);
     dir->put(CDir::PIN_IMPORT);
   } else {
     // i'm now an export
     exports.insert(dir);
     nested_exports[im].insert(dir);
     dir->set_dir_auth( CDIR_AUTH_UNKNOWN );  // not me
-    dir->state_set(CDIR_STATE_EXPORT);
+    dir->state_set(CDir::STATE_EXPORT);
     dir->get(CDir::PIN_EXPORT);
   }
   dout(10) << "  root " << *dir << endl;
@@ -539,210 +551,393 @@ void MDCache::finish_ambiguous_export(inodeno_t dirino, set<inodeno_t>& bounds)
     assert(bd->get_dir_auth().first != CDIR_AUTH_PARENT);
     bd->set_dir_auth( CDIR_AUTH_PARENT );  // not me
 
-    bd->state_clear(CDIR_STATE_EXPORT);
+    bd->state_clear(CDir::STATE_EXPORT);
     bd->put(CDir::PIN_EXPORT);
 
     dout(10) << "  bound " << *bd << endl;
   }
-  
+  */
   show_imports();
 }
 
 
 
-/** import_subtree
- * adjust dir_auth.first.
- * adjust import/export/nested_export maps and pins.
+
+/*
+ * adjust the dir_auth of a subtree.
+ * merge with parent and/or child subtrees, if is it appropriate.
+ * merge can ONLY happen if both parent and child have unambiguous auth.
  */
-void MDCache::import_subtree(CDir *root, set<CDir*>& bounds)
+void MDCache::adjust_subtree_auth(CDir *dir, pair<int,int> auth)
 {
-  dout(7) << "import_subtree_start " << *root << endl;
+  dout(7) << "adjust_subtree_auth " << dir->get_dir_auth() << " -> " << auth
+         << " on " << *dir << endl;
 
-  CDir *im = root;   // the new subtree root (an import)
+  show_subtrees();
 
-  // root
-  if (root->inode->is_auth()) {
-    // parent is already me.  was export, adding back to existing import.
-    im = get_auth_container(root);
-    assert(im);
-    nested_exports[im].erase(root);
-    exports.erase(root);
-    root->set_dir_auth(CDIR_AUTH_PARENT, true);
-    root->state_clear(CDIR_STATE_EXPORT);
-    root->put(CDir::PIN_EXPORT);
+  CDir *root;
+  if (dir->ino() == 1) {
+    root = dir;  // bootstrap hack.
+    subtrees[root].clear();
   } else {
-    // parent isn't me.  new import.
-    imports.insert(root);
-    root->set_dir_auth(mds->get_nodeid(), true);
-    root->state_set(CDIR_STATE_IMPORT);
-    root->get(CDir::PIN_IMPORT);
+    root = get_subtree_root(dir);  // subtree root
   }
+  assert(root);
+  assert(subtrees.count(root));
+  dout(7) << " current root is " << *root << endl;
 
-  dout(10) << "  root " << *root << endl;
-  if (root != im)
-    dout(10) << "  under " << *im << endl;
-
-  // i should have no pins in this region.
-  assert(root->get_cum_auth_pins() == 0);
+  if (root == dir) {
+    // i am already a subtree.
+    dir->set_dir_auth(auth);
+  } else {
+    // i am a new subtree.
+    dout(10) << "  new subtree at " << *dir << endl;
+    assert(subtrees.count(dir) == 0);
+    subtrees[dir].clear();      // create empty subtree bounds list for me.
 
-  // bounds
-  for (set<CDir*>::iterator it = bounds.begin();
-       it != bounds.end();
-       it++) {
-    CDir *bd = *it;
-    
-    if (bd->is_import()) {
-      // bound is still me.  was an import. 
-      imports.erase(bd);
-      bd->set_dir_auth(CDIR_AUTH_PARENT, true);   
-      bd->state_clear(CDIR_STATE_IMPORT);
-      bd->put(CDir::PIN_IMPORT);
-      // move nested exports under this bound to my subtree root.
-      for (set<CDir*>::iterator q = nested_exports[bd].begin();
-          q != nested_exports[bd].end();
-          ++q) 
-       nested_exports[im].insert(*q);
-      nested_exports.erase(bd);        
-    } else {
-      // not me anymore.  now an export.
-      exports.insert(bd);
-      nested_exports[im].insert(bd);
-      assert(bd->get_dir_auth().first != CDIR_AUTH_PARENT);
-      bd->state_set(CDIR_STATE_EXPORT);
-      bd->get(CDir::PIN_EXPORT);
+    // set dir_auth
+    dir->set_dir_auth(auth);
+    
+    // move items nested beneath me, under me.
+    set<CDir*>::iterator p = subtrees[root].begin();
+    while (p != subtrees[root].end()) {
+      set<CDir*>::iterator next = p;
+      next++;
+      if (get_subtree_root((*p)->get_parent_dir()) == dir) {
+       // move under me
+       dout(10) << "  claiming child bound " << **p << endl;
+       subtrees[dir].insert(*p); 
+       subtrees[root].erase(p);
+      }
+      p = next;
     }
     
-    dout(10) << "  bound " << *bd << endl;
+    // i am a bound of the parent subtree.
+    subtrees[root].insert(dir); 
+
+    // i am now the subtree root.
+    root = dir;
   }
+
+  // adjust export pins
+  adjust_export_state(dir);
+  for (set<CDir*>::iterator p = subtrees[dir].begin();
+       p != subtrees[dir].end();
+       ++p) 
+    adjust_export_state(*p);
+  
+  show_subtrees();
 }
 
-void MDCache::import_subtree_finish(CDir *root, set<CDir*>& bounds)
+
+/*
+ * any "export" point must be pinned in cache to ensure a proper
+ * chain of delegation.  we do this by pinning when a dir is nonauth
+ * but the inode is auth.
+ *
+ * import points don't need to be pinned the same way simply because the
+ * exporter is pinned and thus always open.
+ */
+void MDCache::adjust_export_state(CDir *dir)
 {
-  
+  if (!dir->is_auth() && dir->inode->is_auth()) {
+    // export.
+    if (!dir->state_test(CDir::STATE_EXPORT)) {
+      dout(10) << "adjust_export_state pinning new export " << *dir << endl;
+      dir->state_set(CDir::STATE_EXPORT);
+      dir->get(CDir::PIN_EXPORT);
+    }
+  } 
+  else {
+    // not export.
+    if (dir->state_test(CDir::STATE_EXPORT)) {
+      dout(10) << "adjust_export_state unpinning old export " << *dir << endl;
+      dir->state_clear(CDir::STATE_EXPORT);
+      dir->put(CDir::PIN_EXPORT);
+    }
+  }
 }
 
-void MDCache::export_subtree(CDir *root, set<CDir*>& bounds, int dest)
+void MDCache::try_subtree_merge(CDir *dir)
 {
-  dout(7) << "export_subtree " << *root << endl;
-  
-  CDir *im = get_auth_container(root);
+  dout(7) << "try_subtree_merge " << *dir << endl;
 
-  // root
-  if (root->is_import()) {
-    // was an import, hose it
-    assert(im == root);
-    assert(imports.count(root));
-    imports.erase(root);
-    root->set_dir_auth(CDIR_AUTH_PARENT);
-    root->state_clear(CDIR_STATE_IMPORT);
-    root->put(CDir::PIN_IMPORT);
-  } else {
-    // i'm now an export
-    exports.insert(root);
-    nested_exports[im].insert(root);
-    root->set_dir_auth( dest );  // not me
-    root->state_set(CDIR_STATE_EXPORT);
-    root->get(CDir::PIN_EXPORT);
+  // try to merge bounds?
+  set<CDir*>::iterator p = subtrees[dir].begin();
+  while (p != subtrees[dir].end()) {
+    set<CDir*>::iterator next = p;
+    next++;
+    CDir *bound = *p;
+    
+    if (bound->dir_auth == dir->dir_auth &&            // if auth matches,
+       dir->dir_auth.second == CDIR_AUTH_UNKNOWN &&   // auth is unambiguous,
+       !bound->state_test(CDir::STATE_EXPORTBOUND)) { // and not an exportbound,
+      // merge with child.
+      dout(10) << "  merging with child bound " << *bound << endl;
+      bound->set_dir_auth(CDIR_AUTH_DEFAULT);
+      
+      // move child's children under dir.
+      for (set<CDir*>::iterator q = subtrees[bound].begin();
+          q != subtrees[bound].end();
+          ++q) 
+       subtrees[dir].insert(*q);
+      
+      // bound is no longer a separate subtree.
+      subtrees[dir].erase(bound);
+      subtrees.erase(bound);
+    }
+
+    // next!
+    p = next;
   }
 
-  // fix dir_auth
-  if (root->inode->authority().first == dest)
-    root->set_dir_auth( CDIR_AUTH_PARENT );
-  else
-    root->set_dir_auth( dest );
+  // merge with parent?
+  CDir *parent = dir;  
+  if (dir->ino() != 1)
+    parent = get_subtree_root(dir->get_parent_dir());
   
-  dout(10) << "  root " << *root << endl;
-  if (root != im)
-    dout(10) << "  under " << *im << endl;
+  if (parent != dir &&                              // we have a parent,
+      parent->dir_auth == dir->dir_auth &&          // auth matches,
+      dir->dir_auth.second == CDIR_AUTH_UNKNOWN &&  // auth is unambiguous,
+      !dir->state_test(CDir::STATE_EXPORTBOUND)) {  // not an exportbound,
+    // merge with parent.
+    dout(10) << "  merge with parent " << *parent << endl;
+    dir->set_dir_auth(CDIR_AUTH_DEFAULT);
     
-  // bounds (there were exports, before)
-  for (set<CDir*>::iterator p = bounds.begin();
-       p != bounds.end();
-       ++p) {
-    CDir *bd = *p;
+    // move our bounds under the parent
+    for (set<CDir*>::iterator p = subtrees[dir].begin();
+        p != subtrees[dir].end();
+        ++p) 
+      subtrees[parent].insert(*p);
     
-    // hose export
-    assert(exports.count(bd));
-    exports.erase(bd);
-    nested_exports[im].erase(bd);
+    // we are no longer a subtree or bound
+    subtrees.erase(dir);
+    subtrees[parent].erase(dir);
+  } 
 
-    bd->state_clear(CDIR_STATE_EXPORT);
-    bd->put(CDir::PIN_EXPORT);
-    
-    // fix dir_auth
-    assert(bd->get_dir_auth().first != CDIR_AUTH_PARENT);
-    if (bd->get_dir_auth().first == dest)
-      bd->set_dir_auth(CDIR_AUTH_PARENT);
-    else
-      bd->set_dir_auth(dest);
-    
-    dout(10) << "  bound " << *bd << endl;
-  }
+  show_subtrees();
 }
 
 
-/*
- * adjust the dir_auth of a subtree.
- * merge with parent and/or child subtrees, if is it appropriate.
- */
-void MDCache::adjust_subtree_auth(CDir *dir, pair<int,int> auth)
+void MDCache::adjust_bounded_subtree_auth(CDir *dir, set<CDir*>& bounds, pair<int,int> auth)
 {
-  dout(7) << "adjust_subtree_auth " << dir->get_dir_auth() << " -> " << auth
-         << " under " << *dir << endl;
+  dout(7) << "adjust_bounded_subtree_auth " << dir->get_dir_auth() << " -> " << auth
+         << " on " << *dir << endl;
 
-  // note my current bounds.
-  set<CDir*> bounds = subtree_bounds[dir];
+  show_subtrees();
 
-  // join with parent?
-  CDir *root = dir;
-  if (dir->ino() != 1) // i'm the root, screw you
-    root = get_subtree_root(dir->get_parent_dir());
-  
-  if (root != dir && root->get_dir_auth() == auth) {
-    // join the subtrees.
-    dir->set_dir_auth(CDIR_AUTH_DEFAULT);
-    dout(10) << "  merge with parent " << *root << endl;
+  CDir *root;
+  if (dir->ino() == 1) {
+    root = dir;  // bootstrap hack.
+    subtrees[root].clear();
+  } else {
+    root = get_subtree_root(dir);  // subtree root
+  }
+  assert(root);
+  assert(subtrees.count(root));
+  dout(7) << " current root is " << *root << endl;
 
-    // move our bounds under new root
-    subtree_bounds.erase(dir);
-    for (set<CDir*>::iterator p = bounds.begin();
-        p != bounds.end();
-        ++p) 
-      subtree_bounds[root].insert(*p);
+  pair<int,int> oldauth = dir->authority();
 
-    // dir is no longer a subtree
-    subtree_bounds.erase(dir);
+  if (root == dir) {
+    // i am already a subtree.
+    dir->set_dir_auth(auth);
   } else {
-    // don't merge with parent, just update our auth.
+    // i am a new subtree.
+    dout(10) << "  new subtree at " << *dir << endl;
+    assert(subtrees.count(dir) == 0);
+    subtrees[dir].clear();      // create empty subtree bounds list for me.
+    
+    // set dir_auth
     dir->set_dir_auth(auth);
-  }
+    
+    // move items nested beneath me, under me.
+    set<CDir*>::iterator p = subtrees[root].begin();
+    while (p != subtrees[root].end()) {
+      set<CDir*>::iterator next = p;
+      next++;
+      if (get_subtree_root((*p)->get_parent_dir()) == dir) {
+       // move under me
+       dout(10) << "  claiming child bound " << **p << endl;
+       subtrees[dir].insert(*p); 
+       subtrees[root].erase(p);
+      }
+      p = next;
+    }
+    
+    // i am a bound of the parent subtree.
+    subtrees[root].insert(dir); 
 
-  // bounds
+    // i am now the subtree root.
+    root = dir;
+  }
+  
+  // verify/adjust bounds.
+  // these may be new, but no deeper than any existing bounds.
   for (set<CDir*>::iterator p = bounds.begin();
        p != bounds.end();
        ++p) {
     CDir *bound = *p;
-    
-    if (bound->dir_auth == auth) {
-      // merge with child.
-      dout(10) << "  merging bound " << *bound << endl;
-      bound->set_dir_auth(CDIR_AUTH_DEFAULT);
-      
-      // move child's children under root.
-      for (set<CDir*>::iterator q = subtree_bounds[bound].begin();
-          q != subtree_bounds[bound].end();
-          ++q) 
-       subtree_bounds[root].insert(*q);
+    if (subtrees[dir].count(bound)) continue;  // have it.
+    adjust_subtree_auth(bound, oldauth);       // otherwise, adjust at bound.
+  }
 
-      // bound is no longer a subtree.
-      subtree_bounds[root].erase(bound);
-    } else {
-      // don't merge.
-      dout(10) << "  bound " << *bound << endl;
+  verify_subtree_bounds(dir, bounds);
+
+  show_subtrees();
+}
+
+
+CDir *MDCache::get_subtree_root(CDir *dir)
+{
+  // find the underlying dir that delegates (or is about to delegate) auth
+  while (true) {
+    if (dir->is_subtree_root()) 
+      return dir;
+    dir = dir->get_parent_dir();
+    if (!dir) 
+      return 0;             // none
+  }
+}
+
+void MDCache::get_subtree_bounds(CDir *dir, set<CDir*>& bounds)
+{
+  assert(subtrees.count(dir));
+  bounds = subtrees[dir];
+}
+
+void MDCache::get_wouldbe_subtree_bounds(CDir *dir, set<CDir*>& bounds)
+{
+  if (subtrees.count(dir)) {
+    // just copy them, dir is a subtree.
+    get_subtree_bounds(dir, bounds);
+  } else {
+    // find them
+    CDir *root = get_subtree_root(dir);
+    for (set<CDir*>::iterator p = subtrees[root].begin();
+        p != subtrees[root].end();
+        ++p) {
+      CDir *t = *p;
+      while (t != root) {
+       t = t->get_parent_dir();
+       assert(t);
+       if (t == dir) {
+         bounds.insert(*p);
+         continue;
+       }
+      }
     }
   }
 }
 
+void MDCache::verify_subtree_bounds(CDir *dir, const set<CDir*>& bounds)
+{
+  // for debugging only.
+  assert(subtrees.count(dir));
+  if (bounds != subtrees[dir]) {
+    dout(0) << "verify_subtree_bounds failed" << endl;
+    set<CDir*> b = bounds;
+    for (set<CDir*>::iterator p = subtrees[dir].begin();
+        p != subtrees[dir].end();
+        ++p) {
+      if (bounds.count(*p)) {
+       b.erase(*p);
+       continue;
+      }
+      dout(0) << "  missing bound " << **p << endl;
+    }
+    for (set<CDir*>::iterator p = b.begin();
+        p != b.end();
+        ++p) 
+      dout(0) << "    extra bound " << **p << endl;
+  }
+  assert(bounds == subtrees[dir]);
+}
+
+void MDCache::verify_subtree_bounds(CDir *dir, const list<inodeno_t>& bounds)
+{
+  // for debugging only.
+  assert(subtrees.count(dir));
+
+  // make sure that any bounds i do have are properly noted as such.
+  int failed = 0;
+  for (list<inodeno_t>::const_iterator p = bounds.begin();
+       p != bounds.end();
+       ++p) {
+    CInode *bdi = get_inode(*p);
+    if (!bdi) continue;
+    CDir *bd = bdi->dir;
+    if (!bd) continue;
+    if (subtrees[dir].count(bd) == 0) {
+      dout(0) << "verify_subtree_bounds failed: extra bound " << *bd << endl;
+      failed++;
+    }
+  }
+  assert(failed == 0);
+}
+
+
+void MDCache::get_fullauth_subtrees(set<CDir*>& s)
+{
+  for (map<CDir*,set<CDir*> >::iterator p = subtrees.begin();
+       p != subtrees.end();
+       ++p) {
+    CDir *root = p->first;
+    if (root->is_fullauth())
+      s.insert(root);
+  }
+}
+void MDCache::get_auth_subtrees(set<CDir*>& s)
+{
+  for (map<CDir*,set<CDir*> >::iterator p = subtrees.begin();
+       p != subtrees.end();
+       ++p) {
+    CDir *root = p->first;
+    if (root->is_auth())
+      s.insert(root);
+  }
+}
+
+
+// count.
+
+int MDCache::num_subtrees()
+{
+  return subtrees.size();
+}
+
+int MDCache::num_subtrees_fullauth()
+{
+  int n = 0;
+  for (map<CDir*,set<CDir*> >::iterator p = subtrees.begin();
+       p != subtrees.end();
+       ++p) {
+    CDir *root = p->first;
+    if (root->is_fullauth())
+      n++;
+  }
+  return n;
+}
+
+int MDCache::num_subtrees_fullnonauth()
+{
+  int n = 0;
+  for (map<CDir*,set<CDir*> >::iterator p = subtrees.begin();
+       p != subtrees.end();
+       ++p) {
+    CDir *root = p->first;
+    if (root->is_fullnonauth())
+      n++;
+  }
+  return n;
+}
+
+
+
+
+
+
+
 
 
 /*
@@ -1040,12 +1235,14 @@ void MDCache::set_root(CInode *in)
   root->state_set(CInode::STATE_ROOT);
 }
 
+/*
 void MDCache::add_import(CDir *dir)
 {
   imports.insert(dir);
-  dir->state_set(CDIR_STATE_IMPORT);
+  dir->state_set(CDir::STATE_IMPORT);
   dir->get(CDir::PIN_IMPORT);
 }
+*/
 
 
 void MDCache::recalc_auth_bits()
@@ -1076,9 +1273,9 @@ void MDCache::recalc_auth_bits()
 
     if (in->dir) {
       if (in->dir->authority().first == mds->get_nodeid())
-       in->dir->state_set(CDIR_STATE_AUTH);
+       in->dir->state_set(CDir::STATE_AUTH);
       else {
-       in->dir->state_clear(CDIR_STATE_AUTH);
+       in->dir->state_clear(CDir::STATE_AUTH);
        if (in->dir->is_dirty()) 
          in->dir->mark_clean();
       }
@@ -1229,7 +1426,7 @@ bool MDCache::trim(int max)
 
     // adjust the dir state
     CInode *diri = dir->get_inode();
-    diri->dir->state_clear(CDIR_STATE_COMPLETE);  // dir incomplete!
+    diri->dir->state_clear(CDir::STATE_COMPLETE);  // dir incomplete!
 
     // reexport?
     if (diri->dir->is_import() &&             // import
@@ -1274,8 +1471,13 @@ void MDCache::trim_inode(CDentry *dn, CInode *in, inodeno_t conino, map<int, MCa
       // was this an auth delegation?  (if so, slightly modified container)
       inodeno_t dconino = conino;
       if (in->dir->is_subtree_root()) {
-       dout(12) << "  for just this dir, the container is " << *in->dir << endl;
+       dout(12) << "  this is a subtree, removing from map, container is " << *in->dir << endl;
        dconino = in->ino();
+
+       // remove from subtree map
+       assert(subtrees.count(in->dir));
+       assert(subtrees[in->dir].empty());
+       subtrees.erase(in->dir);
       }
       
       for (int a=dirauth.first; 
@@ -1357,7 +1559,7 @@ void MDCache::trim_non_auth()
       
       // adjust the dir state
       CInode *diri = dir->get_inode();
-      diri->dir->state_clear(CDIR_STATE_COMPLETE);  // dir incomplete!
+      diri->dir->state_clear(CDir::STATE_COMPLETE);  // dir incomplete!
     }
   }
 
@@ -1409,9 +1611,6 @@ void MDCache::shutdown_check()
   dout(0) << "log len " << mds->mdlog->get_num_events() << endl;
 
 
-  if (exports.size()) 
-    dout(0) << "still have " << exports.size() << " exports" << endl;
-
   if (mds->filer->is_active()) 
     dout(0) << "filer still active" << endl;
 }
@@ -1438,6 +1637,7 @@ bool MDCache::shutdown_pass()
   }
 
   // unhash dirs?
+  /*
   if (!hashdirs.empty()) {
     // unhash any of my dirs?
     for (set<CDir*>::iterator it = hashdirs.begin();
@@ -1452,6 +1652,7 @@ bool MDCache::shutdown_pass()
     dout(7) << "waiting for dirs to unhash" << endl;
     return false;
   }
+  */
 
   // commit dirs?
   if (g_conf.mds_commit_on_shutdown) {
@@ -1497,80 +1698,61 @@ bool MDCache::shutdown_pass()
 
 
   // send all imports back to 0.
-  if (mds->get_nodeid() != 0 && !did_shutdown_exports) {
+  if (mds->get_nodeid() != 0 && 
+      !migrator->is_exporting() &&
+      !migrator->is_importing()) {
     // flush what i can from the cache first..
     trim(0);
-
+    
     // export to root
-    for (set<CDir*>::iterator it = imports.begin();
-         it != imports.end();
-         ) {
-      CDir *im = *it;
-      it++;
-      if (im->inode->is_root()) continue;
-      if (im->is_frozen() || im->is_freezing()) continue;
+    for (map<CDir*, set<CDir*> >::iterator it = subtrees.begin();
+         it != subtrees.end();
+         it++) {
+      CDir *dir = it->first;
+      if (dir->inode->is_root()) continue;
+      if (dir->is_frozen() || dir->is_freezing()) continue;
+      if (!dir->is_fullauth()) continue;
       
-      dout(7) << "sending " << *im << " back to mds0" << endl;
-      migrator->export_dir(im,0);
+      dout(7) << "sending " << *dir << " back to mds0" << endl;
+      migrator->export_dir(dir, 0);
     }
     did_shutdown_exports = true;
   } 
-
-
-  // waiting for imports?  (e.g. root?)
-  if (exports.size()) {
-    dout(7) << "still have " << exports.size() << " exports" << endl;
-    //show_cache();
-    return false;
-  }
-
   
   // close root?
   if (lru.lru_get_size() == 0 &&
       root &&
-      root->dir) {
-    
-    if (root->dir->is_import()) {
-      // un-import
-      dout(7) << "removing root import" << endl;
-      imports.erase(root->dir);
-      root->dir->state_clear(CDIR_STATE_IMPORT);
-      root->dir->put(CDir::PIN_IMPORT);
-      
-      if (root->is_pinned_by(CInode::PIN_DIRTY)) {
-       dout(7) << "clearing root inode dirty flag" << endl;
-       root->put(CInode::PIN_DIRTY);
-      }
-    }
-
-    // ignore root inode/dir on other nodes, since it's empty anyway. 
+      root->is_pinned_by(CInode::PIN_DIRTY)) {
+    dout(7) << "clearing root inode dirty flag" << endl;
+    root->put(CInode::PIN_DIRTY);
   }
   
-  // imports?
-  if (!imports.empty() || migrator->is_exporting()) {
-    dout(7) << "still have " << imports.size() << " imports, or still exporting" << endl;
+  // subtrees map not empty yet?
+  if (!subtrees.empty()) {
+    dout(7) << "still have " << num_subtrees() << " subtrees" << endl;
     show_cache();
     return false;
   }
+  assert(subtrees.empty());
+  assert(!migrator->is_exporting());
+  assert(!migrator->is_importing());
   
   // cap log?
   if (g_conf.mds_log_flush_on_shutdown) {
 
-    if (imports.empty() && exports.empty()) {
-      // (only do this once!)
-      if (!mds->mdlog->is_capped()) {
-       dout(7) << "capping the log" << endl;
-       mds->mdlog->cap();
-       // note that this won't flush right away, so we'll make at least one more pass
-      }
+    // (only do this once!)
+    if (!mds->mdlog->is_capped()) {
+      dout(7) << "capping the log" << endl;
+      mds->mdlog->cap();
+      // note that this won't flush right away, so we'll make at least one more pass
     }
-
+    
     if (mds->mdlog->get_num_events()) {
       dout(7) << "waiting for log to flush (including import_map, now) .. " << mds->mdlog->get_num_events() 
              << " (" << mds->mdlog->get_non_importmap_events() << ")" << endl;
       return false;
     }
-
+    
     if (!did_shutdown_log_cap) {
       // flush journal header
       dout(7) << "writing header for (now-empty) journal" << endl;
@@ -1640,14 +1822,11 @@ int MDCache::open_root(Context *c)
 
     // root directory too
     assert(root->dir == NULL);
-    root->set_dir( new CDir(root, this, true) );
-    root->dir->set_dir_auth( 0 );  // me!
-    root->dir->dir_rep = CDIR_REP_ALL;   //NONE;
+    root->set_dir(new CDir(root, this, true));
+    adjust_subtree_auth(root->dir, 0);   
+    root->dir->dir_rep = CDir::REP_ALL;   //NONE;
 
-    // root is sort of technically an import (from a vacuum)
-    imports.insert( root->dir );
-    root->dir->state_set(CDIR_STATE_IMPORT);
-    root->dir->get(CDir::PIN_IMPORT);
+    show_imports();
 
     if (c) {
       c->finish(0);
@@ -2842,6 +3021,11 @@ void MDCache::handle_discover_reply(MDiscoverReply *m)
         // add it (_replica_)
         cur->set_dir( new CDir(cur, this, false) );
         m->get_dir(i).update_dir(cur->dir);
+
+       // is this a dir_auth delegation boundary?
+       if (m->get_source().num() != cur->authority().first)
+         adjust_subtree_auth(cur->dir, m->get_source().num());
+       
         dout(7) << "added " << *cur->dir << " nonce " << cur->dir->replica_nonce << endl;
 
         // get waiters
@@ -3328,7 +3512,7 @@ void MDCache::dentry_unlink(CDentry *dn, Context *c)
       if (dn->inode->dir) {
         // mark dir clean too, since it now dne!
         assert(dn->inode->dir->is_auth());
-        dn->inode->dir->state_set(CDIR_STATE_DELETED);
+        dn->inode->dir->state_set(CDir::STATE_DELETED);
         dn->inode->dir->remove_null_dentries();
         dn->inode->dir->mark_clean();
       }
@@ -3445,7 +3629,7 @@ void MDCache::handle_dentry_unlink(MDentryUnlink *m)
       // dir?
       if (dn->inode) {
         if (dn->inode->dir) {
-          dn->inode->dir->state_set(CDIR_STATE_DELETED);
+          dn->inode->dir->state_set(CDir::STATE_DELETED);
           dn->inode->dir->remove_null_dentries();
         }
       }
@@ -3543,6 +3727,8 @@ void MDCache::handle_inode_unlink_ack(MInodeUnlinkAck *m)
  * and we are nested underneath an inode in that dir (that hashes to us).
  * Thus do not assume result->is_auth()!  It is_auth() || is_hashed().
  */
+
+/*
 CDir *MDCache::get_auth_container(CDir *dir)
 {
   CDir *imp = dir;  // might be *dir
@@ -3558,18 +3744,6 @@ CDir *MDCache::get_auth_container(CDir *dir)
   return imp;
 }
 
-CDir *MDCache::get_subtree_root(CDir *dir)
-{
-  // find the underlying dir that delegates (or is about to delegate) auth
-  while (true) {
-    if (dir->is_subtree_root()) 
-      return dir;
-    dir = dir->get_parent_dir();
-    if (!dir) 
-      return 0;             // none
-  }
-}
-
 CDir *MDCache::get_export_container(CDir *dir)
 {
   CDir *ex = dir;  // might be *dir
@@ -3633,7 +3807,7 @@ void MDCache::find_nested_exports_under(CDir *import, CDir *dir, set<CDir*>& s)
 }
 
 
-
+*/
 
 
 
@@ -3652,11 +3826,98 @@ void MDCache::find_nested_exports_under(CDir *import, CDir *dir, set<CDir*>& s)
 // ==============================================================
 // debug crap
 
+void MDCache::show_subtrees()
+{
+  dout(10) << "show_subtrees:" << endl;
+  
+  list<pair<CDir*,int> > q;
+  string indent;
+
+  if (root && root->dir) 
+    q.push_back(pair<CDir*,int>(root->dir, 0));
+
+  set<CDir*> seen;
+
+  while (!q.empty()) {
+    CDir *dir = q.front().first;
+    int d = q.front().second;
+    q.pop_front();
+
+    // sanity check
+    if (seen.count(dir)) dout(0) << "aah, already seen " << *dir << endl;
+    assert(seen.count(dir) == 0);
+    seen.insert(dir);
+
+    // adjust indenter
+    while ((unsigned)d < indent.size()) 
+      indent.resize(d);
+    
+    // pad
+    string pad = "__________________________________";
+    pad.resize(12-indent.size());
+
+    string auth;
+    if (dir->is_auth())
+      auth = "auth ";
+    else
+      auth = "rep  ";
+
+    char s[10];
+    if (dir->get_dir_auth().second == CDIR_AUTH_UNKNOWN)
+      sprintf(s, "%2d   ", dir->get_dir_auth().first);
+    else
+      sprintf(s, "%2d,%2d", dir->get_dir_auth().first, dir->get_dir_auth().second);
+    
+    // print
+    dout(10) << indent << "|_" << pad << s << " " << auth << *dir << endl;
+
+    // nested items?
+    if (!subtrees[dir].empty()) {
+      // more at my level?
+      if (!q.empty() && q.front().second == d)
+       indent += "| ";
+      else
+       indent += "  ";
+
+      for (set<CDir*>::iterator p = subtrees[dir].begin();
+          p != subtrees[dir].end();
+          ++p) 
+       q.push_front(pair<CDir*,int>(*p, d+2));
+    }
+  }
+}
+
 
 void MDCache::show_imports()
 {
   int db = 10;
 
+  dout(db) << "show_imports:" << endl;
+
+  for (map<CDir*,set<CDir*> >::iterator p = subtrees.begin();
+       p != subtrees.end();
+       ++p) {
+    CDir *root = p->first;
+
+    if (!root->is_auth()) continue;
+
+    dout(db) << " ___ " << *root << endl;
+    
+    for (set<CDir*>::iterator q = p->second.begin();
+        q != p->second.end();
+        ++q) {
+      CDir *bound = *q;
+      dout(db) << "  |__" << *bound << endl;
+    }    
+  }
+
+  show_subtrees();
+  return;
+
+
+
+  /// old
+  /*
   if (imports.empty() &&
       hashdirs.empty()) {
     dout(db) << "show_imports: no imports/exports/hashdirs" << endl;
@@ -3718,6 +3979,7 @@ void MDCache::show_imports()
       dout(1) << "***** stray item in exports: " << **it << endl;
     assert(ecopy.size() == 0);
   }
+  */
 }
 
 
index 23baf02f44861c8ab3ee975003a98a7837c2e431..f718d8c7d30af38b1c48176ea14203f216f1c6b9 100644 (file)
@@ -101,26 +101,47 @@ class MDCache {
   // root
   list<Context*>     waiting_for_root;
 
+  /*
   // imports, exports, and hashes.
   set<CDir*>             imports;                // includes root (on mds0)
   set<CDir*>             exports;
   set<CDir*>             hashdirs;
   map<CDir*,set<CDir*> > nested_exports;         // exports nested under imports _or_ hashdirs
 
-  // subtrees
-  map<CDir*,set<CDir*> > subtree_bounds;   // nested bounds on subtrees.
+  void import_subtree(CDir *root, set<CDir*>& bounds);
+  void export_subtree(CDir *root, set<CDir*>& bounds, int dest);
+  */
+
+  // -- subtrees --
+protected:
+  map<CDir*,set<CDir*> > subtrees;   // nested bounds on subtrees.
   
   // adjust subtree auth specification
   //  dir->dir_auth
   //  imports/exports/nested_exports
   //  join/split subtrees as appropriate
-  void import_subtree(CDir *root, set<CDir*>& bounds);
-  void import_subtree_finish(CDir *root, set<CDir*>& bounds);
-  void export_subtree(CDir *root, set<CDir*>& bounds, int dest);
-  void export_subtree_finish(CDir *root, set<CDir*>& bounds, int dest);
-
+public:
   void adjust_subtree_auth(CDir *root, pair<int,int> auth);
+  void adjust_subtree_auth(CDir *root, int a, int b=CDIR_AUTH_UNKNOWN) {
+    adjust_subtree_auth(root, pair<int,int>(a,b)); }
+  void adjust_bounded_subtree_auth(CDir *dir, set<CDir*>& bounds, pair<int,int> auth);
+  void adjust_export_state(CDir *dir);
+  void try_subtree_merge(CDir *root);
+  CDir *get_subtree_root(CDir *dir);
+  void get_subtree_bounds(CDir *root, set<CDir*>& bounds);
+  void get_wouldbe_subtree_bounds(CDir *root, set<CDir*>& bounds);
+  void verify_subtree_bounds(CDir *root, const set<CDir*>& bounds);
+  void verify_subtree_bounds(CDir *root, const list<inodeno_t>& boundinos);
+
+  void get_auth_subtrees(set<CDir*>& s);
+  void get_fullauth_subtrees(set<CDir*>& s);
+
+  int num_subtrees();
+  int num_subtrees_fullauth();
+  int num_subtrees_fullnonauth();
+
   
+protected:
   // delayed cache expire
   map<CDir*, map<int, MCacheExpire*> > delayed_expire; // import|export dir -> expire msg
 
@@ -206,9 +227,9 @@ public:
   CInode *get_root() { return root; }
   void set_root(CInode *r);
 
-  int get_num_imports() { return imports.size(); }
-  void add_import(CDir *dir);
-  void remove_import(CDir *dir);
+  //int get_num_imports() { return imports.size(); }
+  //void add_import(CDir *dir);
+  //void remove_import(CDir *dir);
   void recalc_auth_bits();
 
   void log_import_map(Context *onsync=0);
@@ -280,7 +301,6 @@ public:
 
  public:
   CDir *get_auth_container(CDir *in);
-  CDir *get_subtree_root(CDir *dir);
   CDir *get_export_container(CDir *dir);
   void find_nested_exports(CDir *dir, set<CDir*>& s);
   void find_nested_exports_under(CDir *import, CDir *dir, set<CDir*>& s);
@@ -364,6 +384,7 @@ public:
 
   void show_imports();
   void show_cache();
+  void show_subtrees();
 
 };
 
index 40abe1c7bab71d47006f56251903b08bddeb0278..f5ad90000c9de9fe87fb123b623ea6ddd2cec69f 100644 (file)
@@ -899,6 +899,15 @@ void MDS::my_dispatch(Message *m)
     dout(1) << "MDS dispatch unknown message port" << m->get_dest_port() << endl;
     assert(0);
   }
+  
+  // finish any triggered contexts
+  if (finished_queue.size()) {
+    dout(7) << "mds has " << finished_queue.size() << " queued contexts" << endl;
+    list<Context*> ls;
+    ls.splice(ls.begin(), finished_queue);
+    assert(finished_queue.empty());
+    finish_contexts(ls);
+  }
 
 
   // HACK FOR NOW
@@ -909,22 +918,13 @@ void MDS::my_dispatch(Message *m)
     // trim cache
     mdcache->trim();
   }
-  
-  // finish any triggered contexts
-  if (finished_queue.size()) {
-    dout(7) << "mds has " << finished_queue.size() << " queued contexts" << endl;
-    list<Context*> ls;
-    ls.splice(ls.begin(), finished_queue);
-    assert(finished_queue.empty());
-    finish_contexts(ls);
-  }
 
   
   // hack: thrash exports
   for (int i=0; i<g_conf.mds_thrash_exports; i++) {
     set<int> s;
     mdsmap->get_mds_set(s, MDSMap::STATE_ACTIVE);
-    if (s.size() == 1) 
+    if (s.size() == 1 || mdcache->inode_map.size() < 10
       break;  // need peers for this to work.
 
     dout(7) << "mds thrashing exports pass " << (i+1) << "/" << g_conf.mds_thrash_exports << endl;
@@ -935,16 +935,18 @@ void MDS::my_dispatch(Message *m)
     while (n--) p++;
     
     CDir *dir = p->second->dir;
-    if (dir && dir->is_auth()) {
-      int dest;
-      do {
-       int k = rand() % s.size();
-       set<int>::iterator p = s.begin();
-       while (k--) p++;
-       dest = *p;
-      } while (dest != whoami);
-      mdcache->migrator->export_dir(dir,dest);
-    }
+    if (!dir) continue;                      // must be a dir.
+    if (!dir->get_parent_dir()) continue;    // must be linked.
+    if (!dir->is_auth()) continue;           // must be auth.
+
+    int dest;
+    do {
+      int k = rand() % s.size();
+      set<int>::iterator p = s.begin();
+      while (k--) p++;
+      dest = *p;
+    } while (dest == whoami);
+    mdcache->migrator->export_dir(dir,dest);
   }
 
 
index 66b086e5ea39f8d49ac6f628839899a52a124812..d7c5846bbdf8675b4f509a3b000742187b187c72 100644 (file)
@@ -175,6 +175,7 @@ class MDSMap {
   bool is_rejoin(int m)    { return mds_state.count(m) && mds_state[m] == STATE_REJOIN; }
   bool is_active(int m)   { return mds_state.count(m) && mds_state[m] == STATE_ACTIVE; }
   bool is_stopping(int m) { return mds_state.count(m) && mds_state[m] == STATE_STOPPING; }
+  bool is_active_or_stopping(int m)   { return is_active(m) || is_stopping(m); }
   bool is_stopped(int m)  { return mds_state.count(m) && mds_state[m] == STATE_STOPPED; }
 
   bool has_created(int m) { return mds_created.count(m); }
index 13aa270a2ee6c36105fe3c26032066ac5456a43d..b42e19f9c91bfcc36e5cb04f3774adf8776743f8 100644 (file)
@@ -83,13 +83,13 @@ void MDStore::fetch_dir( CDir *dir,
   if (c) dir->add_waiter(CDIR_WAIT_COMPLETE, c);
   
   // already fetching?
-  if (dir->state_test(CDIR_STATE_FETCHING)) {
+  if (dir->state_test(CDir::STATE_FETCHING)) {
     dout(7) << "already fetching " << *dir << "; waiting" << endl;
     return;
   }
   
   // state
-  dir->state_set(CDIR_STATE_FETCHING);
+  dir->state_set(CDir::STATE_FETCHING);
   
   // stats
   if (mds->logger) mds->logger->inc("fdir");
@@ -118,8 +118,8 @@ void MDStore::fetch_dir_2( int result,
   assert(dir);
   
   // dir is now complete
-  dir->state_set(CDIR_STATE_COMPLETE);
-  dir->state_clear(CDIR_STATE_FETCHING);
+  dir->state_set(CDir::STATE_COMPLETE);
+  dir->state_clear(CDir::STATE_FETCHING);
 
   // finish
   list<Context*> finished;
@@ -483,7 +483,7 @@ void MDStore::commit_dir( CDir *dir,
          dir->is_hashed());
   
   // already committing?
-  if (dir->state_test(CDIR_STATE_COMMITTING)) {
+  if (dir->state_test(CDir::STATE_COMMITTING)) {
     // already mid-commit!
     dout(7) << "commit_dir " << *dir << " mid-commit of " << dir->get_committing_version() << endl;
     dout(7) << "  current version = " << dir->get_version() << endl;
@@ -525,7 +525,7 @@ void MDStore::commit_dir( CDir *dir,
   Context *fin = new C_MDS_CommitDirFinish(this, dir);
   
   // state
-  dir->state_set(CDIR_STATE_COMMITTING);
+  dir->state_set(CDir::STATE_COMMITTING);
   dir->set_committing_version(); 
 
   // stats
@@ -554,7 +554,7 @@ void MDStore::commit_dir_2( int result,
   if (committed_version == dir->get_version())
     dir->mark_clean();
  
-  dir->state_clear(CDIR_STATE_COMMITTING);
+  dir->state_clear(CDir::STATE_COMMITTING);
 
   // finish
   dir->finish_waiting(CDIR_WAIT_COMMITTED);
index cfcf98424aacee591396e70eb2744cd7fa2331ae..4d294296bd194513363b5fe3ae3f41aec8d3db48 100644 (file)
@@ -293,10 +293,10 @@ void Migrator::handle_mds_failure(int who)
       export_finish_waiters.erase(dir);
       
       // send pending import_maps?  (these need to go out when all exports have finished.)
-      mds->mdcache->send_pending_import_maps();
+      cache->send_pending_import_maps();
 
-      mds->mdcache->show_imports();
-      mds->mdcache->show_cache();
+      cache->show_imports();
+      cache->show_cache();
     } else {
       // third party failed.  potential peripheral damage?
       if (p->second == EXPORT_WARNING) {
@@ -354,11 +354,14 @@ void Migrator::handle_mds_failure(int who)
       case IMPORT_PREPPED:
        dout(10) << "state prepping : unpinning base+bounds, unfreezing,  " << *dir << endl;
        assert(dir);
-       dir->set_dir_auth_pending(CDIR_AUTH_UNKNOWN);   // not anymore.
        
        // unfreeze
        dir->unfreeze_tree();
 
+       // adjust auth
+       cache->adjust_subtree_auth(dir, mds->get_nodeid());
+       cache->try_subtree_merge(dir);
+       
        // fall-thru to unpin base+bounds
 
       case IMPORT_PREPPING:
@@ -373,8 +376,8 @@ void Migrator::handle_mds_failure(int who)
             it != import_bounds[dir].end();
             it++) {
          CDir *bd = *it;
-         assert(bd->state_test(CDIR_STATE_IMPORTBOUND));
-         bd->state_clear(CDIR_STATE_IMPORTBOUND);
+         assert(bd->state_test(CDir::STATE_IMPORTBOUND));
+         bd->state_clear(CDir::STATE_IMPORTBOUND);
          bd->put(CDir::PIN_IMPORTBOUND);
        }
        break;
@@ -402,8 +405,8 @@ void Migrator::handle_mds_failure(int who)
       import_bound_inos.erase(dirino);
       import_bounds.erase(dir);
 
-      mds->mdcache->show_imports();
-      mds->mdcache->show_cache();
+      cache->show_imports();
+      cache->show_cache();
     }
 
     // next!
@@ -444,6 +447,7 @@ void Migrator::export_dir(CDir *dir,
                          int dest)
 {
   dout(7) << "export_dir " << *dir << " to " << dest << endl;
+  assert(dir->is_auth());
   assert(dest != mds->get_nodeid());
   assert(!dir->is_hashed());
    
@@ -454,7 +458,7 @@ void Migrator::export_dir(CDir *dir,
 
   if (dir->inode->is_root()) {
     dout(7) << "i won't export root" << endl;
-    assert(0);
+    //assert(0);
     return;
   }
 
@@ -515,6 +519,7 @@ void Migrator::handle_export_dir_discover_ack(MExportDirDiscoverAck *m)
   delete m;  // done
 }
 
+/*
 class C_MDC_ExportStartLogged : public Context {
   Migrator *mig;
   CDir *ex;   // dir i'm exporting
@@ -525,27 +530,26 @@ public:
   C_MDC_ExportStartLogged(Migrator *m, CDir *e, int d, MExportDirPrep *p) :
        mig(m), ex(e), dest(d), prep(p) {}
   virtual void finish(int r) {
-    mig->export_dir_frozen_logged(ex, prep, dest);
+    mig->export_dir_start_logged(ex, prep, dest);
   }
 };
+*/
 
 void Migrator::export_dir_frozen(CDir *dir,
-                                int dest)
+                                int dest)
 {
   // subtree is now frozen!
   dout(7) << "export_dir_frozen on " << *dir << " to " << dest << endl;
   export_state[dir] = EXPORT_LOGGINGSTART;
 
-  show_imports();
+  cache->show_imports();
 
-  // -- note/mark subtree bounds --
-  // also include traces to all nested exports.
-  cache->find_nested_exports(dir, export_bounds[dir]);
+  // note the bounds.
+  //  force it into a subtree by listing auth as <me,me>.
+  cache->adjust_subtree_auth(dir, mds->get_nodeid(), mds->get_nodeid());
+  cache->get_subtree_bounds(dir, export_bounds[dir]);
   set<CDir*> &bounds = export_bounds[dir];
-  
-  // note that dest an ambiguous auth for this subtree.
-  dir->set_dir_auth_pending(export_peer[dir]);
-  
+
   // generate prep message, log entry.
   EExportStart *le = new EExportStart(dir, dest);
   MExportDirPrep *prep = new MExportDirPrep(dir->inode);
@@ -564,23 +568,24 @@ void Migrator::export_dir_frozen(CDir *dir,
   for (set<CDir*>::iterator it = bounds.begin();
        it != bounds.end();
        it++) {
-    CDir *exp = *it;
+    CDir *bound = *it;
 
     // pin it.
-    exp->get(CDir::PIN_EXPORTBOUND);
+    bound->get(CDir::PIN_EXPORTBOUND);
+    bound->state_set(CDir::STATE_EXPORTBOUND);
     
-    dout(7) << " including nested export " << *exp << " in prep" << endl;
+    dout(7) << "  export bound " << *bound << endl;
 
-    prep->add_export( exp->ino() );
-    le->get_bounds().insert(exp->ino());
-    le->metablob.add_dir_context( exp );
-    le->metablob.add_dir( exp, false );
+    prep->add_export( bound->ino() );
+    le->get_bounds().insert(bound->ino());
+    le->metablob.add_dir_context( bound );
+    le->metablob.add_dir( bound, false );
 
     /* first assemble each trace, in trace order, and put in message */
     list<CInode*> inode_trace;  
 
     // trace to dir
-    CDir *cur = exp;
+    CDir *cur = bound;
     while (cur != dir) {
       // don't repeat ourselves
       if (inodes_added.count(cur->ino())) break;   // did already!
@@ -617,12 +622,18 @@ void Migrator::export_dir_frozen(CDir *dir,
   
   // log our intentions
   dout(7) << " logging EExportStart" << endl;
-  mds->mdlog->submit_entry(le, new C_MDC_ExportStartLogged(this, dir, dest, prep));
+  mds->mdlog->submit_entry(le);
+  // don't wait for it to flush, it doesn't matter.
+  // FIXME: just combine Start into Finish, we only need 1 log entry.
+  //, new C_MDC_ExportStartLogged(this, dir, dest, prep));
+
+  /*
+
 }
 
-void Migrator::export_dir_frozen_logged(CDir *dir, MExportDirPrep *prep, int dest)
+void Migrator::export_dir_start_logged(CDir *dir, MExportDirPrep *prep, int dest)
 {
-  dout(7) << "export_dir_frozen_logged " << *dir << endl;
+  dout(7) << "export_dir_start_logged " << *dir << endl;
 
   if (export_state.count(dir) == 0 ||
       export_state[dir] != EXPORT_LOGGINGSTART) {
@@ -632,6 +643,7 @@ void Migrator::export_dir_frozen_logged(CDir *dir, MExportDirPrep *prep, int des
     dir->unfreeze_tree();  // cancel the freeze
     return;
   }
+  */
 
   export_state[dir] = EXPORT_PREPPING;
   mds->send_message_mds(prep, dest, MDS_PORT_MIGRATOR);
@@ -644,7 +656,7 @@ void Migrator::handle_export_dir_prep_ack(MExportDirPrepAck *m)
   CDir *dir = in->dir;
   assert(dir);
 
-  dout(7) << "export_dir_prep_ack " << *dir << ", sending notifies" << endl;
+  dout(7) << "export_dir_prep_ack " << *dir << endl;
   
   if (export_state.count(dir) == 0 ||
       export_state[dir] != EXPORT_PREPPING) {
@@ -663,13 +675,18 @@ void Migrator::handle_export_dir_prep_ack(MExportDirPrepAck *m)
        p != dir->replicas_end();
        ++p) {
     if (p->first == dest) continue;
-    if (!mds->mdsmap->is_active(p->first) || 
-       !mds->mdsmap->is_stopping(p->first)) 
+    if (!mds->mdsmap->is_active_or_stopping(p->first))
       continue;  // only if active
     export_warning_ack_waiting[dir].insert(p->first);
     export_notify_ack_waiting[dir].insert(p->first);  // we'll eventually get a notifyack, too!
-    mds->send_message_mds(new MExportDirWarning(dir->ino(), export_peer[dir]),
-                         p->first, MDS_PORT_MIGRATOR);
+
+    //mds->send_message_mds(new MExportDirWarning(dir->ino(), export_peer[dir]),
+    //p->first, MDS_PORT_MIGRATOR);
+    MExportDirNotify *notify = new MExportDirNotify(dir->ino(), 
+                                                   mds->get_nodeid(), export_peer[dir]);
+    notify->copy_exports(export_bounds[dir]);
+    mds->send_message_mds(notify, p->first, MDS_PORT_MIGRATOR);
+    
   }
   export_state[dir] = EXPORT_WARNING;
 
@@ -718,7 +735,7 @@ void Migrator::export_dir_go(CDir *dir)
   int dest = export_peer[dir];
   dout(7) << "export_dir_go " << *dir << " to " << dest << endl;
 
-  show_imports();
+  cache->show_imports();
   
   export_warning_ack_waiting.erase(dir);
   export_state[dir] = EXPORT_EXPORTING;
@@ -728,16 +745,17 @@ void Migrator::export_dir_go(CDir *dir)
 
   assert(dir->get_cum_auth_pins() == 0);
 
-  // update imports/exports
-  cache->export_subtree(dir, export_bounds[dir], dest);
-
+  // set ambiguous auth
+  cache->adjust_subtree_auth(dir, dest, mds->get_nodeid());
+  cache->verify_subtree_bounds(dir, export_bounds[dir]);
+  
   // fill export message with cache data
   C_Contexts *fin = new C_Contexts;       // collect all the waiters
   int num_exported_inodes = encode_export_dir( export_data[dir], 
-                                             fin, 
-                                             dir,   // base
-                                             dir,   // recur start point
-                                             dest );
+                                              fin, 
+                                              dir,   // base
+                                              dir,   // recur start point
+                                              dest );
   
   // send the export data!
   MExportDir *req = new MExportDir(dir->ino());
@@ -757,19 +775,18 @@ void Migrator::export_dir_go(CDir *dir)
   // queue up the finisher
   dir->add_waiter( CDIR_WAIT_UNFREEZE, fin );
 
-
   // stats
   if (mds->logger) mds->logger->inc("ex");
   if (mds->logger) mds->logger->inc("iex", num_exported_inodes);
 
-  show_imports();
+  cache->show_imports();
 }
 
 
 /** encode_export_inode
  * update our local state for this inode to export.
  * encode relevant state to be sent over the wire.
- * used by: export_dir_walk, file_rename (if foreign)
+ * used by: encode_export_dir, file_rename (if foreign)
  */
 void Migrator::encode_export_inode(CInode *in, bufferlist& enc_state, int new_auth)
 {
@@ -851,7 +868,7 @@ int Migrator::encode_export_dir(list<bufferlist>& dirstatelist,
 {
   int num_exported = 0;
 
-  dout(7) << "export_dir_walk " << *dir << " " << dir->nitems << " items" << endl;
+  dout(7) << "encode_export_dir " << *dir << " " << dir->nitems << " items" << endl;
   
   assert(dir->get_projected_version() == dir->get_version());
 
@@ -866,11 +883,11 @@ int Migrator::encode_export_dir(list<bufferlist>& dirstatelist,
 
   // mark
   assert(dir->is_auth());
-  dir->state_clear(CDIR_STATE_AUTH);
+  dir->state_clear(CDir::STATE_AUTH);
   dir->replica_nonce = CDIR_NONCE_EXPORT;
 
   // proxy
-  //dir->state_set(CDIR_STATE_PROXY);
+  //dir->state_set(CDir::STATE_PROXY);
   //dir->get(CDir::PIN_PROXY);
   //export_proxy_dirinos[basedir].push_back(dir->ino());
 
@@ -878,7 +895,7 @@ int Migrator::encode_export_dir(list<bufferlist>& dirstatelist,
 
   if (dir->is_hashed()) {
     // fix state
-    dir->state_clear( CDIR_STATE_AUTH );
+    dir->state_clear( CDir::STATE_AUTH );
 
   } else {
     
@@ -886,7 +903,7 @@ int Migrator::encode_export_dir(list<bufferlist>& dirstatelist,
       dir->mark_clean();
     
     // discard most dir state
-    dir->state &= CDIR_MASK_STATE_EXPORT_KEPT;  // i only retain a few things.
+    dir->state &= CDir::MASK_STATE_EXPORT_KEPT;  // i only retain a few things.
     
     // suck up all waiters
     list<Context*> waiting;
@@ -903,7 +920,7 @@ int Migrator::encode_export_dir(list<bufferlist>& dirstatelist,
       num_exported++;
       
       // -- dentry
-      dout(7) << "export_dir_walk exporting " << *dn << endl;
+      dout(7) << "encode_export_dir exporting " << *dn << endl;
 
       // name
       _encode(it->first, enc_dir);
@@ -936,12 +953,12 @@ int Migrator::encode_export_dir(list<bufferlist>& dirstatelist,
       encode_export_inode(in, enc_dir, newauth);  // encode, and (update state for) export
       
       // directory?
-      if (in->is_dir() && in->dir) { 
-        if (in->dir->is_auth()) {
-          // nested subdir
-          assert(in->dir->get_dir_auth().first == CDIR_AUTH_PARENT);
-          subdirs.push_back(in->dir);  // it's ours, recurse (later)
-       }
+      if (in->is_dir() && 
+         in->dir &&
+         !in->dir->state_test(CDir::STATE_EXPORTBOUND)) {
+       // include nested subdir
+       assert(in->dir->get_dir_auth().first == CDIR_AUTH_PARENT);
+       subdirs.push_back(in->dir);  // it's ours, recurse (later)
       }
       
       // add to proxy
@@ -997,7 +1014,6 @@ void Migrator::handle_export_dir_ack(MExportDirAck *m)
   
   export_state[dir] = EXPORT_LOGGINGFINISH;
   export_data.erase(dir);
-  export_bounds.erase(dir);
   
   // log export completion, then finish (unfreeze, trigger finish context, etc.)
   dir->get(CDir::PIN_LOGGINGEXPORTFINISH);
@@ -1022,8 +1038,10 @@ void Migrator::reverse_export(CDir *dir)
   assert(export_bounds.count(dir));
   assert(export_data.count(dir));
   
-  // adjust dir_auth, exports
-  cache->import_subtree(dir, export_bounds[dir]);
+  // adjust auth, with possible subtree merge.
+  cache->verify_subtree_bounds(dir, export_bounds[dir]);
+  cache->adjust_subtree_auth(dir, mds->get_nodeid());
+  cache->try_subtree_merge(dir);
 
   // unpin bounds
   for (set<CDir*>::iterator p = export_bounds[dir].begin();
@@ -1031,6 +1049,7 @@ void Migrator::reverse_export(CDir *dir)
        ++p) {
     CDir *bd = *p;
     bd->put(CDir::PIN_EXPORTBOUND);
+    bd->state_clear(CDir::STATE_EXPORTBOUND);
   }
 
   // re-import the metadata
@@ -1059,7 +1078,7 @@ void Migrator::reverse_export(CDir *dir)
        p != export_notify_ack_waiting[dir].end();
        ++p) {
     MExportDirNotify *notify = new MExportDirNotify(dir->ino(), 
-                                                   mds->get_nodeid(), mds->get_nodeid());
+                                                   mds->get_nodeid(), CDIR_AUTH_UNKNOWN);
     notify->copy_exports(export_bounds[dir]);
     mds->send_message_mds(notify, *p, MDS_PORT_MIGRATOR);
   }
@@ -1080,7 +1099,7 @@ void Migrator::reverse_export(CDir *dir)
  */
 void Migrator::export_dir_logged_finish(CDir *dir)
 {
-  dout(7) << "export_dir_commit " << *dir << endl;
+  dout(7) << "export_dir_logged_finish " << *dir << endl;
   dir->put(CDir::PIN_LOGGINGEXPORTFINISH);
 
   if (export_state.count(dir) == 0||
@@ -1089,6 +1108,8 @@ void Migrator::export_dir_logged_finish(CDir *dir)
     return;
   }
 
+  cache->verify_subtree_bounds(dir, export_bounds[dir]);
+
   // send notifies
   int dest = export_peer[dir];
 
@@ -1096,7 +1117,7 @@ void Migrator::export_dir_logged_finish(CDir *dir)
        p != export_notify_ack_waiting[dir].end();
        ++p) {
     MExportDirNotify *notify = new MExportDirNotify(dir->ino(), 
-                                                   mds->get_nodeid(), dest);
+                                                   dest, CDIR_AUTH_UNKNOWN);
     notify->copy_exports(export_bounds[dir]);
     
     mds->send_message_mds(notify, *p, MDS_PORT_MIGRATOR);
@@ -1111,8 +1132,12 @@ void Migrator::export_dir_logged_finish(CDir *dir)
 }
 
 /*
- * i'll get an ack from each bystander.
- * when i get them all, unfreeze and send the finish.
+ * warning:
+ *  i'll get an ack from each bystander.
+ *  when i get them all, do the export.
+ * notify:
+ *  i'll get an ack from each bystander.
+ *  when i get them all, unfreeze and send the finish.
  */
 void Migrator::handle_export_dir_notify_ack(MExportDirNotifyAck *m)
 {
@@ -1130,20 +1155,30 @@ void Migrator::handle_export_dir_notify_ack(MExportDirNotifyAck *m)
   // aborted?
   if (!dir ||
       export_state.count(dir) == 0 ||
-      export_state[dir] != EXPORT_NOTIFYING) {
-    dout(7) << "target must have failed, not sending finish message.  export succeeded anyway." << endl;
-    
+      (export_state[dir] != EXPORT_NOTIFYING &&
+       export_state[dir] != EXPORT_WARNING)) {
+    dout(7) << "target must have failed, ignoring." << endl;
     delete m;
     return;
   }
 
-  // process.
   int from = m->get_source().num();
-  assert(export_notify_ack_waiting.count(dir));
-  export_notify_ack_waiting[dir].erase(from);
-  
-  if (export_notify_ack_waiting[dir].empty())
-    export_dir_finish(dir);
+    
+  if (export_state[dir] == EXPORT_WARNING) {
+    // process warning.
+    assert(export_warning_ack_waiting.count(dir));
+    export_warning_ack_waiting[dir].erase(from);
+    
+    if (export_warning_ack_waiting[dir].empty()) 
+      export_dir_go(dir);     // start export.
+  } else {
+    // process notify.
+    assert(export_notify_ack_waiting.count(dir));
+    export_notify_ack_waiting[dir].erase(from);
+    
+    if (export_notify_ack_waiting[dir].empty())
+      export_dir_finish(dir);
+  }
 
   delete m;
 }
@@ -1153,19 +1188,14 @@ void Migrator::export_dir_finish(CDir *dir)
 {
   dout(7) << "export_dir_finish " << *dir << endl;
 
-  export_notify_ack_waiting.erase(dir);
-
-  if (export_state.count(dir)) {
-    // send finish/commit to new auth
-    mds->send_message_mds(new MExportDirFinish(dir->ino()), export_peer[dir], MDS_PORT_MIGRATOR);
-
-    // remove from exporting list
-    export_state.erase(dir);
-    export_peer.erase(dir);
-  } else {
+  if (export_state.count(dir) == 0) {
     dout(7) << "target must have failed, not sending final commit message.  export succeeded anyway." << endl;
+    return;
   }
-    
+
+  // send finish/commit to new auth
+  mds->send_message_mds(new MExportDirFinish(dir->ino()), export_peer[dir], MDS_PORT_MIGRATOR);
+  
   // unfreeze
   dout(7) << "export_dir_finish unfreezing" << endl;
   dir->unfreeze_tree();
@@ -1176,8 +1206,14 @@ void Migrator::export_dir_finish(CDir *dir)
        ++p) {
     CDir *bd = *p;
     bd->put(CDir::PIN_EXPORTBOUND);
+    bd->state_clear(CDir::STATE_EXPORTBOUND);
   }
 
+  // adjust auth, with possible subtree merge.
+  //  (we do this _after_ removing EXPORTBOUND pins, to allow merges)
+  cache->adjust_subtree_auth(dir, export_peer[dir]);
+  cache->try_subtree_merge(dir);
+  
   // unpin path
   dout(7) << "export_dir_finish unpinning path" << endl;
   vector<CDentry*> trace;
@@ -1190,65 +1226,26 @@ void Migrator::export_dir_finish(CDir *dir)
   // discard delayed expires
   cache->discard_delayed_expire(dir);
 
+  // remove from exporting list, clean up state
+  export_state.erase(dir);
+  export_peer.erase(dir);
+  export_bounds.erase(dir);
+  export_notify_ack_waiting.erase(dir);
+    
   // queue finishers
   mds->queue_finished(export_finish_waiters[dir]);
   export_finish_waiters.erase(dir);
 
   // stats
-  if (mds->logger) mds->logger->set("nex", cache->exports.size());
+  //if (mds->logger) mds->logger->set("nex", cache->exports.size());
 
-  show_imports();
+  cache->show_imports();
 
   // send pending import_maps?
   mds->mdcache->send_pending_import_maps();
 }
 
 
-/*
-void Migrator::clear_export_proxy_pins(CDir *dir)
-{
-  dout(10) << "clear_export_proxy_pins " << *dir << endl;
-
-  // inodes
-  for (list<inodeno_t>::iterator it = export_proxy_inos[dir].begin();
-       it != export_proxy_inos[dir].end();
-       it++) {
-    CInode *in = cache->get_inode(*it);
-    dout(15) << " " << *in << endl;
-    in->put(CInode::PIN_PROXY);
-    assert(in->state_test(CInode::STATE_PROXY));
-    in->state_clear(CInode::STATE_PROXY);
-  }
-  export_proxy_inos.erase(dir);
-  
-  // dirs
-  for (list<inodeno_t>::iterator it = export_proxy_dirinos[dir].begin();
-       it != export_proxy_dirinos[dir].end();
-       it++) {
-    CDir *dir = cache->get_inode(*it)->dir;    
-    dout(15) << " " << *dir << endl;
-    dir->put(CDir::PIN_PROXY);
-    assert(dir->state_test(CDIR_STATE_PROXY));
-    dir->state_clear(CDIR_STATE_PROXY);
-    
-    // hose neg dentries, too, since we're no longer auth
-    CDir_map_t::iterator it;
-    for (it = dir->begin(); it != dir->end(); ) {
-      CDentry *dn = it->second;
-      it++;
-      if (dn->is_null()) {
-       assert(dn->is_sync());
-       dir->remove_dentry(dn);
-      } else {
-       //dout(10) << "export_dir_notify_ack leaving xlocked neg " << *dn << endl;
-       if (dn->is_dirty())
-         dn->mark_clean();
-      }
-    }
-  }
-  export_proxy_dirinos.erase(dir);
-}    
-*/
 
 
 
@@ -1326,7 +1323,6 @@ void Migrator::handle_export_dir_discover_2(MExportDirDiscover *m, CInode *in, i
   import_state[in->ino()] = IMPORT_DISCOVERED;
   import_peer[in->ino()] = m->get_source().num();
 
-  
   // reply
   dout(7) << " sending export_dir_discover_ack on " << *in << endl;
   mds->send_message_mds(new MExportDirDiscoverAck(in->ino()),
@@ -1338,11 +1334,12 @@ void Migrator::handle_export_dir_discover_2(MExportDirDiscover *m, CInode *in, i
 
 void Migrator::handle_export_dir_prep(MExportDirPrep *m)
 {
-  assert(m->get_source().num() != mds->get_nodeid());
-
   CInode *diri = cache->get_inode(m->get_ino());
   assert(diri);
 
+  int oldauth = m->get_source().num();
+  assert(oldauth != mds->get_nodeid());
+
   list<Context*> finished;
 
   // assimilate root dir.
@@ -1366,7 +1363,7 @@ void Migrator::handle_export_dir_prep(MExportDirPrep *m)
   }
   assert(dir->is_auth() == false);
   
-  show_imports();
+  cache->show_imports();
 
   // assimilate contents?
   if (!m->did_assim()) {
@@ -1450,10 +1447,10 @@ void Migrator::handle_export_dir_prep(MExportDirPrep *m)
     CInode *in = cache->get_inode(ino);
     assert(in);
     if (in->dir) {
-      if (!in->dir->state_test(CDIR_STATE_IMPORTBOUND)) {
+      if (!in->dir->state_test(CDir::STATE_IMPORTBOUND)) {
         dout(7) << "  pinning import bound " << *in->dir << endl;
         in->dir->get(CDir::PIN_IMPORTBOUND);
-        in->dir->state_set(CDIR_STATE_IMPORTBOUND);
+        in->dir->state_set(CDir::STATE_IMPORTBOUND);
        import_bounds[dir].insert(in->dir);
       } else {
         dout(7) << "  already pinned import bound " << *in << endl;
@@ -1467,14 +1464,15 @@ void Migrator::handle_export_dir_prep(MExportDirPrep *m)
   if (waiting_for) {
     dout(7) << " waiting for " << waiting_for << " nested export dir opens" << endl;
   } else {
-    // freeze import region
-    // (note: this is a manual freeze.. hack hack hack!)
-    dout(7) << " all ready, freezing import region" << endl;
-
-    // then, note that i am an ambiguous auth for this subtree.
-    dir->set_dir_auth_pending(mds->get_nodeid());
+    dout(7) << " all ready, noting auth and freezing import region" << endl;
 
-    // mark import point frozen
+    // note that i am an ambiguous auth for this subtree.
+    // specify bounds, since the exporter explicitly defines the region.
+    cache->adjust_bounded_subtree_auth(dir, import_bounds[dir], 
+                                      pair<int,int>(oldauth, mds->get_nodeid()));
+    cache->verify_subtree_bounds(dir, import_bounds[dir]);
+    
+    // freeze.
     dir->_freeze_tree();
     
     // ok!
@@ -1525,14 +1523,15 @@ void Migrator::handle_export_dir(MExportDir *m)
   dout(7) << "handle_export_dir importing " << *dir << " from " << oldauth << endl;
   assert(dir->is_auth() == false);
 
-  show_imports();
+  cache->show_imports();
   
   // start the journal entry
   EImportStart *le = new EImportStart(dir->ino(), m->get_exports());
   le->metablob.add_dir_context(dir);
   
-  // update dir_auth, import maps
-  cache->import_subtree(dir, import_bounds[dir]);
+  // adjust auth (list us _first_)
+  cache->adjust_subtree_auth(dir, mds->get_nodeid(), oldauth);
+  cache->verify_subtree_bounds(dir, import_bounds[dir]);
 
   // take out my importing pin
   dir->put(CDir::PIN_IMPORTING);
@@ -1563,7 +1562,7 @@ void Migrator::handle_export_dir(MExportDir *m)
 
     // remove bound pin
     bd->put(CDir::PIN_IMPORTBOUND);
-    bd->state_clear(CDIR_STATE_IMPORTBOUND);
+    bd->state_clear(CDir::STATE_IMPORTBOUND);
     
     // include bounding dirs in EImportStart
     // (now that the interior metadata is already in the event)
@@ -1587,7 +1586,7 @@ void Migrator::handle_export_dir(MExportDir *m)
   if (mds->logger) {
     mds->logger->inc("im");
     mds->logger->inc("iim", num_imported_inodes);
-    mds->logger->set("nim", cache->imports.size());
+    //mds->logger->set("nim", cache->imports.size());
   }
 
   delete m;
@@ -1600,8 +1599,9 @@ void Migrator::reverse_import(CDir *dir)
 
   assert(0); // implement me.
 
-  // update dir_auth, import maps
-  cache->export_subtree(dir, import_bounds[dir], import_peer[dir->ino()]);
+  // update auth, with possible subtree merge.
+  cache->adjust_subtree_auth(dir, import_peer[dir->ino()]);
+  cache->try_subtree_merge(dir);
   
   // remove bound pins
   for (set<CDir*>::iterator it = import_bounds[dir].begin();
@@ -1609,7 +1609,7 @@ void Migrator::reverse_import(CDir *dir)
        it++) {
     CDir *bd = *it;
     bd->put(CDir::PIN_IMPORTBOUND);
-    bd->state_clear(CDIR_STATE_IMPORTBOUND);
+    bd->state_clear(CDir::STATE_IMPORTBOUND);
   }
 
   // ...
@@ -1630,7 +1630,7 @@ void Migrator::import_dir_logged_start(CDir *dir, int from,
   mds->send_message_mds(new MExportDirAck(dir->inode->ino()),
                        from, MDS_PORT_MIGRATOR);
 
-  show_imports();
+  cache->show_imports();
 }
 
 
@@ -1667,8 +1667,13 @@ void Migrator::import_dir_logged_finish(CDir *dir)
 {
   dout(7) << "import_dir_logged_finish " << *dir << endl;
 
-  // unfreeze!
+  // unfreeze
   dir->unfreeze_tree();
+
+  // adjust auth, with possible subtree merge.
+  cache->verify_subtree_bounds(dir, import_bounds[dir]);
+  cache->adjust_subtree_auth(dir, mds->get_nodeid());
+  cache->try_subtree_merge(dir);
   
   // clear import state (we're done!)
   import_state.erase(dir->ino());
@@ -1685,10 +1690,10 @@ void Migrator::import_dir_logged_finish(CDir *dir)
 
   // log it
   if (mds->logger) {
-    mds->logger->set("nex", cache->exports.size());
-    mds->logger->set("nim", cache->imports.size());
+    //mds->logger->set("nex", cache->exports.size());
+    //mds->logger->set("nim", cache->imports.size());
   }
-  show_imports();
+  cache->show_imports();
 
   // is it empty?
   if (dir->get_size() == 0 &&
@@ -1802,7 +1807,7 @@ int Migrator::decode_import_dir(bufferlist& bl,
 
   // mark  (may already be marked from get_or_open_dir() above)
   if (!dir->is_auth())
-    dir->state_set(CDIR_STATE_AUTH);
+    dir->state_set(CDir::STATE_AUTH);
 
   // adjust replica list
   //assert(!dir->is_replica(oldauth));    // not true on failed export
@@ -1898,15 +1903,18 @@ void Migrator::handle_export_dir_warning(MExportDirWarning *m)
   CDir *dir = 0;
   if (diri) dir = diri->dir;
 
+  int oldauth = m->get_source().num();
+  int newauth = m->get_new_dir_auth();
   if (dir) {
-    dout(7) << "handle_export_dir_warning " << m->get_source() 
-           << " -> mds" << m->get_new_dir_auth()
+    dout(7) << "handle_export_dir_warning mds" << oldauth
+           << " -> mds" << newauth
            << " on " << *dir << endl;
-    dir->set_dir_auth_pending(m->get_new_dir_auth());
+    cache->adjust_subtree_auth(dir, oldauth, newauth);
+    // verify?
   } else {
     dout(7) << "handle_export_dir_warning on dir " << m->get_ino() << ", acking" << endl;
   }
-
+  
   // send the ack
   mds->send_message_mds(new MExportDirWarningAck(m->get_ino()),
                        m->get_source().num(), MDS_PORT_MIGRATOR);
@@ -1924,98 +1932,47 @@ void Migrator::handle_export_dir_notify(MExportDirNotify *m)
   CDir *dir = 0;
   if (diri) dir = diri->dir;
 
+  int from = m->get_source().num();
+  pair<int,int> auth = m->get_auth();
+  
   if (!dir) {
-    dout(7) << "handle_export_dir_notify mds" << m->get_old_auth()
-           << " -> mds" << m->get_new_auth()
+    dout(7) << "handle_export_dir_notify " << auth
            << " on missing dir " << m->get_ino() << endl;
-  } else if (m->get_old_auth() == m->get_new_auth()) {
-    dout(7) << "handle_export_dir_notify mds" << m->get_old_auth()
-           << " aborted export on "
-           << *dir << endl;
-    // clear dir_auth_pending
-    dir->set_dir_auth_pending(CDIR_AUTH_UNKNOWN);
-
-    // no ack necessary.
-    delete m;
-    return;
   } else {
-    dout(7) << "handle_export_dir_notify mds" << m->get_old_auth()
-           << " -> mds" << m->get_new_auth()
+    dout(7) << "handle_export_dir_notify " << auth
            << " on " << *dir << endl;
-    
-    // update bounds first
-    for (list<inodeno_t>::iterator it = m->get_exports().begin();
-        it != m->get_exports().end();
-        it++) {
-      CInode *n = cache->get_inode(*it);
-      if (!n) continue;
-      CDir *ndir = n->dir;
-      if (!ndir) continue;
-      
-      int boundauth = ndir->authority().first;
-      dout(7) << "export_dir_notify bound " << *ndir << " was dir_auth " << ndir->get_dir_auth() << " (" << boundauth << ")" << endl;
-      if (ndir->get_dir_auth().first == CDIR_AUTH_PARENT) {
-       if (boundauth != m->get_new_auth())
-         ndir->set_dir_auth( boundauth );
-       else 
-         assert(dir->authority().first == m->get_new_auth());  // apparently we already knew!
-      } else {
-       if (boundauth == m->get_new_auth())
-         ndir->set_dir_auth( CDIR_AUTH_PARENT );
-      }
+    // see which bounds we have in our cache
+    set<CDir*> bounds;
+    for (list<inodeno_t>::iterator p = m->get_exports().begin();
+        p != m->get_exports().end();
+        ++p) {
+      CInode *in = cache->get_inode(*p);
+      if (in && in->dir) 
+       bounds.insert(in->dir);
     }
+
+    // adjust auth
+    cache->adjust_bounded_subtree_auth(dir, bounds, auth);
+    cache->verify_subtree_bounds(dir, bounds);
     
-    // update dir_auth
-    if (diri->authority().first == m->get_new_auth()) {
-      dout(7) << "handle_export_dir_notify on " << *diri << ": inode auth is the same, setting dir_auth -1" << endl;
-      dir->set_dir_auth( CDIR_AUTH_PARENT );
-      assert(!diri->is_auth());
-      assert(!dir->is_auth());
-    } else {
-      dir->set_dir_auth( m->get_new_auth() );
-    }
-    assert(dir->authority().first != mds->get_nodeid());
-    assert(!dir->is_auth());
-    
-  // DEBUG: verify subdirs
-  /*
-  if (g_conf.mds_verify_export_dirauth) {
-    
-    dout(7) << "handle_export_dir_notify on " << *dir << " checking " << m->num_subdirs() << " subdirs" << endl;
-    for (list<inodeno_t>::iterator it = m->subdirs_begin();
-        it != m->subdirs_end();
-        it++) {
-      CInode *diri = cache->get_inode(*it);
-      if (!diri) continue;  // don't have it, don't care
-      if (!diri->dir) continue;
-      dout(10) << "handle_export_dir_notify checking subdir " << *diri->dir << " is auth " << diri->dir->get_dir_auth() << endl;
-      assert(diri->dir != dir);      // base shouldn't be in subdir list
-      if (diri->dir->get_dir_auth() != CDIR_AUTH_PARENT) {
-       dout(7) << "*** weird value for dir_auth " << diri->dir->get_dir_auth() << " on " << *diri->dir << ", should have been -1 probably??? ******************" << endl;
-       assert(0);  // bad news!
-       //dir->set_dir_auth( CDIR_AUTH_PARENT );
-      }
-      assert(diri->dir->authority() == m->get_new_auth());
-    }
-  }
-  */
+    // induce a merge?
+    cache->try_subtree_merge(dir);
   }
   
   // send ack
-  mds->send_message_mds(new MExportDirNotifyAck(m->get_ino()),
-                       m->get_old_auth(), MDS_PORT_MIGRATOR);
+  if (auth.first == from && 
+      auth.second == CDIR_AUTH_UNKNOWN) {
+    // aborted.  no ack.
+    dout(7) << "handle_export_dir_notify mds" << auth.first
+           << " aborted export, not sending ack for "
+           << *dir << endl;
+  } else {
+    mds->send_message_mds(new MExportDirNotifyAck(m->get_ino()),
+                         from, MDS_PORT_MIGRATOR);
+  }
   
   delete m;
 }
 
 
 
-
-
-
-
-
-void Migrator::show_imports()
-{
-  mds->balancer->show_imports();
-}
index 8788595c3da96044e056722d4d0c322903fc6ca5..5740a2ba9d36770c1b57ed2ad95badf80925a4f3 100644 (file)
@@ -137,7 +137,6 @@ public:
 
   // -- misc --
   void handle_mds_failure(int who);
-  void show_imports();
 
 
   // -- import/export --
@@ -158,7 +157,7 @@ public:
  protected:
   void handle_export_dir_discover_ack(MExportDirDiscoverAck *m);
   void export_dir_frozen(CDir *dir, int dest);
-  void export_dir_frozen_logged(CDir *dir, MExportDirPrep *prep, int dest);
+  //void export_dir_start_logged(CDir *dir, MExportDirPrep *prep, int dest);
   void handle_export_dir_prep_ack(MExportDirPrepAck *m);
   void handle_export_dir_warning_ack(MExportDirWarningAck *m);
   void export_dir_go(CDir *dir);
index 07437c2063c074c2c4b775853eb591fa0a62c279..5149d0d47e23f79d7fa7ddf249319972bf4bd75b 100644 (file)
@@ -95,6 +95,13 @@ void Renamer::fix_renamed_dir(CDir *srcdir,
   dout(7) << "fix_renamed_dir on " << *in << endl;
   dout(7) << "fix_renamed_dir on " << *in->dir << endl;
 
+
+  assert(0); // rewrite .
+
+  // 1- fix subtree tree.
+  // 2- adjust subtree auth.
+
+  /*
   if (in->dir->is_auth()) {
     // dir ours
     dout(7) << "dir is auth" << endl;
@@ -102,34 +109,14 @@ void Renamer::fix_renamed_dir(CDir *srcdir,
 
     if (in->is_auth()) {
       // inode now ours
-
       if (authchanged) {
         // inode _was_ replica, now ours
-        dout(7) << "inode was replica, now ours.  removing from import list." << endl;
-        assert(in->dir->is_import());
-        
-        // not import anymore!
-        cache->imports.erase(in->dir);
-        in->dir->state_clear(CDIR_STATE_IMPORT);
-        in->dir->put(CDir::PIN_IMPORT);
-
-        in->dir->set_dir_auth( CDIR_AUTH_PARENT );
-        dout(7) << " fixing dir_auth to be " << in->dir->get_dir_auth() << endl;
-
-        // move my nested imports to in's containing import
-        CDir *con = cache->get_auth_container(in->dir);
-        assert(con);
-        for (set<CDir*>::iterator p = cache->nested_exports[in->dir].begin();
-             p != cache->nested_exports[in->dir].end();
-             p++) {
-          dout(7) << "moving nested export under new container " << *con << endl;
-          cache->nested_exports[con].insert(*p);
-        }
-        cache->nested_exports.erase(in->dir);
-        
+        dout(7) << "inode was replica, now ours." << endl;
+       cache->adjust_subtree_auth(dir, mds->get_nodeid());
       } else {
         // inode was ours, still ours.
         dout(7) << "inode was ours, still ours." << endl;
+       
         assert(!in->dir->is_import());
         assert(in->dir->get_dir_auth().first == CDIR_AUTH_PARENT);
         
@@ -161,7 +148,7 @@ void Renamer::fix_renamed_dir(CDir *srcdir,
 
         // i am now an import
         cache->imports.insert(in->dir);
-        in->dir->state_set(CDIR_STATE_IMPORT);
+        in->dir->state_set(CDir::STATE_IMPORT);
         in->dir->get(CDir::PIN_IMPORT);
 
         in->dir->set_dir_auth( mds->get_nodeid() );
@@ -210,7 +197,7 @@ void Renamer::fix_renamed_dir(CDir *srcdir,
         
         // now export
         cache->exports.insert(in->dir);
-        in->dir->state_set(CDIR_STATE_EXPORT);
+        in->dir->state_set(CDir::STATE_EXPORT);
         in->dir->get(CDir::PIN_EXPORT);
         
         assert(dir_auth >= 0);  // better be defined
@@ -251,7 +238,7 @@ void Renamer::fix_renamed_dir(CDir *srcdir,
 
         // remove from export list
         cache->exports.erase(in->dir);
-        in->dir->state_clear(CDIR_STATE_EXPORT);
+        in->dir->state_clear(CDir::STATE_EXPORT);
         in->dir->put(CDir::PIN_EXPORT);
         
         CDir *oldcon = cache->get_auth_container(srcdir);
@@ -284,7 +271,7 @@ void Renamer::fix_renamed_dir(CDir *srcdir,
       assert(!in->dir->is_export());
     }  
   }
-
+  */
   cache->show_imports();
 }
 
index 8a42cf3206077f52783e6455de7402de2fcfe7fa..e3b47451d4aa03c44fbe5c072aedcb08ce4298a1 100644 (file)
@@ -127,10 +127,10 @@ void EMetaBlob::expire(MDS *mds, Context *c)
     
     // FIXME: check the slice only
 
-    if (dir->is_proxy()) {
+    if (dir->auth_is_ambiguous()) {
       // wait until export is acked (logged on remote) and committed (logged locally)
-      CDir *ex = mds->mdcache->get_export_container(dir);
-      dout(10) << "EMetaBlob.expire proxy for " << *dir
+      CDir *ex = mds->mdcache->get_subtree_root(dir);
+      dout(10) << "EMetaBlob.expire ambiguous auth for " << *dir
               << ", waiting for export finish on " << *ex << endl;
       waitfor_export.push_back(ex);
       continue;
@@ -384,6 +384,7 @@ void EImportMap::expire(MDS *mds, Context *c)
 
 void EImportMap::replay(MDS *mds) 
 {
+  /*
   if (!mds->mdcache->imports.empty()) {
     dout(10) << "EImportMap.replay -- ignoring, already have import map" << endl;
   } else {
@@ -400,7 +401,7 @@ void EImportMap::replay(MDS *mds)
       mds->mdcache->finish_ambiguous_import(*p);
     }
   }
-  
+  */
   mds->mdcache->show_imports();
 }
 
index 09bda336d41f7fa6d905295649064e63929e8852..68de14e7fb57fbbb1da436a4b813fd225f632c37 100644 (file)
 using namespace std;
 
 class MExportDirNotify : public Message {
-  int       new_auth;
-  int       old_auth;
   inodeno_t ino;
-  
+  pair<int,int> auth;
   list<inodeno_t> exports;  // bounds; these dirs are _not_ included (tho the inodes are)
-  list<inodeno_t> subdirs;
+
+  //list<inodeno_t> subdirs;
 
  public:
   inodeno_t get_ino() { return ino; }
-  int get_new_auth() { return new_auth; }
-  int get_old_auth() { return old_auth; }
+  pair<int,int> get_auth() { return auth; }
   list<inodeno_t>& get_exports() { return exports; }
-  list<inodeno_t>::iterator subdirs_begin() { return subdirs.begin(); }
-  list<inodeno_t>::iterator subdirs_end() { return subdirs.end(); }
-  int num_subdirs() { return subdirs.size(); }
+  //list<inodeno_t>::iterator subdirs_begin() { return subdirs.begin(); }
+  //list<inodeno_t>::iterator subdirs_end() { return subdirs.end(); }
+  //int num_subdirs() { return subdirs.size(); }
 
   MExportDirNotify() {}
-  MExportDirNotify(inodeno_t ino, int old_auth, int new_auth) :
-    Message(MSG_MDS_EXPORTDIRNOTIFY) {
-    this->ino = ino;
-    this->old_auth = old_auth;
-    this->new_auth = new_auth;
-  }
+  MExportDirNotify(inodeno_t i, int a, int b) :
+    Message(MSG_MDS_EXPORTDIRNOTIFY),
+    ino(i), auth(a,b) { }
+
   virtual char *get_type_name() { return "ExNot"; }
   
+  /*
   void copy_subdirs(list<inodeno_t>& s) {
     this->subdirs = s;
   }
+  */
   void copy_exports(list<inodeno_t>& ex) {
     this->exports = ex;
   }
@@ -63,21 +61,18 @@ class MExportDirNotify : public Message {
 
   virtual void decode_payload() {
     int off = 0;
-    payload.copy(off, sizeof(int), (char*)&new_auth);
-    off += sizeof(int);
-    payload.copy(off, sizeof(int), (char*)&old_auth);
-    off += sizeof(int);
+    payload.copy(off, sizeof(auth), (char*)&auth);
+    off += sizeof(auth);
     payload.copy(off, sizeof(ino), (char*)&ino);
     off += sizeof(ino);
     ::_decode(exports, payload, off);
-    ::_decode(subdirs, payload, off);
+    //::_decode(subdirs, payload, off);
   }
   virtual void encode_payload() {
-    payload.append((char*)&new_auth, sizeof(int));
-    payload.append((char*)&old_auth, sizeof(int));
+    payload.append((char*)&auth, sizeof(auth));
     payload.append((char*)&ino, sizeof(ino));
     ::_encode(exports, payload);
-    ::_encode(subdirs, payload);
+    //::_encode(subdirs, payload);
   }
 };
 
index 05106e096d1768bd720186d0d397a94110c1e41d..21cbe5f9d330bfb717bc6e2175ab4cc7efc08f2a 100644 (file)
@@ -137,9 +137,13 @@ public:
   void print(ostream& out) {
     out << "osd_op_reply(" << st.reqid
        << " " << MOSDOp::get_opname(st.op)
-       << " " << st.oid << " = " << st.result 
-      //<< " " << this
-       << ")";
+       << " " << st.oid;
+    if (st.commit)
+      out << " commit";
+    else
+      out << " ack";
+    out << " = " << st.result;
+    out << ")";
   }
 
 };