]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: rollback snaprealms when rolling back slave request
authorYan, Zheng <zyan@redhat.com>
Mon, 31 Jul 2017 13:12:25 +0000 (21:12 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 9 Feb 2018 10:41:27 +0000 (18:41 +0800)
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/CInode.cc
src/mds/CInode.h
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/Server.cc
src/mds/Server.h
src/mds/SnapRealm.cc
src/mds/SnapRealm.h
src/mds/events/ESlaveUpdate.h
src/mds/journal.cc

index cc24e3b5354d5f449143f0371b0830167def7199..ae310cc4a25c433b9161023441d0c2a87b3c2fd9 100644 (file)
@@ -65,6 +65,7 @@ public:
   }
 };
 
+sr_t* const CInode::projected_inode::UNDEF_SRNODE = (sr_t*)(unsigned long)-1;
 
 LockType CInode::versionlock_type(CEPH_LOCK_IVERSION);
 LockType CInode::authlock_type(CEPH_LOCK_IAUTH);
@@ -406,9 +407,8 @@ void CInode::pop_and_dirty_projected_inode(LogSegment *ls)
     xattrs = *front.xattrs;
   }
 
-  auto &snapnode = front.snapnode;
-  if (snapnode) {
-    pop_projected_snaprealm(snapnode.get());
+  if (projected_nodes.front().snapnode != projected_inode::UNDEF_SRNODE) {
+    pop_projected_snaprealm(projected_nodes.front().snapnode);
     --num_projected_srnodes;
   }
 
@@ -433,8 +433,8 @@ sr_t *CInode::prepare_new_srnode(snapid_t snapid)
 void CInode::project_snaprealm(sr_t *new_srnode)
 {
   dout(10) << __func__ << " " << new_srnode << dendl;
-  assert(!projected_nodes.back().snapnode);
-  projected_nodes.back().snapnode.reset(new_srnode);
+  assert(projected_nodes.back().snapnode == projected_inode::UNDEF_SRNODE);
+  projected_nodes.back().snapnode = new_srnode;
   ++num_projected_srnodes;
 }
 
@@ -488,32 +488,38 @@ void CInode::record_snaprealm_past_parent(sr_t *new_snap, SnapRealm *newparent)
 
 void CInode::pop_projected_snaprealm(sr_t *next_snaprealm)
 {
-  assert(next_snaprealm);
-  dout(10) << __func__ << " " << next_snaprealm
-          << " seq" << next_snaprealm->seq << dendl;
-  bool invalidate_cached_snaps = false;
-  if (!snaprealm) {
-    open_snaprealm();
-  } else if (next_snaprealm->past_parents.size() !=
-            snaprealm->srnode.past_parents.size()) {
-    invalidate_cached_snaps = true;
-    // re-open past parents
-    snaprealm->_close_parents();
-
-    dout(10) << " realm " << *snaprealm << " past_parents " << snaprealm->srnode.past_parents
-            << " -> " << next_snaprealm->past_parents << dendl;
-  }
-  snaprealm->srnode = *next_snaprealm;
+  if (next_snaprealm) {
+    dout(10) << __func__ << " " << next_snaprealm
+            << " seq" << next_snaprealm->seq << dendl;
+    bool invalidate_cached_snaps = false;
+    if (!snaprealm) {
+      open_snaprealm();
+    } else if (next_snaprealm->past_parents.size() !=
+              snaprealm->srnode.past_parents.size()) {
+      invalidate_cached_snaps = true;
+      // re-open past parents
+      snaprealm->_close_parents();
+
+      dout(10) << " realm " << *snaprealm << " past_parents " << snaprealm->srnode.past_parents
+              << " -> " << next_snaprealm->past_parents << dendl;
+    }
+    snaprealm->srnode = *next_snaprealm;
+    delete next_snaprealm;
 
-  // we should be able to open these up (or have them already be open).
-  bool ok = snaprealm->_open_parents(NULL);
-  assert(ok);
+    // we should be able to open these up (or have them already be open).
+    bool ok = snaprealm->_open_parents(NULL);
+    assert(ok);
 
-  if (invalidate_cached_snaps)
-    snaprealm->invalidate_cached_snaps();
+    if (invalidate_cached_snaps)
+      snaprealm->invalidate_cached_snaps();
 
-  if (snaprealm->parent)
-    dout(10) << " realm " << *snaprealm << " parent " << *snaprealm->parent << dendl;
+    if (snaprealm->parent)
+      dout(10) << " realm " << *snaprealm << " parent " << *snaprealm->parent << dendl;
+  } else {
+    dout(10) << __func__ << " null" << dendl;
+    assert(snaprealm);
+    snaprealm->merge_to(NULL);
+  }
 }
 
 
@@ -2724,6 +2730,9 @@ void CInode::decode_snap_blob(bufferlist& snapbl)
       assert(ok);
     }
     dout(20) << __func__ << " " << *snaprealm << dendl;
