]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: pop projected snaprealm before inode's parent changes
authorYan, Zheng <zyan@redhat.com>
Tue, 19 Sep 2017 02:40:56 +0000 (10:40 +0800)
committerYan, Zheng <zyan@redhat.com>
Fri, 9 Feb 2018 10:41:28 +0000 (18:41 +0800)
When creating new snaprealm, we need to split its parent snaprealm's
inodes_with_caps. If new snaprealm is newly created during rename,
inode's original snaprealm's inodes_with_caps should be split. So in
rename/rmdir cases, we should pop projectd snaprealm before inode's
parent changes

Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/mds/CInode.cc
src/mds/CInode.h
src/mds/Server.cc

index ae310cc4a25c433b9161023441d0c2a87b3c2fd9..761d68de2813647bb753f3af36c9faa0cb241ea6 100644 (file)
@@ -408,7 +408,7 @@ void CInode::pop_and_dirty_projected_inode(LogSegment *ls)
   }
 
   if (projected_nodes.front().snapnode != projected_inode::UNDEF_SRNODE) {
-    pop_projected_snaprealm(projected_nodes.front().snapnode);
+    pop_projected_snaprealm(projected_nodes.front().snapnode, false);
     --num_projected_srnodes;
   }
 
@@ -486,11 +486,21 @@ void CInode::record_snaprealm_past_parent(sr_t *new_snap, SnapRealm *newparent)
   }
 }
 
-void CInode::pop_projected_snaprealm(sr_t *next_snaprealm)
+void CInode::early_pop_projected_snaprealm()
+{
+  assert(!projected_nodes.empty());
+  if (projected_nodes.front().snapnode != projected_inode::UNDEF_SRNODE) {
+    pop_projected_snaprealm(projected_nodes.front().snapnode, true);
+    projected_nodes.front().snapnode = projected_inode::UNDEF_SRNODE;
+    --num_projected_srnodes;
+  }
+}
+
+void CInode::pop_projected_snaprealm(sr_t *next_snaprealm, bool early)
 {
   if (next_snaprealm) {
-    dout(10) << __func__ << " " << next_snaprealm
-            << " seq" << next_snaprealm->seq << dendl;
+    dout(10) << __func__ << (early ? " (early) " : " ")
+            << next_snaprealm << " seq " << next_snaprealm->seq << dendl;
     bool invalidate_cached_snaps = false;
     if (!snaprealm) {
       open_snaprealm();
@@ -516,7 +526,7 @@ void CInode::pop_projected_snaprealm(sr_t *next_snaprealm)
     if (snaprealm->parent)
       dout(10) << " realm " << *snaprealm << " parent " << *snaprealm->parent << dendl;
   } else {
-    dout(10) << __func__ << " null" << dendl;
+    dout(10) << __func__ << (early ? " (early) null" : " null") << dendl;
     assert(snaprealm);
     snaprealm->merge_to(NULL);
   }
index 2d11b84c042c8b5f6c2ad61041d8b0d2a35aa8a3..0ab629b82c36bb691bcdbb709e58ba651f1ee53e 100644 (file)
@@ -512,9 +512,10 @@ public:
   }
   void record_snaprealm_past_parent(sr_t *new_snap, SnapRealm *newparent);
   void project_snaprealm_past_parent(SnapRealm *newparent);
+  void early_pop_projected_snaprealm();
 
 private:
-  void pop_projected_snaprealm(sr_t *next_snaprealm);
+  void pop_projected_snaprealm(sr_t *next_snaprealm, bool early);
 
 public:
   mempool_old_inode& cow_old_inode(snapid_t follows, bool cow_head);
index cfd89fcfe04ee10fd487dc4e079b7c07062a990a..22ca2817872675c1ae95507509b0cd7b1f99a34b 100644 (file)
@@ -6108,7 +6108,6 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn, sna
     dn->make_path_string(t, true);
     pi.inode.stray_prior_path = std::move(t);
   }
