From: Kotresh HR Date: Tue, 25 Feb 2025 07:36:23 +0000 (+0530) Subject: mds/unlink: Remove referent inode on unlink X-Git-Tag: v20.3.0~377^2~25 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=bcf2e7d9a0f9ef9b20de85b95c23a9cbe57525ab;p=ceph.git mds/unlink: Remove referent inode on unlink 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 --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index ef6906bcb974..92535beef4c1 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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