]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
foreign renames getting closer...
authorsage <sage@29311d96-e01e-0410-9327-a35deaab8ce9>
Tue, 10 May 2005 05:52:43 +0000 (05:52 +0000)
committersage <sage@29311d96-e01e-0410-9327-a35deaab8ce9>
Tue, 10 May 2005 05:52:43 +0000 (05:52 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@216 29311d96-e01e-0410-9327-a35deaab8ce9

22 files changed:
ceph/TODO
ceph/common/Timer.cc
ceph/common/Timer.h
ceph/common/clock.cc
ceph/config.cc
ceph/include/types.h
ceph/mds/CDentry.h
ceph/mds/CDir.cc
ceph/mds/CDir.h
ceph/mds/CInode.h
ceph/mds/MDCache.cc
ceph/mds/MDCache.h
ceph/mds/MDS.cc
ceph/messages/MRename.h
ceph/messages/MRenameAck.h
ceph/messages/MRenameNotify.h
ceph/messages/MRenamePrep.h [new file with mode: 0644]
ceph/messages/MRenameReq.h
ceph/messages/MRenameWarning.h [new file with mode: 0644]
ceph/msg/FakeMessenger.cc
ceph/msg/Message.h
ceph/msg/Messenger.cc

index 0722968ced36521b296662b53246df94150dfb13..f8d8125b1d594f8e83a74ca93d42657293757950 100644 (file)
--- a/ceph/TODO
+++ b/ceph/TODO
@@ -1,23 +1,19 @@
 
 SAGE:
 
+- mpimessenger: allow self-addressed messages
+- change export_proxy_*'s to lists (faster)
+
+- fix MExportAck and others to use dir+dentry, not inode
+  (otherwise this all breaks with hard links)
+
 - timer .. integrate with clock?
 
 - path_Traverse
   - fix noperm crap
   - clean up xlock interaction
 
-- foreign renames
- /- how to limit xlock collateral/chatter!
-    - test it!
-
- /- what happens to foreign xlock request when things un-xlock?
- / - unwind foreign xlocks on failure etc.
- /   - LOCK_AC_UNXLOCK?
-
-  - how do deal with the dn discover on initiator after a foreign xlock on a dn it didn't originally have?
-
-  - what about setting up an inode proxy???
+- finish testing foreign renames
 
 - symlink loops
 
index c8e1ed86e01237f42b7b07c0e7b6c61a0f7a04cb..09e2f0b91c39322159638b1edcba896f4c483a68 100644 (file)
 #include <sys/time.h>
 #include <math.h>
 
+// single global instance
+Timer g_timer;
+
+
+/***
+ * signal handler callback fun
+ */
+
 Messenger *messenger_to_kick = 0;
-Timer     *static_timer = 0;
 
 void timer_signal_handler(int sig)
 {
   // kick messenger.
-  if (messenger_to_kick && static_timer) {
-       messenger_to_kick->trigger_timer(static_timer);
+  if (messenger_to_kick) {
+       messenger_to_kick->trigger_timer(&g_timer);
   }
 }
 
-
 void Timer::register_timer()
 {
   dout(10) << "register_timer installing signal handler" << endl;
@@ -36,7 +42,6 @@ void Timer::register_timer()
         process (FakeMessenger), we're actually kicking the same event loop anyway.
   */
   // FIXME i shouldn't have to do this every time?
-  static_timer = this;
   messenger_to_kick = messenger;
   
   // install handler
@@ -66,13 +71,16 @@ void Timer::cancel_timer()
 {
   // clear my callback pointers
   messenger_to_kick = 0;
-  static_timer = 0;
   
   // remove my handler.  MESSILY FIXME
   sigaction(SIGALRM, 0, 0);
 }
 
 
+/***
+ * do user callbacks
+ */
+
 void Timer::execute_pending()
 {
   double now = g_clock.gettime();
index 5fd647ca3ef8dfb51e3f723389d9cbceb2adb38d..ddc541e8c39bb8fc5a56535f3c626da8f78662c9 100644 (file)
@@ -31,7 +31,7 @@ class Timer {
   void cancel_timer();  // make sure i get a callback
 
  public:
-  Timer(Messenger *msg) { messenger = msg; }
+  Timer() : messenger(0) { }
   ~Timer() { 
        // cancel any wakeup crap
        cancel_timer();
@@ -39,6 +39,11 @@ class Timer {
        // 
   }
 
+  void set_messenger(Messenger *m) {
+       messenger = m;
+  }
+
+
   // schedule events
   void add_event_after(double seconds,
                                           Context *callback) {
@@ -72,12 +77,8 @@ class Timer {
 };
 
 
-
-
-
-
-
-
+// single global instance
+extern Timer g_timer;
 
 
 
index a08863c7f200f14a4c2ce739e4c45d7ed1e037a3..d05653df7b9e74261e1b06c56e552cdbc99646e6 100644 (file)
@@ -20,8 +20,8 @@ Clock::Clock() {
 
 double g_now = 0.0;
 
-double Clock::gettime() {
-
+double Clock::gettime() 
+{
   if (g_conf.fake_clock) {
        g_now += .000001;
        return g_now;
index da1cb62e5fd0324c5675ee98a835d30aaf12b666..ec53712f93acfdde4ad30e277465ece41cca02bd 100644 (file)
@@ -12,7 +12,7 @@
 
 
 md_config_t g_conf = {
-  num_mds: 5,
+  num_mds: 3,
   num_osd: 10,
   num_client: 1,
 
@@ -49,7 +49,7 @@ md_config_t g_conf = {
   mds_log_before_reply: true,
 
   // --- fakeclient (mds regression testing) ---
-  num_fakeclient: 1000,
+  num_fakeclient: 100,
   fakeclient_requests: 100,
   fakeclient_deterministic: false,
 
@@ -64,7 +64,7 @@ md_config_t g_conf = {
   fakeclient_op_readdir:  10,
   fakeclient_op_mknod:    100,
   fakeclient_op_link:       false,
-  fakeclient_op_unlink:   100,
+  fakeclient_op_unlink:   10,
   fakeclient_op_rename:   100,
 
   fakeclient_op_mkdir:    100,
index 7a6e49417af5a8d1416edf87e2413def4cb1b5f7..b55da064eb48a3aa68f394476d9a1c3545bc83e4 100644 (file)
@@ -2,12 +2,17 @@
 #define __MDS_TYPES_H
 
 #include <sys/types.h>
-#include <ext/hash_map>
+#include <assert.h>
+
 #include <string>
 #include <set>
 #include <iostream>
 using namespace std;
 
+#include <ext/rope>
+using namespace __gnu_cxx;
+
+
 
 // md ops
 #define MDS_OP_STATFS   1
@@ -145,4 +150,46 @@ inline ostream& operator<<(ostream& out, multiset<int>& iset) {
   return out;
 }
 
+
+// -- rope helpers --
+
+inline void _rope(string& s, crope& r) 
+{
+  r.append(s.c_str());
+  r.append((char)0);
+}
+inline void _unrope(string& s, crope& r, int& off)
+{
+  s = r.c_str() + off;
+  off += s.length() + 1;
+}
+
+inline void _rope(set<int>& s, crope& r)
+{
+  int n = s.size();
+  r.append((char*)&n, sizeof(n));
+  for (set<int>::iterator it = s.begin();
+          it != s.end();
+          it++) {
+       int v = *it;
+       r.append((char*)&v, sizeof(v));
+       n--;
+  }
+  assert(n==0);
+}
+inline void _unrope(set<int>& s, crope& r, int& off) 
+{
+  s.clear();
+  int n;
+  r.copy(off, sizeof(n), (char*)&n);
+  off += sizeof(n);
+  for (int i=0; i<n; i++) {
+       int v;
+       r.copy(off, sizeof(v), (char*)&v);
+       off += sizeof(v);
+       s.insert(v);
+  }
+  assert(s.size() == n);
+}
+
 #endif
index 3025197bd523808c3a2a059f3a4de64646201892..738916fe49dcb0224909c7ec2cfcaa990e3fe3e1 100644 (file)
@@ -49,6 +49,7 @@ class CDentry {
        inode = NULL;
        dir = NULL;
        lockstate = DN_LOCK_SYNC;
+       xlockedby = 0;
        npins = 0;
        dirty = 0;
        parent_dir_version = 0;
@@ -57,6 +58,7 @@ class CDentry {
        name = n;
        inode = in;
        lockstate = DN_LOCK_SYNC;
+       xlockedby = 0;
        npins = 0;
        dirty = 0;
        parent_dir_version = 0;
index 2e44c8bc365319775a6c697c2e59425b71dfe221..bc0f48ae0d28ae2229639c9c4708a854472c5fb4 100644 (file)
@@ -413,7 +413,8 @@ void CDir::add_waiter(int tag, Context *c) {
 
 void CDir::take_waiting(int mask, 
                                                const string& dentry,
-                                               list<Context*>& ls)
+                                               list<Context*>& ls,
+                                               int num)
 {
   if (waiting_on_dentry.empty()) return;
   
@@ -423,6 +424,11 @@ void CDir::take_waiting(int mask,
          ls.push_back(it->second);
          dout(10) << "take_waiting dentry " << dentry << " mask " << mask << " took " << it->second << " tag " << it->first << " on " << *this << endl;
          waiting_on_dentry[dentry].erase(it++);
+
+         if (num) {
+               if (num == 1) break;
+               num--;
+         }
        } else {
          dout(10) << "take_waiting dentry " << dentry << " mask " << mask << " SKIPPING " << it->second << " tag " << it->first << " on " << *this << endl;
          it++;
index f54c3df3bbc10000490e3492b4f77d360b60c573..557bdee4e9f3cfa37f62c2c98fb2c097cd906017 100644 (file)
@@ -427,7 +427,8 @@ class CDir {
   void take_waiting(int mask, list<Context*>& ls);  // includes dentry waiters
   void take_waiting(int mask, 
                                        const string& dentry, 
-                                       list<Context*>& ls);  
+                                       list<Context*>& ls,
+                                       int num=0);  
   void finish_waiting(int mask, int result = 0);    // ditto
   void finish_waiting(int mask, const string& dn, int result = 0);    // ditto
 
index 2e553e687381e66f04e52b352519d6e6f45ae535..46d6b15a0953b9f0b8225654b3ce89d417febcd5 100644 (file)
@@ -138,8 +138,6 @@ static char *cinode_pin_names[CINODE_NUM_PINS] = {
     // waiters: handle_export_dir_warning
     // triggers: handle_export_dir_notify
 
-#define CINODE_WAIT_RENAMEACK    (1<<16)
-
 #define CINODE_WAIT_HARDR        (1<<17)  // 131072
 #define CINODE_WAIT_HARDW        (1<<18)  // 262...
 #define CINODE_WAIT_HARDB        (1<<19)
@@ -154,6 +152,10 @@ static char *cinode_pin_names[CINODE_NUM_PINS] = {
 #define CINODE_WAIT_SOFTNORD     (1<<26)
 #define CINODE_WAIT_SOFTNOWR     (1<<27)
 
+#define CINODE_WAIT_RENAMEACK       (1<<28)
+#define CINODE_WAIT_RENAMENOTIFYACK (1<<29)
+
+
 
 
 
index 1732b9cb8de0f14cc60c107f5b3a62ff9c788f97..a90860a4996925dc19d6244db337025790b16c51 100644 (file)
 #include "messages/MLock.h"
 #include "messages/MDentryUnlink.h"
 
+#include "messages/MRenameWarning.h"
 #include "messages/MRenameNotify.h"
 #include "messages/MRenameNotifyAck.h"
 #include "messages/MRename.h"
 #include "messages/MRenameAck.h"
 #include "messages/MRenameReq.h"
+#include "messages/MRenamePrep.h"
 
 #include "messages/MClientRequest.h"
 
@@ -181,8 +183,10 @@ void MDCache::rename_file(CDentry *srcdn,
 void MDCache::fix_renamed_dir(CDir *srcdir,
                                                          CInode *in,
                                                          CDir *destdir,
-                                                         bool authchanged)   // _inode_ auth
+                                                         bool authchanged,   // _inode_ auth
+                                                         int dir_auth)        // dir auth (for certain cases)
 {
+  dout(7) << "fix_renamed_dir on " << *in << endl;
   dout(7) << "fix_renamed_dir on " << *in->dir << endl;
 
   if (in->dir->is_auth()) {
@@ -203,6 +207,9 @@ void MDCache::fix_renamed_dir(CDir *srcdir,
                in->dir->state_clear(CDIR_STATE_IMPORT);
                in->dir->put(CDIR_PIN_IMPORT);
 
+               in->dir->dir_auth = CDIR_AUTH_PARENT;
+               dout(7) << " fixing dir_auth to be " << in->dir->dir_auth << endl;
+
                // move my nested imports to in's containing import
                CDir *con = get_containing_import(in->dir);
                assert(con);
@@ -218,6 +225,7 @@ void MDCache::fix_renamed_dir(CDir *srcdir,
                // inode was ours, still ours.
                dout(7) << "inode was ours, still ours." << endl;
                assert(!in->dir->is_import());
+               assert(in->dir->dir_auth == CDIR_AUTH_PARENT);
                
                // move any exports nested beneath me?
                CDir *newcon = get_containing_import(in->dir);
@@ -227,7 +235,7 @@ void MDCache::fix_renamed_dir(CDir *srcdir,
                if (newcon != oldcon) {
                  dout(7) << "moving nested exports under new container" << endl;
                  set<CDir*> nested;
-                 find_nested_exports(in->dir, nested);
+                 find_nested_exports_under(oldcon, in->dir, nested);
                  for (set<CDir*>::iterator it = nested.begin();
                           it != nested.end();
                           it++) {
@@ -250,13 +258,17 @@ void MDCache::fix_renamed_dir(CDir *srcdir,
                in->dir->state_set(CDIR_STATE_IMPORT);
                in->dir->get(CDIR_PIN_IMPORT);
 
+               in->dir->dir_auth = mds->get_nodeid();
+               dout(7) << " fixing dir_auth to be " << in->dir->dir_auth << endl;
+
                // find old import
                CDir *oldcon = get_containing_import(srcdir);
                assert(oldcon);
+               dout(7) << " oldcon is " << *oldcon << endl;
 
-               // move nested exports under me
+               // move nested exports under me 
                set<CDir*> nested;
-               find_nested_exports(in->dir, nested);
+               find_nested_exports_under(oldcon, in->dir, nested);  
                for (set<CDir*>::iterator it = nested.begin();
                         it != nested.end();
                         it++) {
@@ -264,12 +276,15 @@ void MDCache::fix_renamed_dir(CDir *srcdir,
                  nested_exports[oldcon].erase(*it);
                  nested_exports[in->dir].insert(*it);
                }
+
          } else {
                // inode was replica, still replica
                dout(7) << "inode was replica, still replica.  doing nothing." << endl;
                assert(in->dir->is_import());
 
-               // do nothing.
+               // verify dir_auth
+               assert(in->dir->dir_auth == mds->get_nodeid()); // me, because i'm auth for dir.
+               assert(in->authority() != in->dir->dir_auth);   // inode not me.
          }
 
          assert(in->dir->is_import());
@@ -291,11 +306,32 @@ void MDCache::fix_renamed_dir(CDir *srcdir,
                exports.insert(in->dir);
                in->dir->state_set(CDIR_STATE_EXPORT);
                in->dir->get(CDIR_PIN_EXPORT);
+               
+               assert(dir_auth >= 0);  // better be defined
+               in->dir->dir_auth = dir_auth;
+               dout(7) << " fixing dir_auth to be " << in->dir->dir_auth << endl;
+               
+               CDir *newcon = get_containing_import(in->dir);
+               assert(newcon);
+               nested_exports[newcon].insert(in->dir);
+
          } else {
                // inode was ours, still ours
-               dout(7) << "inode was ours, still ours.  doing nothing." << endl;
-               
-               // do nothing.
+               dout(7) << "inode was ours, still ours.  did my import change?" << endl;
+
+               // sanity
+               assert(in->dir->is_export());
+               assert(in->dir->dir_auth >= 0);              
+               assert(in->dir->dir_auth != in->authority());
+
+               // moved under new import?
+               CDir *oldcon = get_containing_import(srcdir);
+               CDir *newcon = get_containing_import(in->dir);
+               if (oldcon != newcon) {
+                 dout(7) << "moving myself under new import " << *newcon << endl;
+                 nested_exports[oldcon].erase(in->dir);
+                 nested_exports[newcon].insert(in->dir);
+               }
          }
 
          assert(in->dir->is_export());
@@ -311,15 +347,30 @@ void MDCache::fix_renamed_dir(CDir *srcdir,
                exports.erase(in->dir);
                in->dir->state_clear(CDIR_STATE_EXPORT);
                in->dir->put(CDIR_PIN_EXPORT);
-
+               
                CDir *oldcon = get_containing_import(srcdir);
                assert(oldcon);
                assert(nested_exports[oldcon].count(in->dir) == 1);
                nested_exports[oldcon].erase(in->dir);
 
+               // simplify dir_auth
+               if (in->authority() == in->dir->authority()) {
+                 in->dir->dir_auth = CDIR_AUTH_PARENT;
+                 dout(7) << "simplified dir_auth to -1, inode auth is (also) " << in->authority() << endl;
+               } else {
+                 assert(in->dir->dir_auth >= 0);    // someone else's export,
+               }
+
          } else {
                // inode was replica, still replica
                dout(7) << "inode was replica, still replica.  do nothing." << endl;
+               
+               // fix dir_auth?
+               if (in->authority() == dir_auth)
+                 in->dir->dir_auth = CDIR_AUTH_PARENT;
+               else
+                 in->dir->dir_auth = dir_auth;
+               dout(7) << " fixing dir_auth to be " << dir_auth << endl;
 
                // do nothing.
          }
@@ -705,6 +756,9 @@ int MDCache::proc_message(Message *m)
        handle_dentry_unlink((MDentryUnlink*)m);
        break;
 
+  case MSG_MDS_RENAMEWARNING:
+       handle_rename_warning((MRenameWarning*)m);
+       break;
   case MSG_MDS_RENAMENOTIFY:
        handle_rename_notify((MRenameNotify*)m);
        break;
@@ -717,6 +771,9 @@ int MDCache::proc_message(Message *m)
   case MSG_MDS_RENAMEREQ:
        handle_rename_req((MRenameReq*)m);
        break;
+  case MSG_MDS_RENAMEPREP:
+       handle_rename_prep((MRenamePrep*)m);
+       break;
   case MSG_MDS_RENAMEACK:
        handle_rename_ack((MRenameAck*)m);
        break;
@@ -922,11 +979,10 @@ int MDCache::path_traverse(filepath& origpath,
        // dentry
        CDentry *dn = cur->dir->lookup(path[depth]);
 
-       // xlocked and null?  ** all wrong, FIXME
-       if (onfail == MDS_TRAVERSE_DISCOVERXLOCK &&
-               dn && !dn->inode && dn->is_xlockedbyme(req) &&
+       // xlocked by me?
+       if (dn && !dn->inode && dn->is_xlockedbyme(req) &&
                depth == path.depth()-1) {
-         dout(10) << "traverse: hit null xlocked dentry at tail of traverse, succeeding" << endl;
+         dout(10) << "traverse: hit (my) xlocked dentry at tail of traverse, succeeding" << endl;
          trace.push_back(dn);
          break; // done!
        }
@@ -1207,7 +1263,7 @@ void MDCache::request_cleanup(Message *req)
   }
 
   // foreign xlocks?
-  if (active_requests[req].xlocks.size()) {
+  if (active_requests[req].foreign_xlocks.size()) {
        set<CDentry*> dns = active_requests[req].foreign_xlocks;
        active_requests[req].foreign_xlocks.clear();
        
@@ -1217,6 +1273,7 @@ void MDCache::request_cleanup(Message *req)
          CDentry *dn = *it;
          
          dout(7) << "request_cleanup sending unxlock for foreign xlock on " << *dn << endl;
+         assert(dn->is_xlocked());
          int dauth = dn->dir->dentry_authority(dn->name);
          MLock *m = new MLock(LOCK_AC_UNXLOCK, mds->get_nodeid());
          m->set_dn(dn->dir->ino(), dn->name);
@@ -1246,13 +1303,15 @@ void MDCache::request_finish(Message *req)
 }
 
 
-void MDCache::request_forward(Message *req, int who)
+void MDCache::request_forward(Message *req, int who, int port)
 {
+  if (!port) port = MDS_PORT_SERVER;
+
   dout(7) << "request_forward to " << who << " req " << *req << endl;
   request_cleanup(req);
   mds->messenger->send_message(req,
-                                                          MSG_ADDR_MDS(who), MDS_PORT_SERVER,
-                                                          MDS_PORT_SERVER);
+                                                          MSG_ADDR_MDS(who), port,
+                                                          port);
 }
 
 
@@ -1609,6 +1668,7 @@ void MDCache::handle_discover_reply(MDiscoverReply *m)
                if (m->get_dentry_xlock(i)) {
                  dout(7) << " new dentry is xlock " << *dn << endl;
                  dn->lockstate = DN_LOCK_XLOCK;
+                 dn->xlockedby = 0;
                }
                dout(7) << "added " << *dn << endl;
          }
@@ -1758,11 +1818,8 @@ void MDCache::handle_cache_expire(MCacheExpire *m)
          assert(in);  // OOPS  i should be authority, or recent authority (and thus frozen).
        }  
        if (!in->is_auth()) {
-         int newauth = ino_proxy_auth(in->ino(), 
-                                                                  from,
-                                                                  export_proxy_inos);
+         int newauth = in->authority();
          dout(7) << "proxy inode expire on " << *in << " to " << newauth << endl;
-         in->is_proxy();
          assert(newauth >= 0);
          assert(in->state_test(CINODE_STATE_PROXY));
          if (proxymap.count(newauth) == 0) proxymap[newauth] = new MCacheExpire(from);
@@ -1813,9 +1870,7 @@ void MDCache::handle_cache_expire(MCacheExpire *m)
          assert(dir);  // OOPS  i should be authority, or recent authority (and thus frozen).
        }  
        if (!dir->is_auth()) {
-         int newauth = ino_proxy_auth(dir->ino(), 
-                                                                  from,
-                                                                  export_proxy_dirinos);
+         int newauth = dir->authority();
          dout(7) << "proxy dir expire on " << *dir << " to " << newauth << endl;
          assert(dir->is_proxy());
          assert(newauth >= 0);
@@ -1864,9 +1919,7 @@ void MDCache::handle_inode_writer_closed(MInodeWriterClosed *m)
   int from = m->get_from();
 
   if (in->is_proxy()) {
-       int newauth = ino_proxy_auth(in->ino(), 
-                                                                from,
-                                                                export_proxy_inos);
+       int newauth = in->authority();
        assert(newauth >= 0);
        dout(7) << "handle_inode_writer_closed " << m->get_ino() << " from " << from << ": proxy, fw to " << newauth << endl;
        mds->messenger->send_message(m,
@@ -2023,6 +2076,34 @@ void MDCache::handle_dentry_unlink(MDentryUnlink *m)
 
 // renaming!
 
+/*
+ * when initiator gets an ack back for a foreign rename
+ */
+
+class C_MDC_RenameNotifyAck : public Context {
+  MDCache *mdc;
+  CInode *in;
+  int initiator;
+
+public:
+  C_MDC_RenameNotifyAck(MDCache *mdc, 
+                                               CInode *in, int initiator) {
+       this->mdc = mdc;
+       this->in = in;
+       this->initiator = initiator;
+  }
+  void finish(int r) {
+       mdc->file_rename_ack(in, initiator);
+  }
+};
+
+
+
+/************** initiator ****************/
+
+/*
+ * when we get MRenameAck (and rename is done, notifies gone out+acked, etc.)
+ */
 class C_MDC_RenameAck : public Context {
   MDCache *mdc;
   CDir *srcdir;
@@ -2040,139 +2121,142 @@ public:
   }
 };
 
-void MDCache::file_rename(CDentry *srcdn, CDentry *destdn, Context *c)
+
+void MDCache::file_rename(CDentry *srcdn, CDentry *destdn, Context *onfinish)
 {
   assert(srcdn->is_xlocked());  // by me
   assert(destdn->is_xlocked());  // by me
 
   CDir *srcdir = srcdn->dir;
   string srcname = srcdn->name;
-  bool srcauth = srcdir->dentry_authority(srcdn->name) == mds->get_nodeid();
-
+  
   CDir *destdir = destdn->dir;
   string destname = destdn->name;
-  bool destauth = destdir->dentry_authority(destdn->name) == mds->get_nodeid();
-  
+
   CInode *in = srcdn->inode;
   Message *req = srcdn->xlockedby;
 
+
+  // determine the players
+  int srcauth = srcdir->dentry_authority(srcdn->name);
+  int destauth = destdir->dentry_authority(destname);
+
+
   // FOREIGN rename?
-  if (srcauth && !destauth) {
-       dout(7) << "file_rename src auth, not dest auth.  sending MRename" << endl;
+  if (srcauth != mds->get_nodeid() ||
+         destauth != mds->get_nodeid()) {
+       dout(7) << "foreign rename.  srcauth " << srcauth << ", destauth " << destauth << ", isdir " << srcdn->inode->is_dir() << endl;
        
-       file_rename_foreign_src(srcdn, destdn, 
-                                                       mds->get_nodeid());  // i'm the initiator
+       string destpath;
+       destdn->make_path(destpath);
 
-       // set waiter on the inode (is this the best place?)
-       in->add_waiter(CINODE_WAIT_RENAMEACK, c);
-       return;
-  }
-  else if (!srcauth) {
-       if (destauth) {
-         dout(7) << "file_rename dest auth, not src auth.  sending MRenameReq" << endl;        
-       } else {
-         dout(7) << "file_rename neither src auth nor dest auth.  sending MRenameReq" << endl; 
+       if (destauth != mds->get_nodeid()) { 
+         // make sure dest has dir open.
+         dout(7) << "file_rename i'm not dest auth.  sending MRenamePrep to " << destauth << endl;
+         
+         // prep dest first, they must have the dir open!  rest will follow.
+         string srcpath;
+         srcdn->make_path(srcpath);
+         
+         MRenamePrep *m = new MRenamePrep(mds->get_nodeid(),  // i'm the initiator
+                                                                          srcdir->ino(), srcname, srcpath, 
+                                                                          destdir->ino(), destname, destpath,
+                                                                          srcauth);  // tell dest who src is (maybe even me)
+         mds->messenger->send_message(m,
+                                                                  MSG_ADDR_MDS(destauth), MDS_PORT_CACHE, MDS_PORT_CACHE);
+         
+         show_imports();
+         
        }
        
-       MRenameReq *m = new MRenameReq(mds->get_nodeid(),  // i'm the initiator
-                                                                  srcdir->ino(), srcname, destdir->ino(), destname);
-       int srcauth = srcdir->dentry_authority(srcdn->name);
-       mds->messenger->send_message(m,
-                                                                MSG_ADDR_MDS(srcauth), MDS_PORT_CACHE, MDS_PORT_CACHE);
+       else if (srcauth != mds->get_nodeid()) {
+         if (destauth == mds->get_nodeid()) {
+               dout(7) << "file_rename dest auth, not src auth.  sending MRenameReq" << endl;  
+         } else {
+               dout(7) << "file_rename neither src auth nor dest auth.  sending MRenameReq" << endl;   
+         }
+         
+         // srcdn not important on destauth, just request
+         MRenameReq *m = new MRenameReq(mds->get_nodeid(),  // i'm the initiator
+                                                                        srcdir->ino(), srcname, 
+                                                                        destdir->ino(), destname, destpath, destauth);  // tell src who dest is (they may not know)
+         mds->messenger->send_message(m,
+                                                                  MSG_ADDR_MDS(srcauth), MDS_PORT_CACHE, MDS_PORT_CACHE);
+       }
+       
+       else
+         assert(0);
 
        // set waiter on the inode (is this the best place?)
-       in->add_waiter(CINODE_WAIT_RENAMEACK, c);
+       in->add_waiter(CINODE_WAIT_RENAMEACK, 
+                                  new C_MDC_RenameAck(this, 
+                                                                          srcdir, in, onfinish));
        return;
-  } 
+  }
 
-  // LOCAL rename
-  assert(srcauth && destauth);
+  // LOCAL rename!
+  assert(srcauth == mds->get_nodeid() && destauth == mds->get_nodeid());
   dout(7) << "file_rename src and dest auth, renaming locally (easy!)" << endl;
   
   // update our cache
   rename_file(srcdn, destdn);
   
-  // mark dentries dirty
-  srcdn->mark_dirty();
-  destdn->mark_dirty();
-  in->mark_dirty();
-  
   // update imports/exports?
   if (in->is_dir() && in->dir) 
        fix_renamed_dir(srcdir, in, destdir, false);  // auth didnt change
 
-  
-  // tell replicas (no need to wait for ack) to do the same, and un-xlock.
-  // make list
-  set<int> notify;
-  notify = srcdir->get_open_by();
+  // mark dentries dirty
+  srcdn->mark_dirty();
+  destdn->mark_dirty();
+  in->mark_dirty();
+  // local, restrict notify to ppl with open dirs
+  set<int> notify = srcdir->get_open_by();
   for (set<int>::iterator it = destdir->open_by_begin();
           it != destdir->open_by_end();
           it++)
        if (notify.count(*it) == 0) notify.insert(*it);
-
+  
   if (notify.size()) {
-       // tell
-       string destdirpath;
-       destdir->inode->make_path(destdirpath);
-       
-       for (set<int>::iterator it = notify.begin();
-                it != notify.end();
-                it++) {
-         mds->messenger->send_message(new MRenameNotify(in->ino(),
-                                                                                                        srcdir->ino(),
-                                                                                                        srcname,
-                                                                                                        destdir->ino(),
-                                                                                                        destdirpath,
-                                                                                                        destname),
-                                                                  MSG_ADDR_MDS(*it), MDS_PORT_CACHE, MDS_PORT_CACHE);
-       }
+       // warn + notify
+       file_rename_warn(in, notify);
+       file_rename_notify(in, srcdir, srcname, destdir, destname, notify, mds->get_nodeid());
 
-       // wait for acks
-       in->rename_waiting_for_ack = notify;
+       // wait for MRenameNotifyAck's
+       in->add_waiter(CINODE_WAIT_RENAMENOTIFYACK,
+                                  new C_MDC_RenameNotifyAck(this, in, mds->get_nodeid()));  // i am initiator
+
+       // wait for finish
        in->add_waiter(CINODE_WAIT_RENAMEACK,
-                                  new C_MDC_RenameAck(this, srcdir, in, c));
+                                  new C_MDC_RenameAck(this, srcdir, in, onfinish));
   } else {
-       file_rename_finish(srcdir, in, c);
+       // sweet, no notify necessary, we're done!
+       file_rename_finish(srcdir, in, onfinish);
   }
 }
 
-
-void MDCache::handle_rename_notify_ack(MRenameNotifyAck *m)
+void MDCache::handle_rename_ack(MRenameAck *m)
 {
   CInode *in = get_inode(m->get_ino());
   assert(in);
-  dout(7) << "handle_rename_notify_ack on " << *in << endl;
+  
+  dout(7) << "handle_rename_ack on " << *in << endl;
 
-  in->rename_waiting_for_ack.erase(m->get_source());
-  if (in->rename_waiting_for_ack.empty()) {
-       // last one!
-       in->finish_waiting(CINODE_WAIT_RENAMEACK, 0);
-  } else {
-       dout(7) << "still waiting for " << in->rename_waiting_for_ack << endl;
-  }
-}
+  // all done!
+  in->finish_waiting(CINODE_WAIT_RENAMEACK);
 
+  delete m;
+}
 
 void MDCache::file_rename_finish(CDir *srcdir, CInode *in, Context *c)
 {
   dout(10) << "file_rename_finish on " << *in << endl;
 
-  // did i empty out an imported dir?
+  // did i empty out an imported dir?  FIXME this check should go somewhere else???
   if (srcdir->is_import() && !srcdir->inode->is_root() && srcdir->get_size() == 0) 
        export_empty_import(srcdir);
 
-  /* just let the finished request drop the locks.
-
-  // clean up xlocks
-  dentry_xlock_finish(srcdn);
-  dentry_xlock_finish(destdn);
-
-  // other waiters
-  srcdir->take_waiting(CDIR_WAIT_ANY, srcname, mds->finished_queue);
-  destdir->take_waiting(CDIR_WAIT_DNREAD, destname, mds->finished_queue);
-  */
-  
   // finish our caller
   if (c) {
        c->finish(0);
@@ -2181,12 +2265,37 @@ void MDCache::file_rename_finish(CDir *srcdir, CInode *in, Context *c)
 }
 
 
-void MDCache::file_rename_foreign_src(CDentry *srcdn, CDentry *destdn, int initiator)
+/************* src **************/
+
+
+/** handle_rename_req
+ * received by auth of src dentry (from init, or destauth if dir).  
+ * src may not have dest dir open.
+ * src will export inode, unlink|rename, and send MRename to dest.
+ */
+void MDCache::handle_rename_req(MRenameReq *m)
+{
+  // i am auth, i will have it.
+  CInode *srcdiri = get_inode(m->get_srcdirino());
+  CDir *srcdir = srcdiri->dir;
+  CDentry *srcdn = srcdir->lookup(m->get_srcname());
+  assert(srcdn);
+  
+  // do it
+  file_rename_foreign_src(srcdn, 
+                                                 m->get_destdirino(), m->get_destname(), m->get_destpath(), m->get_destauth(), 
+                                                 m->get_initiator());
+  delete m;
+}
+
+
+void MDCache::file_rename_foreign_src(CDentry *srcdn, 
+                                                                         inodeno_t destdirino, string& destname, string& destpath, int destauth, 
+                                                                         int initiator)
 {
-  dout(7) << "file_rename_foreign_src " << *srcdn << " to " << *destdn << endl;
+  dout(7) << "file_rename_foreign_src " << *srcdn << endl;
 
   CDir *srcdir = srcdn->dir;
-  CDir *destdir = destdn->dir;
   string srcname = srcdn->name;
 
   // (we're basically exporting this inode)
@@ -2194,142 +2303,305 @@ void MDCache::file_rename_foreign_src(CDentry *srcdn, CDentry *destdn, int initi
   assert(in);
   assert(in->is_auth());
 
-  string srcpath;
-  srcdn->inode->make_path(srcpath);
-  
+  if (in->is_dir()) show_imports();
+
   // encode and export inode state
   crope inode_state;
   encode_export_inode(in, inode_state);
-  
+
+  // send
   MRename *m = new MRename(initiator,
-                                                  srcdir->ino(), srcdn->name, srcpath, destdir->ino(), destdn->name,
+                                                  srcdir->ino(), srcdn->name, destdirino, destname,
                                                   inode_state);
-  int destauth = destdir->dentry_authority(destdn->name);
   mds->messenger->send_message(m,
                                                           MSG_ADDR_MDS(destauth), MDS_PORT_CACHE, MDS_PORT_CACHE);
+  
+  // have dest?
+  CInode *destdiri = get_inode(m->get_destdirino());
+  CDir *destdir = 0;
+  if (destdiri) destdir = destdiri->dir;
+  CDentry *destdn = 0;
+  if (destdir) destdn = destdir->lookup(m->get_destname());
+
+  // discover src
+  if (!destdn) {
+       dout(7) << "file_rename_foreign_src doesn't have destdn, discovering " << destpath << endl;
+
+       filepath destfilepath = destpath;
+       vector<CDentry*> trace;
+       int r = path_traverse(destfilepath, trace, true,
+                                                 m, new C_MDS_RetryMessage(mds, m), 
+                                                 MDS_TRAVERSE_DISCOVER);
+       assert(r>0);
+       return;
+  }
+
+  assert(destdn);
 
   // update our cache
   rename_file(srcdn, destdn);
-  srcdn->mark_dirty();
-       
+  
   // update imports/exports?
   if (in->is_dir() && in->dir) 
        fix_renamed_dir(srcdir, in, destdir, true);  // auth changed
 
-  /* let the initiator do this.
-  // drop xlock on src
-  dentry_xlock_finish(srcdn);
-  srcdir->take_waiting(CDIR_WAIT_ANY, srcname, mds->finished_queue);
-  */
+  srcdn->mark_dirty();
+
+  // proxy!
+  in->state_set(CINODE_STATE_PROXY);
+  in->get(CINODE_PIN_PROXY);
+  
+  // generate notify list (everybody but src|dst) and send warnings
+  set<int> notify;
+  for (int i=0; i<mds->get_cluster()->get_num_mds(); i++) {
+       if (i != mds->get_nodeid() &&  // except the source
+               i != destauth)             // and the dest
+         notify.insert(i);
+  }
+  file_rename_warn(in, notify);
+
+
+  // wait for MRenameNotifyAck's
+  in->add_waiter(CINODE_WAIT_RENAMENOTIFYACK,
+                                new C_MDC_RenameNotifyAck(this, in, initiator));
 }
 
-void MDCache::handle_rename_req(MRenameReq *m)
+void MDCache::file_rename_warn(CInode *in,
+                                                          set<int>& notify)
 {
-  CInode *srcdiri = get_inode(m->get_srcdirino());
-  CDir *srcdir = srcdiri->dir;
-  CDentry *srcdn = srcdir->lookup(m->get_srcname());
-  assert(srcdn);
+  // note gather list
+  in->rename_waiting_for_ack = notify;
 
-  CInode *destdiri = get_inode(m->get_destdirino());
-  CDir *destdir = destdiri->dir;
-  CDentry *destdn = destdir->lookup(m->get_destname());
-  assert(destdn);
+  // send
+  for (set<int>::iterator it = notify.begin();
+          it != notify.end();
+          it++) {
+       dout(10) << "file_rename_warn to " << *it << " for " << *in << endl;
+       mds->messenger->send_message(new MRenameWarning(in->ino()),
+                                                                MSG_ADDR_MDS(*it), MDS_PORT_CACHE, MDS_PORT_CACHE);
+  }
+}
+
+
+void MDCache::handle_rename_notify_ack(MRenameNotifyAck *m)
+{
+  CInode *in = get_inode(m->get_ino());
+  assert(in);
+  dout(7) << "handle_rename_notify_ack on " << *in << endl;
+
+  in->rename_waiting_for_ack.erase(m->get_source());
+  if (in->rename_waiting_for_ack.empty()) {
+       // last one!
+       in->finish_waiting(CINODE_WAIT_RENAMENOTIFYACK, 0);
+  } else {
+       dout(7) << "still waiting for " << in->rename_waiting_for_ack << endl;
+  }
+}
+
+
+void MDCache::file_rename_ack(CInode *in, int initiator) 
+{
+  // we got all our MNotifyAck's.
+
+  // was i proxy (if not, it's cuz this was a local rename)
+  if (in->state_test(CINODE_STATE_PROXY)) {
+       dout(10) << "file_rename_ack clearing proxy bit on " << *in << endl;
+       in->state_clear(CINODE_STATE_PROXY);
+       in->put(CINODE_PIN_PROXY);
+  }
+
+  // done!
+  if (initiator == mds->get_nodeid()) {
+       // it's me, finish
+       dout(7) << "file_rename_ack i am initiator, finishing" << endl;
+       in->finish_waiting(CINODE_WAIT_RENAMEACK);
+  } else {
+       // send ack
+       dout(7) << "file_rename_ack sending MRenameAck to initiator " << initiator << endl;
+       mds->messenger->send_message(new MRenameAck(in->ino()),
+                                                                MSG_ADDR_MDS(initiator), MDS_PORT_CACHE, MDS_PORT_CACHE);
+  }  
+}
+
+
+
+
+/************ dest *************/
+
+/** handle_rename_prep
+ * received by auth of dest dentry to make sure they have src + dir open.
+ * this is so that when they get the inode and dir, they can update exports etc properly.
+ * will send MRenameReq to src.
+ */
+void MDCache::handle_rename_prep(MRenamePrep *m)
+{
+  // open src
+  filepath srcpath = m->get_srcpath();
+  vector<CDentry*> trace;
+  int r = path_traverse(srcpath, trace, true,
+                                               m, new C_MDS_RetryMessage(mds, m), 
+                                               MDS_TRAVERSE_DISCOVER);
 
-  file_rename_foreign_src(srcdn, destdn, m->get_initiator());
+  if (r>0) return;
+
+  // ok!
+  CInode *srcin = trace[trace.size()-1]->inode;
+  assert(srcin);
+  
+  dout(7) << "handle_rename_prep have srcin " << *srcin << endl;
+
+  if (srcin->is_dir()) {
+       if (!srcin->dir) {
+         dout(7) << "handle_rename_prep need to open dir" << endl;
+         open_remote_dir(srcin,
+                                         new C_MDS_RetryMessage(mds,m));
+         return;
+       }
+
+       dout(7) << "handle_rename_prep have dir " << *srcin->dir << endl;       
+  }
+
+  // ok!
+
+  // send rename request
+  MRenameReq *req = new MRenameReq(m->get_initiator(),  // i'm the initiator
+                                                                  m->get_srcdirino(), m->get_srcname(), 
+                                                                  m->get_destdirino(), m->get_destname(), m->get_destpath(),
+                                                                  mds->get_nodeid());  // i am dest
+  mds->messenger->send_message(req,
+                                                          MSG_ADDR_MDS(m->get_srcauth()), MDS_PORT_CACHE, MDS_PORT_CACHE);
   delete m;
+  return;
 }
 
+
+
+/** handle_rename
+ * received by auth of dest dentry.   includes exported inode info.
+ * dest may not have srcdir open.
+ */
 void MDCache::handle_rename(MRename *m)
 {
+  // srcdn (required)
   CInode *srcdiri = get_inode(m->get_srcdirino());
-  CDir *srcdir = 0;
-  if (srcdiri) srcdir = srcdiri->dir;
-  CDentry *srcdn = 0;
-  if (srcdir) srcdn = srcdir->lookup(m->get_srcname());
-  
-  if (!srcdn) {
-       dout(7) << "handle_rename don't have src path " << m->get_srcpath() << ", discovering" << endl;
+  CDir *srcdir = srcdiri->dir;
+  CDentry *srcdn = srcdir->lookup(m->get_srcname());
+  string srcname = srcdn->name;
+  assert(srcdn && srcdn->inode);
 
-       vector<CDentry*> trace;
-       filepath srcpath = m->get_srcpath();
-       int r = path_traverse(srcpath, trace, true,
-                                                 m, new C_MDS_RetryMessage(mds, m), 
-                                                 MDS_TRAVERSE_DISCOVERXLOCK);             // ??? FIXME
-       assert(r>0);
-       return;
-  }
-  
+  dout(7) << "handle_rename srcdn " << *srcdn << endl;
 
+  // destdn (required).  i am auth, so i will have it.
   CInode *destdiri = get_inode(m->get_destdirino());
   CDir *destdir = destdiri->dir;
   CDentry *destdn = destdir->lookup(m->get_destname());
-  assert(destdn);
   string destname = destdn->name;
+  assert(destdn);
+  
+  dout(7) << "handle_rename destdn " << *destdn << endl;
 
-  dout(7) << "handle_rename " << *srcdn << " to " << *destdn << endl;
-
-  if (srcdn->inode) {
-       // rename replica into position
-       rename_file(srcdn, destdn);
-  } else {
-       // unlink dest inode if it's there
-       if (destdn->inode) destdir->unlink_inode(destdn);
-  }
+  // note old dir auth
+  int old_dir_auth = -1;
+  if (srcdn->inode->dir) old_dir_auth = srcdn->inode->dir->authority();
+       
+  // rename replica into position
+  rename_file(srcdn, destdn);
 
   // decode + import inode (into new location start)
   int off = 0;
   decode_import_inode(destdn, m->get_inode_state(), off, m->get_source());
 
-  CInode *in = srcdn->inode;
+  CInode *in = destdn->inode;
   assert(in);
 
+  // update imports/exports?
+  if (in->is_dir()) {
+       assert(in->dir);  // i had better already ahve it open.. see MRenamePrep
+       fix_renamed_dir(srcdir, in, destdir, true,  // auth changed
+                                       old_dir_auth);              // src is possibly new dir auth.
+  }
+  
+  // mark dirty
   destdn->mark_dirty();
   in->mark_dirty();
 
-  // update imports/exports?
-  if (in->is_dir() && in->dir) 
-       fix_renamed_dir(srcdir, in, destdir, true);  // auth changed
-
-  // ok, tell the initiator
-  if (m->get_initiator() == mds->get_nodeid()) {
-       // it's me!
-       in->take_waiting(CINODE_WAIT_RENAMEACK, mds->finished_queue);
-  } else {
-       MRenameAck *ack = new MRenameAck(srcdir->ino(), srcdn->name, destdir->ino(), destdn->name);
-       mds->messenger->send_message(ack,
-                                                                MSG_ADDR_MDS(m->get_initiator()), MDS_PORT_CACHE, MDS_PORT_CACHE);
+  // ok, send notifies.
+  set<int> notify;
+  for (int i=0; i<mds->get_cluster()->get_num_mds(); i++) {
+       if (i != m->get_source() &&  // except the source
+               i != mds->get_nodeid())  // and the dest
+         notify.insert(i);
   }
-
-
-  /* let the initiator do this.
-  // drop xlock on dst
-  dentry_xlock_finish(destdn);
-  destdir->take_waiting(CDIR_WAIT_DNREAD, destname, mds->finished_queue);
-  */
+  file_rename_notify(in, srcdir, srcname, destdir, destname, notify, m->get_source());
 
   delete m;
 }
 
 
-void MDCache::handle_rename_ack(MRenameAck *m)
+void MDCache::file_rename_notify(CInode *in, 
+                                                                CDir *srcdir, string& srcname, CDir *destdir, string& destname,
+                                                                set<int>& notify,
+                                                                int srcauth)
 {
-  CInode *destdiri = get_inode(m->get_destdirino());
-  CDir *destdir = destdiri->dir;
-  CDentry *destdn = destdir->lookup(m->get_destname());
-  assert(destdn);
-  CInode *in = destdn->inode;
+  /* NOTE: notify list might include myself */
   
-  dout(7) << "handle_rename_ack on " << *in << endl;
+  // tell
+  string destdirpath;
+  destdir->inode->make_path(destdirpath);
+  
+  for (set<int>::iterator it = notify.begin();
+          it != notify.end();
+          it++) {
+       dout(10) << "file_rename_notify to " << *it << " for " << *in << endl;
+       mds->messenger->send_message(new MRenameNotify(in->ino(),
+                                                                                                  srcdir->ino(),
+                                                                                                  srcname,
+                                                                                                  destdir->ino(),
+                                                                                                  destdirpath,
+                                                                                                  destname,
+                                                                                                  srcauth),
+                                                                MSG_ADDR_MDS(*it), MDS_PORT_CACHE, MDS_PORT_CACHE);
+  }
+}
+
 
-  // all done!
-  in->take_waiting(CINODE_WAIT_RENAMEACK, mds->finished_queue);
 
+/************ bystanders ****************/
+
+void MDCache::handle_rename_warning(MRenameWarning *m)
+{
+  // add to warning list
+  stray_rename_warnings.insert( m->get_ino() );
+  
+  // did i already see the notify?
+  if (stray_rename_notifies.count(m->get_ino())) {
+       // i did, we're good.
+       dout(7) << "handle_rename_warning on " << m->get_ino() << ".  already got notify." << endl;
+       
+       handle_rename_notify(stray_rename_notifies[m->get_ino()]);
+       stray_rename_notifies.erase(m->get_ino());
+  } else {
+       dout(7) << "handle_rename_warning on " << m->get_ino() << ".  waiting for notify." << endl;
+  }
+  
+  // done
   delete m;
 }
 
 
 void MDCache::handle_rename_notify(MRenameNotify *m)
 {
+  // FIXME: when we do hard links, i think we need to 
+  // have srcdn and destdn both, or neither,  always!
+
+  // did i see the warning yet?
+  if (!stray_rename_warnings.count(m->get_ino())) {
+       // wait for it.
+       dout(7) << "handle_rename_notify on " << m->get_ino() << ", waiting for warning." << endl;
+       stray_rename_notifies[m->get_ino()] = m;
+       return;
+  }
+
   dout(7) << "handle_rename_notify dir " << m->get_srcdirino() << " dn " << m->get_srcname() << " to dir " << m->get_destdirino() << " dname " << m->get_destname() << endl;
   
   // src
@@ -2351,6 +2623,9 @@ void MDCache::handle_rename_notify(MRenameNotify *m)
   if (srcdn && destdir) {
        CInode *in = srcdn->inode;
 
+       int old_dir_auth = -1;
+       if (in && in->dir) old_dir_auth = in->dir->authority();
+
        if (!destdn) {
          destdn = destdir->add_dentry(m->get_destname());  // create null dentry
          destdn->lockstate = DN_LOCK_XLOCK;                // that's xlocked!
@@ -2360,48 +2635,36 @@ void MDCache::handle_rename_notify(MRenameNotify *m)
        
        if (in) {
          rename_file(srcdn, destdn);
+
+         // update imports/exports?
+         if (in && in->is_dir() && in->dir) {
+               fix_renamed_dir(srcdir, in, destdir, false, old_dir_auth);  // auth didnt change
+         }
        } else {
          dout(7) << " i don't have the inode (just null dentries)" << endl;
        }
        
-       // remove src dentry
-       //srcdn->dir->remove_dentry(srcdn);
-       
-       // update imports/exports?
-       if (in && in->is_dir() && in->dir) 
-         fix_renamed_dir(srcdir, in, destdir, false);  // auth didnt change
-       
-       //srcdir->take_waiting(CDIR_WAIT_ANY, m->get_srcname(), finished);
-       //destdir->take_waiting(CDIR_WAIT_ANY, m->get_destname(), finished);
   }
 
   else if (srcdn) {
-       if (srcdn->inode && srcdn->inode->dir) {
-         dout(7) << "handle_rename_notify no dest, but src is an open dir." << endl;
-         dout(7) << "srcdn is " << *srcdn << endl;
-
-         if (destdiri) {
-               dout(7) << "have destdiri, opening dir " << *destdiri << endl;
-               open_remote_dir(destdiri,
-                                               new C_MDS_RetryMessage(mds,m));
-         } else {
-               filepath destdirpath = m->get_destdirpath();
-               dout(7) << "don't have destdiri even, doing traverse+discover on " << destdirpath << endl;
+       dout(7) << "handle_rename_notify no dest, but have src" << endl;
+       dout(7) << "srcdn is " << *srcdn << endl;
 
-               vector<CDentry*> trace;
-               int r = path_traverse(destdirpath, trace, true,
-                                                         m, new C_MDS_RetryMessage(mds, m), 
-                                                         MDS_TRAVERSE_DISCOVER);
-               assert(r>0);
-         }
-         return;
+       if (destdiri) {
+         dout(7) << "have destdiri, opening dir " << *destdiri << endl;
+         open_remote_dir(destdiri,
+                                         new C_MDS_RetryMessage(mds,m));
        } else {
-         dout(7) << "handle_rename_notify unlinking src only " << *srcdn << endl;
-         if (srcdn->inode) {
-               assert(!srcdn->inode->dir);    // dir shouldn't be open, or we would have discovered dest (above)
-               srcdir->unlink_inode(srcdn);
-         }
+         filepath destdirpath = m->get_destdirpath();
+         dout(7) << "don't have destdiri even, doing traverse+discover on " << destdirpath << endl;
+         
+         vector<CDentry*> trace;
+         int r = path_traverse(destdirpath, trace, true,
+                                                       m, new C_MDS_RetryMessage(mds, m), 
+                                                       MDS_TRAVERSE_DISCOVER);
+         assert(r>0);
        }
+       return;
   }
 
   else if (destdn) {
@@ -2420,11 +2683,13 @@ void MDCache::handle_rename_notify(MRenameNotify *m)
 
 
   // ack
-  dout(10) << "sending RenameNotifyAck back to initiator" << endl;
+  dout(10) << "sending RenameNotifyAck back to srcauth " << m->get_srcauth() << endl;
   MRenameNotifyAck *ack = new MRenameNotifyAck(m->get_ino());
   mds->messenger->send_message(ack,
-                                                          MSG_ADDR_MDS(m->get_source()), MDS_PORT_CACHE, MDS_PORT_CACHE);
+                                                          MSG_ADDR_MDS(m->get_srcauth()), MDS_PORT_CACHE, MDS_PORT_CACHE);
   
+
+  stray_rename_warnings.erase( m->get_ino() );
   delete m;
 }
 
@@ -2432,6 +2697,8 @@ void MDCache::handle_rename_notify(MRenameNotify *m)
 
 
 
+
+
 // locks ----------------------------------------------------------------
 
 /*
@@ -2816,9 +3083,7 @@ void MDCache::handle_lock_inode_hard(MLock *m)
 
        if (in->is_proxy()) {
          // fw
-         int newauth = ino_proxy_auth(in->ino(), 
-                                                                  from,
-                                                                  export_proxy_inos);
+         int newauth = in->authority();
          assert(newauth >= 0);
          dout(7) << "handle_lock " << m->get_ino() << " from " << from << ": proxy, fw to " << newauth << endl;
          mds->messenger->send_message(m,
@@ -3418,9 +3683,7 @@ void MDCache::handle_lock_inode_soft(MLock *m)
        
        if (in->is_proxy()) {
          // fw
-         int newauth = ino_proxy_auth(in->ino(), 
-                                                                  from,
-                                                                  export_proxy_inos);
+         int newauth = in->authority();
          assert(newauth >= 0);
          dout(7) << "handle_lock " << m->get_ino() << " from " << from << ": proxy, fw to " << newauth << endl;
          mds->messenger->send_message(m,
@@ -3726,7 +3989,7 @@ void MDCache::handle_lock_dir(MLock *m)
 
 // DENTRY
 
-bool MDCache::dentry_xlock_start(CDentry *dn, Message *m, CInode *ref, bool all_nodes)
+bool MDCache::dentry_xlock_start(CDentry *dn, Message *m, CInode *ref)
 {
   dout(7) << "dentry_xlock_start on " << *dn << endl;
 
@@ -3801,17 +4064,11 @@ bool MDCache::dentry_xlock_start(CDentry *dn, Message *m, CInode *ref, bool all_
   // mine!
   dn->xlockedby = m;
 
-  if (dn->dir->is_open_by_anyone() || all_nodes) {
+  if (dn->dir->is_open_by_anyone()) {
        dn->lockstate = DN_LOCK_PREXLOCK;
        
        // xlock with whom?
-       set<int> who;
-       if (all_nodes) {
-         for (int i=0; i<mds->get_cluster()->get_num_mds(); i++)
-               if (i != mds->get_nodeid()) who.insert(i);
-       } else {
-         who = dn->dir->get_open_by();
-       }
+       set<int> who = dn->dir->get_open_by();
        dn->gather_set = who;
 
        // make path
@@ -3908,12 +4165,12 @@ public:
 
   void finish(int r) {
        cout << "xlockrequest->finish r = " << r << endl;
-       if (r == 0) {
+       if (r == 1) {  // 1 for xlock request success
          CDentry *dn = dir->lookup(dname);
          if (dn && dn->xlockedby == 0) {
-               cout << "xlock request success, now xlocked by " << req << endl;
                // success
                dn->xlockedby = req;   // our request was the winner
+               cout << "xlock request success, now xlocked by req " << req << " dn " << *dn << endl;
 
                // remember!
                mdc->active_requests[req].foreign_xlocks.insert(dn);
@@ -3972,16 +4229,30 @@ void MDCache::handle_lock_dn(MLock *m)
          if (dir->is_proxy()) {
 
                assert(dauth >= 0);
+
+               if (dauth == m->get_asker() && 
+                       (m->get_action() == LOCK_AC_REQXLOCK ||
+                        m->get_action() == LOCK_AC_REQXLOCKC)) {
+                 dout(7) << "handle_lock_dn got reqxlock from " << dauth << " and they are auth.. dropping on floor (their import will have woken them up)" << endl;
+                 if (active_requests.count(m)) 
+                       request_finish(m);
+                 else
+                       delete m;
+                 return;
+               }
+
                dout(7) << "handle_lock_dn " << m << " " << m->get_ino() << " dname " << dname << " from " << from << ": proxy, fw to " << dauth << endl;
 
-               // fw
+               // forward
                if (active_requests.count(m)) {
                  // xlock requests are requests, use request_* functions!
                  assert(m->get_action() == LOCK_AC_REQXLOCK ||
                                 m->get_action() == LOCK_AC_REQXLOCKC);
-                 request_forward(m, dauth);
+                 // forward as a request
+                 request_forward(m, dauth, MDS_PORT_CACHE);
                } else {
-                 // not an xlock req (or we just didn't register the request yet)
+                 // not an xlock req, or it is and we just didn't register the request yet
+                 // forward normally
                  mds->messenger->send_message(m,
                                                                           MSG_ADDR_MDS(dauth), MDS_PORT_CACHE,
                                                                           MDS_PORT_CACHE);
@@ -3997,6 +4268,11 @@ void MDCache::handle_lock_dn(MLock *m)
          assert(dir);  // we should still have the dir, though!  the requester has the dir open.
          switch (m->get_action()) {
 
+         case LOCK_AC_LOCK:
+               dout(7) << "handle_lock_dn xlock on " << dname << ", adding (null)" << endl;
+               dn = dir->add_dentry(dname);
+               break;
+
          case LOCK_AC_REQXLOCK:
                // send nak
                {
@@ -4111,6 +4387,7 @@ void MDCache::handle_lock_dn(MLock *m)
   case LOCK_AC_SYNC:
        assert(dn->lockstate == DN_LOCK_XLOCK);
        dn->lockstate = DN_LOCK_SYNC;
+       dn->xlockedby = 0;
 
        // null?  hose it.
        if (dn->is_null()) {
@@ -4127,9 +4404,9 @@ void MDCache::handle_lock_dn(MLock *m)
        {
          dout(10) << "handle_lock_dn got ack/nak on a reqxlock for " << *dn << endl;
          list<Context*> finished;
-         dir->take_waiting(CDIR_WAIT_DNREQXLOCK, m->get_dn(), finished);
+         dir->take_waiting(CDIR_WAIT_DNREQXLOCK, m->get_dn(), finished, 1);  // TAKE ONE ONLY!
          finish_contexts(finished, 
-                                         (m->get_action() == LOCK_AC_REQXLOCKACK) ? 0:-1);
+                                         (m->get_action() == LOCK_AC_REQXLOCKACK) ? 1:-1);
        }
        break;
 
@@ -4169,7 +4446,7 @@ void MDCache::handle_lock_dn(MLock *m)
        }
 
        if (dn->xlockedby != m) {
-         if (!dentry_xlock_start(dn, m, dir->inode, true)) {
+         if (!dentry_xlock_start(dn, m, dir->inode)) {
                // hose null dn if we're waiting on something
                if (dn->is_clean() && dn->is_null() && dn->is_sync()) dir->remove_dentry(dn);
                return;    // waiting for xlock
@@ -4178,6 +4455,8 @@ void MDCache::handle_lock_dn(MLock *m)
          // successfully xlocked!  on behalf of requestor.
          string path;
          dn->make_path(path);
+
+         dout(7) << "handle_lock_dn reqxlock success for " << m->get_asker() << " on " << *dn << ", acking" << endl;
          
          // ACK xlock request
          MLock *reply = new MLock(LOCK_AC_REQXLOCKACK, mds->get_nodeid());
@@ -4187,13 +4466,16 @@ void MDCache::handle_lock_dn(MLock *m)
                                                                   MSG_ADDR_MDS(m->get_asker()), MDS_PORT_CACHE,
                                                                   MDS_PORT_CACHE);
 
+         /* no: keep this around!
+         dn->xlockedby = DN_XLOCK_FOREIGN;  // not 0, not a valid pointer.
+
          // disassociate xlock from MLock
          active_requests[m].xlocks.clear();
          active_requests[m].traces.clear();
-         dn->xlockedby = DN_XLOCK_FOREIGN;  // not 0, not a valid pointer.
 
          // finish request
          request_finish(m);
+         */
          return;
        }
        break;
@@ -4203,8 +4485,17 @@ void MDCache::handle_lock_dn(MLock *m)
        {
          CDir *dir = dn->dir;
          string dname = dn->name;
-         dentry_xlock_finish(dn);
-         dir->take_waiting(CDIR_WAIT_ANY, dname, mds->finished_queue);
+
+         Message *m = dn->xlockedby;
+
+         // finish request
+         request_finish(m);  // this will drop the locks (and unpin paths!)
+
+         // unxlock
+         //dentry_xlock_finish(dn);
+         //dir->take_waiting(CDIR_WAIT_ANY, dname, mds->finished_queue);
+
+         return;
        }
        break;
 
@@ -4224,68 +4515,6 @@ void MDCache::handle_lock_dn(MLock *m)
 
 
 
-// ino proxy
-
-int MDCache::ino_proxy_auth(inodeno_t ino, 
-                                                       int frommds,
-                                                       map<CDir*, set<inodeno_t> >& inomap) 
-{
-  // check proxy sets for this ino
-  for (map<CDir*, set<inodeno_t> >::iterator wit = inomap.begin();
-          wit != inomap.end();
-          wit++) {
-       CDir *dir = wit->first;
-
-       // does this map apply to this node?
-       if (export_notify_ack_waiting[dir].count(frommds) == 0) continue;
-
-       // is this ino in the set?
-       if (inomap[dir].count(ino)) {
-         int dirauth = dir->authority();
-         assert(dirauth >= 0);
-         return dirauth;
-       }
-  }
-  return -1;   // no proxy
-}
-
-
-void MDCache::do_ino_proxy(CInode *in, Message *m)
-{
-  // check proxy maps
-  int newauth = ino_proxy_auth(in->ino(), 
-                                                          m->get_source(),    // works bc we only every proxy 1 hop
-                                                          export_proxy_inos);
-  dout(7) << "inode " << *in << " proxy, new auth is " << newauth << endl;
-  assert(newauth >= 0);     // we should know the new authority!
-  assert(in->is_frozen());  // i should be frozen right now!
-  assert(in->state_test(CINODE_STATE_PROXY));
-  
-  // forward
-  mds->messenger->send_message(m,
-                                                          MSG_ADDR_MDS(newauth), MDS_PORT_CACHE, MDS_PORT_CACHE);
-  return;
-}
-
-
-void MDCache::do_dir_proxy(CDir *dir, Message *m)
-{
-  // check proxy maps
-  int newauth = ino_proxy_auth(dir->ino(), 
-                                                          m->get_source(),   // works because we only every proxy 1 hop
-                                                          export_proxy_dirinos);
-  dout(7) << "dir " << *dir << " proxy, new auth is " << newauth << endl;
-  assert(newauth >= 0);     // we should know the new authority!
-  assert(dir->is_frozen());  // i should be frozen right now!
-  assert(dir->state_test(CDIR_STATE_PROXY));
-  
-  // forward
-  mds->messenger->send_message(m,
-                                                          MSG_ADDR_MDS(newauth), MDS_PORT_CACHE, MDS_PORT_CACHE);
-  return;
-}
-
-
 
 
 
@@ -4301,9 +4530,17 @@ void MDCache::do_dir_proxy(CDir *dir, Message *m)
 
 // IMPORT/EXPORT
 
-void MDCache::find_nested_exports(CDir *dir, set<CDir*>& s)
+void MDCache::find_nested_exports(CDir *dir, set<CDir*>& s) 
 {
   CDir *import = get_containing_import(dir);
+  find_nested_exports_under(import, dir, s);
+}
+
+void MDCache::find_nested_exports_under(CDir *import, CDir *dir, set<CDir*>& s)
+{
+
+  dout(10) << "find_nested_exports for " << *dir << endl;
+  dout(10) << "find_nested_exports under import " << *import << endl;
 
   if (import == dir) {
        // yay, my job is easy!
@@ -4322,10 +4559,12 @@ void MDCache::find_nested_exports(CDir *dir, set<CDir*>& s)
           p != nested_exports[import].end();
           p++) {
        CDir *nested = *p;
+       
+       dout(12) << "find_nested_exports checking " << *nested << endl;
 
        // trace back to import, or dir
        CDir *cur = nested->get_parent_dir();
-       while (!cur->is_import()) {
+       while (!cur->is_import() || cur == dir) {
          if (cur == dir) {
                s.insert(nested);
                dout(10) << "find_nested_exports " << *dir << " " << *nested << endl;
@@ -5775,6 +6014,7 @@ void MDCache::handle_export_dir_notify(MExportDirNotify *m)
   
 
   // done
+  stray_export_warnings.erase( m->get_ino() );
   delete m;
 }
 
index 6f0796d74192182eb11e3620a5d6a1dcb149f609..ef502d0bdf53857b8d5c7a48bf5ec4af3ac99c6d 100644 (file)
@@ -37,9 +37,11 @@ class MDentryUnlink;
 class MInodeWriterClosed;
 class MLock;
 
+class MRenameWarning;
 class MRenameNotify;
 class MRenameNotifyAck;
 class MRename;
+class MRenamePrep;
 class MRenameReq;
 class MRenameAck;
 
@@ -95,15 +97,19 @@ class MDCache {
   multimap<inodeno_t, inodeno_t>    import_hashed_replicate_waiting;  // nodes i am waiting to discover to complete my import of a hashed dir
         // maps frozen_dir_ino's to waiting-for-discover ino's.
   multimap<inodeno_t, inodeno_t>    import_hashed_frozen_waiting;    // dirs i froze (for the above)
-        // maps import_root_ino's to frozen dir ino's (with pending discovers)
+  // maps import_root_ino's to frozen dir ino's (with pending discovers)
 
-  map<CDir*, set<int> >   export_notify_ack_waiting; // nodes i am waiting to get export_notify_ack's from
+  // export fun
+  map<CDir*, set<int> >  export_notify_ack_waiting; // nodes i am waiting to get export_notify_ack's from
   map<CDir*, set<inodeno_t> > export_proxy_inos;
   map<CDir*, set<inodeno_t> > export_proxy_dirinos;
 
-  set<inodeno_t>         stray_export_warnings; // warnings for export dirs i don't have open
+  set<inodeno_t>                    stray_export_warnings; // notifies i haven't seen
   map<inodeno_t, MExportDirNotify*> stray_export_notifies;
 
+  // rename fun
+  set<inodeno_t>                    stray_rename_warnings; // notifies i haven't seen
+  map<inodeno_t, MRenameNotify*>    stray_rename_notifies;
 
  public:
   // active MDS requests
@@ -168,7 +174,8 @@ class MDCache {
   void fix_renamed_dir(CDir *srcdir,
                                           CInode *in,
                                           CDir *destdir,
-                                          bool authchanged);   // _inode_ auth
+                                          bool authchanged,   // _inode_ auth changed
+                                          int dirauth=-1);    // dirauth (for certain cases)
 
  public:
   int open_root(Context *c);
@@ -187,7 +194,7 @@ class MDCache {
                                         vector<CDentry*>& trace);
   void request_cleanup(Message *req);
   void request_finish(Message *req);
-  void request_forward(Message *req, int mds);
+  void request_forward(Message *req, int mds, int port=0);
 
 
   // == messages ==
@@ -204,14 +211,34 @@ class MDCache {
   void dentry_unlink(CDentry *in, Context *c);
   void handle_dentry_unlink(MDentryUnlink *m);
 
+  // initiator
   void file_rename(CDentry *srcdn, CDentry *destdn, Context *c);
+  void handle_rename_ack(MRenameAck *m);              // dest -> init (almost always)
   void file_rename_finish(CDir *srcdir, CInode *in, Context *c);
-  void file_rename_foreign_src(CDentry *srcdn, CDentry *destdn, int initiator);
-  void handle_rename_notify(MRenameNotify *m);        // init -> bystanders
-  void handle_rename_notify_ack(MRenameNotifyAck *m); // bystanders -> init
+
+  // src
+  void handle_rename_req(MRenameReq *m);              // dest -> src
+  void file_rename_foreign_src(CDentry *srcdn, 
+                                                          inodeno_t destdirino, string& destname, string& destpath, int destauth, 
+                                                          int initiator);
+  void file_rename_warn(CInode *in, set<int>& notify);
+  void handle_rename_notify_ack(MRenameNotifyAck *m); // bystanders -> src
+  void file_rename_ack(CInode *in, int initiator);
+
+  // dest
+  void handle_rename_prep(MRenamePrep *m);            // init -> dest
   void handle_rename(MRename *m);                     // src -> dest
-  void handle_rename_req(MRenameReq *m);              // init -> src (rarely)
-  void handle_rename_ack(MRenameAck *m);              // dest -> init (almost always)
+  void file_rename_notify(CInode *in, 
+                                                 CDir *srcdir, string& srcname, CDir *destdir, string& destname,
+                                                 set<int>& notify, int srcauth);
+
+  // bystander
+  void handle_rename_warning(MRenameWarning *m);      // src -> bystanders
+  void handle_rename_notify(MRenameNotify *m);        // dest -> bystanders
+
+
+
+
   
 
 
@@ -232,6 +259,7 @@ class MDCache {
        return exports.count(dir);
   }
   void find_nested_exports(CDir *dir, set<CDir*>& s);
+  void find_nested_exports_under(CDir *import, CDir *dir, set<CDir*>& s);
 
   // exporter
   void export_dir(CDir *dir,
@@ -344,8 +372,7 @@ class MDCache {
 
   // dentry locks
   bool dentry_xlock_start(CDentry *dn, 
-                                                 Message *m, CInode *ref, 
-                                                 bool allnodes=false);
+                                                 Message *m, CInode *ref);
   void dentry_xlock_finish(CDentry *dn, bool quiet=false);
   void handle_lock_dn(MLock *m);
   void dentry_xlock_request(CDir *dir, string& dname, bool create,
index d6eae05e8ad89e40db56fdc865dbf3ffa039bd51..35dbbce862eac18cea071703319c58166bad48bf 100644 (file)
@@ -311,7 +311,7 @@ void MDS::dispatch(Message *m)
   }
 
   // balance?
-  if (whoami == 0 &&
+  if (true && whoami == 0 &&
          stat_ops >= last_heartbeat + g_conf.mds_heartbeat_op_interval) {
        last_heartbeat = stat_ops;
        balancer->send_heartbeat();
@@ -1280,7 +1280,8 @@ void MDS::handle_client_rename(MClientRequest *req,
                                                                 req, new C_MDS_RetryRequest(this, req, ref),
                                                                 MDS_TRAVERSE_FORWARD);
   if (r == 2) {
-       dout(7) << "forwarded, ending request" << endl;
+       dout(7) << "path traverse forwarded, ending request, doing manual request_cleanup" << endl;
+       dout(7) << "(pseudo) request_forward to 9999 req " << *req << endl;
        mdcache->request_cleanup(req);  // not _finish (deletes) or _forward (path_traverse did that)
        return;
   }
@@ -1395,7 +1396,6 @@ void MDS::handle_client_rename_2(MClientRequest *req,
   assert(srci);
   CDir*  destdir = 0;
   string destname;
-  int destauth = -1;
   bool result;
   
   // what is the dest?  (dir or file or complete filename)
@@ -1466,7 +1466,7 @@ void MDS::handle_client_rename_2(MClientRequest *req,
 
   // src == dest?
   if (srcdn->get_dir() == destdir && srcdn->name == destname) {
-       dout(7) << "rename src=dest, same file " << destauth << endl;
+       dout(7) << "rename src=dest, same file " << endl;
        reply_request(req, -EINVAL);
        return;
   }
@@ -1507,15 +1507,22 @@ void MDS::handle_client_rename_2(MClientRequest *req,
   
 
   // local or remote?
-  destauth = destdir->dentry_authority(destname);
+  int srcauth = srcdir->dentry_authority(srcdn->name);
+  int destauth = destdir->dentry_authority(destname);
   dout(7) << "handle_client_rename_2 destname " << destname << " destdir " << *destdir << " auth " << destauth << endl;
   
-  if (destauth != get_nodeid()) {
+  // 
+  if (srcauth != get_nodeid() || 
+         destauth != get_nodeid()) {
        dout(7) << "rename has remote dest " << destauth << endl;
 
        dout(7) << "FOREIGN RENAME" << endl;
-       reply_request(req, -EINVAL);  // punt for now!
-       return;
+       
+       // punt?
+       if (true && srcdn->inode->is_dir()) {
+         reply_request(req, -EINVAL);  
+         return; 
+       }
 
   } else {
        dout(7) << "rename is local" << endl;
@@ -1541,7 +1548,7 @@ void MDS::handle_client_rename_local(MClientRequest *req,
                                                                         string& destname)
 {
   bool everybody = false;
-  if (true || srcdn->inode->is_dir()) {
+  //if (true || srcdn->inode->is_dir()) {
        /* overkill warning: lock w/ everyone for simplicity.  FIXME someday!  along with the foreign rename crap!
           i could limit this to cases where something beneath me is exported.
           could possibly limit the list.    (maybe.)
@@ -1579,9 +1586,9 @@ void MDS::handle_client_rename_local(MClientRequest *req,
          /- notify goes to everybody on a foreign rename 
          /- handle_notify needs to gracefully ignore spurious notifies
        */
-       dout(7) << "handle_client_rename_local: overkill?  doing xlocks with _all_ nodes" << endl;
-       everybody = true;
-  }
+  //dout(7) << "handle_client_rename_local: overkill?  doing xlocks with _all_ nodes" << endl;
+  //everybody = true;
+  //}
 
   bool srclocal = srcdn->dir->dentry_authority(srcdn->name) == whoami;
   bool destlocal = destdir->dentry_authority(destname) == whoami;
@@ -1602,7 +1609,7 @@ void MDS::handle_client_rename_local(MClientRequest *req,
          // src
          if (srclocal) {
                if (!srcdn->is_xlockedbyme(req) &&
-                       !mdcache->dentry_xlock_start(srcdn, req, ref, everybody))
+                       !mdcache->dentry_xlock_start(srcdn, req, ref))
                  return;  
          } else {
                if (!srcdn || srcdn->xlockedby != req) {
@@ -1618,7 +1625,7 @@ void MDS::handle_client_rename_local(MClientRequest *req,
                // dest
                if (!destdn) destdn = destdir->add_dentry(destname);
                if (!destdn->is_xlockedbyme(req) &&
-                       !mdcache->dentry_xlock_start(destdn, req, ref, everybody)) {
+                       !mdcache->dentry_xlock_start(destdn, req, ref)) {
                  if (destdn->is_clean() && destdn->is_null() && destdn->is_sync()) destdir->remove_dentry(destdn);
                  return;
                }
index 13d821e63eda3cb533d1bc5cda8fc92ec722a46d..9ddcfcb8bfb2fed435c2f033244dc144b3e120d6 100644 (file)
@@ -4,7 +4,6 @@
 class MRename : public Message {
   inodeno_t srcdirino;
   string srcname;
-  string srcpath;
   inodeno_t destdirino;
   string destname;
   int initiator;
@@ -15,7 +14,6 @@ class MRename : public Message {
   int get_initiator() { return initiator; }
   inodeno_t get_srcdirino() { return srcdirino; }
   string& get_srcname() { return srcname; }
-  string& get_srcpath() { return srcpath; }
   inodeno_t get_destdirino() { return destdirino; }
   string& get_destname() { return destname; }
   crope& get_inode_state() { return inode_state; }
@@ -24,7 +22,6 @@ class MRename : public Message {
   MRename(int initiator,
                  inodeno_t srcdirino,
                  const string& srcname,
-                 const string& srcpath,
                  inodeno_t destdirino,
                  const string& destname,
                  crope& inode_state) :
@@ -32,7 +29,6 @@ class MRename : public Message {
        this->initiator = initiator;
        this->srcdirino = srcdirino;
        this->srcname = srcname;
-       this->srcpath = srcpath;
        this->destdirino = destdirino;
        this->destname = destname;
        this->inode_state = inode_state;
@@ -49,8 +45,6 @@ class MRename : public Message {
        off += sizeof(destdirino);
        srcname = s.c_str() + off;
        off += srcname.length() + 1;
-       srcpath = s.c_str() + off;
-       off += srcpath.length() + 1;
        destname = s.c_str() + off;
        off += destname.length() + 1;
        inode_state = s.substr(off, s.length()-off);
@@ -61,8 +55,6 @@ class MRename : public Message {
        s.append((char*)&destdirino,sizeof(destdirino));
        s.append((char*)srcname.c_str());
        s.append((char)0);
-       s.append((char*)srcpath.c_str());
-       s.append((char)0);
        s.append((char*)destname.c_str());
        s.append((char)0);
        s.append(inode_state);
index b363419e07c5cb071be7caebfa18450ce7890d24..b3f3b2fc628b929ce7a6c423baefda7f96056a40 100644 (file)
@@ -1,49 +1,28 @@
 #ifndef __MRENAMEACK_H
 #define __MRENAMEACK_H
 
+/* FIXME: relateive to dn, not inode */
+
 class MRenameAck : public Message {
-  inodeno_t srcdirino;
-  string srcname;
-  inodeno_t destdirino;
-  string destname;
+  inodeno_t ino;
 
  public:
-  inodeno_t get_srcdirino() { return srcdirino; }
-  string& get_srcname() { return srcname; }
-  inodeno_t get_destdirino() { return destdirino; }
-  string& get_destname() { return destname; }
+  inodeno_t get_ino() { return ino; }
 
   MRenameAck() {}
-  MRenameAck(inodeno_t srcdirino,
-                        const string& srcname,
-                        inodeno_t destdirino,
-                        const string& destname) :
+  MRenameAck(inodeno_t ino) :
        Message(MSG_MDS_RENAMEACK) {
-       this->srcdirino = srcdirino;
-       this->srcname = srcname;
-       this->destdirino = destdirino;
-       this->destname = destname;
+       this->ino = ino;
   }
   virtual char *get_type_name() { return "RnAck";}
 
   virtual void decode_payload(crope& s) {
        int off = 0;
-       s.copy(off, sizeof(srcdirino), (char*)&srcdirino);
-       off += sizeof(srcdirino);
-       s.copy(off, sizeof(destdirino), (char*)&destdirino);
-       off += sizeof(destdirino);
-       srcname = s.c_str() + off;
-       off += srcname.length() + 1;
-       destname = s.c_str() + off;
-       off += destname.length() + 1;
+       s.copy(off, sizeof(ino), (char*)&ino);
+       off += sizeof(ino);
   }
   virtual void encode_payload(crope& s) {
-       s.append((char*)&srcdirino,sizeof(srcdirino));
-       s.append((char*)&destdirino,sizeof(destdirino));
-       s.append((char*)srcname.c_str());
-       s.append((char)0);
-       s.append((char*)destname.c_str());
-       s.append((char)0);
+       s.append((char*)&ino,sizeof(ino));
   }
 };
 
index 03df500cd73e7d85a42029ad236f73d36df53553..11a3b351504991a7854e54d12119da8f8bbd6567 100644 (file)
@@ -8,6 +8,8 @@ class MRenameNotify : public Message {
   inodeno_t destdirino;
   string destname;
   string destdirpath;
+  int srcauth;
+  bool warning;
 
  public:
   inodeno_t get_ino() { return ino; }
@@ -16,6 +18,8 @@ class MRenameNotify : public Message {
   inodeno_t get_destdirino() { return destdirino; }
   string& get_destname() { return destname; }
   string& get_destdirpath() { return destdirpath; }
+  int get_srcauth() { return srcauth; }
+  bool is_warning() { return warning; }
 
   MRenameNotify() {}
   MRenameNotify(inodeno_t ino,
@@ -23,7 +27,10 @@ class MRenameNotify : public Message {
                                const string& srcname,
                                inodeno_t destdirino,
                                const string& destdirpath,
-                               const string& destname) :
+                               const string& destname,
+                               int srcauth
+                               //,                     bool warning
+                               ) :
        Message(MSG_MDS_RENAMENOTIFY) {
        this->ino = ino;
        this->srcdirino = srcdirino;
@@ -31,6 +38,8 @@ class MRenameNotify : public Message {
        this->destdirino = destdirino;
        this->destname = destname;
        this->destdirpath = destdirpath;
+       this->srcauth = srcauth;
+       this->warning = warning;
   }
   virtual char *get_type_name() { return "Rnot";}
   
@@ -42,23 +51,21 @@ class MRenameNotify : public Message {
        off += sizeof(srcdirino);
        s.copy(off, sizeof(destdirino), (char*)&destdirino);
        off += sizeof(destdirino);
-       srcname = s.c_str() + off;
-       off += srcname.length() + 1;
-       destname = s.c_str() + off;
-       off += destname.length() + 1;
-       destdirpath = s.c_str() + off;
-       off += destdirpath.length() + 1;
+       _unrope(srcname, s, off);
+       _unrope(destname, s, off);
+       _unrope(destdirpath, s, off);
+       s.copy(off, sizeof(srcauth), (char*)&srcauth);
+       s.copy(off, sizeof(warning), (char*)&warning);
   }
   virtual void encode_payload(crope& s) {
        s.append((char*)&ino,sizeof(ino));
        s.append((char*)&srcdirino,sizeof(srcdirino));
        s.append((char*)&destdirino,sizeof(destdirino));
-       s.append((char*)srcname.c_str());
-       s.append((char)0);
-       s.append((char*)destname.c_str());
-       s.append((char)0);
-       s.append((char*)destdirpath.c_str());
-       s.append((char)0);
+       _rope(srcname, s);
+       _rope(destname, s);
+       _rope(destdirpath, s);
+       s.append((char*)&srcauth, sizeof(srcauth));
+       s.append((char*)&warning, sizeof(warning));
   }
 };
 
diff --git a/ceph/messages/MRenamePrep.h b/ceph/messages/MRenamePrep.h
new file mode 100644 (file)
index 0000000..0b3a91f
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __MRENAMEPREP_H
+#define __MRENAMEPREP_H
+
+class MRenamePrep : public Message {
+  inodeno_t srcdirino;
+  string srcname;
+  string srcpath;
+  inodeno_t destdirino;
+  string destname;
+  string destpath;
+  int initiator;
+  int srcauth;
+
+ public:
+  int get_initiator() { return initiator; }
+  inodeno_t get_srcdirino() { return srcdirino; }
+  string& get_srcname() { return srcname; }
+  string& get_srcpath() { return srcpath; }
+  int get_srcauth() { return srcauth; }
+  inodeno_t get_destdirino() { return destdirino; }
+  string& get_destname() { return destname; }
+  string& get_destpath() { return destpath; }
+
+  MRenamePrep() {}
+  MRenamePrep(int initiator,
+                         inodeno_t srcdirino,
+                         const string& srcname,
+                         const string& srcpath,
+                         inodeno_t destdirino,
+                         const string& destname,
+                         const string& destpath,
+                         int srcauth) :
+       Message(MSG_MDS_RENAMEPREP) {
+       this->initiator = initiator;
+       this->srcdirino = srcdirino;
+       this->srcname = srcname;
+       this->srcpath = srcpath;
+       this->destdirino = destdirino;
+       this->destname = destname;
+       this->destpath = destpath;
+       this->srcauth = srcauth;
+  }
+  virtual char *get_type_name() { return "RnP";}
+  
+  virtual void decode_payload(crope& s) {
+       int off = 0;
+       s.copy(off, sizeof(initiator), (char*)&initiator);
+       off += sizeof(initiator);
+       s.copy(off, sizeof(srcdirino), (char*)&srcdirino);
+       off += sizeof(srcdirino);
+       s.copy(off, sizeof(destdirino), (char*)&destdirino);
+       off += sizeof(destdirino);
+       _unrope(srcname, s, off);
+       _unrope(srcpath, s, off);
+       _unrope(destname, s, off);
+       _unrope(destpath, s, off);
+       s.copy(off, sizeof(srcauth), (char*)&srcauth);
+  }
+  virtual void encode_payload(crope& s) {
+       s.append((char*)&initiator,sizeof(initiator));
+       s.append((char*)&srcdirino,sizeof(srcdirino));
+       s.append((char*)&destdirino,sizeof(destdirino));
+       _rope(srcname, s);
+       _rope(srcpath, s);
+       _rope(destname, s);
+       _rope(destpath, s);
+       s.append((char*)&srcauth, sizeof(srcauth));
+  }
+};
+
+#endif
index 49750b68251d6f8830174a2b559fc51c07e63fe3..6cb2cbb725881b687d3ef32b03ca60641079abf2 100644 (file)
@@ -7,6 +7,8 @@ class MRenameReq : public Message {
   string srcname;
   inodeno_t destdirino;
   string destname;
+  string destpath;
+  int destauth;
 
  public:
   int get_initiator() { return initiator; }
@@ -14,19 +16,25 @@ class MRenameReq : public Message {
   string& get_srcname() { return srcname; }
   inodeno_t get_destdirino() { return destdirino; }
   string& get_destname() { return destname; }
+  string& get_destpath() { return destpath; }
+  int get_destauth() { return destauth; }
 
   MRenameReq() {}
   MRenameReq(int initiator,
                         inodeno_t srcdirino,
                         const string& srcname,
                         inodeno_t destdirino,
-                        const string& destname) :
+                        const string& destname,
+                        const string& destpath, 
+                        int destauth) :
        Message(MSG_MDS_RENAMEREQ) {
        this->initiator = initiator;
        this->srcdirino = srcdirino;
        this->srcname = srcname;
        this->destdirino = destdirino;
        this->destname = destname;
+       this->destpath = destpath;
+       this->destauth = destauth;
   }
   virtual char *get_type_name() { return "RnReq";}
 
@@ -38,19 +46,20 @@ class MRenameReq : public Message {
        off += sizeof(srcdirino);
        s.copy(off, sizeof(destdirino), (char*)&destdirino);
        off += sizeof(destdirino);
-       srcname = s.c_str() + off;
-       off += srcname.length() + 1;
-       destname = s.c_str() + off;
-       off += destname.length() + 1;
+       _unrope(srcname, s, off);
+       _unrope(destname, s, off);
+       _unrope(destpath, s, off);
+       s.copy(off, sizeof(destauth), (char*)&destauth);
+       off += sizeof(destauth);
   }
   virtual void encode_payload(crope& s) {
        s.append((char*)&initiator,sizeof(initiator));
        s.append((char*)&srcdirino,sizeof(srcdirino));
        s.append((char*)&destdirino,sizeof(destdirino));
-       s.append((char*)srcname.c_str());
-       s.append((char)0);
-       s.append((char*)destname.c_str());
-       s.append((char)0);
+       _rope(srcname, s);
+       _rope(destname, s);
+       _rope(destpath, s);
+       s.append((char*)&destauth, sizeof(destauth));
   }
 };
 
diff --git a/ceph/messages/MRenameWarning.h b/ceph/messages/MRenameWarning.h
new file mode 100644 (file)
index 0000000..ec8d108
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __MRENAMEWARNING_H
+#define __MRENAMEWARNING_H
+
+class MRenameWarning : public Message {
+  inodeno_t ino;
+
+ public:
+  inodeno_t get_ino() { return ino; }
+
+  MRenameWarning() {}
+  MRenameWarning(inodeno_t ino) :
+       Message(MSG_MDS_RENAMEWARNING) {
+       this->ino = ino;
+  }
+  virtual char *get_type_name() { return "RnW";}
+  
+  virtual void decode_payload(crope& s) {
+       int off = 0;
+       s.copy(off, sizeof(ino), (char*)&ino);
+       off += sizeof(ino);
+  }
+  virtual void encode_payload(crope& s) {
+       s.append((char*)&ino,sizeof(ino));
+  }
+};
+
+#endif
index 84a9982b897bb9811d77bdbb698082853258e2c0..c9b49b514ee6dcb1a2a738b023ba159bf02332d9 100644 (file)
@@ -6,6 +6,7 @@
 #include "mds/MDS.h"
 
 #include "common/Timer.h"
+
 #include "common/LogType.h"
 #include "common/Logger.h"
 
@@ -166,6 +167,7 @@ FakeMessenger::FakeMessenger(long me)
   whoami = me;
   directory[ whoami ] = this;
 
+  g_timer.set_messenger(this);
   pending_timer = 0;
 
   cout << "fakemessenger " << whoami << " messenger is " << this << endl;
index 1a8251bdfdb3e7728f0c44e7bd4e988832c90024..87ee439fefab3e78cf8cae8bb4b5cf7d8a851342 100644 (file)
 
 #define MSG_MDS_DENTRYUNLINK      200
 
-#define MSG_MDS_RENAMENOTIFY     300   // sent from initiator to bystanders
-#define MSG_MDS_RENAMENOTIFYACK  301   // sent back to initiator
-#define MSG_MDS_RENAMEREQ        302   // sent from initiator to src auth (rare)
-#define MSG_MDS_RENAME           303   // sent from src to dest, includes inode
-#define MSG_MDS_RENAMEACK        304   // sent from dest to initiator, to xlock_finish
+#define MSG_MDS_RENAMEWARNING    300   // sent from src to bystanders
+#define MSG_MDS_RENAMENOTIFY     301   // sent from dest to bystanders
+#define MSG_MDS_RENAMENOTIFYACK  302   // sent back to src
+#define MSG_MDS_RENAMEACK        303   // sent from src to initiator, to xlock_finish
+
+#define MSG_MDS_RENAMEPREP       304   // sent from initiator to dest auth (if dir)
+#define MSG_MDS_RENAMEREQ        305   // sent from initiator (or dest if dir) to src auth
+#define MSG_MDS_RENAME           306   // sent from src to dest, includes inode
 
 #define MSG_MDS_LOCK             500
 
index ac81a1795419e485e2d6160bc8ae63d1c234a34c..39d249459a09f196a6fc803b1053bcd752f459d9 100644 (file)
@@ -36,9 +36,11 @@ using namespace std;
 #include "messages/MExportDirNotifyAck.h"
 #include "messages/MExportDirFinish.h"
 
+#include "messages/MRenameWarning.h"
 #include "messages/MRenameNotify.h"
 #include "messages/MRenameNotifyAck.h"
 #include "messages/MRename.h"
+#include "messages/MRenamePrep.h"
 #include "messages/MRenameReq.h"
 #include "messages/MRenameAck.h"
 #include "messages/MDentryUnlink.h"
@@ -155,6 +157,9 @@ decode_message(crope& ser)
        m = new MExportDirWarning();
        break;
 
+  case MSG_MDS_RENAMEWARNING:
+       m = new MRenameWarning();
+       break;
   case MSG_MDS_RENAMENOTIFY:
        m = new MRenameNotify();
        break;
@@ -164,6 +169,9 @@ decode_message(crope& ser)
   case MSG_MDS_RENAME:
        m = new MRename();
        break;
+  case MSG_MDS_RENAMEPREP:
+       m = new MRenamePrep();
+       break;
   case MSG_MDS_RENAMEREQ:
        m = new MRenameReq();
        break;