-  mdr->add_projected_inode(in); // do this _after_ my dn->pre_dirty().. we apply that one manually.
   pi.inode.version = in->pre_dirty();
   pi.inode.ctime = mdr->get_op_stamp();
   pi.inode.change_attr++;
@@ -6116,9 +6115,10 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn, sna
   if (pi.inode.nlink == 0)
     in->state_set(CInode::STATE_ORPHAN);
 
-  if (dnl->is_primary()) {
+  if (straydn) {
+    // will manually pop projected inode
+
     // primary link.  add stray dentry.
-    assert(straydn);
     mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, -1);
     mdcache->predirty_journal_parents(mdr, &le->metablob, in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
 
@@ -6134,6 +6134,7 @@ void Server::_unlink_local(MDRequestRef& mdr, CDentry *dn, CDentry *straydn, sna
     pi.inode.update_backtrace();
     le->metablob.add_primary_dentry(straydn, in, true, true);
   } else {
+    mdr->add_projected_inode(in);
     // remote link.  update remote inode.
     mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_DIR, -1);
     mdcache->predirty_journal_parents(mdr, &le->metablob, in, 0, PREDIRTY_PRIMARY);
@@ -6174,19 +6175,26 @@ void Server::_unlink_local_finish(MDRequestRef& mdr,
   if (!mdr->more()->witnessed.empty())
     mdcache->logged_master_update(mdr->reqid);
 
+  CInode *strayin = NULL;
+  bool hadrealm = false;
+  if (straydn) {
+    // if there is newly created snaprealm, need to split old snaprealm's
+    // inodes_with_caps. So pop snaprealm before linkage changes.
+    strayin = dn->get_linkage()->get_inode();
+    hadrealm = strayin->snaprealm ? true : false;
+    strayin->early_pop_projected_snaprealm();
+  }
+
   // unlink main dentry
   dn->get_dir()->unlink_inode(dn);
   dn->pop_projected_linkage();
 
   // relink as stray?  (i.e. was primary link?)
-  CInode *strayin = NULL;
-  bool hadrealm = false;
   if (straydn) {
     dout(20) << " straydn is " << *straydn << dendl;
-    CDentry::linkage_t *straydnl = straydn->pop_projected_linkage();
-    strayin = straydnl->get_inode();
+    straydn->pop_projected_linkage();
 
-    hadrealm = strayin->snaprealm ? true : false;
+    strayin->pop_and_dirty_projected_inode(mdr->ls);
 
     mdcache->touch_dentry_bottom(straydn);
   }
@@ -6355,24 +6363,28 @@ void Server::handle_slave_rmdir_prep(MDRequestRef& mdr)
 void Server::_logged_slave_rmdir(MDRequestRef& mdr, CDentry *dn, CDentry *straydn)
 {
   dout(10) << "_logged_slave_rmdir " << *mdr << " on " << *dn << dendl;
+  CInode *in = dn->get_linkage()->get_inode();
+
+  bool new_realm;
+  if (mdr->slave_request->desti_snapbl.length()) {
+    new_realm = !in->snaprealm;
+    in->decode_snap_blob(mdr->slave_request->desti_snapbl);
+    assert(in->snaprealm);
+    assert(in->snaprealm->have_past_parents_open());
+  } else {
+    new_realm = false;
+  }
 
   // update our cache now, so we are consistent with what is in the journal
   // when we journal a subtree map
-  CInode *in = dn->get_linkage()->get_inode();
   dn->get_dir()->unlink_inode(dn);
   straydn->pop_projected_linkage();
   dn->pop_projected_linkage();
 
   mdcache->adjust_subtree_after_rename(in, dn->get_dir(), mdr->more()->slave_update_journaled);
 
-  if (mdr->slave_request->desti_snapbl.length()) {
-    bool hadrealm = (in->snaprealm ? true : false);
-    in->decode_snap_blob(mdr->slave_request->desti_snapbl);
-    assert(in->snaprealm);
-    assert(in->snaprealm->have_past_parents_open());
-    if (!hadrealm)
+  if (new_realm)
       mdcache->do_realm_invalidate_and_update_notify(in, CEPH_SNAP_OP_SPLIT, false);
-  }
 
   // done.
   mdr->slave_request->put();
@@ -7557,18 +7569,12 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
     if (destdnl->is_primary()) {
       assert(straydn);
       dout(10) << "straydn is " << *straydn << dendl;
-      destdn->get_dir()->unlink_inode(destdn, false);
 
-      straydn->pop_projected_linkage();
-      if (mdr->is_slave() && !mdr->more()->slave_update_journaled)
-       assert(!straydn->is_projected()); // no other projected
-
-      mdcache->touch_dentry_bottom(straydn);  // drop dn as quickly as possible.
-
-      // nlink-- targeti
+      // if there is newly created snaprealm, need to split old snaprealm's
+      // inodes_with_caps. So pop snaprealm before linkage changes.
       if (destdn->is_auth()) {
        bool hadrealm = (oldin->snaprealm ? true : false);
-       oldin->pop_and_dirty_projected_inode(mdr->ls);
+       oldin->early_pop_projected_snaprealm();
        new_oldin_snaprealm = (oldin->snaprealm && !hadrealm);
       } else {
        assert(mdr->slave_request);
@@ -7579,6 +7585,18 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
          assert(oldin->snaprealm->have_past_parents_open());
        }
       }
+
+      destdn->get_dir()->unlink_inode(destdn, false);
+
+      straydn->pop_projected_linkage();
+      if (mdr->is_slave() && !mdr->more()->slave_update_journaled)
+       assert(!straydn->is_projected()); // no other projected
+
+      // nlink-- targeti
+      if (destdn->is_auth())
+       oldin->pop_and_dirty_projected_inode(mdr->ls);
+
+      mdcache->touch_dentry_bottom(straydn);  // drop dn as quickly as possible.
     } else if (destdnl->is_remote()) {
       destdn->get_dir()->unlink_inode(destdn, false);
       if (oldin->is_auth())
@@ -7591,6 +7609,24 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
   assert(in);
 
   bool srcdn_was_remote = srcdnl->is_remote();
+  if (!srcdn_was_remote) {
+    // if there is newly created snaprealm, need to split old snaprealm's
+    // inodes_with_caps. So pop snaprealm before linkage changes.
+    if (destdn->is_auth()) {
+      bool hadrealm = (in->snaprealm ? true : false);
+      in->early_pop_projected_snaprealm();
+      new_in_snaprealm = (in->snaprealm && !hadrealm);
+    } else {
+      assert(mdr->slave_request);
+      if (mdr->slave_request->srci_snapbl.length()) {
+       new_in_snaprealm = !in->snaprealm;
+       in->decode_snap_blob(mdr->slave_request->srci_snapbl);
+       assert(in->snaprealm);
+       assert(in->snaprealm->have_past_parents_open());
+      }
+    }
+  }
+
   srcdn->get_dir()->unlink_inode(srcdn);
 
   // dest
@@ -7654,19 +7690,8 @@ void Server::_rename_apply(MDRequestRef& mdr, CDentry *srcdn, CDentry *destdn, C
       mdr->clear_ambiguous_auth();
     }
 
-    if (destdn->is_auth()) {
-      bool hadrealm = (in->snaprealm ? true : false);
+    if (destdn->is_auth())
       in->pop_and_dirty_projected_inode(mdr->ls);
-      new_in_snaprealm = (in->snaprealm && !hadrealm);
-    } else {
-      assert(mdr->slave_request);
-      if (mdr->slave_request->srci_snapbl.length()) {
-       new_in_snaprealm = !in->snaprealm;
-       in->decode_snap_blob(mdr->slave_request->srci_snapbl);
-       assert(in->snaprealm);
-       assert(in->snaprealm->have_past_parents_open());
-      }
-    }
   }
 
   // src