]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
multi-mds/link: Reverse link primary inode to hardlink
authorKotresh HR <khiremat@redhat.com>
Mon, 24 Feb 2025 10:32:36 +0000 (16:02 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 06:20:47 +0000 (11:50 +0530)
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 <khiremat@redhat.com>
src/mds/Server.cc
src/messages/MMDSPeerRequest.h

index 81659ee4ba22b0ddd62f91b22fba3c4a3a8f2b2a..4f1343849870d431695373479569e7e25d9326fa 100644 (file)
@@ -7897,6 +7897,12 @@ void Server::_link_remote(const MDRequestRef& mdr, bool inc, CDentry *dn, CInode
     auto req = make_message<MMDSPeerRequest>(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--;
index 1799ab361a11587cac19e4d0c2c4bb40a06d1bb6..4b13ebfca67d31d71998293eb759fa912c0bf232 100644 (file)
@@ -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"; }