Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / mds / Migrator.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software 
11  * Foundation.  See file COPYING.
12  * 
13  */
14
15 #include "MDSRank.h"
16 #include "MDCache.h"
17 #include "CInode.h"
18 #include "CDir.h"
19 #include "CDentry.h"
20 #include "Migrator.h"
21 #include "Locker.h"
22 #include "Server.h"
23
24 #include "MDBalancer.h"
25 #include "MDLog.h"
26 #include "MDSMap.h"
27 #include "Mutation.h"
28
29 #include "include/filepath.h"
30
31 #include "events/EExport.h"
32 #include "events/EImportStart.h"
33 #include "events/EImportFinish.h"
34 #include "events/ESessions.h"
35
36 #include "msg/Messenger.h"
37
38 #include "messages/MClientCaps.h"
39
40 #include "messages/MExportDirDiscover.h"
41 #include "messages/MExportDirDiscoverAck.h"
42 #include "messages/MExportDirCancel.h"
43 #include "messages/MExportDirPrep.h"
44 #include "messages/MExportDirPrepAck.h"
45 #include "messages/MExportDir.h"
46 #include "messages/MExportDirAck.h"
47 #include "messages/MExportDirNotify.h"
48 #include "messages/MExportDirNotifyAck.h"
49 #include "messages/MExportDirFinish.h"
50
51 #include "messages/MExportCaps.h"
52 #include "messages/MExportCapsAck.h"
53 #include "messages/MGatherCaps.h"
54
55
56 /*
57  * this is what the dir->dir_auth values look like
58  *
59  *   dir_auth  authbits  
60  * export
61  *   me         me      - before
62  *   me, me     me      - still me, but preparing for export
63  *   me, them   me      - send MExportDir (peer is preparing)
64  *   them, me   me      - journaled EExport
65  *   them       them    - done
66  *
67  * import:
68  *   them       them    - before
69  *   me, them   me      - journaled EImportStart
70  *   me         me      - done
71  *
72  * which implies:
73  *  - auth bit is set if i am listed as first _or_ second dir_auth.
74  */
75
76 #include "common/config.h"
77
78
79 #define dout_context g_ceph_context
80 #define dout_subsys ceph_subsys_mds
81 #undef dout_prefix
82 #define dout_prefix *_dout << "mds." << mds->get_nodeid() << ".migrator "
83
84
85 class MigratorContext : public MDSInternalContextBase {
86 protected:
87   Migrator *mig;
88   MDSRank *get_mds() override {
89     return mig->mds;
90   }
91 public:
92   explicit MigratorContext(Migrator *mig_) : mig(mig_) {
93     assert(mig != NULL);
94   }
95 };
96
97 class MigratorLogContext : public MDSLogContextBase {
98 protected:
99   Migrator *mig;
100   MDSRank *get_mds() override {
101     return mig->mds;
102   }
103 public:
104   explicit MigratorLogContext(Migrator *mig_) : mig(mig_) {
105     assert(mig != NULL);
106   }
107 };
108
109 /* This function DOES put the passed message before returning*/
110 void Migrator::dispatch(Message *m)
111 {
112   switch (m->get_type()) {
113     // import
114   case MSG_MDS_EXPORTDIRDISCOVER:
115     handle_export_discover(static_cast<MExportDirDiscover*>(m));
116     break;
117   case MSG_MDS_EXPORTDIRPREP:
118     handle_export_prep(static_cast<MExportDirPrep*>(m));
119     break;
120   case MSG_MDS_EXPORTDIR:
121     handle_export_dir(static_cast<MExportDir*>(m));
122     break;
123   case MSG_MDS_EXPORTDIRFINISH:
124     handle_export_finish(static_cast<MExportDirFinish*>(m));
125     break;
126   case MSG_MDS_EXPORTDIRCANCEL:
127     handle_export_cancel(static_cast<MExportDirCancel*>(m));
128     break;
129
130     // export 
131   case MSG_MDS_EXPORTDIRDISCOVERACK:
132     handle_export_discover_ack(static_cast<MExportDirDiscoverAck*>(m));
133     break;
134   case MSG_MDS_EXPORTDIRPREPACK:
135     handle_export_prep_ack(static_cast<MExportDirPrepAck*>(m));
136     break;
137   case MSG_MDS_EXPORTDIRACK:
138     handle_export_ack(static_cast<MExportDirAck*>(m));
139     break;
140   case MSG_MDS_EXPORTDIRNOTIFYACK:
141     handle_export_notify_ack(static_cast<MExportDirNotifyAck*>(m));
142     break;    
143
144     // export 3rd party (dir_auth adjustments)
145   case MSG_MDS_EXPORTDIRNOTIFY:
146     handle_export_notify(static_cast<MExportDirNotify*>(m));
147     break;
148
149     // caps
150   case MSG_MDS_EXPORTCAPS:
151     handle_export_caps(static_cast<MExportCaps*>(m));
152     break;
153   case MSG_MDS_GATHERCAPS:
154     handle_gather_caps(static_cast<MGatherCaps*>(m));
155     break;
156
157   default:
158     derr << "migrator unknown message " << m->get_type() << dendl;
159     assert(0 == "migrator unknown message");
160   }
161 }
162
163
164 class C_MDC_EmptyImport : public MigratorContext {
165   CDir *dir;
166 public:
167   C_MDC_EmptyImport(Migrator *m, CDir *d) : MigratorContext(m), dir(d) {}
168   void finish(int r) override {
169     mig->export_empty_import(dir);
170   }
171 };
172
173
174 void Migrator::export_empty_import(CDir *dir)
175 {
176   dout(7) << "export_empty_import " << *dir << dendl;
177   assert(dir->is_subtree_root());
178
179   if (dir->inode->is_auth()) {
180     dout(7) << " inode is auth" << dendl;
181     return;
182   }
183   if (!dir->is_auth()) {
184     dout(7) << " not auth" << dendl;
185     return;
186   }
187   if (dir->is_freezing() || dir->is_frozen()) {
188     dout(7) << " freezing or frozen" << dendl;
189     return;
190   }
191   if (dir->get_num_head_items() > 0) {
192     dout(7) << " not actually empty" << dendl;
193     return;
194   }
195   if (dir->inode->is_root()) {
196     dout(7) << " root" << dendl;
197     return;
198   }
199   
200   mds_rank_t dest = dir->inode->authority().first;
201   //if (mds->is_shutting_down()) dest = 0;  // this is more efficient.
202   
203   dout(7) << " really empty, exporting to " << dest << dendl;
204   assert (dest != mds->get_nodeid());
205   
206   dout(7) << "exporting to mds." << dest 
207            << " empty import " << *dir << dendl;
208   export_dir( dir, dest );
209 }
210
211 void Migrator::find_stale_export_freeze()
212 {
213   utime_t now = ceph_clock_now();
214   utime_t cutoff = now;
215   cutoff -= g_conf->mds_freeze_tree_timeout;
216
217
218   /*
219    * We could have situations like:
220    *
221    * - mds.0 authpins an item in subtree A
222    * - mds.0 sends request to mds.1 to authpin an item in subtree B
223    * - mds.0 freezes subtree A
224    * - mds.1 authpins an item in subtree B
225    * - mds.1 sends request to mds.0 to authpin an item in subtree A
226    * - mds.1 freezes subtree B
227    * - mds.1 receives the remote authpin request from mds.0
228    *   (wait because subtree B is freezing)
229    * - mds.0 receives the remote authpin request from mds.1
230    *   (wait because subtree A is freezing)
231    *
232    *
233    * - client request authpins items in subtree B
234    * - freeze subtree B
235    * - import subtree A which is parent of subtree B
236    *   (authpins parent inode of subtree B, see CDir::set_dir_auth())
237    * - freeze subtree A
238    * - client request tries authpinning items in subtree A
239    *   (wait because subtree A is freezing)
240    */
241   for (map<CDir*,export_state_t>::iterator p = export_state.begin();
242        p != export_state.end(); ) {
243     CDir* dir = p->first;
244     export_state_t& stat = p->second;
245     ++p;
246     if (stat.state != EXPORT_DISCOVERING && stat.state != EXPORT_FREEZING)
247       continue;
248     if (stat.last_cum_auth_pins != dir->get_cum_auth_pins()) {
249       stat.last_cum_auth_pins = dir->get_cum_auth_pins();
250       stat.last_cum_auth_pins_change = now;
251       continue;
252     }
253     if (stat.last_cum_auth_pins_change >= cutoff)
254       continue;
255     if (stat.num_remote_waiters > 0 ||
256         (!dir->inode->is_root() && dir->get_parent_dir()->is_freezing())) {
257       export_try_cancel(dir);
258     }
259   }
260 }
261
262 void Migrator::export_try_cancel(CDir *dir, bool notify_peer)
263 {
264   dout(10) << "export_try_cancel " << *dir << dendl;
265
266   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
267   assert(it != export_state.end());
268
269   int state = it->second.state;
270   switch (state) {
271   case EXPORT_LOCKING:
272     dout(10) << "export state=locking : dropping locks and removing auth_pin" << dendl;
273     it->second.state = EXPORT_CANCELLED;
274     dir->auth_unpin(this);
275     break;
276   case EXPORT_DISCOVERING:
277     dout(10) << "export state=discovering : canceling freeze and removing auth_pin" << dendl;
278     it->second.state = EXPORT_CANCELLED;
279     dir->unfreeze_tree();  // cancel the freeze
280     dir->auth_unpin(this);
281     if (notify_peer &&
282         (!mds->is_cluster_degraded() ||
283          mds->mdsmap->is_clientreplay_or_active_or_stopping(it->second.peer))) // tell them.
284       mds->send_message_mds(new MExportDirCancel(dir->dirfrag(), it->second.tid), it->second.peer);
285     break;
286
287   case EXPORT_FREEZING:
288     dout(10) << "export state=freezing : canceling freeze" << dendl;
289     it->second.state = EXPORT_CANCELLED;
290     dir->unfreeze_tree();  // cancel the freeze
291     if (dir->is_subtree_root())
292       cache->try_subtree_merge(dir);
293     if (notify_peer &&
294         (!mds->is_cluster_degraded() ||
295          mds->mdsmap->is_clientreplay_or_active_or_stopping(it->second.peer))) // tell them.
296       mds->send_message_mds(new MExportDirCancel(dir->dirfrag(), it->second.tid), it->second.peer);
297     break;
298
299     // NOTE: state order reversal, warning comes after prepping
300   case EXPORT_WARNING:
301     dout(10) << "export state=warning : unpinning bounds, unfreezing, notifying" << dendl;
302     it->second.state = EXPORT_CANCELLING;
303     // fall-thru
304
305   case EXPORT_PREPPING:
306     if (state != EXPORT_WARNING) {
307       dout(10) << "export state=prepping : unpinning bounds, unfreezing" << dendl;
308       it->second.state = EXPORT_CANCELLED;
309     }
310
311     {
312       // unpin bounds
313       set<CDir*> bounds;
314       cache->get_subtree_bounds(dir, bounds);
315       for (set<CDir*>::iterator q = bounds.begin();
316           q != bounds.end();
317           ++q) {
318         CDir *bd = *q;
319         bd->put(CDir::PIN_EXPORTBOUND);
320         bd->state_clear(CDir::STATE_EXPORTBOUND);
321       }
322       if (state == EXPORT_WARNING) {
323         // notify bystanders
324         export_notify_abort(dir, bounds);
325         // process delayed expires
326         cache->process_delayed_expire(dir);
327       }
328     }
329     dir->unfreeze_tree();
330     cache->try_subtree_merge(dir);
331     if (notify_peer &&
332         (!mds->is_cluster_degraded() ||
333          mds->mdsmap->is_clientreplay_or_active_or_stopping(it->second.peer))) // tell them.
334       mds->send_message_mds(new MExportDirCancel(dir->dirfrag(), it->second.tid), it->second.peer);
335     break;
336
337   case EXPORT_EXPORTING:
338     dout(10) << "export state=exporting : reversing, and unfreezing" << dendl;
339     it->second.state = EXPORT_CANCELLING;
340     export_reverse(dir);
341     break;
342
343   case EXPORT_LOGGINGFINISH:
344   case EXPORT_NOTIFYING:
345     dout(10) << "export state=loggingfinish|notifying : ignoring dest failure, we were successful." << dendl;
346     // leave export_state, don't clean up now.
347     break;
348   case EXPORT_CANCELLING:
349     break;
350
351   default:
352     ceph_abort();
353   }
354
355   // finish clean-up?
356   if (it->second.state == EXPORT_CANCELLING ||
357       it->second.state == EXPORT_CANCELLED) {
358     MutationRef mut;
359     mut.swap(it->second.mut);
360
361     if (it->second.state == EXPORT_CANCELLED) {
362       export_state.erase(it);
363       dir->state_clear(CDir::STATE_EXPORTING);
364       // send pending import_maps?
365       cache->maybe_send_pending_resolves();
366     }
367
368     // drop locks
369     if (state == EXPORT_LOCKING || state == EXPORT_DISCOVERING) {
370       MDRequestRef mdr = static_cast<MDRequestImpl*>(mut.get());
371       assert(mdr);
372       if (mdr->more()->waiting_on_slave.empty())
373         mds->mdcache->request_finish(mdr);
374     } else if (mut) {
375       mds->locker->drop_locks(mut.get());
376       mut->cleanup();
377     }
378
379     cache->show_subtrees();
380
381     maybe_do_queued_export();
382   }
383 }
384
385 void Migrator::export_cancel_finish(CDir *dir)
386 {
387   assert(dir->state_test(CDir::STATE_EXPORTING));
388   dir->state_clear(CDir::STATE_EXPORTING);
389
390   // pinned by Migrator::export_notify_abort()
391   dir->auth_unpin(this);
392   // send pending import_maps?  (these need to go out when all exports have finished.)
393   cache->maybe_send_pending_resolves();
394 }
395
396 // ==========================================================
397 // mds failure handling
398
399 void Migrator::handle_mds_failure_or_stop(mds_rank_t who)
400 {
401   dout(5) << "handle_mds_failure_or_stop mds." << who << dendl;
402
403   // check my exports
404
405   // first add an extra auth_pin on any freezes, so that canceling a
406   // nested freeze doesn't complete one further up the hierarchy and
407   // confuse the shit out of us.  we'll remove it after canceling the
408   // freeze.  this way no freeze completions run before we want them
409   // to.
410   list<CDir*> pinned_dirs;
411   for (map<CDir*,export_state_t>::iterator p = export_state.begin();
412        p != export_state.end();
413        ++p) {
414     if (p->second.state == EXPORT_FREEZING) {
415       CDir *dir = p->first;
416       dout(10) << "adding temp auth_pin on freezing " << *dir << dendl;
417       dir->auth_pin(this);
418       pinned_dirs.push_back(dir);
419     }
420   }
421
422   map<CDir*,export_state_t>::iterator p = export_state.begin();
423   while (p != export_state.end()) {
424     map<CDir*,export_state_t>::iterator next = p;
425     ++next;
426     CDir *dir = p->first;
427     
428     // abort exports:
429     //  - that are going to the failed node
430     //  - that aren't frozen yet (to avoid auth_pin deadlock)
431     //  - they havne't prepped yet (they may need to discover bounds to do that)
432     if ((p->second.peer == who &&
433          p->second.state != EXPORT_CANCELLING) ||
434         p->second.state == EXPORT_LOCKING ||
435         p->second.state == EXPORT_DISCOVERING ||
436         p->second.state == EXPORT_FREEZING ||
437         p->second.state == EXPORT_PREPPING) {
438       // the guy i'm exporting to failed, or we're just freezing.
439       dout(10) << "cleaning up export state (" << p->second.state << ")"
440                << get_export_statename(p->second.state) << " of " << *dir << dendl;
441       export_try_cancel(dir);
442     } else if (p->second.peer != who) {
443       // bystander failed.
444       if (p->second.warning_ack_waiting.erase(who)) {
445         if (p->second.state == EXPORT_WARNING) {
446           p->second.notify_ack_waiting.erase(who);   // they won't get a notify either.
447           // exporter waiting for warning acks, let's fake theirs.
448           dout(10) << "faking export_warning_ack from mds." << who
449                    << " on " << *dir << " to mds." << p->second.peer
450                    << dendl;
451           if (p->second.warning_ack_waiting.empty())
452             export_go(dir);
453         }
454       }
455       if (p->second.notify_ack_waiting.erase(who)) {
456         // exporter is waiting for notify acks, fake it
457         dout(10) << "faking export_notify_ack from mds." << who
458                  << " on " << *dir << " to mds." << p->second.peer
459                  << dendl;
460         if (p->second.state == EXPORT_NOTIFYING) {
461           if (p->second.notify_ack_waiting.empty())
462             export_finish(dir);
463         } else if (p->second.state == EXPORT_CANCELLING) {
464           if (p->second.notify_ack_waiting.empty()) {
465             export_state.erase(p);
466             export_cancel_finish(dir);
467           }
468         }
469       }
470     }
471     
472     // next!
473     p = next;
474   }
475
476
477   // check my imports
478   map<dirfrag_t,import_state_t>::iterator q = import_state.begin();
479   while (q != import_state.end()) {
480     map<dirfrag_t,import_state_t>::iterator next = q;
481     ++next;
482     dirfrag_t df = q->first;
483     CInode *diri = mds->mdcache->get_inode(df.ino);
484     CDir *dir = mds->mdcache->get_dirfrag(df);
485
486     if (q->second.peer == who) {
487       if (dir)
488         dout(10) << "cleaning up import state (" << q->second.state << ")"
489                  << get_import_statename(q->second.state) << " of " << *dir << dendl;
490       else
491         dout(10) << "cleaning up import state (" << q->second.state << ")"
492                  << get_import_statename(q->second.state) << " of " << df << dendl;
493
494       switch (q->second.state) {
495       case IMPORT_DISCOVERING:
496         dout(10) << "import state=discovering : clearing state" << dendl;
497         import_reverse_discovering(df);
498         break;
499
500       case IMPORT_DISCOVERED:
501         assert(diri);
502         dout(10) << "import state=discovered : unpinning inode " << *diri << dendl;
503         import_reverse_discovered(df, diri);
504         break;
505
506       case IMPORT_PREPPING:
507         assert(dir);
508         dout(10) << "import state=prepping : unpinning base+bounds " << *dir << dendl;
509         import_reverse_prepping(dir);
510         break;
511
512       case IMPORT_PREPPED:
513         assert(dir);
514         dout(10) << "import state=prepped : unpinning base+bounds, unfreezing " << *dir << dendl;
515         {
516           set<CDir*> bounds;
517           cache->get_subtree_bounds(dir, bounds);
518           import_remove_pins(dir, bounds);
519           
520           // adjust auth back to the exporter
521           cache->adjust_subtree_auth(dir, q->second.peer);
522
523           // notify bystanders ; wait in aborting state
524           import_state[df].state = IMPORT_ABORTING;
525           import_notify_abort(dir, bounds);
526           assert(g_conf->mds_kill_import_at != 10);
527         }
528         break;
529
530       case IMPORT_LOGGINGSTART:
531         assert(dir);
532         dout(10) << "import state=loggingstart : reversing import on " << *dir << dendl;
533         import_reverse(dir);
534         break;
535
536       case IMPORT_ACKING:
537         assert(dir);
538         // hrm.  make this an ambiguous import, and wait for exporter recovery to disambiguate
539         dout(10) << "import state=acking : noting ambiguous import " << *dir << dendl;
540         {
541           set<CDir*> bounds;
542           cache->get_subtree_bounds(dir, bounds);
543           cache->add_ambiguous_import(dir, bounds);
544         }
545         break;
546         
547       case IMPORT_FINISHING:
548         assert(dir);
549         dout(10) << "import state=finishing : finishing import on " << *dir << dendl;
550         import_finish(dir, true);
551         break;
552
553       case IMPORT_ABORTING:
554         assert(dir);
555         dout(10) << "import state=aborting : ignoring repeat failure " << *dir << dendl;
556         break;
557       }
558     } else {
559       auto bystanders_entry = q->second.bystanders.find(who);
560       if (bystanders_entry != q->second.bystanders.end()) {
561         q->second.bystanders.erase(bystanders_entry);
562         if (q->second.state == IMPORT_ABORTING) {
563           assert(dir);
564           dout(10) << "faking export_notify_ack from mds." << who
565                    << " on aborting import " << *dir << " from mds." << q->second.peer
566                    << dendl;
567           if (q->second.bystanders.empty())
568             import_reverse_unfreeze(dir);
569         }
570       }
571     }
572
573     // next!
574     q = next;
575   }
576
577   while (!pinned_dirs.empty()) {
578     CDir *dir = pinned_dirs.front();
579     dout(10) << "removing temp auth_pin on " << *dir << dendl;
580     dir->auth_unpin(this);
581     pinned_dirs.pop_front();
582   }  
583 }
584
585
586
587 void Migrator::show_importing()
588 {  
589   dout(10) << "show_importing" << dendl;
590   for (map<dirfrag_t,import_state_t>::iterator p = import_state.begin();
591        p != import_state.end();
592        ++p) {
593     CDir *dir = mds->mdcache->get_dirfrag(p->first);
594     if (dir) {
595       dout(10) << " importing from " << p->second.peer
596                << ": (" << p->second.state << ") " << get_import_statename(p->second.state)
597                << " " << p->first << " " << *dir << dendl;
598     } else {
599       dout(10) << " importing from " << p->second.peer
600                << ": (" << p->second.state << ") " << get_import_statename(p->second.state)
601                << " " << p->first << dendl;
602     }
603   }
604 }
605
606 void Migrator::show_exporting() 
607 {
608   dout(10) << "show_exporting" << dendl;
609   for (map<CDir*,export_state_t>::iterator p = export_state.begin();
610        p != export_state.end();
611        ++p) 
612     dout(10) << " exporting to " << p->second.peer
613              << ": (" << p->second.state << ") " << get_export_statename(p->second.state)
614              << " " << p->first->dirfrag() << " " << *p->first << dendl;
615 }
616
617
618
619 void Migrator::audit()
620 {
621   if (!g_conf->subsys.should_gather(ceph_subsys_mds, 5))
622     return;  // hrm.
623
624   // import_state
625   show_importing();
626   for (map<dirfrag_t,import_state_t>::iterator p = import_state.begin();
627        p != import_state.end();
628        ++p) {
629     if (p->second.state == IMPORT_DISCOVERING)
630       continue;
631     if (p->second.state == IMPORT_DISCOVERED) {
632       CInode *in = cache->get_inode(p->first.ino);
633       assert(in);
634       continue;
635     }
636     CDir *dir = cache->get_dirfrag(p->first);
637     assert(dir);
638     if (p->second.state == IMPORT_PREPPING)
639       continue;
640     if (p->second.state == IMPORT_ABORTING) {
641       assert(!dir->is_ambiguous_dir_auth());
642       assert(dir->get_dir_auth().first != mds->get_nodeid());
643       continue;
644     }
645     assert(dir->is_ambiguous_dir_auth());
646     assert(dir->authority().first  == mds->get_nodeid() ||
647            dir->authority().second == mds->get_nodeid());
648   }
649
650   // export_state
651   show_exporting();
652   for (map<CDir*,export_state_t>::iterator p = export_state.begin();
653        p != export_state.end();
654        ++p) {
655     CDir *dir = p->first;
656     if (p->second.state == EXPORT_LOCKING ||
657         p->second.state == EXPORT_DISCOVERING ||
658         p->second.state == EXPORT_FREEZING ||
659         p->second.state == EXPORT_CANCELLING)
660       continue;
661     assert(dir->is_ambiguous_dir_auth());
662     assert(dir->authority().first  == mds->get_nodeid() ||
663            dir->authority().second == mds->get_nodeid());
664   }
665
666   // ambiguous+me subtrees should be importing|exporting
667
668   // write me
669 }
670
671
672
673
674
675 // ==========================================================
676 // EXPORT
677
678 void Migrator::export_dir_nicely(CDir *dir, mds_rank_t dest)
679 {
680   // enqueue
681   dout(7) << "export_dir_nicely " << *dir << " to " << dest << dendl;
682   export_queue.push_back(pair<dirfrag_t,mds_rank_t>(dir->dirfrag(), dest));
683
684   maybe_do_queued_export();
685 }
686
687 void Migrator::maybe_do_queued_export()
688 {
689   static bool running;
690   if (running)
691     return;
692   running = true;
693   while (!export_queue.empty() &&
694          export_state.size() <= 4) {
695     dirfrag_t df = export_queue.front().first;
696     mds_rank_t dest = export_queue.front().second;
697     export_queue.pop_front();
698     
699     CDir *dir = mds->mdcache->get_dirfrag(df);
700     if (!dir) continue;
701     if (!dir->is_auth()) continue;
702
703     dout(0) << "nicely exporting to mds." << dest << " " << *dir << dendl;
704
705     export_dir(dir, dest);
706   }
707   running = false;
708 }
709
710
711
712
713 class C_MDC_ExportFreeze : public MigratorContext {
714   CDir *ex;   // dir i'm exporting
715   uint64_t tid;
716 public:
717   C_MDC_ExportFreeze(Migrator *m, CDir *e, uint64_t t) :
718         MigratorContext(m), ex(e), tid(t) {
719           assert(ex != NULL);
720         }
721   void finish(int r) override {
722     if (r >= 0)
723       mig->export_frozen(ex, tid);
724   }
725 };
726
727
728 void Migrator::get_export_lock_set(CDir *dir, set<SimpleLock*>& locks)
729 {
730   // path
731   vector<CDentry*> trace;
732   cache->make_trace(trace, dir->inode);
733   for (vector<CDentry*>::iterator it = trace.begin();
734        it != trace.end();
735        ++it)
736     locks.insert(&(*it)->lock);
737
738   // prevent scatter gather race
739   locks.insert(&dir->get_inode()->dirfragtreelock);
740
741   // bound dftlocks:
742   // NOTE: We need to take an rdlock on bounding dirfrags during
743   //  migration for a rather irritating reason: when we export the
744   //  bound inode, we need to send scatterlock state for the dirfrags
745   //  as well, so that the new auth also gets the correct info.  If we
746   //  race with a refragment, this info is useless, as we can't
747   //  redivvy it up.  And it's needed for the scatterlocks to work
748   //  properly: when the auth is in a sync/lock state it keeps each
749   //  dirfrag's portion in the local (auth OR replica) dirfrag.
750   set<CDir*> wouldbe_bounds;
751   cache->get_wouldbe_subtree_bounds(dir, wouldbe_bounds);
752   for (set<CDir*>::iterator p = wouldbe_bounds.begin(); p != wouldbe_bounds.end(); ++p)
753     locks.insert(&(*p)->get_inode()->dirfragtreelock);
754 }
755
756
757 class C_M_ExportDirWait : public MigratorContext {
758   MDRequestRef mdr;
759   int count;
760 public:
761   C_M_ExportDirWait(Migrator *m, MDRequestRef mdr, int count)
762    : MigratorContext(m), mdr(mdr), count(count) {}
763   void finish(int r) override {
764     mig->dispatch_export_dir(mdr, count);
765   }
766 };
767
768
769 /** export_dir(dir, dest)
770  * public method to initiate an export.
771  * will fail if the directory is freezing, frozen, unpinnable, or root. 
772  */
773 void Migrator::export_dir(CDir *dir, mds_rank_t dest)
774 {
775   dout(7) << "export_dir " << *dir << " to " << dest << dendl;
776   assert(dir->is_auth());
777   assert(dest != mds->get_nodeid());
778    
779   if (!(mds->is_active() || mds->is_stopping())) {
780     dout(7) << "i'm not active, no exports for now" << dendl;
781     return;
782   }
783   if (mds->mdcache->is_readonly()) {
784     dout(7) << "read-only FS, no exports for now" << dendl;
785     return;
786   }
787   if (!mds->mdsmap->is_active(dest)) {
788     dout(7) << "dest not active, no exports for now" << dendl;
789     return;
790   }
791   if (mds->is_cluster_degraded()) {
792     dout(7) << "cluster degraded, no exports for now" << dendl;
793     return;
794   }
795   if (dir->inode->is_system()) {
796     dout(7) << "i won't export system dirs (root, mdsdirs, stray, /.ceph, etc.)" << dendl;
797     //ceph_abort();
798     return;
799   }
800
801   if (!dir->inode->is_base() && dir->inode->get_projected_parent_dir()->inode->is_stray() &&
802       dir->inode->get_projected_parent_dir()->get_parent_dir()->ino() != MDS_INO_MDSDIR(dest)) {
803     dout(7) << "i won't export anything in stray" << dendl;
804     return;
805   }
806
807   if (dir->is_frozen() ||
808       dir->is_freezing()) {
809     dout(7) << " can't export, freezing|frozen.  wait for other exports to finish first." << dendl;
810     return;
811   }
812   if (dir->state_test(CDir::STATE_EXPORTING)) {
813     dout(7) << "already exporting" << dendl;
814     return;
815   }
816
817   if (!mds->is_stopping() && !dir->inode->is_exportable(dest)) {
818     dout(7) << "dir is export pinned" << dendl;
819     return;
820   }
821
822   if (dest == mds->get_nodeid() || !mds->mdsmap->is_up(dest)) {
823     dout(7) << "cannot export: dest " << dest << " is me or is not active" << dendl;
824     return;
825   }
826
827   if (g_conf->mds_thrash_exports) {
828     // create random subtree bound (which will not be exported)
829     list<CDir*> ls;
830     for (auto p = dir->begin(); p != dir->end(); ++p) {
831       auto dn = p->second;
832       CDentry::linkage_t *dnl= dn->get_linkage();
833       if (dnl->is_primary()) {
834         CInode *in = dnl->get_inode();
835         if (in->is_dir())
836           in->get_nested_dirfrags(ls);
837       }
838     }
839     if (ls.size() > 0) {
840       int n = rand() % ls.size();
841       auto p = ls.begin();
842       while (n--) ++p;
843       CDir *bd = *p;
844       if (!(bd->is_frozen() || bd->is_freezing())) {
845         assert(bd->is_auth());
846         dir->state_set(CDir::STATE_AUXSUBTREE);
847         mds->mdcache->adjust_subtree_auth(dir, mds->get_nodeid());
848         dout(0) << "export_dir: create aux subtree " << *bd << " under " << *dir << dendl;
849       }
850     }
851   }
852
853   mds->hit_export_target(ceph_clock_now(), dest, -1);
854
855   dir->auth_pin(this);
856   dir->state_set(CDir::STATE_EXPORTING);
857
858   MDRequestRef mdr = mds->mdcache->request_start_internal(CEPH_MDS_OP_EXPORTDIR);
859   mdr->more()->export_dir = dir;
860
861   assert(export_state.count(dir) == 0);
862   export_state_t& stat = export_state[dir];
863   stat.state = EXPORT_LOCKING;
864   stat.peer = dest;
865   stat.tid = mdr->reqid.tid;
866   stat.mut = mdr;
867
868   return mds->mdcache->dispatch_request(mdr);
869 }
870
871 void Migrator::dispatch_export_dir(MDRequestRef& mdr, int count)
872 {
873   dout(7) << "dispatch_export_dir " << *mdr << dendl;
874
875   CDir *dir = mdr->more()->export_dir;
876   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
877   if (it == export_state.end() || it->second.tid != mdr->reqid.tid) {
878     // export must have aborted.
879     dout(7) << "export must have aborted " << *mdr << dendl;
880     mds->mdcache->request_finish(mdr);
881     return;
882   }
883   assert(it->second.state == EXPORT_LOCKING);
884
885   mds_rank_t dest = it->second.peer;
886
887   if (!mds->is_export_target(dest)) {
888     dout(7) << "dest is not yet an export target" << dendl;
889     if (count > 3) {
890       dout(5) << "dest has not been added as export target after three MDSMap epochs, canceling export" << dendl;
891       export_try_cancel(dir);
892       return;
893     }
894
895     mds->locker->drop_locks(mdr.get());
896     mdr->drop_local_auth_pins();
897
898     mds->wait_for_mdsmap(mds->mdsmap->get_epoch(), new C_M_ExportDirWait(this, mdr, count+1));
899     return;
900   }
901
902   if (!dir->inode->get_parent_dn()) {
903     dout(7) << "waiting for dir to become stable before export: " << *dir << dendl;
904     dir->add_waiter(CDir::WAIT_CREATED, new C_M_ExportDirWait(this, mdr, 1));
905     return;
906   }
907
908   if (mdr->aborted || dir->is_frozen() || dir->is_freezing()) {
909     dout(7) << "wouldblock|freezing|frozen, canceling export" << dendl;
910     export_try_cancel(dir);
911     return;
912   }
913
914   // locks?
915   set<SimpleLock*> rdlocks;
916   set<SimpleLock*> xlocks;
917   set<SimpleLock*> wrlocks;
918   get_export_lock_set(dir, rdlocks);
919   // If auth MDS of the subtree root inode is neither the exporter MDS
920   // nor the importer MDS and it gathers subtree root's fragstat/neststat
921   // while the subtree is exporting. It's possible that the exporter MDS
922   // and the importer MDS both are auth MDS of the subtree root or both
923   // are not auth MDS of the subtree root at the time they receive the
924   // lock messages. So the auth MDS of the subtree root inode may get no
925   // or duplicated fragstat/neststat for the subtree root dirfrag.
926   wrlocks.insert(&dir->get_inode()->filelock);
927   wrlocks.insert(&dir->get_inode()->nestlock);
928   if (dir->get_inode()->is_auth()) {
929     dir->get_inode()->filelock.set_scatter_wanted();
930     dir->get_inode()->nestlock.set_scatter_wanted();
931   }
932
933   if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks, NULL, NULL, true)) {
934     if (mdr->aborted)
935       export_try_cancel(dir);
936     return;
937   }
938
939   assert(g_conf->mds_kill_export_at != 1);
940   it->second.state = EXPORT_DISCOVERING;
941
942   // send ExportDirDiscover (ask target)
943   filepath path;
944   dir->inode->make_path(path);
945   MExportDirDiscover *discover = new MExportDirDiscover(dir->dirfrag(), path,
946                                                         mds->get_nodeid(),
947                                                         it->second.tid);
948   mds->send_message_mds(discover, dest);
949   assert(g_conf->mds_kill_export_at != 2);
950
951   it->second.last_cum_auth_pins_change = ceph_clock_now();
952
953   // start the freeze, but hold it up with an auth_pin.
954   dir->freeze_tree();
955   assert(dir->is_freezing_tree());
956   dir->add_waiter(CDir::WAIT_FROZEN, new C_MDC_ExportFreeze(this, dir, it->second.tid));
957 }
958
959 /*
960  * called on receipt of MExportDirDiscoverAck
961  * the importer now has the directory's _inode_ in memory, and pinned.
962  *
963  * This function DOES put the passed message before returning
964  */
965 void Migrator::handle_export_discover_ack(MExportDirDiscoverAck *m)
966 {
967   CDir *dir = cache->get_dirfrag(m->get_dirfrag());
968   mds_rank_t dest(m->get_source().num());
969   utime_t now = ceph_clock_now();
970   assert(dir);
971   
972   dout(7) << "export_discover_ack from " << m->get_source()
973           << " on " << *dir << dendl;
974
975   mds->hit_export_target(now, dest, -1);
976
977   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
978   if (it == export_state.end() ||
979       it->second.tid != m->get_tid() ||
980       it->second.peer != dest) {
981     dout(7) << "must have aborted" << dendl;
982   } else {
983     assert(it->second.state == EXPORT_DISCOVERING);
984
985     if (m->is_success()) {
986       // release locks to avoid deadlock
987       MDRequestRef mdr = static_cast<MDRequestImpl*>(it->second.mut.get());
988       assert(mdr);
989       mds->mdcache->request_finish(mdr);
990       it->second.mut.reset();
991       // freeze the subtree
992       it->second.state = EXPORT_FREEZING;
993       dir->auth_unpin(this);
994       assert(g_conf->mds_kill_export_at != 3);
995
996     } else {
997       dout(7) << "peer failed to discover (not active?), canceling" << dendl;
998       export_try_cancel(dir, false);
999     }
1000   }
1001   
1002   m->put();  // done
1003 }
1004
1005 class C_M_ExportSessionsFlushed : public MigratorContext {
1006   CDir *dir;
1007   uint64_t tid;
1008 public:
1009   C_M_ExportSessionsFlushed(Migrator *m, CDir *d, uint64_t t)
1010    : MigratorContext(m), dir(d), tid(t) {
1011     assert(dir != NULL);
1012   }
1013   void finish(int r) override {
1014     mig->export_sessions_flushed(dir, tid);
1015   }
1016 };
1017
1018 void Migrator::export_sessions_flushed(CDir *dir, uint64_t tid)
1019 {
1020   dout(7) << "export_sessions_flushed " << *dir << dendl;
1021
1022   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
1023   if (it == export_state.end() ||
1024       it->second.state == EXPORT_CANCELLING ||
1025       it->second.tid != tid) {
1026     // export must have aborted.
1027     dout(7) << "export must have aborted on " << dir << dendl;
1028     return;
1029   }
1030
1031   assert(it->second.state == EXPORT_PREPPING || it->second.state == EXPORT_WARNING);
1032   assert(it->second.warning_ack_waiting.count(MDS_RANK_NONE) > 0);
1033   it->second.warning_ack_waiting.erase(MDS_RANK_NONE);
1034   if (it->second.state == EXPORT_WARNING && it->second.warning_ack_waiting.empty())
1035     export_go(dir);     // start export.
1036 }
1037
1038 void Migrator::export_frozen(CDir *dir, uint64_t tid)
1039 {
1040   dout(7) << "export_frozen on " << *dir << dendl;
1041
1042   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
1043   if (it == export_state.end() || it->second.tid != tid) {
1044     dout(7) << "export must have aborted" << dendl;
1045     return;
1046   }
1047
1048   assert(it->second.state == EXPORT_FREEZING);
1049   assert(dir->is_frozen_tree_root());
1050   assert(dir->get_cum_auth_pins() == 0);
1051
1052   CInode *diri = dir->get_inode();
1053
1054   // ok, try to grab all my locks.
1055   set<SimpleLock*> rdlocks;
1056   get_export_lock_set(dir, rdlocks);
1057   if ((diri->is_auth() && diri->is_frozen()) ||
1058       !mds->locker->can_rdlock_set(rdlocks) ||
1059       !diri->filelock.can_wrlock(-1) ||
1060       !diri->nestlock.can_wrlock(-1)) {
1061     dout(7) << "export_dir couldn't acquire all needed locks, failing. "
1062             << *dir << dendl;
1063     // .. unwind ..
1064     dir->unfreeze_tree();
1065     cache->try_subtree_merge(dir);
1066
1067     mds->send_message_mds(new MExportDirCancel(dir->dirfrag(), it->second.tid), it->second.peer);
1068     export_state.erase(it);
1069
1070     dir->state_clear(CDir::STATE_EXPORTING);
1071     cache->maybe_send_pending_resolves();
1072     return;
1073   }
1074
1075   it->second.mut = new MutationImpl();
1076   if (diri->is_auth())
1077     it->second.mut->auth_pin(diri);
1078   mds->locker->rdlock_take_set(rdlocks, it->second.mut);
1079   mds->locker->wrlock_force(&diri->filelock, it->second.mut);
1080   mds->locker->wrlock_force(&diri->nestlock, it->second.mut);
1081
1082   cache->show_subtrees();
1083
1084   // CDir::_freeze_tree() should have forced it into subtree.
1085   assert(dir->get_dir_auth() == mds_authority_t(mds->get_nodeid(), mds->get_nodeid()));
1086   // note the bounds.
1087   set<CDir*> bounds;
1088   cache->get_subtree_bounds(dir, bounds);
1089
1090   // generate prep message, log entry.
1091   MExportDirPrep *prep = new MExportDirPrep(dir->dirfrag(), it->second.tid);
1092
1093   // include list of bystanders
1094   for (const auto &p : dir->get_replicas()) {
1095     if (p.first != it->second.peer) {
1096       dout(10) << "bystander mds." << p.first << dendl;
1097       prep->add_bystander(p.first);
1098     }
1099   }
1100
1101   // include base dirfrag
1102   cache->replicate_dir(dir, it->second.peer, prep->basedir);
1103   
1104   /*
1105    * include spanning tree for all nested exports.
1106    * these need to be on the destination _before_ the final export so that
1107    * dir_auth updates on any nested exports are properly absorbed.
1108    * this includes inodes and dirfrags included in the subtree, but
1109    * only the inodes at the bounds.
1110    *
1111    * each trace is: df ('-' | ('f' dir | 'd') dentry inode (dir dentry inode)*)
1112    */
1113   set<inodeno_t> inodes_added;
1114   set<dirfrag_t> dirfrags_added;
1115
1116   // check bounds
1117   for (set<CDir*>::iterator p = bounds.begin();
1118        p != bounds.end();
1119        ++p) {
1120     CDir *bound = *p;
1121
1122     // pin it.
1123     bound->get(CDir::PIN_EXPORTBOUND);
1124     bound->state_set(CDir::STATE_EXPORTBOUND);
1125     
1126     dout(7) << "  export bound " << *bound << dendl;
1127     prep->add_bound( bound->dirfrag() );
1128
1129     // trace to bound
1130     bufferlist tracebl;
1131     CDir *cur = bound;
1132     
1133     char start = '-';
1134     while (1) {
1135       // don't repeat inodes
1136       if (inodes_added.count(cur->inode->ino()))
1137         break;
1138       inodes_added.insert(cur->inode->ino());
1139
1140       // prepend dentry + inode
1141       assert(cur->inode->is_auth());
1142       bufferlist bl;
1143       cache->replicate_dentry(cur->inode->parent, it->second.peer, bl);
1144       dout(7) << "  added " << *cur->inode->parent << dendl;
1145       cache->replicate_inode(cur->inode, it->second.peer, bl,
1146                              mds->mdsmap->get_up_features());
1147       dout(7) << "  added " << *cur->inode << dendl;
1148       bl.claim_append(tracebl);
1149       tracebl.claim(bl);
1150
1151       cur = cur->get_parent_dir();
1152
1153       // don't repeat dirfrags
1154       if (dirfrags_added.count(cur->dirfrag()) ||
1155           cur == dir) {
1156         start = 'd';  // start with dentry
1157         break;
1158       }
1159       dirfrags_added.insert(cur->dirfrag());
1160
1161       // prepend dir
1162       cache->replicate_dir(cur, it->second.peer, bl);
1163       dout(7) << "  added " << *cur << dendl;
1164       bl.claim_append(tracebl);
1165       tracebl.claim(bl);
1166
1167       start = 'f';  // start with dirfrag
1168     }
1169     bufferlist final_bl;
1170     dirfrag_t df = cur->dirfrag();
1171     ::encode(df, final_bl);
1172     ::encode(start, final_bl);
1173     final_bl.claim_append(tracebl);
1174     prep->add_trace(final_bl);
1175   }
1176
1177   // send.
1178   it->second.state = EXPORT_PREPPING;
1179   mds->send_message_mds(prep, it->second.peer);
1180   assert (g_conf->mds_kill_export_at != 4);
1181
1182   // make sure any new instantiations of caps are flushed out
1183   assert(it->second.warning_ack_waiting.empty());
1184
1185   set<client_t> export_client_set;
1186   get_export_client_set(dir, export_client_set);
1187
1188   MDSGatherBuilder gather(g_ceph_context);
1189   mds->server->flush_client_sessions(export_client_set, gather);
1190   if (gather.has_subs()) {
1191     it->second.warning_ack_waiting.insert(MDS_RANK_NONE);
1192     gather.set_finisher(new C_M_ExportSessionsFlushed(this, dir, it->second.tid));
1193     gather.activate();
1194   }
1195 }
1196
1197 void Migrator::get_export_client_set(CDir *dir, set<client_t>& client_set)
1198 {
1199   list<CDir*> dfs;
1200   dfs.push_back(dir);
1201   while (!dfs.empty()) {
1202     CDir *dir = dfs.front();
1203     dfs.pop_front();
1204     for (CDir::map_t::iterator p = dir->begin(); p != dir->end(); ++p) {
1205       CDentry *dn = p->second;
1206       if (!dn->get_linkage()->is_primary())
1207         continue;
1208       CInode *in = dn->get_linkage()->get_inode();
1209       if (in->is_dir()) {
1210         // directory?
1211         list<CDir*> ls;
1212         in->get_dirfrags(ls);
1213         for (list<CDir*>::iterator q = ls.begin(); q != ls.end(); ++q) {
1214           if (!(*q)->state_test(CDir::STATE_EXPORTBOUND)) {
1215             // include nested dirfrag
1216             assert((*q)->get_dir_auth().first == CDIR_AUTH_PARENT);
1217             dfs.push_back(*q); // it's ours, recurse (later)
1218           }
1219         }
1220       }
1221       for (map<client_t, Capability*>::iterator q = in->client_caps.begin();
1222            q != in->client_caps.end();
1223            ++q)
1224         client_set.insert(q->first);
1225     }
1226   }
1227 }
1228
1229 void Migrator::get_export_client_set(CInode *in, set<client_t>& client_set)
1230 {
1231   for (map<client_t, Capability*>::iterator q = in->client_caps.begin();
1232       q != in->client_caps.end();
1233       ++q)
1234     client_set.insert(q->first);
1235 }
1236
1237 /* This function DOES put the passed message before returning*/
1238 void Migrator::handle_export_prep_ack(MExportDirPrepAck *m)
1239 {
1240   CDir *dir = cache->get_dirfrag(m->get_dirfrag());
1241   mds_rank_t dest(m->get_source().num());
1242   utime_t now = ceph_clock_now();
1243   assert(dir);
1244
1245   dout(7) << "export_prep_ack " << *dir << dendl;
1246
1247   mds->hit_export_target(now, dest, -1);
1248
1249   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
1250   if (it == export_state.end() ||
1251       it->second.tid != m->get_tid() ||
1252       it->second.peer != mds_rank_t(m->get_source().num())) {
1253     // export must have aborted.  
1254     dout(7) << "export must have aborted" << dendl;
1255     m->put();
1256     return;
1257   }
1258   assert(it->second.state == EXPORT_PREPPING);
1259
1260   if (!m->is_success()) {
1261     dout(7) << "peer couldn't acquire all needed locks or wasn't active, canceling" << dendl;
1262     export_try_cancel(dir, false);
1263     m->put();
1264     return;
1265   }
1266
1267   assert (g_conf->mds_kill_export_at != 5);
1268   // send warnings
1269   set<CDir*> bounds;
1270   cache->get_subtree_bounds(dir, bounds);
1271
1272   assert(it->second.warning_ack_waiting.empty() ||
1273          (it->second.warning_ack_waiting.size() == 1 &&
1274           it->second.warning_ack_waiting.count(MDS_RANK_NONE) > 0));
1275   assert(it->second.notify_ack_waiting.empty());
1276
1277   for (const auto &p : dir->get_replicas()) {
1278     if (p.first == it->second.peer) continue;
1279     if (mds->is_cluster_degraded() &&
1280         !mds->mdsmap->is_clientreplay_or_active_or_stopping(p.first))
1281       continue;  // only if active
1282     it->second.warning_ack_waiting.insert(p.first);
1283     it->second.notify_ack_waiting.insert(p.first);  // we'll eventually get a notifyack, too!
1284
1285     MExportDirNotify *notify = new MExportDirNotify(dir->dirfrag(), it->second.tid, true,
1286                                                     mds_authority_t(mds->get_nodeid(),CDIR_AUTH_UNKNOWN),
1287                                                     mds_authority_t(mds->get_nodeid(),it->second.peer));
1288     for (set<CDir*>::iterator q = bounds.begin(); q != bounds.end(); ++q)
1289       notify->get_bounds().push_back((*q)->dirfrag());
1290     mds->send_message_mds(notify, p.first);
1291     
1292   }
1293
1294   it->second.state = EXPORT_WARNING;
1295
1296   assert(g_conf->mds_kill_export_at != 6);
1297   // nobody to warn?
1298   if (it->second.warning_ack_waiting.empty())
1299     export_go(dir);  // start export.
1300     
1301   // done.
1302   m->put();
1303 }
1304
1305
1306 class C_M_ExportGo : public MigratorContext {
1307   CDir *dir;
1308   uint64_t tid;
1309 public:
1310   C_M_ExportGo(Migrator *m, CDir *d, uint64_t t) :
1311     MigratorContext(m), dir(d), tid(t) {
1312       assert(dir != NULL);
1313     }
1314   void finish(int r) override {
1315     mig->export_go_synced(dir, tid);
1316   }
1317 };
1318
1319 void Migrator::export_go(CDir *dir)
1320 {
1321   assert(export_state.count(dir));
1322   dout(7) << "export_go " << *dir << " to " << export_state[dir].peer << dendl;
1323
1324   // first sync log to flush out e.g. any cap imports
1325   mds->mdlog->wait_for_safe(new C_M_ExportGo(this, dir, export_state[dir].tid));
1326   mds->mdlog->flush();
1327 }
1328
1329 void Migrator::export_go_synced(CDir *dir, uint64_t tid)
1330 {
1331   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
1332   if (it == export_state.end() ||
1333       it->second.state == EXPORT_CANCELLING ||
1334       it->second.tid != tid) {
1335     // export must have aborted.  
1336     dout(7) << "export must have aborted on " << dir << dendl;
1337     return;
1338   }
1339   assert(it->second.state == EXPORT_WARNING);
1340   mds_rank_t dest = it->second.peer;
1341
1342   dout(7) << "export_go_synced " << *dir << " to " << dest << dendl;
1343
1344   cache->show_subtrees();
1345   
1346   it->second.state = EXPORT_EXPORTING;
1347   assert(g_conf->mds_kill_export_at != 7);
1348
1349   assert(dir->is_frozen_tree_root());
1350   assert(dir->get_cum_auth_pins() == 0);
1351
1352   // set ambiguous auth
1353   cache->adjust_subtree_auth(dir, mds->get_nodeid(), dest);
1354
1355   // take away the popularity we're sending.
1356   utime_t now = ceph_clock_now();
1357   mds->balancer->subtract_export(dir, now);
1358   
1359   // fill export message with cache data
1360   MExportDir *req = new MExportDir(dir->dirfrag(), it->second.tid);
1361   map<client_t,entity_inst_t> exported_client_map;
1362   uint64_t num_exported_inodes = encode_export_dir(req->export_data,
1363                                               dir,   // recur start point
1364                                               exported_client_map,
1365                                               now);
1366   ::encode(exported_client_map, req->client_map,
1367            mds->mdsmap->get_up_features());
1368
1369   // add bounds to message
1370   set<CDir*> bounds;
1371   cache->get_subtree_bounds(dir, bounds);
1372   for (set<CDir*>::iterator p = bounds.begin();
1373        p != bounds.end();
1374        ++p)
1375     req->add_export((*p)->dirfrag());
1376
1377   // send
1378   mds->send_message_mds(req, dest);
1379   assert(g_conf->mds_kill_export_at != 8);
1380
1381   mds->hit_export_target(now, dest, num_exported_inodes+1);
1382
1383   // stats
1384   if (mds->logger) mds->logger->inc(l_mds_exported);
1385   if (mds->logger) mds->logger->inc(l_mds_exported_inodes, num_exported_inodes);
1386
1387   cache->show_subtrees();
1388 }
1389
1390
1391 /** encode_export_inode
1392  * update our local state for this inode to export.
1393  * encode relevant state to be sent over the wire.
1394  * used by: encode_export_dir, file_rename (if foreign)
1395  *
1396  * FIXME: the separation between CInode.encode_export and these methods 
1397  * is pretty arbitrary and dumb.
1398  */
1399 void Migrator::encode_export_inode(CInode *in, bufferlist& enc_state, 
1400                                    map<client_t,entity_inst_t>& exported_client_map)
1401 {
1402   dout(7) << "encode_export_inode " << *in << dendl;
1403   assert(!in->is_replica(mds->get_nodeid()));
1404
1405   // relax locks?
1406   if (!in->is_replicated()) {
1407     in->replicate_relax_locks();
1408     dout(20) << " did replicate_relax_locks, now " << *in << dendl;
1409   }
1410
1411   ::encode(in->inode.ino, enc_state);
1412   ::encode(in->last, enc_state);
1413   in->encode_export(enc_state);
1414
1415   // caps 
1416   encode_export_inode_caps(in, true, enc_state, exported_client_map);
1417 }
1418
1419 void Migrator::encode_export_inode_caps(CInode *in, bool auth_cap, bufferlist& bl,
1420                                         map<client_t,entity_inst_t>& exported_client_map)
1421 {
1422   dout(20) << "encode_export_inode_caps " << *in << dendl;
1423
1424   // encode caps
1425   map<client_t,Capability::Export> cap_map;
1426   in->export_client_caps(cap_map);
1427   ::encode(cap_map, bl);
1428   if (auth_cap) {
1429     ::encode(in->get_mds_caps_wanted(), bl);
1430
1431     in->state_set(CInode::STATE_EXPORTINGCAPS);
1432     in->get(CInode::PIN_EXPORTINGCAPS);
1433   }
1434
1435   // make note of clients named by exported capabilities
1436   for (map<client_t, Capability*>::iterator it = in->client_caps.begin();
1437        it != in->client_caps.end();
1438        ++it) 
1439     exported_client_map[it->first] = mds->sessionmap.get_inst(entity_name_t::CLIENT(it->first.v));
1440 }
1441
1442 void Migrator::finish_export_inode_caps(CInode *in, mds_rank_t peer,
1443                                         map<client_t,Capability::Import>& peer_imported)
1444 {
1445   dout(20) << "finish_export_inode_caps " << *in << dendl;
1446
1447   in->state_clear(CInode::STATE_EXPORTINGCAPS);
1448   in->put(CInode::PIN_EXPORTINGCAPS);
1449
1450   // tell (all) clients about migrating caps.. 
1451   for (map<client_t, Capability*>::iterator it = in->client_caps.begin();
1452        it != in->client_caps.end();
1453        ++it) {
1454     Capability *cap = it->second;
1455     dout(7) << "finish_export_inode_caps telling client." << it->first
1456             << " exported caps on " << *in << dendl;
1457     MClientCaps *m = new MClientCaps(CEPH_CAP_OP_EXPORT, in->ino(), 0,
1458                                      cap->get_cap_id(), cap->get_mseq(), mds->get_osd_epoch_barrier());
1459
1460     map<client_t,Capability::Import>::iterator q = peer_imported.find(it->first);
1461     assert(q != peer_imported.end());
1462     m->set_cap_peer(q->second.cap_id, q->second.issue_seq, q->second.mseq, peer, 0);
1463     mds->send_message_client_counted(m, it->first);
1464   }
1465   in->clear_client_caps_after_export();
1466   mds->locker->eval(in, CEPH_CAP_LOCKS);
1467 }
1468
1469 void Migrator::finish_export_inode(CInode *in, utime_t now, mds_rank_t peer,
1470                                    map<client_t,Capability::Import>& peer_imported,
1471                                    list<MDSInternalContextBase*>& finished)
1472 {
1473   dout(12) << "finish_export_inode " << *in << dendl;
1474
1475   // clean
1476   if (in->is_dirty())
1477     in->mark_clean();
1478   
1479   // clear/unpin cached_by (we're no longer the authority)
1480   in->clear_replica_map();
1481   
1482   // twiddle lock states for auth -> replica transition
1483   in->authlock.export_twiddle();
1484   in->linklock.export_twiddle();
1485   in->dirfragtreelock.export_twiddle();
1486   in->filelock.export_twiddle();
1487   in->nestlock.export_twiddle();
1488   in->xattrlock.export_twiddle();
1489   in->snaplock.export_twiddle();
1490   in->flocklock.export_twiddle();
1491   in->policylock.export_twiddle();
1492   
1493   // mark auth
1494   assert(in->is_auth());
1495   in->state_clear(CInode::STATE_AUTH);
1496   in->replica_nonce = CInode::EXPORT_NONCE;
1497   
1498   in->clear_dirty_rstat();
1499
1500   // no more auth subtree? clear scatter dirty
1501   if (!in->has_subtree_root_dirfrag(mds->get_nodeid()))
1502     in->clear_scatter_dirty();
1503
1504   in->item_open_file.remove_myself();
1505
1506   in->clear_dirty_parent();
1507
1508   in->clear_file_locks();
1509
1510   // waiters
1511   in->take_waiting(CInode::WAIT_ANY_MASK, finished);
1512
1513   in->finish_export(now);
1514   
1515   finish_export_inode_caps(in, peer, peer_imported);
1516 }
1517
1518 uint64_t Migrator::encode_export_dir(bufferlist& exportbl,
1519                                 CDir *dir,
1520                                 map<client_t,entity_inst_t>& exported_client_map,
1521                                 utime_t now)
1522 {
1523   uint64_t num_exported = 0;
1524
1525   dout(7) << "encode_export_dir " << *dir << " " << dir->get_num_head_items() << " head items" << dendl;
1526   
1527   assert(dir->get_projected_version() == dir->get_version());
1528
1529 #ifdef MDS_VERIFY_FRAGSTAT
1530   if (dir->is_complete())
1531     dir->verify_fragstat();
1532 #endif
1533
1534   // dir 
1535   dirfrag_t df = dir->dirfrag();
1536   ::encode(df, exportbl);
1537   dir->encode_export(exportbl);
1538   
1539   __u32 nden = dir->items.size();
1540   ::encode(nden, exportbl);
1541   
1542   // dentries
1543   list<CDir*> subdirs;
1544   CDir::map_t::iterator it;
1545   for (it = dir->begin(); it != dir->end(); ++it) {
1546     CDentry *dn = it->second;
1547     CInode *in = dn->get_linkage()->get_inode();
1548     
1549     if (!dn->is_replicated())
1550       dn->lock.replicate_relax();
1551
1552     num_exported++;
1553     
1554     // -- dentry
1555     dout(7) << "encode_export_dir exporting " << *dn << dendl;
1556     
1557     // dn name
1558     ::encode(dn->name, exportbl);
1559     ::encode(dn->last, exportbl);
1560     
1561     // state
1562     dn->encode_export(exportbl);
1563     
1564     // points to...
1565     
1566     // null dentry?
1567     if (dn->get_linkage()->is_null()) {
1568       exportbl.append("N", 1);  // null dentry
1569       continue;
1570     }
1571     
1572     if (dn->get_linkage()->is_remote()) {
1573       // remote link
1574       exportbl.append("L", 1);  // remote link
1575       
1576       inodeno_t ino = dn->get_linkage()->get_remote_ino();
1577       unsigned char d_type = dn->get_linkage()->get_remote_d_type();
1578       ::encode(ino, exportbl);
1579       ::encode(d_type, exportbl);
1580       continue;
1581     }
1582
1583     // primary link
1584     // -- inode
1585     exportbl.append("I", 1);    // inode dentry
1586     
1587     encode_export_inode(in, exportbl, exported_client_map);  // encode, and (update state for) export
1588     
1589     // directory?
1590     list<CDir*> dfs;
1591     in->get_dirfrags(dfs);
1592     for (list<CDir*>::iterator p = dfs.begin(); p != dfs.end(); ++p) {
1593       CDir *t = *p;
1594       if (!t->state_test(CDir::STATE_EXPORTBOUND)) {
1595         // include nested dirfrag
1596         assert(t->get_dir_auth().first == CDIR_AUTH_PARENT);
1597         subdirs.push_back(t);  // it's ours, recurse (later)
1598       }
1599     }
1600   }
1601
1602   // subdirs
1603   for (list<CDir*>::iterator it = subdirs.begin(); it != subdirs.end(); ++it)
1604     num_exported += encode_export_dir(exportbl, *it, exported_client_map, now);
1605
1606   return num_exported;
1607 }
1608
1609 void Migrator::finish_export_dir(CDir *dir, utime_t now, mds_rank_t peer,
1610                                  map<inodeno_t,map<client_t,Capability::Import> >& peer_imported,
1611                                  list<MDSInternalContextBase*>& finished, int *num_dentries)
1612 {
1613   dout(10) << "finish_export_dir " << *dir << dendl;
1614
1615   // release open_by 
1616   dir->clear_replica_map();
1617
1618   // mark
1619   assert(dir->is_auth());
1620   dir->state_clear(CDir::STATE_AUTH);
1621   dir->remove_bloom();
1622   dir->replica_nonce = CDir::EXPORT_NONCE;
1623
1624   if (dir->is_dirty())
1625     dir->mark_clean();
1626
1627   // suck up all waiters
1628   dir->take_waiting(CDir::WAIT_ANY_MASK, finished);    // all dir waiters
1629   
1630   // pop
1631   dir->finish_export(now);
1632
1633   // dentries
1634   list<CDir*> subdirs;
1635   CDir::map_t::iterator it;
1636   for (it = dir->begin(); it != dir->end(); ++it) {
1637     CDentry *dn = it->second;
1638     CInode *in = dn->get_linkage()->get_inode();
1639
1640     // dentry
1641     dn->finish_export();
1642
1643     // inode?
1644     if (dn->get_linkage()->is_primary()) {
1645       finish_export_inode(in, now, peer, peer_imported[in->ino()], finished);
1646
1647       // subdirs?
1648       in->get_nested_dirfrags(subdirs);
1649     }
1650
1651     cache->touch_dentry_bottom(dn); // move dentry to tail of LRU
1652     ++(*num_dentries);
1653   }
1654
1655   // subdirs
1656   for (list<CDir*>::iterator it = subdirs.begin(); it != subdirs.end(); ++it) 
1657     finish_export_dir(*it, now, peer, peer_imported, finished, num_dentries);
1658 }
1659
1660 class C_MDS_ExportFinishLogged : public MigratorLogContext {
1661   CDir *dir;
1662 public:
1663   C_MDS_ExportFinishLogged(Migrator *m, CDir *d) : MigratorLogContext(m), dir(d) {}
1664   void finish(int r) override {
1665     mig->export_logged_finish(dir);
1666   }
1667 };
1668
1669
1670 /*
1671  * i should get an export_ack from the export target.
1672  *
1673  * This function DOES put the passed message before returning
1674  */
1675 void Migrator::handle_export_ack(MExportDirAck *m)
1676 {
1677   CDir *dir = cache->get_dirfrag(m->get_dirfrag());
1678   mds_rank_t dest(m->get_source().num());
1679   utime_t now = ceph_clock_now();
1680   assert(dir);
1681   assert(dir->is_frozen_tree_root());  // i'm exporting!
1682
1683   // yay!
1684   dout(7) << "handle_export_ack " << *dir << dendl;
1685
1686   mds->hit_export_target(now, dest, -1);
1687
1688   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
1689   assert(it != export_state.end());
1690   assert(it->second.state == EXPORT_EXPORTING);
1691   assert(it->second.tid == m->get_tid());
1692
1693   bufferlist::iterator bp = m->imported_caps.begin();
1694   ::decode(it->second.peer_imported, bp);
1695
1696   it->second.state = EXPORT_LOGGINGFINISH;
1697   assert (g_conf->mds_kill_export_at != 9);
1698   set<CDir*> bounds;
1699   cache->get_subtree_bounds(dir, bounds);
1700
1701   // log completion. 
1702   //  include export bounds, to ensure they're in the journal.
1703   EExport *le = new EExport(mds->mdlog, dir, it->second.peer);;
1704   mds->mdlog->start_entry(le);
1705
1706   le->metablob.add_dir_context(dir, EMetaBlob::TO_ROOT);
1707   le->metablob.add_dir(dir, false);
1708   for (set<CDir*>::iterator p = bounds.begin();
1709        p != bounds.end();
1710        ++p) {
1711     CDir *bound = *p;
1712     le->get_bounds().insert(bound->dirfrag());
1713     le->metablob.add_dir_context(bound);
1714     le->metablob.add_dir(bound, false);
1715   }
1716
1717   // list us second, them first.
1718   // this keeps authority().first in sync with subtree auth state in the journal.
1719   cache->adjust_subtree_auth(dir, it->second.peer, mds->get_nodeid());
1720
1721   // log export completion, then finish (unfreeze, trigger finish context, etc.)
1722   mds->mdlog->submit_entry(le, new C_MDS_ExportFinishLogged(this, dir));
1723   mds->mdlog->flush();
1724   assert (g_conf->mds_kill_export_at != 10);
1725   
1726   m->put();
1727 }
1728
1729 void Migrator::export_notify_abort(CDir *dir, set<CDir*>& bounds)
1730 {
1731   dout(7) << "export_notify_abort " << *dir << dendl;
1732
1733   export_state_t& stat = export_state[dir];
1734   assert(stat.state == EXPORT_CANCELLING);
1735
1736   if (stat.notify_ack_waiting.empty()) {
1737     stat.state = EXPORT_CANCELLED;
1738     return;
1739   }
1740
1741   dir->auth_pin(this);
1742
1743   for (set<mds_rank_t>::iterator p = stat.notify_ack_waiting.begin();
1744        p != stat.notify_ack_waiting.end();
1745        ++p) {
1746     MExportDirNotify *notify = new MExportDirNotify(dir->dirfrag(),stat.tid, true,
1747                                                     pair<int,int>(mds->get_nodeid(),stat.peer),
1748                                                     pair<int,int>(mds->get_nodeid(),CDIR_AUTH_UNKNOWN));
1749     for (set<CDir*>::iterator i = bounds.begin(); i != bounds.end(); ++i)
1750       notify->get_bounds().push_back((*i)->dirfrag());
1751     mds->send_message_mds(notify, *p);
1752   }
1753 }
1754
1755 /*
1756  * this happens if hte dest failes after i send teh export data but before it is acked
1757  * that is, we don't know they safely received and logged it, so we reverse our changes
1758  * and go on.
1759  */
1760 void Migrator::export_reverse(CDir *dir)
1761 {
1762   dout(7) << "export_reverse " << *dir << dendl;
1763
1764   set<CInode*> to_eval;
1765
1766   set<CDir*> bounds;
1767   cache->get_subtree_bounds(dir, bounds);
1768
1769   // remove exporting pins
1770   list<CDir*> rq;
1771   rq.push_back(dir);
1772   while (!rq.empty()) {
1773     CDir *t = rq.front(); 
1774     rq.pop_front();
1775     t->abort_export();
1776     for (CDir::map_t::iterator p = t->items.begin(); p != t->items.end(); ++p) {
1777       p->second->abort_export();
1778       if (!p->second->get_linkage()->is_primary())
1779         continue;
1780       CInode *in = p->second->get_linkage()->get_inode();
1781       in->abort_export();
1782       if (in->state_test(CInode::STATE_EVALSTALECAPS)) {
1783         in->state_clear(CInode::STATE_EVALSTALECAPS);
1784         to_eval.insert(in);
1785       }
1786       if (in->is_dir())
1787         in->get_nested_dirfrags(rq);
1788     }
1789   }
1790   
1791   // unpin bounds
1792   for (const auto &bd : bounds) {
1793     bd->put(CDir::PIN_EXPORTBOUND);
1794     bd->state_clear(CDir::STATE_EXPORTBOUND);
1795   }
1796
1797   // notify bystanders
1798   export_notify_abort(dir, bounds);
1799
1800   // unfreeze tree, with possible subtree merge.
1801   cache->adjust_subtree_auth(dir, mds->get_nodeid(), mds->get_nodeid());
1802
1803   // process delayed expires
1804   cache->process_delayed_expire(dir);
1805
1806   dir->unfreeze_tree();
1807   cache->try_subtree_merge(dir);
1808
1809   // revoke/resume stale caps
1810   for (auto in : to_eval) {
1811     bool need_issue = false;
1812     for (auto& p : in->get_client_caps()) {
1813       Capability *cap = p.second;
1814       if (cap->is_stale()) {
1815         mds->locker->revoke_stale_caps(cap);
1816       } else {
1817         need_issue = true;
1818       }
1819     }
1820     if (need_issue &&
1821         (!in->is_auth() || !mds->locker->eval(in, CEPH_CAP_LOCKS)))
1822       mds->locker->issue_caps(in);
1823   }
1824
1825   cache->show_cache();
1826 }
1827
1828
1829 /*
1830  * once i get the ack, and logged the EExportFinish(true),
1831  * send notifies (if any), otherwise go straight to finish.
1832  * 
1833  */
1834 void Migrator::export_logged_finish(CDir *dir)
1835 {
1836   dout(7) << "export_logged_finish " << *dir << dendl;
1837
1838   export_state_t& stat = export_state[dir];
1839
1840   // send notifies
1841   set<CDir*> bounds;
1842   cache->get_subtree_bounds(dir, bounds);
1843
1844   for (set<mds_rank_t>::iterator p = stat.notify_ack_waiting.begin();
1845        p != stat.notify_ack_waiting.end();
1846        ++p) {
1847     MExportDirNotify *notify = new MExportDirNotify(dir->dirfrag(), stat.tid, true,
1848                                                     pair<int,int>(mds->get_nodeid(), stat.peer),
1849                                                     pair<int,int>(stat.peer, CDIR_AUTH_UNKNOWN));
1850
1851     for (set<CDir*>::iterator i = bounds.begin(); i != bounds.end(); ++i)
1852       notify->get_bounds().push_back((*i)->dirfrag());
1853     
1854     mds->send_message_mds(notify, *p);
1855   }
1856
1857   // wait for notifyacks
1858   stat.state = EXPORT_NOTIFYING;
1859   assert (g_conf->mds_kill_export_at != 11);
1860   
1861   // no notifies to wait for?
1862   if (stat.notify_ack_waiting.empty()) {
1863     export_finish(dir);  // skip notify/notify_ack stage.
1864   } else {
1865     // notify peer to send cap import messages to clients
1866     if (!mds->is_cluster_degraded() ||
1867         mds->mdsmap->is_clientreplay_or_active_or_stopping(stat.peer)) {
1868       mds->send_message_mds(new MExportDirFinish(dir->dirfrag(), false, stat.tid), stat.peer);
1869     } else {
1870       dout(7) << "not sending MExportDirFinish, dest has failed" << dendl;
1871     }
1872   }
1873 }
1874
1875 /*
1876  * warning:
1877  *  i'll get an ack from each bystander.
1878  *  when i get them all, do the export.
1879  * notify:
1880  *  i'll get an ack from each bystander.
1881  *  when i get them all, unfreeze and send the finish.
1882  *
1883  * This function DOES put the passed message before returning
1884  */
1885 void Migrator::handle_export_notify_ack(MExportDirNotifyAck *m)
1886 {
1887   CDir *dir = cache->get_dirfrag(m->get_dirfrag());
1888   mds_rank_t dest(m->get_source().num());
1889   utime_t now = ceph_clock_now();
1890   assert(dir);
1891   mds_rank_t from = mds_rank_t(m->get_source().num());
1892
1893   mds->hit_export_target(now, dest, -1);
1894
1895   auto export_state_entry = export_state.find(dir);
1896   if (export_state_entry != export_state.end()) {
1897     export_state_t& stat = export_state_entry->second;
1898     if (stat.state == EXPORT_WARNING &&
1899         stat.warning_ack_waiting.erase(from)) {
1900       // exporting. process warning.
1901       dout(7) << "handle_export_notify_ack from " << m->get_source()
1902               << ": exporting, processing warning on " << *dir << dendl;
1903       if (stat.warning_ack_waiting.empty())
1904         export_go(dir);     // start export.
1905     } else if (stat.state == EXPORT_NOTIFYING &&
1906                stat.notify_ack_waiting.erase(from)) {
1907       // exporting. process notify.
1908       dout(7) << "handle_export_notify_ack from " << m->get_source()
1909               << ": exporting, processing notify on " << *dir << dendl;
1910       if (stat.notify_ack_waiting.empty())
1911         export_finish(dir);
1912     } else if (stat.state == EXPORT_CANCELLING &&
1913                m->get_new_auth().second == CDIR_AUTH_UNKNOWN && // not warning ack
1914                stat.notify_ack_waiting.erase(from)) {
1915       dout(7) << "handle_export_notify_ack from " << m->get_source()
1916               << ": cancelling export, processing notify on " << *dir << dendl;
1917       if (stat.notify_ack_waiting.empty()) {
1918         export_state.erase(export_state_entry);
1919         export_cancel_finish(dir);
1920       }
1921     }
1922   }
1923   else {
1924     auto import_state_entry = import_state.find(dir->dirfrag());
1925     if (import_state_entry != import_state.end()) {
1926       import_state_t& stat = import_state_entry->second;
1927       if (stat.state == IMPORT_ABORTING) {
1928         // reversing import
1929         dout(7) << "handle_export_notify_ack from " << m->get_source()
1930           << ": aborting import on " << *dir << dendl;
1931         assert(stat.bystanders.count(from));
1932         stat.bystanders.erase(from);
1933         if (stat.bystanders.empty())
1934           import_reverse_unfreeze(dir);
1935       }
1936     }
1937   }
1938
1939   m->put();
1940 }
1941
1942 void Migrator::export_finish(CDir *dir)
1943 {
1944   dout(5) << "export_finish " << *dir << dendl;
1945
1946   assert (g_conf->mds_kill_export_at != 12);
1947   map<CDir*,export_state_t>::iterator it = export_state.find(dir);
1948   if (it == export_state.end()) {
1949     dout(7) << "target must have failed, not sending final commit message.  export succeeded anyway." << dendl;
1950     return;
1951   }
1952
1953   // send finish/commit to new auth
1954   if (!mds->is_cluster_degraded() ||
1955       mds->mdsmap->is_clientreplay_or_active_or_stopping(it->second.peer)) {
1956     mds->send_message_mds(new MExportDirFinish(dir->dirfrag(), true, it->second.tid), it->second.peer);
1957   } else {
1958     dout(7) << "not sending MExportDirFinish last, dest has failed" << dendl;
1959   }
1960   assert(g_conf->mds_kill_export_at != 13);
1961   
1962   // finish export (adjust local cache state)
1963   int num_dentries = 0;
1964   list<MDSInternalContextBase*> finished;
1965   finish_export_dir(dir, ceph_clock_now(), it->second.peer,
1966                     it->second.peer_imported, finished, &num_dentries);
1967
1968   assert(!dir->is_auth());
1969   cache->adjust_subtree_auth(dir, it->second.peer);
1970
1971   // unpin bounds
1972   set<CDir*> bounds;
1973   cache->get_subtree_bounds(dir, bounds);
1974   for (set<CDir*>::iterator p = bounds.begin();
1975        p != bounds.end();
1976        ++p) {
1977     CDir *bd = *p;
1978     bd->put(CDir::PIN_EXPORTBOUND);
1979     bd->state_clear(CDir::STATE_EXPORTBOUND);
1980   }
1981
1982   if (dir->state_test(CDir::STATE_AUXSUBTREE))
1983     dir->state_clear(CDir::STATE_AUXSUBTREE);
1984
1985   // discard delayed expires
1986   cache->discard_delayed_expire(dir);
1987
1988   dout(7) << "export_finish unfreezing" << dendl;
1989
1990   // unfreeze tree, with possible subtree merge.
1991   //  (we do this _after_ removing EXPORTBOUND pins, to allow merges)
1992   dir->unfreeze_tree();
1993   cache->try_subtree_merge(dir);
1994
1995   // no more auth subtree? clear scatter dirty
1996   if (!dir->get_inode()->is_auth() &&
1997       !dir->get_inode()->has_subtree_root_dirfrag(mds->get_nodeid())) {
1998     dir->get_inode()->clear_scatter_dirty();
1999     // wake up scatter_nudge waiters
2000     dir->get_inode()->take_waiting(CInode::WAIT_ANY_MASK, finished);
2001   }
2002
2003   if (!finished.empty())
2004     mds->queue_waiters(finished);
2005
2006   MutationRef mut = it->second.mut;
2007   // remove from exporting list, clean up state
2008   export_state.erase(it);
2009   dir->state_clear(CDir::STATE_EXPORTING);
2010
2011   cache->show_subtrees();
2012   audit();
2013
2014   cache->trim(num_dentries); // try trimming exported dentries
2015
2016   // send pending import_maps?
2017   mds->mdcache->maybe_send_pending_resolves();
2018
2019   // drop locks, unpin path
2020   if (mut) {
2021     mds->locker->drop_locks(mut.get());
2022     mut->cleanup();
2023   }
2024   
2025   maybe_do_queued_export();
2026 }
2027
2028
2029
2030
2031
2032
2033
2034
2035 // ==========================================================
2036 // IMPORT
2037
2038 void Migrator::handle_export_discover(MExportDirDiscover *m)
2039 {
2040   mds_rank_t from = m->get_source_mds();
2041   assert(from != mds->get_nodeid());
2042
2043   dout(7) << "handle_export_discover on " << m->get_path() << dendl;
2044
2045   // note import state
2046   dirfrag_t df = m->get_dirfrag();
2047
2048   if (!mds->is_active()) {
2049     dout(7) << " not active, send NACK " << dendl;
2050     mds->send_message_mds(new MExportDirDiscoverAck(df, m->get_tid(), false), from);
2051     m->put();
2052     return;
2053   }
2054
2055   // only start discovering on this message once.
2056   map<dirfrag_t,import_state_t>::iterator it = import_state.find(df);
2057   if (!m->started) {
2058     assert(it == import_state.end());
2059     m->started = true;
2060     import_state[df].state = IMPORT_DISCOVERING;
2061     import_state[df].peer = from;
2062     import_state[df].tid = m->get_tid();
2063   } else {
2064     // am i retrying after ancient path_traverse results?
2065     if (it == import_state.end() ||
2066         it->second.peer != from ||
2067         it->second.tid != m->get_tid()) {
2068       dout(7) << " dropping obsolete message" << dendl;
2069       m->put();
2070       return;
2071     }
2072     assert(it->second.state == IMPORT_DISCOVERING);
2073   }
2074
2075   if (!mds->mdcache->is_open()) {
2076     dout(5) << " waiting for root" << dendl;
2077     mds->mdcache->wait_for_open(new C_MDS_RetryMessage(mds, m));
2078     return;
2079   }
2080
2081   assert (g_conf->mds_kill_import_at != 1);
2082
2083   // do we have it?
2084   CInode *in = cache->get_inode(m->get_dirfrag().ino);
2085   if (!in) {
2086     // must discover it!
2087     filepath fpath(m->get_path());
2088     vector<CDentry*> trace;
2089     MDRequestRef null_ref;
2090     int r = cache->path_traverse(null_ref, m, NULL, fpath, &trace, NULL, MDS_TRAVERSE_DISCOVER);
2091     if (r > 0) return;
2092     if (r < 0) {
2093       dout(7) << "handle_export_discover_2 failed to discover or not dir " << m->get_path() << ", NAK" << dendl;
2094       ceph_abort();    // this shouldn't happen if the auth pins its path properly!!!!
2095     }
2096
2097     ceph_abort(); // this shouldn't happen; the get_inode above would have succeeded.
2098   }
2099
2100   // yay
2101   dout(7) << "handle_export_discover have " << df << " inode " << *in << dendl;
2102   
2103   import_state[df].state = IMPORT_DISCOVERED;
2104
2105   // pin inode in the cache (for now)
2106   assert(in->is_dir());
2107   in->get(CInode::PIN_IMPORTING);
2108
2109   // reply
2110   dout(7) << " sending export_discover_ack on " << *in << dendl;
2111   mds->send_message_mds(new MExportDirDiscoverAck(df, m->get_tid()), import_state[df].peer);
2112   m->put();
2113   assert (g_conf->mds_kill_import_at != 2);  
2114 }
2115
2116 void Migrator::import_reverse_discovering(dirfrag_t df)
2117 {
2118   import_state.erase(df);
2119 }
2120
2121 void Migrator::import_reverse_discovered(dirfrag_t df, CInode *diri)
2122 {
2123   // unpin base
2124   diri->put(CInode::PIN_IMPORTING);
2125   import_state.erase(df);
2126 }
2127
2128 void Migrator::import_reverse_prepping(CDir *dir)
2129 {
2130   set<CDir*> bounds;
2131   cache->map_dirfrag_set(import_state[dir->dirfrag()].bound_ls, bounds);
2132   import_remove_pins(dir, bounds);
2133   import_reverse_final(dir);
2134 }
2135
2136 /* This function DOES put the passed message before returning*/
2137 void Migrator::handle_export_cancel(MExportDirCancel *m)
2138 {
2139   dout(7) << "handle_export_cancel on " << m->get_dirfrag() << dendl;
2140   dirfrag_t df = m->get_dirfrag();
2141   map<dirfrag_t,import_state_t>::iterator it = import_state.find(df);
2142   if (it == import_state.end()) {
2143     assert(0 == "got export_cancel in weird state");
2144   } else if (it->second.state == IMPORT_DISCOVERING) {
2145     import_reverse_discovering(df);
2146   } else if (it->second.state == IMPORT_DISCOVERED) {
2147     CInode *in = cache->get_inode(df.ino);
2148     assert(in);
2149     import_reverse_discovered(df, in);
2150   } else if (it->second.state == IMPORT_PREPPING) {
2151     CDir *dir = mds->mdcache->get_dirfrag(df);
2152     assert(dir);
2153     import_reverse_prepping(dir);
2154   } else if (it->second.state == IMPORT_PREPPED) {
2155     CDir *dir = mds->mdcache->get_dirfrag(df);
2156     assert(dir);
2157     set<CDir*> bounds;
2158     cache->get_subtree_bounds(dir, bounds);
2159     import_remove_pins(dir, bounds);
2160     // adjust auth back to the exportor
2161     cache->adjust_subtree_auth(dir, it->second.peer);
2162     import_reverse_unfreeze(dir);
2163   } else {
2164     assert(0 == "got export_cancel in weird state");
2165   }
2166   m->put();
2167 }
2168
2169 /* This function DOES put the passed message before returning*/
2170 void Migrator::handle_export_prep(MExportDirPrep *m)
2171 {
2172   mds_rank_t oldauth = mds_rank_t(m->get_source().num());
2173   assert(oldauth != mds->get_nodeid());
2174
2175   CDir *dir;
2176   CInode *diri;
2177   list<MDSInternalContextBase*> finished;
2178
2179   // assimilate root dir.
2180   map<dirfrag_t,import_state_t>::iterator it = import_state.find(m->get_dirfrag());
2181   if (!m->did_assim()) {
2182     assert(it != import_state.end());
2183     assert(it->second.state == IMPORT_DISCOVERED);
2184     assert(it->second.peer == oldauth);
2185     diri = cache->get_inode(m->get_dirfrag().ino);
2186     assert(diri);
2187     bufferlist::iterator p = m->basedir.begin();
2188     dir = cache->add_replica_dir(p, diri, oldauth, finished);
2189     dout(7) << "handle_export_prep on " << *dir << " (first pass)" << dendl;
2190   } else {
2191     if (it == import_state.end() ||
2192         it->second.peer != oldauth ||
2193         it->second.tid != m->get_tid()) {
2194       dout(7) << "handle_export_prep obsolete message, dropping" << dendl;
2195       m->put();
2196       return;
2197     }
2198     assert(it->second.state == IMPORT_PREPPING);
2199     assert(it->second.peer == oldauth);
2200
2201     dir = cache->get_dirfrag(m->get_dirfrag());
2202     assert(dir);
2203     dout(7) << "handle_export_prep on " << *dir << " (subsequent pass)" << dendl;
2204     diri = dir->get_inode();
2205   }
2206   assert(dir->is_auth() == false);
2207
2208   cache->show_subtrees();
2209
2210   // build import bound map
2211   map<inodeno_t, fragset_t> import_bound_fragset;
2212   for (list<dirfrag_t>::iterator p = m->get_bounds().begin();
2213        p != m->get_bounds().end();
2214        ++p) {
2215     dout(10) << " bound " << *p << dendl;
2216     import_bound_fragset[p->ino].insert(p->frag);
2217   }
2218
2219   // assimilate contents?
2220   if (!m->did_assim()) {
2221     dout(7) << "doing assim on " << *dir << dendl;
2222     m->mark_assim();  // only do this the first time!
2223
2224     // change import state
2225     it->second.state = IMPORT_PREPPING;
2226     it->second.bound_ls = m->get_bounds();
2227     it->second.bystanders = m->get_bystanders();
2228     assert(g_conf->mds_kill_import_at != 3);
2229
2230     // bystander list
2231     dout(7) << "bystanders are " << it->second.bystanders << dendl;
2232
2233     // move pin to dir
2234     diri->put(CInode::PIN_IMPORTING);
2235     dir->get(CDir::PIN_IMPORTING);  
2236     dir->state_set(CDir::STATE_IMPORTING);
2237
2238     // assimilate traces to exports
2239     // each trace is: df ('-' | ('f' dir | 'd') dentry inode (dir dentry inode)*)
2240     for (list<bufferlist>::iterator p = m->traces.begin();
2241          p != m->traces.end();
2242          ++p) {
2243       bufferlist::iterator q = p->begin();
2244       dirfrag_t df;
2245       ::decode(df, q);
2246       char start;
2247       ::decode(start, q);
2248       dout(10) << " trace from " << df << " start " << start << " len " << p->length() << dendl;
2249
2250       CDir *cur = 0;
2251       if (start == 'd') {
2252         cur = cache->get_dirfrag(df);
2253         assert(cur);
2254         dout(10) << "  had " << *cur << dendl;
2255       } else if (start == 'f') {
2256         CInode *in = cache->get_inode(df.ino);
2257         assert(in);
2258         dout(10) << "  had " << *in << dendl;
2259         cur = cache->add_replica_dir(q, in, oldauth, finished);
2260         dout(10) << "  added " << *cur << dendl;
2261       } else if (start == '-') {
2262         // nothing
2263       } else
2264         assert(0 == "unrecognized start char");
2265
2266       while (start != '-') {
2267         CDentry *dn = cache->add_replica_dentry(q, cur, finished);
2268         dout(10) << "  added " << *dn << dendl;
2269         CInode *in = cache->add_replica_inode(q, dn, finished);
2270         dout(10) << "  added " << *in << dendl;
2271         if (q.end())
2272           break;
2273         cur = cache->add_replica_dir(q, in, oldauth, finished);
2274         dout(10) << "  added " << *cur << dendl;
2275       }
2276     }
2277
2278     // make bound sticky
2279     for (map<inodeno_t,fragset_t>::iterator p = import_bound_fragset.begin();
2280          p != import_bound_fragset.end();
2281          ++p) {
2282       CInode *in = cache->get_inode(p->first);
2283       assert(in);
2284       in->get_stickydirs();
2285       dout(7) << " set stickydirs on bound inode " << *in << dendl;
2286     }
2287
2288   } else {
2289     dout(7) << " not doing assim on " << *dir << dendl;
2290   }
2291
2292   if (!finished.empty())
2293     mds->queue_waiters(finished);
2294
2295
2296   bool success = true;
2297   if (mds->is_active()) {
2298     // open all bounds
2299     set<CDir*> import_bounds;
2300     for (map<inodeno_t,fragset_t>::iterator p = import_bound_fragset.begin();
2301          p != import_bound_fragset.end();
2302          ++p) {
2303       CInode *in = cache->get_inode(p->first);
2304       assert(in);
2305
2306       // map fragset into a frag_t list, based on the inode fragtree
2307       list<frag_t> fglist;
2308       for (set<frag_t>::iterator q = p->second.begin(); q != p->second.end(); ++q)
2309         in->dirfragtree.get_leaves_under(*q, fglist);
2310       dout(10) << " bound inode " << p->first << " fragset " << p->second << " maps to " << fglist << dendl;
2311
2312       for (list<frag_t>::iterator q = fglist.begin();
2313            q != fglist.end();
2314            ++q) {
2315         CDir *bound = cache->get_dirfrag(dirfrag_t(p->first, *q));
2316         if (!bound) {
2317           dout(7) << "  opening bounding dirfrag " << *q << " on " << *in << dendl;
2318           cache->open_remote_dirfrag(in, *q,
2319               new C_MDS_RetryMessage(mds, m));
2320           return;
2321         }
2322
2323         if (!bound->state_test(CDir::STATE_IMPORTBOUND)) {
2324           dout(7) << "  pinning import bound " << *bound << dendl;
2325           bound->get(CDir::PIN_IMPORTBOUND);
2326           bound->state_set(CDir::STATE_IMPORTBOUND);
2327         } else {
2328           dout(7) << "  already pinned import bound " << *bound << dendl;
2329         }
2330         import_bounds.insert(bound);
2331       }
2332     }
2333
2334     dout(7) << " all ready, noting auth and freezing import region" << dendl;
2335
2336     if (!mds->mdcache->is_readonly() &&
2337         dir->get_inode()->filelock.can_wrlock(-1) &&
2338         dir->get_inode()->nestlock.can_wrlock(-1)) {
2339       it->second.mut = new MutationImpl();
2340       // force some locks.  hacky.
2341       mds->locker->wrlock_force(&dir->inode->filelock, it->second.mut);
2342       mds->locker->wrlock_force(&dir->inode->nestlock, it->second.mut);
2343
2344       // note that i am an ambiguous auth for this subtree.
2345       // specify bounds, since the exporter explicitly defines the region.
2346       cache->adjust_bounded_subtree_auth(dir, import_bounds,
2347                                          pair<int,int>(oldauth, mds->get_nodeid()));
2348       cache->verify_subtree_bounds(dir, import_bounds);
2349       // freeze.
2350       dir->_freeze_tree();
2351       // note new state
2352       it->second.state = IMPORT_PREPPED;
2353     } else {
2354       dout(7) << " couldn't acquire all needed locks, failing. " << *dir << dendl;
2355       success = false;
2356     }
2357   } else {
2358     dout(7) << " not active, failing. " << *dir << dendl;
2359     success = false;
2360   }
2361
2362   if (!success)
2363     import_reverse_prepping(dir);
2364
2365   // ok!
2366   dout(7) << " sending export_prep_ack on " << *dir << dendl;
2367   mds->send_message(new MExportDirPrepAck(dir->dirfrag(), success, m->get_tid()), m->get_connection());
2368
2369   assert(g_conf->mds_kill_import_at != 4);
2370   // done 
2371   m->put();
2372 }
2373
2374
2375
2376
2377 class C_MDS_ImportDirLoggedStart : public MigratorLogContext {
2378   dirfrag_t df;
2379   CDir *dir;
2380   mds_rank_t from;
2381 public:
2382   map<client_t,entity_inst_t> imported_client_map;
2383   map<client_t,uint64_t> sseqmap;
2384
2385   C_MDS_ImportDirLoggedStart(Migrator *m, CDir *d, mds_rank_t f) :
2386     MigratorLogContext(m), df(d->dirfrag()), dir(d), from(f) {
2387   }
2388   void finish(int r) override {
2389     mig->import_logged_start(df, dir, from, imported_client_map, sseqmap);
2390   }
2391 };
2392
2393 /* This function DOES put the passed message before returning*/
2394 void Migrator::handle_export_dir(MExportDir *m)
2395 {
2396   assert (g_conf->mds_kill_import_at != 5);
2397   CDir *dir = cache->get_dirfrag(m->dirfrag);
2398   assert(dir);
2399
2400   mds_rank_t oldauth = mds_rank_t(m->get_source().num());
2401   dout(7) << "handle_export_dir importing " << *dir << " from " << oldauth << dendl;
2402
2403   assert(!dir->is_auth());
2404   
2405   map<dirfrag_t,import_state_t>::iterator it = import_state.find(m->dirfrag);
2406   assert(it != import_state.end());
2407   assert(it->second.state == IMPORT_PREPPED);
2408   assert(it->second.tid == m->get_tid());
2409   assert(it->second.peer == oldauth);
2410
2411   utime_t now = ceph_clock_now();
2412
2413   if (!dir->get_inode()->dirfragtree.is_leaf(dir->get_frag()))
2414     dir->get_inode()->dirfragtree.force_to_leaf(g_ceph_context, dir->get_frag());
2415
2416   cache->show_subtrees();
2417
2418   C_MDS_ImportDirLoggedStart *onlogged = new C_MDS_ImportDirLoggedStart(this, dir, oldauth);
2419
2420   // start the journal entry
2421   EImportStart *le = new EImportStart(mds->mdlog, dir->dirfrag(), m->bounds, oldauth);
2422   mds->mdlog->start_entry(le);
2423
2424   le->metablob.add_dir_context(dir);
2425   
2426   // adjust auth (list us _first_)
2427   cache->adjust_subtree_auth(dir, mds->get_nodeid(), oldauth);
2428
2429   // new client sessions, open these after we journal
2430   // include imported sessions in EImportStart
2431   bufferlist::iterator cmp = m->client_map.begin();
2432   ::decode(onlogged->imported_client_map, cmp);
2433   assert(cmp.end());
2434   le->cmapv = mds->server->prepare_force_open_sessions(onlogged->imported_client_map, onlogged->sseqmap);
2435   le->client_map.claim(m->client_map);
2436
2437   bufferlist::iterator blp = m->export_data.begin();
2438   int num_imported_inodes = 0;
2439   while (!blp.end()) {
2440     num_imported_inodes += 
2441       decode_import_dir(blp,
2442                         oldauth, 
2443                         dir,                 // import root
2444                         le,
2445                         mds->mdlog->get_current_segment(),
2446                         it->second.peer_exports,
2447                         it->second.updated_scatterlocks,
2448                         now);
2449   }
2450   dout(10) << " " << m->bounds.size() << " imported bounds" << dendl;
2451   
2452   // include bounds in EImportStart
2453   set<CDir*> import_bounds;
2454   for (vector<dirfrag_t>::iterator p = m->bounds.begin();
2455        p != m->bounds.end();
2456        ++p) {
2457     CDir *bd = cache->get_dirfrag(*p);
2458     assert(bd);
2459     le->metablob.add_dir(bd, false);  // note that parent metadata is already in the event
2460     import_bounds.insert(bd);
2461   }
2462   cache->verify_subtree_bounds(dir, import_bounds);
2463
2464   // adjust popularity
2465   mds->balancer->add_import(dir, now);
2466
2467   dout(7) << "handle_export_dir did " << *dir << dendl;
2468
2469   // note state
2470   it->second.state = IMPORT_LOGGINGSTART;
2471   assert (g_conf->mds_kill_import_at != 6);
2472
2473   // log it
2474   mds->mdlog->submit_entry(le, onlogged);
2475   mds->mdlog->flush();
2476
2477   // some stats
2478   if (mds->logger) {
2479     mds->logger->inc(l_mds_imported);
2480     mds->logger->inc(l_mds_imported_inodes, num_imported_inodes);
2481   }
2482
2483   m->put();
2484 }
2485
2486
2487 /*
2488  * this is an import helper
2489  *  called by import_finish, and import_reverse and friends.
2490  */
2491 void Migrator::import_remove_pins(CDir *dir, set<CDir*>& bounds)
2492 {
2493   import_state_t& stat = import_state[dir->dirfrag()];
2494   // root
2495   dir->put(CDir::PIN_IMPORTING);
2496   dir->state_clear(CDir::STATE_IMPORTING);
2497
2498   // bounding inodes
2499   set<inodeno_t> did;
2500   for (list<dirfrag_t>::iterator p = stat.bound_ls.begin();
2501        p != stat.bound_ls.end();
2502        ++p) {
2503     if (did.count(p->ino))
2504       continue;
2505     did.insert(p->ino);
2506     CInode *in = cache->get_inode(p->ino);
2507     assert(in);
2508     in->put_stickydirs();
2509   }
2510
2511   if (stat.state == IMPORT_PREPPING) {
2512     for (auto bd : bounds) {
2513       if (bd->state_test(CDir::STATE_IMPORTBOUND)) {
2514         bd->put(CDir::PIN_IMPORTBOUND);
2515         bd->state_clear(CDir::STATE_IMPORTBOUND);
2516       }
2517     }
2518   } else if (stat.state >= IMPORT_PREPPED) {
2519     // bounding dirfrags
2520     for (auto bd : bounds) {
2521       assert(bd->state_test(CDir::STATE_IMPORTBOUND));
2522       bd->put(CDir::PIN_IMPORTBOUND);
2523       bd->state_clear(CDir::STATE_IMPORTBOUND);
2524     }
2525   }
2526 }
2527
2528
2529 /*
2530  * note: this does teh full work of reversing and import and cleaning up
2531  *  state.  
2532  * called by both handle_mds_failure and by handle_resolve (if we are
2533  *  a survivor coping with an exporter failure+recovery).
2534  */
2535 void Migrator::import_reverse(CDir *dir)
2536 {
2537   dout(7) << "import_reverse " << *dir << dendl;
2538
2539   import_state_t& stat = import_state[dir->dirfrag()];
2540   stat.state = IMPORT_ABORTING;
2541
2542   set<CDir*> bounds;
2543   cache->get_subtree_bounds(dir, bounds);
2544
2545   // remove pins
2546   import_remove_pins(dir, bounds);
2547
2548   // update auth, with possible subtree merge.
2549   assert(dir->is_subtree_root());
2550   if (mds->is_resolve())
2551     cache->trim_non_auth_subtree(dir);
2552
2553   cache->adjust_subtree_auth(dir, stat.peer);
2554
2555   C_ContextsBase<MDSInternalContextBase, MDSInternalContextGather> *fin = new C_ContextsBase<MDSInternalContextBase, MDSInternalContextGather>(g_ceph_context);
2556   if (!dir->get_inode()->is_auth() &&
2557       !dir->get_inode()->has_subtree_root_dirfrag(mds->get_nodeid())) {
2558     dir->get_inode()->clear_scatter_dirty();
2559     // wake up scatter_nudge waiters
2560     dir->get_inode()->take_waiting(CInode::WAIT_ANY_MASK, fin->contexts);
2561   }
2562
2563   int num_dentries = 0;
2564   // adjust auth bits.
2565   list<CDir*> q;
2566   q.push_back(dir);
2567   while (!q.empty()) {
2568     CDir *cur = q.front();
2569     q.pop_front();
2570     
2571     // dir
2572     assert(cur->is_auth());
2573     cur->state_clear(CDir::STATE_AUTH);
2574     cur->remove_bloom();
2575     cur->clear_replica_map();
2576     cur->set_replica_nonce(CDir::EXPORT_NONCE);
2577     if (cur->is_dirty())
2578       cur->mark_clean();
2579
2580     CDir::map_t::iterator it;
2581     for (it = cur->begin(); it != cur->end(); ++it) {
2582       CDentry *dn = it->second;
2583
2584       // dentry
2585       dn->state_clear(CDentry::STATE_AUTH);
2586       dn->clear_replica_map();
2587       dn->set_replica_nonce(CDentry::EXPORT_NONCE);
2588       if (dn->is_dirty()) 
2589         dn->mark_clean();
2590
2591       // inode?
2592       if (dn->get_linkage()->is_primary()) {
2593         CInode *in = dn->get_linkage()->get_inode();
2594         in->state_clear(CDentry::STATE_AUTH);
2595         in->clear_replica_map();
2596         in->set_replica_nonce(CInode::EXPORT_NONCE);
2597         if (in->is_dirty()) 
2598           in->mark_clean();
2599         in->clear_dirty_rstat();
2600         if (!in->has_subtree_root_dirfrag(mds->get_nodeid())) {
2601           in->clear_scatter_dirty();
2602           in->take_waiting(CInode::WAIT_ANY_MASK, fin->contexts);
2603         }
2604
2605         in->clear_dirty_parent();
2606
2607         in->authlock.clear_gather();
2608         in->linklock.clear_gather();
2609         in->dirfragtreelock.clear_gather();
2610         in->filelock.clear_gather();
2611
2612         in->clear_file_locks();
2613
2614         // non-bounding dir?
2615         list<CDir*> dfs;
2616         in->get_dirfrags(dfs);
2617         for (list<CDir*>::iterator p = dfs.begin(); p != dfs.end(); ++p)
2618           if (bounds.count(*p) == 0)
2619             q.push_back(*p);
2620       }
2621
2622       cache->touch_dentry_bottom(dn); // move dentry to tail of LRU
2623       ++num_dentries;
2624     }
2625   }
2626
2627   dir->add_waiter(CDir::WAIT_UNFREEZE, fin);
2628
2629   if (stat.state == IMPORT_ACKING) {
2630     // remove imported caps
2631     for (map<CInode*,map<client_t,Capability::Export> >::iterator p = stat.peer_exports.begin();
2632         p != stat.peer_exports.end();
2633         ++p) {
2634       CInode *in = p->first;
2635       for (map<client_t,Capability::Export>::iterator q = p->second.begin();
2636           q != p->second.end();
2637           ++q) {
2638         Capability *cap = in->get_client_cap(q->first);
2639         assert(cap);
2640         if (cap->is_importing())
2641           in->remove_client_cap(q->first);
2642       }
2643       in->put(CInode::PIN_IMPORTINGCAPS);
2644     }
2645     for (map<client_t,entity_inst_t>::iterator p = stat.client_map.begin();
2646          p != stat.client_map.end();
2647          ++p) {
2648       Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p->first.v));
2649       assert(session);
2650       session->dec_importing();
2651     }
2652   }
2653          
2654   // log our failure
2655   mds->mdlog->start_submit_entry(new EImportFinish(dir, false));        // log failure
2656
2657   cache->trim(num_dentries); // try trimming dentries
2658
2659   // notify bystanders; wait in aborting state
2660   import_notify_abort(dir, bounds);
2661 }
2662
2663 void Migrator::import_notify_finish(CDir *dir, set<CDir*>& bounds)
2664 {
2665   dout(7) << "import_notify_finish " << *dir << dendl;
2666
2667   import_state_t& stat = import_state[dir->dirfrag()];
2668   for (set<mds_rank_t>::iterator p = stat.bystanders.begin();
2669        p != stat.bystanders.end();
2670        ++p) {
2671     MExportDirNotify *notify =
2672       new MExportDirNotify(dir->dirfrag(), stat.tid, false,
2673                            pair<int,int>(stat.peer, mds->get_nodeid()),
2674                            pair<int,int>(mds->get_nodeid(), CDIR_AUTH_UNKNOWN));
2675     for (set<CDir*>::iterator i = bounds.begin(); i != bounds.end(); ++i)
2676       notify->get_bounds().push_back((*i)->dirfrag());
2677     mds->send_message_mds(notify, *p);
2678   }
2679 }
2680
2681 void Migrator::import_notify_abort(CDir *dir, set<CDir*>& bounds)
2682 {
2683   dout(7) << "import_notify_abort " << *dir << dendl;
2684   
2685   import_state_t& stat = import_state[dir->dirfrag()];
2686   for (set<mds_rank_t>::iterator p = stat.bystanders.begin();
2687        p != stat.bystanders.end(); ) {
2688     if (mds->is_cluster_degraded() &&
2689         !mds->mdsmap->is_clientreplay_or_active_or_stopping(*p)) {
2690       // this can happen if both exporter and bystander fail in the same mdsmap epoch
2691       stat.bystanders.erase(p++);
2692       continue;
2693     }
2694     MExportDirNotify *notify =
2695       new MExportDirNotify(dir->dirfrag(), stat.tid, true,
2696                            mds_authority_t(stat.peer, mds->get_nodeid()),
2697                            mds_authority_t(stat.peer, CDIR_AUTH_UNKNOWN));
2698     for (set<CDir*>::iterator i = bounds.begin(); i != bounds.end(); ++i)
2699       notify->get_bounds().push_back((*i)->dirfrag());
2700     mds->send_message_mds(notify, *p);
2701     ++p;
2702   }
2703   if (stat.bystanders.empty()) {
2704     dout(7) << "no bystanders, finishing reverse now" << dendl;
2705     import_reverse_unfreeze(dir);
2706   } else {
2707     assert (g_conf->mds_kill_import_at != 10);
2708   }
2709 }
2710
2711 void Migrator::import_reverse_unfreeze(CDir *dir)
2712 {
2713   dout(7) << "import_reverse_unfreeze " << *dir << dendl;
2714   assert(!dir->is_auth());
2715   cache->discard_delayed_expire(dir);
2716   dir->unfreeze_tree();
2717   if (dir->is_subtree_root())
2718     cache->try_subtree_merge(dir);
2719   import_reverse_final(dir);
2720 }
2721
2722 void Migrator::import_reverse_final(CDir *dir) 
2723 {
2724   dout(7) << "import_reverse_final " << *dir << dendl;
2725
2726   // clean up
2727   map<dirfrag_t, import_state_t>::iterator it = import_state.find(dir->dirfrag());
2728   assert(it != import_state.end());
2729
2730   MutationRef mut = it->second.mut;
2731   import_state.erase(it);
2732
2733   // send pending import_maps?
2734   mds->mdcache->maybe_send_pending_resolves();
2735
2736   if (mut) {
2737     mds->locker->drop_locks(mut.get());
2738     mut->cleanup();
2739   }
2740
2741   cache->show_subtrees();
2742   //audit();  // this fails, bc we munge up the subtree map during handle_import_map (resolve phase)
2743 }
2744
2745
2746
2747
2748 void Migrator::import_logged_start(dirfrag_t df, CDir *dir, mds_rank_t from,
2749                                    map<client_t,entity_inst_t>& imported_client_map,
2750                                    map<client_t,uint64_t>& sseqmap)
2751 {
2752   map<dirfrag_t, import_state_t>::iterator it = import_state.find(dir->dirfrag());
2753   if (it == import_state.end() ||
2754       it->second.state != IMPORT_LOGGINGSTART) {
2755     dout(7) << "import " << df << " must have aborted" << dendl;
2756     mds->server->finish_force_open_sessions(imported_client_map, sseqmap);
2757     return;
2758   }
2759
2760   dout(7) << "import_logged " << *dir << dendl;
2761
2762   // note state
2763   it->second.state = IMPORT_ACKING;
2764
2765   assert (g_conf->mds_kill_import_at != 7);
2766
2767   // force open client sessions and finish cap import
2768   mds->server->finish_force_open_sessions(imported_client_map, sseqmap, false);
2769   it->second.client_map.swap(imported_client_map);
2770   
2771   map<inodeno_t,map<client_t,Capability::Import> > imported_caps;
2772   for (map<CInode*, map<client_t,Capability::Export> >::iterator p = it->second.peer_exports.begin();
2773        p != it->second.peer_exports.end();
2774        ++p) {
2775     // parameter 'peer' is NONE, delay sending cap import messages to client
2776     finish_import_inode_caps(p->first, MDS_RANK_NONE, true, p->second, imported_caps[p->first->ino()]);
2777   }
2778   
2779   // send notify's etc.
2780   dout(7) << "sending ack for " << *dir << " to old auth mds." << from << dendl;
2781
2782   // test surviving observer of a failed migration that did not complete
2783   //assert(dir->replica_map.size() < 2 || mds->get_nodeid() != 0);
2784
2785   MExportDirAck *ack = new MExportDirAck(dir->dirfrag(), it->second.tid);
2786   ::encode(imported_caps, ack->imported_caps);
2787
2788   mds->send_message_mds(ack, from);
2789   assert (g_conf->mds_kill_import_at != 8);
2790
2791   cache->show_subtrees();
2792 }
2793
2794 /* This function DOES put the passed message before returning*/
2795 void Migrator::handle_export_finish(MExportDirFinish *m)
2796 {
2797   CDir *dir = cache->get_dirfrag(m->get_dirfrag());
2798   assert(dir);
2799   dout(7) << "handle_export_finish on " << *dir << (m->is_last() ? " last" : "") << dendl;
2800
2801   map<dirfrag_t,import_state_t>::iterator it = import_state.find(m->get_dirfrag());
2802   assert(it != import_state.end());
2803   assert(it->second.tid == m->get_tid());
2804
2805   import_finish(dir, false, m->is_last());
2806
2807   m->put();
2808 }
2809
2810 void Migrator::import_finish(CDir *dir, bool notify, bool last)
2811 {
2812   dout(7) << "import_finish on " << *dir << dendl;
2813
2814   map<dirfrag_t,import_state_t>::iterator it = import_state.find(dir->dirfrag());
2815   assert(it != import_state.end());
2816   assert(it->second.state == IMPORT_ACKING || it->second.state == IMPORT_FINISHING);
2817
2818   if (it->second.state == IMPORT_ACKING) {
2819     assert(dir->is_auth());
2820     cache->adjust_subtree_auth(dir, mds->get_nodeid(), mds->get_nodeid());
2821   }
2822
2823   // log finish
2824   assert(g_conf->mds_kill_import_at != 9);
2825
2826   if (it->second.state == IMPORT_ACKING) {
2827     for (map<CInode*, map<client_t,Capability::Export> >::iterator p = it->second.peer_exports.begin();
2828         p != it->second.peer_exports.end();
2829         ++p) {
2830       CInode *in = p->first;
2831       assert(in->is_auth());
2832       for (map<client_t,Capability::Export>::iterator q = p->second.begin();
2833           q != p->second.end();
2834           ++q) {
2835         Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(q->first.v));
2836         assert(session);
2837         Capability *cap = in->get_client_cap(q->first);
2838         assert(cap);
2839         cap->merge(q->second, true);
2840         cap->clear_importing();
2841         mds->mdcache->do_cap_import(session, in, cap, q->second.cap_id, q->second.seq,
2842                                     q->second.mseq - 1, it->second.peer, CEPH_CAP_FLAG_AUTH);
2843       }
2844       p->second.clear();
2845       in->replica_caps_wanted = 0;
2846     }
2847     for (map<client_t,entity_inst_t>::iterator p = it->second.client_map.begin();
2848          p != it->second.client_map.end();
2849          ++p) {
2850       Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(p->first.v));
2851       assert(session);
2852       session->dec_importing();
2853     }
2854   }
2855
2856   if (!last) {
2857     assert(it->second.state == IMPORT_ACKING);
2858     it->second.state = IMPORT_FINISHING;
2859     return;
2860   }
2861
2862   // remove pins
2863   set<CDir*> bounds;
2864   cache->get_subtree_bounds(dir, bounds);
2865
2866   if (notify)
2867     import_notify_finish(dir, bounds);
2868
2869   import_remove_pins(dir, bounds);
2870
2871   map<CInode*, map<client_t,Capability::Export> > peer_exports;
2872   it->second.peer_exports.swap(peer_exports);
2873
2874   // clear import state (we're done!)
2875   MutationRef mut = it->second.mut;
2876   import_state.erase(it);
2877
2878   mds->mdlog->start_submit_entry(new EImportFinish(dir, true));
2879
2880   // process delayed expires
2881   cache->process_delayed_expire(dir);
2882
2883   // unfreeze tree, with possible subtree merge.
2884   dir->unfreeze_tree();
2885   cache->try_subtree_merge(dir);
2886
2887   cache->show_subtrees();
2888   //audit();  // this fails, bc we munge up the subtree map during handle_import_map (resolve phase)
2889
2890   if (mut) {
2891     mds->locker->drop_locks(mut.get());
2892     mut->cleanup();
2893   }
2894
2895   // re-eval imported caps
2896   for (map<CInode*, map<client_t,Capability::Export> >::iterator p = peer_exports.begin();
2897        p != peer_exports.end();
2898        ++p) {
2899     if (p->first->is_auth())
2900       mds->locker->eval(p->first, CEPH_CAP_LOCKS, true);
2901     p->first->put(CInode::PIN_IMPORTINGCAPS);
2902   }
2903
2904   // send pending import_maps?
2905   mds->mdcache->maybe_send_pending_resolves();
2906
2907   // did i just import mydir?
2908   if (dir->ino() == MDS_INO_MDSDIR(mds->get_nodeid()))
2909     cache->populate_mydir();
2910
2911   // is it empty?
2912   if (dir->get_num_head_items() == 0 &&
2913       !dir->inode->is_auth()) {
2914     // reexport!
2915     export_empty_import(dir);
2916   }
2917 }
2918
2919
2920 void Migrator::decode_import_inode(CDentry *dn, bufferlist::iterator& blp,
2921                                    mds_rank_t oldauth, LogSegment *ls,
2922                                    map<CInode*, map<client_t,Capability::Export> >& peer_exports,
2923                                    list<ScatterLock*>& updated_scatterlocks)
2924 {  
2925   dout(15) << "decode_import_inode on " << *dn << dendl;
2926
2927   inodeno_t ino;
2928   snapid_t last;
2929   ::decode(ino, blp);
2930   ::decode(last, blp);
2931
2932   bool added = false;
2933   CInode *in = cache->get_inode(ino, last);
2934   if (!in) {
2935     in = new CInode(mds->mdcache, true, 1, last);
2936     added = true;
2937   }
2938
2939   // state after link  -- or not!  -sage
2940   in->decode_import(blp, ls);  // cap imports are noted for later action
2941
2942   // caps
2943   decode_import_inode_caps(in, true, blp, peer_exports);
2944
2945   // link before state  -- or not!  -sage
2946   if (dn->get_linkage()->get_inode() != in) {
2947     assert(!dn->get_linkage()->get_inode());
2948     dn->dir->link_primary_inode(dn, in);
2949   }
2950  
2951   // add inode?
2952   if (added) {
2953     cache->add_inode(in);
2954     dout(10) << "added " << *in << dendl;
2955   } else {
2956     dout(10) << "  had " << *in << dendl;
2957   }
2958
2959   if (in->inode.is_dirty_rstat())
2960     in->mark_dirty_rstat();
2961   
2962   // clear if dirtyscattered, since we're going to journal this
2963   //  but not until we _actually_ finish the import...
2964   if (in->filelock.is_dirty()) {
2965     updated_scatterlocks.push_back(&in->filelock);
2966     mds->locker->mark_updated_scatterlock(&in->filelock);
2967   }
2968
2969   if (in->dirfragtreelock.is_dirty()) {
2970     updated_scatterlocks.push_back(&in->dirfragtreelock);
2971     mds->locker->mark_updated_scatterlock(&in->dirfragtreelock);
2972   }
2973
2974   // adjust replica list
2975   //assert(!in->is_replica(oldauth));  // not true on failed export
2976   in->add_replica(oldauth, CInode::EXPORT_NONCE);
2977   if (in->is_replica(mds->get_nodeid()))
2978     in->remove_replica(mds->get_nodeid());
2979 }
2980
2981 void Migrator::decode_import_inode_caps(CInode *in, bool auth_cap,
2982                                         bufferlist::iterator &blp,
2983                                         map<CInode*, map<client_t,Capability::Export> >& peer_exports)
2984 {
2985   map<client_t,Capability::Export> cap_map;
2986   ::decode(cap_map, blp);
2987   if (auth_cap)
2988     ::decode(in->get_mds_caps_wanted(), blp);
2989   if (!cap_map.empty() ||
2990       (auth_cap && !in->get_mds_caps_wanted().empty())) {
2991     peer_exports[in].swap(cap_map);
2992     in->get(CInode::PIN_IMPORTINGCAPS);
2993   }
2994 }
2995
2996 void Migrator::finish_import_inode_caps(CInode *in, mds_rank_t peer, bool auth_cap,
2997                                         map<client_t,Capability::Export> &export_map,
2998                                         map<client_t,Capability::Import> &import_map)
2999 {
3000   for (map<client_t,Capability::Export>::iterator it = export_map.begin();
3001        it != export_map.end();
3002        ++it) {
3003     dout(10) << "finish_import_inode_caps for client." << it->first << " on " << *in << dendl;
3004     Session *session = mds->sessionmap.get_session(entity_name_t::CLIENT(it->first.v));
3005     assert(session);
3006
3007     Capability *cap = in->get_client_cap(it->first);
3008     if (!cap) {
3009       cap = in->add_client_cap(it->first, session);
3010       if (peer < 0)
3011         cap->mark_importing();
3012     }
3013
3014     Capability::Import& im = import_map[it->first];
3015     im.cap_id = cap->get_cap_id();
3016     im.mseq = auth_cap ? it->second.mseq : cap->get_mseq();
3017     im.issue_seq = cap->get_last_seq() + 1;
3018
3019     if (peer >= 0) {
3020       cap->merge(it->second, auth_cap);
3021       mds->mdcache->do_cap_import(session, in, cap, it->second.cap_id,
3022                                   it->second.seq, it->second.mseq - 1, peer,
3023                                   auth_cap ? CEPH_CAP_FLAG_AUTH : CEPH_CAP_FLAG_RELEASE);
3024     }
3025   }
3026
3027   if (peer >= 0) {
3028     in->replica_caps_wanted = 0;
3029     in->put(CInode::PIN_IMPORTINGCAPS);
3030   }
3031 }
3032
3033 int Migrator::decode_import_dir(bufferlist::iterator& blp,
3034                                 mds_rank_t oldauth,
3035                                 CDir *import_root,
3036                                 EImportStart *le,
3037                                 LogSegment *ls,
3038                                 map<CInode*,map<client_t,Capability::Export> >& peer_exports,
3039                                 list<ScatterLock*>& updated_scatterlocks, utime_t now)
3040 {
3041   // set up dir
3042   dirfrag_t df;
3043   ::decode(df, blp);
3044
3045   CInode *diri = cache->get_inode(df.ino);
3046   assert(diri);
3047   CDir *dir = diri->get_or_open_dirfrag(mds->mdcache, df.frag);
3048   assert(dir);
3049   
3050   dout(7) << "decode_import_dir " << *dir << dendl;
3051
3052   // assimilate state
3053   dir->decode_import(blp, now, ls);
3054
3055   // adjust replica list
3056   //assert(!dir->is_replica(oldauth));    // not true on failed export
3057   dir->add_replica(oldauth, CDir::EXPORT_NONCE);
3058   if (dir->is_replica(mds->get_nodeid()))
3059     dir->remove_replica(mds->get_nodeid());
3060
3061   // add to journal entry
3062   if (le) 
3063     le->metablob.add_import_dir(dir);
3064
3065   int num_imported = 0;
3066
3067   // take all waiters on this dir
3068   // NOTE: a pass of imported data is guaranteed to get all of my waiters because
3069   // a replica's presense in my cache implies/forces it's presense in authority's.
3070   list<MDSInternalContextBase*> waiters;
3071   
3072   dir->take_waiting(CDir::WAIT_ANY_MASK, waiters);
3073   for (list<MDSInternalContextBase*>::iterator it = waiters.begin();
3074        it != waiters.end();
3075        ++it) 
3076     import_root->add_waiter(CDir::WAIT_UNFREEZE, *it);  // UNFREEZE will get kicked both on success or failure
3077   
3078   dout(15) << "doing contents" << dendl;
3079   
3080   // contents
3081   __u32 nden;
3082   ::decode(nden, blp);
3083   
3084   for (; nden>0; nden--) {
3085     num_imported++;
3086     
3087     // dentry
3088     string dname;
3089     snapid_t last;
3090     ::decode(dname, blp);
3091     ::decode(last, blp);
3092     
3093     CDentry *dn = dir->lookup_exact_snap(dname, last);
3094     if (!dn)
3095       dn = dir->add_null_dentry(dname, 1, last);
3096     
3097     dn->decode_import(blp, ls);
3098
3099     dn->add_replica(oldauth, CDentry::EXPORT_NONCE);
3100     if (dn->is_replica(mds->get_nodeid()))
3101       dn->remove_replica(mds->get_nodeid());
3102
3103     // dentry lock in unreadable state can block path traverse
3104     if (dn->lock.get_state() != LOCK_SYNC)
3105       mds->locker->try_eval(&dn->lock, NULL);
3106
3107     dout(15) << "decode_import_dir got " << *dn << dendl;
3108     
3109     // points to...
3110     char icode;
3111     ::decode(icode, blp);
3112     
3113     if (icode == 'N') {
3114       // null dentry
3115       assert(dn->get_linkage()->is_null());  
3116       
3117       // fall thru
3118     }
3119     else if (icode == 'L') {
3120       // remote link
3121       inodeno_t ino;
3122       unsigned char d_type;
3123       ::decode(ino, blp);
3124       ::decode(d_type, blp);
3125       if (dn->get_linkage()->is_remote()) {
3126         assert(dn->get_linkage()->get_remote_ino() == ino);
3127       } else {
3128         dir->link_remote_inode(dn, ino, d_type);
3129       }
3130     }
3131     else if (icode == 'I') {
3132       // inode
3133       assert(le);
3134       decode_import_inode(dn, blp, oldauth, ls,
3135                           peer_exports, updated_scatterlocks);
3136     }
3137     
3138     // add dentry to journal entry
3139     if (le)
3140       le->metablob.add_import_dentry(dn);
3141   }
3142   
3143 #ifdef MDS_VERIFY_FRAGSTAT
3144   if (dir->is_complete())
3145     dir->verify_fragstat();
3146 #endif
3147
3148   dir->inode->maybe_export_pin();
3149
3150   dout(7) << "decode_import_dir done " << *dir << dendl;
3151   return num_imported;
3152 }
3153
3154
3155
3156
3157
3158 // authority bystander
3159
3160 /* This function DOES put the passed message before returning*/
3161 void Migrator::handle_export_notify(MExportDirNotify *m)
3162 {
3163   if (!(mds->is_clientreplay() || mds->is_active() || mds->is_stopping())) {
3164     m->put();
3165     return;
3166   }
3167
3168   CDir *dir = cache->get_dirfrag(m->get_dirfrag());
3169
3170   mds_rank_t from = mds_rank_t(m->get_source().num());
3171   mds_authority_t old_auth = m->get_old_auth();
3172   mds_authority_t new_auth = m->get_new_auth();
3173   
3174   if (!dir) {
3175     dout(7) << "handle_export_notify " << old_auth << " -> " << new_auth
3176             << " on missing dir " << m->get_dirfrag() << dendl;
3177   } else if (dir->authority() != old_auth) {
3178     dout(7) << "handle_export_notify old_auth was " << dir->authority() 
3179             << " != " << old_auth << " -> " << new_auth
3180             << " on " << *dir << dendl;
3181   } else {
3182     dout(7) << "handle_export_notify " << old_auth << " -> " << new_auth
3183             << " on " << *dir << dendl;
3184     // adjust auth
3185     set<CDir*> have;
3186     cache->map_dirfrag_set(m->get_bounds(), have);
3187     cache->adjust_bounded_subtree_auth(dir, have, new_auth);
3188     
3189     // induce a merge?
3190     cache->try_subtree_merge(dir);
3191   }
3192   
3193   // send ack
3194   if (m->wants_ack()) {
3195     mds->send_message_mds(new MExportDirNotifyAck(m->get_dirfrag(), m->get_tid(), m->get_new_auth()), from);
3196   } else {
3197     // aborted.  no ack.
3198     dout(7) << "handle_export_notify no ack requested" << dendl;
3199   }
3200   
3201   m->put();
3202 }
3203
3204 /** cap exports **/
3205 void Migrator::export_caps(CInode *in)
3206 {
3207   mds_rank_t dest = in->authority().first;
3208   dout(7) << "export_caps to mds." << dest << " " << *in << dendl;
3209
3210   assert(in->is_any_caps());
3211   assert(!in->is_auth());
3212   assert(!in->is_ambiguous_auth());
3213   assert(!in->state_test(CInode::STATE_EXPORTINGCAPS));
3214
3215   MExportCaps *ex = new MExportCaps;
3216   ex->ino = in->ino();
3217
3218   encode_export_inode_caps(in, false, ex->cap_bl, ex->client_map);
3219
3220   mds->send_message_mds(ex, dest);
3221 }
3222
3223 void Migrator::handle_gather_caps(MGatherCaps *m)
3224 {
3225   CInode *in = cache->get_inode(m->ino);
3226
3227   if (!in)
3228     goto out;
3229
3230   dout(10) << "handle_gather_caps " << *m << " from " << m->get_source()
3231            << " on " << *in
3232            << dendl;
3233   if (in->is_any_caps() &&
3234       !in->is_auth() &&
3235       !in->is_ambiguous_auth() &&
3236       !in->state_test(CInode::STATE_EXPORTINGCAPS))
3237     export_caps(in);
3238
3239 out:
3240   m->put();
3241 }
3242
3243 class C_M_LoggedImportCaps : public MigratorLogContext {
3244   CInode *in;
3245   mds_rank_t from;
3246 public:
3247   map<CInode*, map<client_t,Capability::Export> > peer_exports;
3248   map<client_t,entity_inst_t> client_map;
3249   map<client_t,uint64_t> sseqmap;
3250
3251   C_M_LoggedImportCaps(Migrator *m, CInode *i, mds_rank_t f) : MigratorLogContext(m), in(i), from(f) {}
3252   void finish(int r) override {
3253     mig->logged_import_caps(in, from, peer_exports, client_map, sseqmap);
3254   }  
3255 };
3256
3257 /* This function DOES put the passed message before returning*/
3258 void Migrator::handle_export_caps(MExportCaps *ex)
3259 {
3260   dout(10) << "handle_export_caps " << *ex << " from " << ex->get_source() << dendl;
3261   CInode *in = cache->get_inode(ex->ino);
3262   
3263   assert(in);
3264   assert(in->is_auth());
3265
3266   // FIXME
3267   if (!in->can_auth_pin())
3268     return;
3269   in->auth_pin(this);
3270
3271   C_M_LoggedImportCaps *finish = new C_M_LoggedImportCaps(
3272       this, in, mds_rank_t(ex->get_source().num()));
3273   finish->client_map = ex->client_map;
3274
3275   // decode new caps
3276   bufferlist::iterator blp = ex->cap_bl.begin();
3277   decode_import_inode_caps(in, false, blp, finish->peer_exports);
3278   assert(!finish->peer_exports.empty());   // thus, inode is pinned.
3279
3280   // journal open client sessions
3281   version_t pv = mds->server->prepare_force_open_sessions(finish->client_map, finish->sseqmap);
3282   
3283   ESessions *le = new ESessions(pv, ex->client_map);
3284   mds->mdlog->start_submit_entry(le, finish);
3285   mds->mdlog->flush();
3286
3287   ex->put();
3288 }
3289
3290
3291 void Migrator::logged_import_caps(CInode *in, 
3292                                   mds_rank_t from,
3293                                   map<CInode*, map<client_t,Capability::Export> >& peer_exports,
3294                                   map<client_t,entity_inst_t>& client_map,
3295                                   map<client_t,uint64_t>& sseqmap) 
3296 {
3297   dout(10) << "logged_import_caps on " << *in << dendl;
3298   // see export_go() vs export_go_synced()
3299   assert(in->is_auth());
3300
3301   // force open client sessions and finish cap import
3302   mds->server->finish_force_open_sessions(client_map, sseqmap);
3303
3304   map<client_t,Capability::Import> imported_caps;
3305
3306   assert(peer_exports.count(in));
3307   // clients will release caps from the exporter when they receive the cap import message.
3308   finish_import_inode_caps(in, from, false, peer_exports[in], imported_caps);
3309   mds->locker->eval(in, CEPH_CAP_LOCKS, true);
3310   in->auth_unpin(this);
3311 }