From: Kotresh HR Date: Mon, 24 Feb 2025 10:32:36 +0000 (+0530) Subject: multi-mds/link: Reverse link primary inode to hardlink X-Git-Tag: v20.3.0~377^2~28 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=18165365fe6e5af985c0bb9c7eaa6b5c276c5d3b;p=ceph.git multi-mds/link: Reverse link primary inode to hardlink Reverse link primary/real inode to the hardlink using the referent inode. This patch takes care of link with multiple active mds link. So the primary inode would be auth on one mds and the new hardlink dentry being created would be auth on different mds. This is done as below. 1. Primary inode (CInode) maintains the referent_inodes list 2. Upon referent inode creation on auth mds of dentry being created, the referent inode number is sent to auth mds of the primary/real inode using MMDSPeerRequest::OP_LINKPREP. The auth mds of primary/real inode adds it to the referent_inodes list 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 81659ee4ba22b..4f1343849870d 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -7897,6 +7897,12 @@ void Server::_link_remote(const MDRequestRef& mdr, bool inc, CDentry *dn, CInode auto req = make_message(mdr->reqid, mdr->attempt, op); targeti->set_object_info(req->get_object_info()); req->op_stamp = mdr->get_op_stamp(); + if (mds->mdsmap->allow_referent_inodes()) { + if (inc && newi) + req->referent_ino = newi->ino(); + } else { + req->referent_ino = inodeno_t(0); + } if (auto& desti_srnode = mdr->more()->desti_srnode) encode(*desti_srnode, req->desti_snapbl); @@ -8072,6 +8078,7 @@ void Server::handle_peer_link_prep(const MDRequestRef& mdr) bool inc; bool adjust_realm = false; bool realm_projected = false; + inodeno_t referent_ino = mdr->peer_request->referent_ino; if (mdr->peer_request->get_op() == MMDSPeerRequest::OP_LINKPREP) { inc = true; pi.inode->nlink++; @@ -8085,6 +8092,12 @@ void Server::handle_peer_link_prep(const MDRequestRef& mdr) adjust_realm = true; realm_projected = true; } + // Reverse link referent inode to the primary inode (targeti) + if (referent_ino > 0) { + pi.inode->add_referent_ino(referent_ino); + dout(20) << __func__ << " referent_inodes " << std::hex << pi.inode->get_referent_inodes() + << " referent ino added " << referent_ino << dendl; + } } else { inc = false; pi.inode->nlink--; diff --git a/src/messages/MMDSPeerRequest.h b/src/messages/MMDSPeerRequest.h index 1799ab361a115..4b13ebfca67d3 100644 --- a/src/messages/MMDSPeerRequest.h +++ b/src/messages/MMDSPeerRequest.h @@ -20,7 +20,7 @@ #include "messages/MMDSOp.h" class MMDSPeerRequest final : public MMDSOp { - static constexpr int HEAD_VERSION = 1; + static constexpr int HEAD_VERSION = 2; static constexpr int COMPAT_VERSION = 1; public: static constexpr int OP_XLOCK = 1; @@ -129,6 +129,7 @@ public: ceph::buffer::list srci_snapbl; ceph::buffer::list desti_snapbl; + inodeno_t referent_ino; //referent inode public: metareqid_t get_reqid() const { return reqid; } __u32 get_attempt() const { return attempt; } @@ -194,6 +195,7 @@ public: encode(srci_snapbl, payload); encode(desti_snapbl, payload); encode(alternate_name, payload); + encode(referent_ino, payload); } void decode_payload() override { using ceph::decode; @@ -216,6 +218,8 @@ public: decode(srci_snapbl, p); decode(desti_snapbl, p); decode(alternate_name, p); + if (header.version >= 2) + decode(referent_ino, p); } std::string_view get_type_name() const override { return "peer_request"; }