From: Kotresh HR Date: Mon, 24 Feb 2025 08:12:44 +0000 (+0530) Subject: multi-mds/link: Create referent inode and store backtrace X-Git-Tag: v20.3.0~377^2~30 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=79c3d122d2e8d13791cd519eeb3117ecd214fa68;p=ceph.git multi-mds/link: Create referent inode and store backtrace 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 --- diff --git a/src/mds/Server.cc b/src/mds/Server.cc index 04ddf87c97733..81659ee4ba22b 100644 --- a/src/mds/Server.cc +++ b/src/mds/Server.cc @@ -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(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); diff --git a/src/mds/Server.h b/src/mds/Server.h index ac09c00ffa44c..5f3f63d7ca9bb 100644 --- a/src/mds/Server.h +++ b/src/mds/Server.h @@ -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);