+  } else if (snaprealm) {
+    assert(mdcache->mds->is_any_replay());
+    snaprealm->merge_to(NULL);
   }
 }
 
index f82873c47fcb92100285516b8a2b27306c35a4f8..2d11b84c042c8b5f6c2ad61041d8b0d2a35aa8a3 100644 (file)
@@ -417,9 +417,11 @@ public:
 
   class projected_inode {
   public:
+    static sr_t* const UNDEF_SRNODE;
+
     mempool_inode inode;
     std::unique_ptr<mempool_xattr_map> xattrs;
-    std::unique_ptr<sr_t> snapnode;
+    sr_t *snapnode = UNDEF_SRNODE;
 
     projected_inode() = delete;
     projected_inode(const mempool_inode &in) : inode(in) {}
@@ -500,8 +502,8 @@ public:
   const sr_t *get_projected_srnode() const {
     if (num_projected_srnodes > 0) {
       for (auto it = projected_nodes.rbegin(); it != projected_nodes.rend(); ++it)
-       if (it->snapnode)
-         return it->snapnode.get();
+       if (it->snapnode != projected_inode::UNDEF_SRNODE)
+         return it->snapnode;
     }
     if (snaprealm)
       return &snaprealm->srnode;
index 67c4a002dfdca97854ec280efb763a2a3eb0e397..9a703d9c5e373874a45d9c2ee6158651249ab739 100644 (file)
@@ -5565,6 +5565,38 @@ void MDCache::prepare_realm_split(SnapRealm *realm, client_t client, inodeno_t i
   snap->split_inos.push_back(ino);     
 }
 
+void MDCache::prepare_realm_merge(SnapRealm *realm, SnapRealm *parent_realm,
+                                 map<client_t,MClientSnap*>& splits)
+{
+  assert(parent_realm);
+
+  vector<inodeno_t> split_inos;
+  vector<inodeno_t> split_realms;
+  bufferlist snapbl;
+
+  for (elist<CInode*>::iterator p = realm->inodes_with_caps.begin(member_offset(CInode, item_caps));
+       !p.end();
+       ++p)
+    split_inos.push_back((*p)->ino());
+  for (set<SnapRealm*>::iterator p = realm->open_children.begin();
+       p != realm->open_children.end();
+       ++p)
+    split_realms.push_back((*p)->inode->ino());
+  parent_realm->build_snap_trace(snapbl);
+
+  for (auto p : realm->client_caps) {
+    assert(!p.second->empty());
+    if (splits.count(p.first) == 0) {
+      MClientSnap *update = new MClientSnap(CEPH_SNAP_OP_SPLIT);
+      splits[p.first] = update;
+      update->head.split = parent_realm->inode->ino();
+      update->split_inos = split_inos;
+      update->split_realms = split_realms;
+      update->bl = snapbl;
+    }
+  }
+}
+
 void MDCache::send_snaps(map<client_t,MClientSnap*>& splits)
 {
   dout(10) << "send_snaps" << dendl;
index e6e966b7a751af6de176903402fd15b5989e3230..effa3a67ea5dab61de47efb643a859dcfe7997f3 100644 (file)
@@ -654,6 +654,7 @@ public:
   void choose_lock_states_and_reconnect_caps();
   void prepare_realm_split(SnapRealm *realm, client_t client, inodeno_t ino,
                           map<client_t,MClientSnap*>& splits);
+  void prepare_realm_merge(SnapRealm *realm, SnapRealm *parent_realm, map<client_t,MClientSnap*>& splits);
   void send_snaps(map<client_t,MClientSnap*>& splits);
   Capability* rejoin_import_cap(CInode *in, client_t client, const cap_reconnect_t& icr, mds_rank_t frommds);
   void finish_snaprealm_reconnect(client_t client, SnapRealm *realm, snapid_t seq,
index db8cdd86d2c6bb955ef2d0f1a93f162b037bc4c3..1002bfc600e87b6932354cd6f4387b9cec5b2e77 100644 (file)
@@ -939,8 +939,12 @@ void Server::handle_client_reconnect(MClientReconnect *m)
     if (in && in->state_test(CInode::STATE_PURGING))
       continue;
     if (in) {
-      assert(in->snaprealm || !in->is_auth());
-      dout(15) << "open snaprealm (w inode) on " << *in << dendl;
+      if (in->snaprealm) {
+       dout(15) << "open snaprealm (w inode) on " << *in << dendl;
+      } else {
+       // this can happen if we are non-auth or we rollback snaprealm
+       dout(15) << "open snaprealm (null snaprealm) on " << *in << dendl;
+      }
       mdcache->add_reconnected_snaprealm(from, inodeno_t(p->ino), snapid_t(p->seq));
     } else {
       dout(15) << "open snaprealm (w/o inode) on " << inodeno_t(p->ino)
@@ -5989,9 +5993,12 @@ void Server::handle_client_unlink(MDRequestRef& mdr)
     wrlocks.insert(&straydn->get_dir()->inode->nestlock);
     xlocks.insert(&straydn->lock);
   }
-  if (in->is_dir())
+  mds->locker->include_snap_rdlocks(rdlocks, diri);
+  if (dnl->is_primary() && in->is_dir()) {
     rdlocks.insert(&in->filelock);   // to verify it's empty
-  mds->locker->include_snap_rdlocks(rdlocks, dnl->get_inode());
+    xlocks.insert(&in->snaplock);
+  } else
+    rdlocks.insert(&in->snaplock);
 
   if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks))
     return;
@@ -6298,6 +6305,14 @@ void Server::handle_slave_rmdir_prep(MDRequestRef& mdr)
   rollback.src_dname = dn->get_name();
   rollback.dest_dir = straydn->get_dir()->dirfrag();
   rollback.dest_dname = straydn->get_name();
+  if (mdr->slave_request->desti_snapbl.length()) {
+    if (in->snaprealm) {
+      encode(true, rollback.snapbl);
+      in->encode_snap_blob(rollback.snapbl);
+    } else {
+      encode(false, rollback.snapbl);
+    }
+  }
   encode(rollback, mdr->more()->rollback_bl);
   // FIXME: rollback snaprealm
   dout(20) << " rollback is " << mdr->more()->rollback_bl.length() << " bytes" << dendl;
@@ -6461,28 +6476,34 @@ void Server::do_rmdir_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef&
   CDentry *dn = dir->lookup(rollback.src_dname);
   assert(dn);
   dout(10) << " dn " << *dn << dendl;
-  dir = mdcache->get_dirfrag(rollback.dest_dir);
-  assert(dir);
-  CDentry *straydn = dir->lookup(rollback.dest_dname);
+  CDir *straydir = mdcache->get_dirfrag(rollback.dest_dir);
+  assert(straydir);
+  CDentry *straydn = straydir->lookup(rollback.dest_dname);
   assert(straydn);
-  dout(10) << " straydn " << *dn << dendl;
+  dout(10) << " straydn " << *straydn << dendl;
   CInode *in = straydn->get_linkage()->get_inode();
 
-  if (mdr && !mdr->more()->slave_update_journaled) {
-    assert(!in->has_subtree_root_dirfrag(mds->get_nodeid()));
+  dn->push_projected_linkage(in);
+  straydn->push_projected_linkage();
 
-    straydn->get_dir()->unlink_inode(straydn);
-    dn->get_dir()->link_primary_inode(dn, in);
+  if (rollback.snapbl.length() && in->snaprealm) {
+    bool hadrealm;
+    bufferlist::iterator p = rollback.snapbl.begin();
+    decode(hadrealm, p);
+    if (hadrealm) {
+      decode(in->snaprealm->srnode, p);
+    } else {
+      in->snaprealm->merge_to(dir->get_inode()->find_snaprealm());
+    }
+  }
 
-    mdcache->adjust_subtree_after_rename(in, straydn->get_dir(), false);
+  if (mdr && !mdr->more()->slave_update_journaled) {
+    assert(!in->has_subtree_root_dirfrag(mds->get_nodeid()));
 
-    mdcache->request_finish(mdr);
-    mdcache->finish_rollback(rollback.reqid);
+    _rmdir_rollback_finish(mdr, rollback.reqid, dn, straydn);
     return;
   }
 
-  dn->push_projected_linkage(in);
-  straydn->push_projected_linkage();
 
   ESlaveUpdate *le = new ESlaveUpdate(mdlog, "slave_rmdir_rollback", rollback.reqid, master,
                                      ESlaveUpdate::OP_ROLLBACK, ESlaveUpdate::RMDIR);
@@ -6513,7 +6534,9 @@ void Server::_rmdir_rollback_finish(MDRequestRef& mdr, metareqid_t reqid, CDentr
   straydn->pop_projected_linkage();
 
   CInode *in = dn->get_linkage()->get_inode();
-  mdcache->adjust_subtree_after_rename(in, straydn->get_dir(), true);
+  mdcache->adjust_subtree_after_rename(in, straydn->get_dir(),
+                                      !mdr || mdr->more()->slave_update_journaled);
+
   if (mds->is_resolve()) {
     CDir *root = mdcache->get_subtree_root(straydn->get_dir());
     mdcache->try_trim_non_auth_subtree(root);
@@ -6857,21 +6880,20 @@ void Server::handle_client_rename(MDRequestRef& mdr)
 
   // we need to update srci's ctime.  xlock its least contended lock to do that...
   xlocks.insert(&srci->linklock);
+  if (srcdnl->is_primary() && srci->is_dir())
+    xlocks.insert(&srci->snaplock);
+  else
+    rdlocks.insert(&srci->snaplock);
 
-  // xlock oldin (for nlink--)
   if (oldin) {
+    // xlock oldin (for nlink--)
     xlocks.insert(&oldin->linklock);
-    if (oldin->is_dir())
-      rdlocks.insert(&oldin->filelock);
-  }
-  if (srcdnl->is_primary() && srci->is_dir())  
-    // FIXME: this should happen whenever we are renamning between
-    // realms, regardless of the file type
-    // FIXME: If/when this changes, make sure to update the
-    // "allowance" in handle_slave_rename_prep
-    xlocks.insert(&srci->snaplock);  // FIXME: an auth bcast could be sufficient?
-  else
-    rdlocks.insert(&srci->snaplock);
+    if (destdnl->is_primary() && oldin->is_dir()) {
+      rdlocks.insert(&oldin->filelock);   // to verify it's empty
+      xlocks.insert(&oldin->snaplock);
+    } else
+      rdlocks.insert(&oldin->snaplock);
+  }
 
   CInode *auth_pin_freeze = !srcdn->is_auth() && srcdnl->is_primary() ? srci : NULL;
   if (!mds->locker->acquire_locks(mdr, rdlocks, wrlocks, xlocks,
@@ -7921,6 +7943,25 @@ void Server::handle_slave_rename_prep(MDRequestRef& mdr)
     rollback.stray.dirfrag_old_rctime = straydn->get_dir()->get_projected_fnode()->rstat.rctime;
     rollback.stray.dname = straydn->get_name();
   }
+  if (mdr->slave_request->desti_snapbl.length()) {
+    assert(destdnl->is_primary());
+    CInode *oldin = destdnl->get_inode();
+    if (oldin->snaprealm) {
+      encode(true, rollback.desti_snapbl);
+      oldin->encode_snap_blob(rollback.desti_snapbl);
+    } else {
+      encode(false, rollback.desti_snapbl);
+    }
+  }
+  if (mdr->slave_request->srci_snapbl.length()) {
+    assert(srcdnl->is_primary());
+    if (srci->snaprealm) {
+      encode(true, rollback.srci_snapbl);
+      srci->encode_snap_blob(rollback.srci_snapbl);
+    } else {
+      encode(false, rollback.srci_snapbl);
+    }
+  }
   encode(rollback, mdr->more()->rollback_bl);
   // FIXME: rollback snaprealm
   dout(20) << " rollback is " << mdr->more()->rollback_bl.length() << " bytes" << dendl;
@@ -8161,15 +8202,19 @@ struct C_MDS_LoggedRenameRollback : public ServerLogContext {
   version_t srcdnpv;
   CDentry *destdn;
   CDentry *straydn;
+  map<client_t,MClientSnap*> splits[2];
   bool finish_mdr;
   C_MDS_LoggedRenameRollback(Server *s, MutationRef& m, MDRequestRef& r,
-                            CDentry *sd, version_t pv, CDentry *dd,
-                            CDentry *st, bool f) :
+                            CDentry *sd, version_t pv, CDentry *dd, CDentry *st,
+                            map<client_t,MClientSnap*> _splits[2], bool f) :
     ServerLogContext(s, r), mut(m), srcdn(sd), srcdnpv(pv), destdn(dd),
-    straydn(st), finish_mdr(f) {}
+    straydn(st), finish_mdr(f) {
+      splits[0].swap(_splits[0]);
+      splits[1].swap(_splits[1]);
+    }
   void finish(int r) override {
     server->_rename_rollback_finish(mut, mdr, srcdn, srcdnpv,
-                                   destdn, straydn, finish_mdr);
+                                   destdn, straydn, splits, finish_mdr);
   }
 };
 
@@ -8274,17 +8319,51 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef
                                    rollback.orig_src.remote_d_type);
   }
 
-  CInode::mempool_inode *pip = 0;
+  map<client_t,MClientSnap*> splits[2];
+
+  CInode::mempool_inode *pip = nullptr;
   if (in) {
-    if (in->authority().first == whoami) {
+    bool projected;
+    if (in->get_projected_parent_dn()->authority().first == whoami) {
       auto &pi = in->project_inode();
-      mut->add_projected_inode(in);
-      pi.inode.version = in->pre_dirty();
       pip = &pi.inode;
-    } else
+      mut->add_projected_inode(in);
+      pip->version = in->pre_dirty();
+      projected = true;
+    } else {
       pip = in->get_projected_inode();
+      projected = false;
+    }
     if (pip->ctime == rollback.ctime)
       pip->ctime = rollback.orig_src.old_ctime;
+
+    if (rollback.srci_snapbl.length() && in->snaprealm) {
+      bool hadrealm;
+      bufferlist::iterator p = rollback.srci_snapbl.begin();
+      decode(hadrealm, p);
+      if (hadrealm) {
+       if (projected && !mds->is_resolve()) {
+         sr_t *new_srnode = new sr_t();
+         decode(*new_srnode, p);
+         in->project_snaprealm(new_srnode);
+       } else
+         decode(in->snaprealm->srnode, p);
+      } else {
+       SnapRealm *realm;
+       if (rollback.orig_src.ino) {
+         assert(srcdir);
+         realm = srcdir->get_inode()->find_snaprealm();
+       } else {
+         realm = in->snaprealm->parent;
+       }
+       if (!mds->is_resolve())
+         mdcache->prepare_realm_merge(in->snaprealm, realm, splits[0]);
+       if (projected)
+         in->project_snaprealm(NULL);
+       else
+         in->snaprealm->merge_to(realm);
+      }
+    }
   }
 
   if (srcdn && srcdn->authority().first == whoami) {
@@ -8312,14 +8391,18 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef
     straydn->push_projected_linkage();
 
   if (target) {
-    CInode::mempool_inode *ti = NULL;
-    if (target->authority().first == whoami) {
+    bool projected;
+    CInode::mempool_inode *ti = nullptr;
+    if (target->get_projected_parent_dn()->authority().first == whoami) {
       auto &pi = target->project_inode();
-      mut->add_projected_inode(target);
-      pi.inode.version = target->pre_dirty();
       ti = &pi.inode;
-    } else 
+      mut->add_projected_inode(target);
+      ti->version = target->pre_dirty();
+      projected = true;
+    } else {
       ti = target->get_projected_inode();
+      projected = false;
+    }
     if (ti->ctime == rollback.ctime)
       ti->ctime = rollback.orig_dest.old_ctime;
     if (MDS_INO_IS_STRAY(rollback.orig_src.dirfrag.ino)) {
@@ -8330,6 +8413,34 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef
               rollback.orig_dest.remote_ino == rollback.orig_src.ino);
     } else
       ti->nlink++;
+
+    if (rollback.desti_snapbl.length() && target->snaprealm) {
+      bool hadrealm;
+      bufferlist::iterator p = rollback.desti_snapbl.begin();
+      decode(hadrealm, p);
+      if (hadrealm) {
+       if (projected && !mds->is_resolve()) {
+         sr_t *new_srnode = new sr_t();
+         decode(*new_srnode, p);
+         target->project_snaprealm(new_srnode);
+       } else
+         decode(target->snaprealm->srnode, p);
+      } else {
+       SnapRealm *realm;
+       if (rollback.orig_dest.ino) {
+         assert(destdir);
+         realm = destdir->get_inode()->find_snaprealm();
+       } else {
+         realm = target->snaprealm->parent;
+       }
+       if (!mds->is_resolve())
+         mdcache->prepare_realm_merge(target->snaprealm, realm, splits[1]);
+       if (projected)
+         target->project_snaprealm(NULL);
+       else
+         target->snaprealm->merge_to(realm);
+      }
+    }
   }
 
   if (srcdn)
@@ -8406,21 +8517,22 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef
     assert(le->commit.empty());
     mdlog->cancel_entry(le);
     mut->ls = NULL;
-    _rename_rollback_finish(mut, mdr, srcdn, srcdnpv, destdn, straydn, finish_mdr);
+    _rename_rollback_finish(mut, mdr, srcdn, srcdnpv, destdn, straydn, splits, finish_mdr);
   } else {
     assert(!le->commit.empty());
     if (mdr)
       mdr->more()->slave_update_journaled = false;
-    MDSLogContextBase *fin = new C_MDS_LoggedRenameRollback(this, mut, mdr, srcdn, srcdnpv,
-                                                 destdn, straydn, finish_mdr);
+    MDSLogContextBase *fin = new C_MDS_LoggedRenameRollback(this, mut, mdr,
+                                                           srcdn, srcdnpv, destdn, straydn,
+                                                           splits, finish_mdr);
     submit_mdlog_entry(le, fin, mdr, __func__);
     mdlog->flush();
   }
 }
 
 void Server::_rename_rollback_finish(MutationRef& mut, MDRequestRef& mdr, CDentry *srcdn,
-                                    version_t srcdnpv, CDentry *destdn,
-                                    CDentry *straydn, bool finish_mdr)
+                                    version_t srcdnpv, CDentry *destdn, CDentry *straydn,
+                                    map<client_t,MClientSnap*> splits[2], bool finish_mdr)
 {
   dout(10) << "_rename_rollback_finish " << mut->reqid << dendl;
 
@@ -8434,17 +8546,17 @@ void Server::_rename_rollback_finish(MutationRef& mut, MDRequestRef& mdr, CDentr
   }
   if (srcdn) {
     srcdn->pop_projected_linkage();
-    if (srcdn->authority().first == mds->get_nodeid())
+    if (srcdn->authority().first == mds->get_nodeid()) {
       srcdn->mark_dirty(srcdnpv, mut->ls);
+      if (srcdn->get_linkage()->is_primary())
+       srcdn->get_linkage()->get_inode()->state_set(CInode::STATE_AUTH);
+    }
   }
 
   mut->apply();
 
   if (srcdn && srcdn->get_linkage()->is_primary()) {
     CInode *in = srcdn->get_linkage()->get_inode();
-    if (srcdn->authority().first == mds->get_nodeid())
-      in->state_set(CInode::STATE_AUTH);
-    // update subtree map?
     if (in && in->is_dir()) {
       assert(destdn);
       mdcache->adjust_subtree_after_rename(in, destdn->get_dir(), true);
@@ -8468,6 +8580,9 @@ void Server::_rename_rollback_finish(MutationRef& mut, MDRequestRef& mdr, CDentr
       root = mdcache->get_subtree_root(destdn->get_dir());
     if (root)
       mdcache->try_trim_non_auth_subtree(root);
+  } else {
+    mdcache->send_snaps(splits[1]);
+    mdcache->send_snaps(splits[0]);
   }
 
   if (mdr) {
index 653afaf9c0d69f361c784fa903b1b534b911e31e..108eb53f2d70e232d184d415b60c24231270306f 100644 (file)
@@ -307,7 +307,8 @@ public:
   void _commit_slave_rename(MDRequestRef& mdr, int r, CDentry *srcdn, CDentry *destdn, CDentry *straydn);
   void do_rename_rollback(bufferlist &rbl, mds_rank_t master, MDRequestRef& mdr, bool finish_mdr=false);
   void _rename_rollback_finish(MutationRef& mut, MDRequestRef& mdr, CDentry *srcdn, version_t srcdnpv,
-                              CDentry *destdn, CDentry *staydn, bool finish_mdr);
+                              CDentry *destdn, CDentry *staydn, map<client_t,MClientSnap*> splits[2],
+                              bool finish_mdr);
 
 private:
   void reply_client_request(MDRequestRef& mdr, MClientReply *reply);
index bfef001dd267be0310f7296e79f55e99796654cd..4b7f7075daf71d0aef93ceef8481c488e19f4c99 100644 (file)
@@ -553,7 +553,34 @@ void SnapRealm::split_at(SnapRealm *child)
       dout(20) << "    keeping " << *in << dendl;
     }
   }
+}
+
+void SnapRealm::merge_to(SnapRealm *newparent)
+{
+  if (!newparent)
+    newparent = parent;
+  dout(10) << "merge to " << *newparent << " on " << *newparent->inode << dendl;
+
+  assert(open_past_children.empty());
+
+  dout(10) << " open_children are " << open_children << dendl;
+  for (auto realm : open_children) {
+    dout(20) << " child realm " << *realm << " on " << *realm->inode << dendl;
+    newparent->open_children.insert(realm);
+    realm->parent = newparent;
+  }
+  open_children.clear();
+
+  elist<CInode*>::iterator p = inodes_with_caps.begin(member_offset(CInode, item_caps));
+  while (!p.end()) {
+    CInode *in = *p;
+    ++p;
+    in->move_to_realm(newparent);
+  }
+  assert(inodes_with_caps.empty());
 
+  // delete this
+  inode->close_snaprealm();
 }
 
 const bufferlist& SnapRealm::get_snap_trace()
