]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds/rename: Handle referent inode rollback
authorKotresh HR <khiremat@redhat.com>
Wed, 26 Feb 2025 12:27:32 +0000 (17:57 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 06:20:47 +0000 (11:50 +0530)
If the destination dentry exists and is referent
remote, then the rollback should take care of
restoring the referent inode and the add back
the referent inode number to the referent_inode
list of the primary/real inode. This patch takes
care of the same.

Fixes: https://tracker.ceph.com/issues/54205
Signed-off-by: Kotresh HR <khiremat@redhat.com>
src/mds/Server.cc
src/mds/events/EPeerUpdate.h
src/mds/journal.cc

index d12b696dad11da8d52bc87681fad9d358fa9cd34..4f2fc1c029684b02a648d0788a2ebf94026cf2fa 100644 (file)
@@ -10913,23 +10913,29 @@ void Server::handle_peer_rename_prep(const MDRequestRef& mdr)
   rollback.orig_src.dirfrag_old_mtime = srcdn->get_dir()->get_projected_fnode()->fragstat.mtime;
   rollback.orig_src.dirfrag_old_rctime = srcdn->get_dir()->get_projected_fnode()->rstat.rctime;
   rollback.orig_src.dname = srcdn->get_name();
+  rollback.orig_src.referent_ino = 0;
   if (srcdnl->is_primary())
     rollback.orig_src.ino = srcdnl->get_inode()->ino();
   else {
     ceph_assert(srcdnl->is_remote() || srcdnl->is_referent_remote());
     rollback.orig_src.remote_ino = srcdnl->get_remote_ino();
     rollback.orig_src.remote_d_type = srcdnl->get_remote_d_type();
+    if (srcdnl->is_referent_remote())
+      rollback.orig_src.referent_ino = srcdnl->get_referent_ino();
   }
   
   rollback.orig_dest.dirfrag = destdn->get_dir()->dirfrag();
   rollback.orig_dest.dirfrag_old_mtime = destdn->get_dir()->get_projected_fnode()->fragstat.mtime;
   rollback.orig_dest.dirfrag_old_rctime = destdn->get_dir()->get_projected_fnode()->rstat.rctime;
   rollback.orig_dest.dname = destdn->get_name();
+  rollback.orig_dest.referent_ino = 0;
   if (destdnl->is_primary())
     rollback.orig_dest.ino = destdnl->get_inode()->ino();
   else if (destdnl->is_remote() || destdnl->is_referent_remote()) {
     rollback.orig_dest.remote_ino = destdnl->get_remote_ino();
     rollback.orig_dest.remote_d_type = destdnl->get_remote_d_type();
+    if (destdnl->is_referent_remote())
+      rollback.orig_dest.referent_ino = destdnl->get_referent_ino();
   }
   
   if (straydn) {
@@ -11296,12 +11302,16 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t leader, const MDRequ
     dout(10) << " destdir not found" << dendl;
 
   CInode *in = NULL;
+  CInode *referent_in = nullptr;
   if (rollback.orig_src.ino) {
     in = mdcache->get_inode(rollback.orig_src.ino);
     if (in && in->is_dir())
       ceph_assert(srcdn && destdn);
-  } else
+  } else {
     in = mdcache->get_inode(rollback.orig_src.remote_ino);
+    if (rollback.orig_src.referent_ino)
+      referent_in = mdcache->get_inode(rollback.orig_src.referent_ino);
+  }
 
   CDir *straydir = NULL;
   CDentry *straydn = NULL;
@@ -11320,12 +11330,16 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t leader, const MDRequ
   }
 
   CInode *target = NULL;
+  CInode *target_referent_in = nullptr;
   if (rollback.orig_dest.ino) {
     target = mdcache->get_inode(rollback.orig_dest.ino);
     if (target)
       ceph_assert(destdn && straydn);
-  } else if (rollback.orig_dest.remote_ino)
+  } else if (rollback.orig_dest.remote_ino) {
     target = mdcache->get_inode(rollback.orig_dest.remote_ino);
+    if (rollback.orig_dest.referent_ino)
+      target_referent_in = mdcache->get_inode(rollback.orig_dest.referent_ino);
+  }
 
   // can't use is_auth() in the resolve stage
   mds_rank_t whoami = mds->get_nodeid();
