From: Kotresh HR Date: Wed, 26 Feb 2025 12:27:32 +0000 (+0530) Subject: mds/rename: Handle referent inode rollback X-Git-Tag: v20.3.0~377^2~16 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=f66353d36e7ac0651417cd1dccb6a34d6ce7f784;p=ceph.git mds/rename: Handle referent inode rollback 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 --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index d12b696dad11..4f2fc1c02968 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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> 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); diff --git a/src/mds/events/EPeerUpdate.h b/src/mds/events/EPeerUpdate.h index 087caa77996a..772bd81dc300 100644 --- a/src/mds/events/EPeerUpdate.h +++ b/src/mds/events/EPeerUpdate.h @@ -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) {} diff --git a/src/mds/journal.cc b/src/mds/journal.cc index b1888bda3a0c..e786a02a3ae7 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -2655,7 +2655,7 @@ void rmdir_rollback::generate_test_instances(std::list& 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) {