index 7abe656bae784ba7970ec2e97787c606b5cd1ced..cbbe6abb460d7989a443106f0ee3ab64321f281c 100644 (file)
@@ -148,7 +148,7 @@ public:
   void adjust_parent();
 
   void split_at(SnapRealm *child);
-  void join(SnapRealm *child);
+  void merge_to(SnapRealm *newparent);
 
   void add_cap(client_t client, Capability *cap) {
     auto client_caps_entry = client_caps.find(client);
@@ -164,7 +164,6 @@ public:
       client_caps.erase(client);
     }
   }
-
 };
 
 ostream& operator<<(ostream& out, const SnapRealm &realm);
index 28e19822f0b2fa7a1f933017662411e407000f03..1ec3ae662b5e69e7a65d116c7b52d509b721e4c4 100644 (file)
@@ -52,6 +52,7 @@ struct rmdir_rollback {
   string src_dname;
   dirfrag_t dest_dir;
   string dest_dname;
+  bufferlist snapbl;
 
   void encode(bufferlist& bl) const;
   void decode(bufferlist::iterator& bl);
@@ -83,6 +84,8 @@ struct rename_rollback {
   drec orig_src, orig_dest;
   drec stray; // we know this is null, but we want dname, old mtime/rctime
   utime_t ctime;
+  bufferlist srci_snapbl;
+  bufferlist desti_snapbl;
 
   void encode(bufferlist& bl) const;
   void decode(bufferlist::iterator& bl);
index ed796b9b0717b215eb6112f374ec1cec27aa887b..41a087acacfda719e871a1bad398d694ab94517f 100644 (file)
@@ -2301,23 +2301,26 @@ void link_rollback::generate_test_instances(list<link_rollback*>& ls)
 
 void rmdir_rollback::encode(bufferlist& bl) const
 {
-  ENCODE_START(2, 2, bl);
+  ENCODE_START(3, 2, bl);
   encode(reqid, bl);
   encode(src_dir, bl);
   encode(src_dname, bl);
   encode(dest_dir, bl);
   encode(dest_dname, bl);
+  encode(snapbl, bl);
   ENCODE_FINISH(bl);
 }
 
 void rmdir_rollback::decode(bufferlist::iterator& bl)
 {
-  DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl);
+  DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
   decode(reqid, bl);
   decode(src_dir, bl);
   decode(src_dname, bl);
   decode(dest_dir, bl);
   decode(dest_dname, bl);
+  if (struct_v >= 3)
+    decode(snapbl, bl);
   DECODE_FINISH(bl);
 }
 
@@ -2395,23 +2398,29 @@ void rename_rollback::drec::generate_test_instances(list<drec*>& ls)
 
 void rename_rollback::encode(bufferlist &bl) const
 {
-  ENCODE_START(2, 2, bl);
+  ENCODE_START(3, 2, bl);
   encode(reqid, bl);
   encode(orig_src, bl);
   encode(orig_dest, bl);
   encode(stray, bl);
   encode(ctime, bl);
+  encode(srci_snapbl, bl);
+  encode(desti_snapbl, bl);
   ENCODE_FINISH(bl);
 }
 
 void rename_rollback::decode(bufferlist::iterator &bl)
 {
-  DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl);
+  DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
   decode(reqid, bl);
   decode(orig_src, bl);
   decode(orig_dest, bl);
   decode(stray, bl);
   decode(ctime, bl);
+  if (struct_v >= 3) {
+    decode(srci_snapbl, bl);
+    decode(desti_snapbl, bl);
+  }
   DECODE_FINISH(bl);
 }