@@ -11348,9 +11362,15 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t leader, const MDRequ
     if (rollback.orig_src.ino) {
       ceph_assert(in);
       srcdn->push_projected_linkage(in);
-    } else
-      srcdn->push_projected_linkage(rollback.orig_src.remote_ino,
-                                   rollback.orig_src.remote_d_type);
+    } else {
+      if (rollback.orig_src.referent_ino) {
+       ceph_assert(referent_in);
+        srcdn->push_projected_linkage(referent_in, rollback.orig_src.remote_ino, rollback.orig_src.referent_ino);
+      } else {
+        srcdn->push_projected_linkage(rollback.orig_src.remote_ino,
+                                      rollback.orig_src.remote_d_type);
+      }
+    }
   }
 
   map<client_t,ref_t<MClientSnap>> splits[2];
@@ -11413,8 +11433,13 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t leader, const MDRequ
     if (rollback.orig_dest.ino && target) {
       destdn->push_projected_linkage(target);
     } else if (rollback.orig_dest.remote_ino) {
-      destdn->push_projected_linkage(rollback.orig_dest.remote_ino,
-                                    rollback.orig_dest.remote_d_type);
+      if (rollback.orig_dest.referent_ino) {
+       ceph_assert(target_referent_in);
+        destdn->push_projected_linkage(target_referent_in, rollback.orig_dest.remote_ino, rollback.orig_dest.referent_ino);
+      } else {
+        destdn->push_projected_linkage(rollback.orig_dest.remote_ino,
+                                       rollback.orig_dest.remote_d_type);
+      }
     } else {
       // the dentry will be trimmed soon, it's ok to have wrong linkage
       if (rollback.orig_dest.ino)
@@ -11452,8 +11477,15 @@ void Server::do_rename_rollback(bufferlist &rbl, mds_rank_t leader, const MDRequ
       else
        ceph_assert(rollback.orig_dest.remote_ino &&
               rollback.orig_dest.remote_ino == rollback.orig_src.ino);
-    } else
+    } else {
       ti->nlink++;
+      //add referent inode back to the list
+      if (rollback.orig_dest.referent_ino) {
+        ti->add_referent_ino(rollback.orig_dest.referent_ino);
+        dout(10) << __func__ << " referent_inodes " << std::hex << ti->get_referent_inodes()
+                 << " referent ino added " << rollback.orig_dest.referent_ino << dendl;
+      }
+    }
 
     if (!projected)
       target->reset_inode(ti);
index 087caa77996abee4022116c1770b54672bce4dee..772bd81dc3007b68645832a27d711cdc90827e31 100644 (file)
@@ -74,6 +74,7 @@ struct rename_rollback {
     std::string dname;
     char remote_d_type;
     utime_t old_ctime;
+    inodeno_t referent_ino;
 
     drec() : remote_d_type((char)S_IFREG) {}
 
index b1888bda3a0c3e1876778d563d39917e06e7251e..e786a02a3ae77b9160f68b11fe647e72c81902a6 100644 (file)
@@ -2655,7 +2655,7 @@ void rmdir_rollback::generate_test_instances(std::list<rmdir_rollback*>& ls)
 
 void rename_rollback::drec::encode(bufferlist &bl) const
 {
-  ENCODE_START(2, 2, bl);
+  ENCODE_START(3, 2, bl);
   encode(dirfrag, bl);
   encode(dirfrag_old_mtime, bl);
   encode(dirfrag_old_rctime, bl);
@@ -2664,12 +2664,13 @@ void rename_rollback::drec::encode(bufferlist &bl) const
   encode(dname, bl);
   encode(remote_d_type, bl);
   encode(old_ctime, bl);
+  encode(referent_ino, bl);
   ENCODE_FINISH(bl);
 }
 
 void rename_rollback::drec::decode(bufferlist::const_iterator &bl)
 {
-  DECODE_START_LEGACY_COMPAT_LEN(2, 2, 2, bl);
+  DECODE_START_LEGACY_COMPAT_LEN(3, 2, 2, bl);
   decode(dirfrag, bl);
   decode(dirfrag_old_mtime, bl);
   decode(dirfrag_old_rctime, bl);
@@ -2678,6 +2679,8 @@ void rename_rollback::drec::decode(bufferlist::const_iterator &bl)
   decode(dname, bl);
   decode(remote_d_type, bl);
   decode(old_ctime, bl);
+  if (struct_v >= 3)
+    decode(referent_ino, bl);
   DECODE_FINISH(bl);
 }
 
@@ -2689,6 +2692,7 @@ void rename_rollback::drec::dump(Formatter *f) const
   f->dump_int("ino", ino);
   f->dump_int("remote ino", remote_ino);
   f->dump_string("dname", dname);
+  f->dump_int("referent_ino", referent_ino);
   uint32_t type = DTTOIF(remote_d_type) & S_IFMT; // convert to type entries
   string type_string;
   switch(type) {