]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
multi-mds/link: Create referent inode and store backtrace
authorKotresh HR <khiremat@redhat.com>
Mon, 24 Feb 2025 08:12:44 +0000 (13:42 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 06:20:47 +0000 (11:50 +0530)
On hardlink creation, create a referent inode (CInode)
and store backtrace for the hardlink. This patch
takes care of multiple active mds. So the primary inode
would be auth on one mds and the new hardlink dentry
being created would be auth on different mds.

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

index 04ddf87c977332ac9b32d7ddfe07580bee702508..81659ee4ba22b0ddd62f91b22fba3c4a3a8f2b2a 100644 (file)
@@ -7848,14 +7848,15 @@ class C_MDS_link_remote_finish : public ServerLogContext {
   bool inc;
   CDentry *dn;
   CInode *targeti;
+  CInode *referenti;
   version_t dpv;
 public:
-  C_MDS_link_remote_finish(Server *s, const MDRequestRef& r, bool i, CDentry *d, CInode *ti) :
-    ServerLogContext(s, r), inc(i), dn(d), targeti(ti),
+  C_MDS_link_remote_finish(Server *s, const MDRequestRef& r, bool i, CDentry *d, CInode *ti, CInode *ri) :
+    ServerLogContext(s, r), inc(i), dn(d), targeti(ti), referenti(ri),
     dpv(d->get_projected_version()) {}
   void finish(int r) override {
     ceph_assert(r == 0);
-    server->_link_remote_finish(mdr, inc, dn, targeti, dpv);
+    server->_link_remote_finish(mdr, inc, dn, targeti, referenti, dpv);
   }
 };
 
@@ -7865,6 +7866,17 @@ void Server::_link_remote(const MDRequestRef& mdr, bool inc, CDentry *dn, CInode
           << (inc ? "link ":"unlink ")
           << *dn << " to " << *targeti << dendl;
 
+  CInode *newi = nullptr;
+
+  // create referent inode. Don't re-create on retry
+  if (mds->mdsmap->allow_referent_inodes() && inc) {
+    if (!mdr->alloc_ino && !mdr->used_prealloc_ino)
+      newi = prepare_new_inode(mdr, dn->get_dir(), inodeno_t(0), targeti->inode->mode, nullptr, true);
+    else
+      newi = mdcache->get_inode(mdr->alloc_ino ? mdr->alloc_ino : mdr->used_prealloc_ino);
+    ceph_assert(newi);
+  }
+
   // 1. send LinkPrepare to dest (journal nlink++ prepare)
   mds_rank_t linkauth = targeti->authority().first;
   if (mdr->more()->witnessed.count(linkauth) == 0) {
@@ -7885,6 +7897,7 @@ 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 (auto& desti_srnode = mdr->more()->desti_srnode)
       encode(*desti_srnode, req->desti_snapbl);
     mds->send_message_mds(req, linkauth);
@@ -7916,11 +7929,27 @@ void Server::_link_remote(const MDRequestRef& mdr, bool inc, CDentry *dn, CInode
   }
 
   if (inc) {
-    dn->pre_dirty();
+    version_t dnpv = dn->pre_dirty();
+
+    //referent inode stuff
+    if (newi) {
+      auto _inode = newi->_get_inode();
+      _inode->version = dnpv;
+      _inode->update_backtrace();
+    }
+
     mdcache->predirty_journal_parents(mdr, &le->metablob, targeti, dn->get_dir(), PREDIRTY_DIR, 1);
-    // TODO: Pass referent inode upon creation. It's adding just remote dentry now
-    le->metablob.add_remote_dentry(dn, true, targeti->ino(), targeti->d_type(), 0, nullptr); // new remote
-    dn->push_projected_linkage(targeti->ino(), targeti->d_type());
+
+    if (newi) {
+      dout(20) << __func__ << " calling metablob add_remote_dentry with referent_ino= " << newi->ino() << dendl;
+      le->metablob.add_remote_dentry(dn, true, targeti->ino(), targeti->d_type(), newi->ino(), newi); // new remote
+      // journal allocated referent inode.
+      journal_allocated_inos(mdr, &le->metablob);
+      dn->push_projected_linkage(newi, targeti->ino(), newi->ino());
+    } else {
+      le->metablob.add_remote_dentry(dn, true, targeti->ino(), targeti->d_type(), inodeno_t(0), nullptr); // new remote
+      dn->push_projected_linkage(targeti->ino(), targeti->d_type());
+    }
   } else {
     dn->pre_dirty();
     mdcache->predirty_journal_parents(mdr, &le->metablob, targeti, dn->get_dir(), PREDIRTY_DIR, -1);
@@ -7930,11 +7959,11 @@ void Server::_link_remote(const MDRequestRef& mdr, bool inc, CDentry *dn, CInode
   }
 
   journal_and_reply(mdr, (inc ? targeti : nullptr), dn, le,
-                   new C_MDS_link_remote_finish(this, mdr, inc, dn, targeti));
+                   new C_MDS_link_remote_finish(this, mdr, inc, dn, targeti, newi));
 }
 
 void Server::_link_remote_finish(const MDRequestRef& mdr, bool inc,
-                                CDentry *dn, CInode *targeti,
+                                CDentry *dn, CInode *targeti, CInode *referenti,
                                 version_t dpv)
 {
   dout(10) << "_link_remote_finish "
@@ -7952,6 +7981,12 @@ void Server::_link_remote_finish(const MDRequestRef& mdr, bool inc,
     if (!dnl->get_inode())
       dn->link_remote(dnl, targeti);
     dn->mark_dirty(dpv, mdr->ls);
+
+    if (referenti) {
+      // dirty referent inode
+      referenti->mark_dirty(mdr->ls);
+      referenti->mark_dirty_parent(mdr->ls, true);
+    }
   } else {
     // unlink main dentry
     dn->get_dir()->unlink_inode(dn);
index ac09c00ffa44c4cc8c5f5d3e1c852f6514794539..5f3f63d7ca9bb9ef583a494ba6408fe21985bae9 100644 (file)
@@ -284,7 +284,7 @@ public:
 
   void _link_remote(const MDRequestRef& mdr, bool inc, CDentry *dn, CInode *targeti);
   void _link_remote_finish(const MDRequestRef& mdr, bool inc, CDentry *dn, CInode *targeti,
-                          version_t);
+                           CInode *referenti, version_t);
 
   void handle_peer_link_prep(const MDRequestRef& mdr);
   void _logged_peer_link(const MDRequestRef& mdr, CInode *targeti, bool adjust_realm);