]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mds/unlink: Remove referent inode on unlink
authorKotresh HR <khiremat@redhat.com>
Tue, 25 Feb 2025 07:36:23 +0000 (13:06 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 06:20:47 +0000 (11:50 +0530)
The referent inode needs to be removed as part
of unlink operation on the secondary hardlink.
So prepare a straydn for the referent inode
and remove it. This patch takes care of single
mds

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

index ef6906bcb9741f8cbde91e0a111f963e8bbdb872..92535beef4c100dc6d7b8160afa4b3c4edf0d36f 100644 (file)
@@ -8441,6 +8441,11 @@ void Server::handle_client_unlink(const MDRequestRef& mdr)
     if (!straydn)
       return;
     dout(10) << " straydn is " << *straydn << dendl;
+  } else if (dnl->is_referent_remote()) {
+    straydn = prepare_stray_dentry(mdr, dnl->get_referent_inode());
+    if (!straydn)
+      return;
+    dout(10) << __func__ << " referent straydn is " << *straydn << dendl;
   } else if (mdr->straydn) {
     mdr->unpin(mdr->straydn);
     mdr->straydn = NULL;
@@ -8553,7 +8558,9 @@ void Server::_unlink_local(const MDRequestRef& mdr, CDentry *dn, CDentry *strayd
 
   CDentry::linkage_t *dnl = dn->get_projected_linkage();
   CInode *in = dnl->get_inode();
-
+  CInode *ref_in = dnl->get_referent_inode();
+  if (dnl->is_referent_remote())
+    ceph_assert(ref_in->is_auth());
 
   // ok, let's do it.
   mdr->ls = mdlog->get_current_segment();
@@ -8569,8 +8576,12 @@ void Server::_unlink_local(const MDRequestRef& mdr, CDentry *dn, CDentry *strayd
   }
 
   if (straydn) {
-    ceph_assert(dnl->is_primary());
-    straydn->push_projected_linkage(in);
+    ceph_assert(dnl->is_primary() || dnl->is_referent_remote());
+    if (dnl->is_primary())
+      straydn->push_projected_linkage(in);
+    else if (dnl->is_referent_remote()) {
+      straydn->push_projected_linkage(ref_in);
+    }
   }
 
   // the unlinked dentry
@@ -8602,11 +8613,33 @@ void Server::_unlink_local(const MDRequestRef& mdr, CDentry *dn, CDentry *strayd
     // will manually pop projected inode
 
     // primary link.  add stray dentry.
-    mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, -1);
-    mdcache->predirty_journal_parents(mdr, &le->metablob, in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
+    if (dnl->is_primary()) {
+      mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, -1);
+      mdcache->predirty_journal_parents(mdr, &le->metablob, in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
 
-    pi.inode->update_backtrace();
-    le->metablob.add_primary_dentry(straydn, in, true, true);
+      pi.inode->update_backtrace();
+      le->metablob.add_primary_dentry(straydn, in, true, true);
+    } else if (dnl->is_referent_remote()) {
+      // referent remote link - to purge the referent inode created
+      auto pri = ref_in->project_inode(mdr);
+      {
+        std::string t;
+        dn->make_path_string(t, true);
+        pri.inode->stray_prior_path = std::move(t);
+      }
+      pri.inode->version = ref_in->pre_dirty();
+      // Purge enqueue requires inode to be primary and nlink to be 0
+      // link count is never > 1 for referent inode, just set it to 0
+      pri.inode->nlink = 0;
+      ref_in->state_set(CInode::STATE_ORPHAN);
+      mdcache->predirty_journal_parents(mdr, &le->metablob, ref_in, straydn->get_dir(), PREDIRTY_PRIMARY|PREDIRTY_DIR, 1);
+      pri.inode->update_backtrace();
+      le->metablob.add_primary_dentry(straydn, ref_in, true, true);
+
+      mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_DIR, -1);
+      mdcache->predirty_journal_parents(mdr, &le->metablob, in, 0, PREDIRTY_PRIMARY);
+      mdcache->journal_dirty_inode(mdr.get(), &le->metablob, in);
+    }
   } else {
     // remote link.  update remote inode.
     mdcache->predirty_journal_parents(mdr, &le->metablob, in, dn->get_dir(), PREDIRTY_DIR, -1);
@@ -8651,9 +8684,14 @@ void Server::_unlink_local_finish(const MDRequestRef& mdr,
   if (straydn) {
     // if there is newly created snaprealm, need to split old snaprealm's
     // inodes_with_caps. So pop snaprealm before linkage changes.
-    strayin = dn->get_linkage()->get_inode();
-    hadrealm = strayin->snaprealm ? true : false;
-    strayin->early_pop_projected_snaprealm();
+    if (dn->get_linkage()->is_primary()) {
+      strayin = dn->get_linkage()->get_inode();
+      hadrealm = strayin->snaprealm ? true : false;
+      strayin->early_pop_projected_snaprealm();
+    } else if (dn->get_linkage()->is_referent_remote()) {
+      // No snapshots on referent inodes - Ignore snaprealm related stuff for referent inodes
+      strayin = dn->get_linkage()->get_referent_inode();
+    }
   }
 
   // unlink main dentry