From ce3181ed251b1e75c2b5e78336fc289d41d0cc64 Mon Sep 17 00:00:00 2001 From: Kotresh HR Date: Tue, 4 Mar 2025 21:48:57 +0530 Subject: [PATCH] mds: Fix MMDSCacheRejoin::dn_strong version check failure MMDSCacheRejoin::dn_strong structure inside MMDSCacheRejoin class is not versioned. But the referent inodes feature requires to add a new variable to 'dn_strong'. Since it's not versioned, the ceph-object-corpus encode/decode test (src//readable.sh) is failing for no backward compatibility. This patch fixes the versioning issue of MMDSCacheRejoin::dn_strong by introducing a new struct MMDSCacheRejoin::dn_strong_new which encapsulates 'dn_strong' and the new variable and is versioned. Signed-off-by: Kotresh HR --- src/mds/MDCache.cc | 470 ++++++++++++++----------- src/messages/MMDSCacheRejoin.h | 79 ++++- src/tools/ceph-dencoder/common_types.h | 1 + 3 files changed, 340 insertions(+), 210 deletions(-) diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 166f90e3054d6..c432fe4beb3b1 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -81,6 +81,17 @@ using namespace std; +// variants to handle MMDSCacheRejoin::dn_strong version handling +using StrongDentriesVariant = std::variant< + decltype(MMDSCacheRejoin::strong_dentries), + decltype(MMDSCacheRejoin::strong_dentries_new) +>; + +using DnStrongVariant = std::variant< + MMDSCacheRejoin::dn_strong, + MMDSCacheRejoin::dn_strong_new +>; + static ostream& _prefix(std::ostream *_dout, MDSRank *mds) { return *_dout << "mds." << mds->get_nodeid() << ".cache "; } @@ -4683,10 +4694,18 @@ void MDCache::rejoin_scour_survivor_replicas(mds_rank_t from, const cref_tis_replica(from)) { if (ack) { - const auto it = ack->strong_dentries.find(dir->dirfrag()); - if (it != ack->strong_dentries.end() && it->second.count(string_snap_t(dn->get_name(), dn->last)) > 0) { - continue; - } + //MMDSCacheRejoin::dn_strong version handling + if (!ack->strong_dentries_new.empty()) { + const auto it = ack->strong_dentries_new.find(dir->dirfrag()); + if (it != ack->strong_dentries_new.end() && it->second.count(string_snap_t(dn->get_name(), dn->last)) > 0) { + continue; + } + } else { + const auto it = ack->strong_dentries.find(dir->dirfrag()); + if (it != ack->strong_dentries.end() && it->second.count(string_snap_t(dn->get_name(), dn->last)) > 0) { + continue; + } + } } dentry_remove_replica(dn, from, gather_locks); dout(10) << " rem " << *dn << dendl; @@ -4800,121 +4819,139 @@ void MDCache::handle_cache_rejoin_strong(const cref_t &strong) refragged = true; } - const auto it = strong->strong_dentries.find(dirfrag); - if (it != strong->strong_dentries.end()) { - const auto& dmap = it->second; - for (const auto &q : dmap) { - const string_snap_t& ss = q.first; - const MMDSCacheRejoin::dn_strong& d = q.second; - CDentry *dn; - if (!refragged) - dn = dir->lookup(ss.name, ss.snapid); - else { - frag_t fg = diri->pick_dirfrag(ss.name); - dir = diri->get_dirfrag(fg); - ceph_assert(dir); - dn = dir->lookup(ss.name, ss.snapid); - } - if (!dn) { - if (d.is_remote() || d.is_referent_remote()) { - CInode *ref_in = nullptr; - if (d.is_referent_remote()) { - // TODO: ss.snapid for referent inode ? Since it's not snapped, always use - // default CEPH_NOSNAP. Validate this by testing. - ref_in = get_inode(d.referent_ino); - if (!ref_in) { - dout(20) << __func__ << " rejoin: no dentry, referent inode not found in memory inventing " << dendl; - ref_in = rejoin_invent_inode(d.referent_ino, CEPH_NOSNAP); - ref_in->set_remote_ino(d.remote_ino); + // MMDSCacheRejoin::dn_strong version handling + // When both of them are empty, strong_dentries is chosen but it doesn't matter since the map is empty + const StrongDentriesVariant sd_variant = (strong->strong_dentries_new.empty()) + ? StrongDentriesVariant(strong->strong_dentries) + : StrongDentriesVariant(strong->strong_dentries_new); + std::visit([&](auto& strong_dentries) { + using Tp = std::decay_t; + if constexpr (std::is_same_v) { + dout(20) << " handle_cache_rejoin_strong" << " variant:strong_dentries_new " << dendl; + } else { + dout(20) << " handle_cache_rejoin_strong" << " variant:strong_dentries " + << "is_map_empty?" << (strong_dentries.empty()? "yes ":"no ") << dendl; + } + const auto it = strong_dentries.find(dirfrag); + if (it != strong_dentries.end()) { + const auto& dmap = it->second; + for (const auto &q : dmap) { + const string_snap_t& ss = q.first; + const DnStrongVariant dns_variant = q.second; + std::visit([&](auto& d) { + using T = std::decay_t; + CDentry *dn; + if (!refragged) + dn = dir->lookup(ss.name, ss.snapid); + else { + frag_t fg = diri->pick_dirfrag(ss.name); + dir = diri->get_dirfrag(fg); + ceph_assert(dir); + dn = dir->lookup(ss.name, ss.snapid); + } + if (!dn) { + if constexpr (std::is_same_v) { + if (d.is_referent_remote()) { + CInode *ref_in = nullptr; + // ss.snapid for referent inode ? Since it's not snapped, always use CEPH_NOSNAP. + ref_in = get_inode(d.referent_ino); + if (!ref_in) { + dout(20) << "handle_cache_rejoin_strong " << " rejoin: no dentry, referent inode not found in memory inventing " << dendl; + ref_in = rejoin_invent_inode(d.referent_ino, CEPH_NOSNAP); + ref_in->set_remote_ino(d.remote_ino); + } + dout(20) << "handle_cache_rejoin_strong " << " rejoin: no dentry, add remote referent, referent inode= " << *ref_in << dendl; + dn = dir->add_remote_dentry(ss.name, ref_in, d.remote_ino, d.remote_d_type, mempool::mds_co::string(d.alternate_name), d.first, ss.snapid); + } } - dout(20) << __func__ << " rejoin: no dentry, referent inode invented " << *ref_in << dendl; - } else { - dout(20) << __func__ << " rejoin: no dentry, add remote inode " << dendl; - } - dn = dir->add_remote_dentry(ss.name, ref_in, d.remote_ino, d.remote_d_type, mempool::mds_co::string(d.alternate_name), d.first, ss.snapid); - } else if (d.is_null()) { - dn = dir->add_null_dentry(ss.name, d.first, ss.snapid); - } else { - CInode *in = get_inode(d.ino, ss.snapid); - if (!in) in = rejoin_invent_inode(d.ino, ss.snapid); - dn = dir->add_primary_dentry(ss.name, in, mempool::mds_co::string(d.alternate_name), d.first, ss.snapid); - } - dout(10) << " invented " << *dn << dendl; - } - CDentry::linkage_t *dnl = dn->get_linkage(); - - // dn auth_pin? - const auto pinned_it = strong->authpinned_dentries.find(dirfrag); - if (pinned_it != strong->authpinned_dentries.end()) { - const auto peer_reqid_it = pinned_it->second.find(ss); - if (peer_reqid_it != pinned_it->second.end()) { - for (const auto &r : peer_reqid_it->second) { - dout(10) << " dn authpin by " << r << " on " << *dn << dendl; - - // get/create peer mdrequest - MDRequestRef mdr; - if (have_request(r.reqid)) - mdr = request_get(r.reqid); - else - mdr = request_start_peer(r.reqid, r.attempt, strong); - mdr->auth_pin(dn); + if (d.is_remote()) { + dn = dir->add_remote_dentry(ss.name, nullptr, d.remote_ino, d.remote_d_type, mempool::mds_co::string(d.alternate_name), d.first, ss.snapid); + dout(20) << __func__ << " rejoin: no dentry, add remote inode " << dendl; + } else if (d.is_null()) { + dn = dir->add_null_dentry(ss.name, d.first, ss.snapid); + } else if (d.is_primary()) { + CInode *in = get_inode(d.ino, ss.snapid); + if (!in) in = rejoin_invent_inode(d.ino, ss.snapid); + dn = dir->add_primary_dentry(ss.name, in, mempool::mds_co::string(d.alternate_name), d.first, ss.snapid); + } + dout(10) << " invented " << *dn << dendl; } - } - } - - // dn xlock? - const auto xlocked_it = strong->xlocked_dentries.find(dirfrag); - if (xlocked_it != strong->xlocked_dentries.end()) { - const auto ss_req_it = xlocked_it->second.find(ss); - if (ss_req_it != xlocked_it->second.end()) { - const MMDSCacheRejoin::peer_reqid& r = ss_req_it->second; - dout(10) << " dn xlock by " << r << " on " << *dn << dendl; - MDRequestRef mdr = request_get(r.reqid); // should have this from auth_pin above. - ceph_assert(mdr->is_auth_pinned(dn)); - if (!mdr->is_xlocked(&dn->versionlock)) { - ceph_assert(dn->versionlock.can_xlock_local()); - dn->versionlock.get_xlock(mdr, mdr->get_client()); - mdr->emplace_lock(&dn->versionlock, MutationImpl::LockOp::XLOCK); + CDentry::linkage_t *dnl = dn->get_linkage(); + + // dn auth_pin? + const auto pinned_it = strong->authpinned_dentries.find(dirfrag); + if (pinned_it != strong->authpinned_dentries.end()) { + const auto peer_reqid_it = pinned_it->second.find(ss); + if (peer_reqid_it != pinned_it->second.end()) { + for (const auto &r : peer_reqid_it->second) { + dout(10) << " dn authpin by " << r << " on " << *dn << dendl; + + // get/create peer mdrequest + MDRequestRef mdr; + if (have_request(r.reqid)) + mdr = request_get(r.reqid); + else + mdr = request_start_peer(r.reqid, r.attempt, strong); + mdr->auth_pin(dn); + } + } } - if (dn->lock.is_stable()) - dn->auth_pin(&dn->lock); - dn->lock.set_state(LOCK_XLOCK); - dn->lock.get_xlock(mdr, mdr->get_client()); - mdr->emplace_lock(&dn->lock, MutationImpl::LockOp::XLOCK); - } - } - dn->add_replica(from, d.nonce); - dout(10) << " have " << *dn << dendl; - - if (dnl->is_primary()) { - if (d.is_primary()) { - if (vinodeno_t(d.ino, ss.snapid) != dnl->get_inode()->vino()) { - // the survivor missed MDentryUnlink+MDentryLink messages ? - ceph_assert(strong->strong_inodes.count(dnl->get_inode()->vino()) == 0); - CInode *in = get_inode(d.ino, ss.snapid); - ceph_assert(in); - ceph_assert(in->get_parent_dn()); - rejoin_unlinked_inodes[from].insert(in); - dout(7) << " sender has primary dentry but wrong inode" << dendl; - } - } else { - // the survivor missed MDentryLink message ? - ceph_assert(strong->strong_inodes.count(dnl->get_inode()->vino()) == 0); - dout(7) << " sender doesn't have primay dentry" << dendl; - } - } else { - if (d.is_primary()) { - // the survivor missed MDentryUnlink message ? - CInode *in = get_inode(d.ino, ss.snapid); - ceph_assert(in); - ceph_assert(in->get_parent_dn()); - rejoin_unlinked_inodes[from].insert(in); - dout(7) << " sender has primary dentry but we don't" << dendl; - } + // dn xlock? + const auto xlocked_it = strong->xlocked_dentries.find(dirfrag); + if (xlocked_it != strong->xlocked_dentries.end()) { + const auto ss_req_it = xlocked_it->second.find(ss); + if (ss_req_it != xlocked_it->second.end()) { + const MMDSCacheRejoin::peer_reqid& r = ss_req_it->second; + dout(10) << " dn xlock by " << r << " on " << *dn << dendl; + MDRequestRef mdr = request_get(r.reqid); // should have this from auth_pin above. + ceph_assert(mdr->is_auth_pinned(dn)); + if (!mdr->is_xlocked(&dn->versionlock)) { + ceph_assert(dn->versionlock.can_xlock_local()); + dn->versionlock.get_xlock(mdr, mdr->get_client()); + mdr->emplace_lock(&dn->versionlock, MutationImpl::LockOp::XLOCK); + } + if (dn->lock.is_stable()) + dn->auth_pin(&dn->lock); + dn->lock.set_state(LOCK_XLOCK); + dn->lock.get_xlock(mdr, mdr->get_client()); + mdr->emplace_lock(&dn->lock, MutationImpl::LockOp::XLOCK); + } + } + + dn->add_replica(from, d.nonce); + dout(10) << " have " << *dn << dendl; + + if (dnl->is_primary()) { + if (d.is_primary()) { + if (vinodeno_t(d.ino, ss.snapid) != dnl->get_inode()->vino()) { + // the survivor missed MDentryUnlink+MDentryLink messages ? + ceph_assert(strong->strong_inodes.count(dnl->get_inode()->vino()) == 0); + CInode *in = get_inode(d.ino, ss.snapid); + ceph_assert(in); + ceph_assert(in->get_parent_dn()); + rejoin_unlinked_inodes[from].insert(in); + dout(7) << " sender has primary dentry but wrong inode" << dendl; + } + } else { + // the survivor missed MDentryLink message ? + ceph_assert(strong->strong_inodes.count(dnl->get_inode()->vino()) == 0); + dout(7) << " sender doesn't have primay dentry" << dendl; + } + } else { + if (d.is_primary()) { + // the survivor missed MDentryUnlink message ? + CInode *in = get_inode(d.ino, ss.snapid); + ceph_assert(in); + ceph_assert(in->get_parent_dn()); + rejoin_unlinked_inodes[from].insert(in); + dout(7) << " sender has primary dentry but we don't" << dendl; + } + } + }, dns_variant); } } - } + }, sd_variant); } for (const auto &p : strong->strong_inodes) { @@ -5070,98 +5107,131 @@ void MDCache::handle_cache_rejoin_ack(const cref_t &ack) dout(10) << " got " << *dir << dendl; // dentries - auto it = ack->strong_dentries.find(p.first); - if (it != ack->strong_dentries.end()) { - for (const auto &q : it->second) { - CDentry *dn = dir->lookup(q.first.name, q.first.snapid); - if(!dn) - dn = dir->add_null_dentry(q.first.name, q.second.first, q.first.snapid); - - CDentry::linkage_t *dnl = dn->get_linkage(); - - ceph_assert(dn->last == q.first.snapid); - if (dn->first != q.second.first) { - dout(10) << " adjust dn.first " << dn->first << " -> " << q.second.first << " on " << *dn << dendl; - dn->first = q.second.first; - } + // MMDSCacheRejoin::dn_strong version handling + // When both of them are empty, strong_dentries is chosen but it doesn't matter since the map is empty + const StrongDentriesVariant sd_variant = (ack->strong_dentries_new.empty()) + ? StrongDentriesVariant(ack->strong_dentries) + : StrongDentriesVariant(ack->strong_dentries_new); + std::visit([&](auto& strong_dentries) { + using Tp = std::decay_t; + if constexpr (std::is_same_v) { + dout(20) << " handle_cache_rejoin_ack" << " variant:strong_dentries_new " << dendl; + } else { + dout(20) << " handle_cache_rejoin_ack" << " variant:strong_dentries " + << "is_map_empty?" << (strong_dentries.empty()? "yes ":"no ") << dendl; + } + auto it = strong_dentries.find(p.first); + if (it != strong_dentries.end()) { + for (const auto &q : it->second) { + CDentry *dn = dir->lookup(q.first.name, q.first.snapid); + const DnStrongVariant dns_variant = q.second; + std::visit( [&](auto& d) { + using T = std::decay_t; + if(!dn) + dn = dir->add_null_dentry(q.first.name, q.second.first, q.first.snapid); + + CDentry::linkage_t *dnl = dn->get_linkage(); + + ceph_assert(dn->last == q.first.snapid); + if (dn->first != q.second.first) { + dout(10) << " adjust dn.first " << dn->first << " -> " << q.second.first << " on " << *dn << dendl; + dn->first = q.second.first; + } - // may have bad linkage if we missed dentry link/unlink messages - if (dnl->is_primary()) { - CInode *in = dnl->get_inode(); - if (!q.second.is_primary() || - vinodeno_t(q.second.ino, q.first.snapid) != in->vino()) { - dout(10) << " had bad linkage for " << *dn << ", unlinking " << *in << dendl; - dir->unlink_inode(dn); - } - } else if (dnl->is_remote()) { - if (!q.second.is_remote() || - q.second.remote_ino != dnl->get_remote_ino() || - q.second.remote_d_type != dnl->get_remote_d_type()) { - dout(10) << " had bad linkage for " << *dn << dendl; - dir->unlink_inode(dn); - } - } else if (dnl->is_referent_remote()) { - if (!q.second.is_referent_remote() || - q.second.remote_ino != dnl->get_remote_ino() || - q.second.remote_d_type != dnl->get_remote_d_type() || - q.second.referent_ino != dnl->get_referent_ino()) { - dout(10) << __func__ << " had bad referent remote linkage for " << *dn << dendl; - dir->unlink_inode(dn); - } - } else { - if (!q.second.is_null()) - dout(10) << " had bad linkage for " << *dn << dendl; - } + // may have bad linkage if we missed dentry link/unlink messages + if (dnl->is_primary()) { + CInode *in = dnl->get_inode(); + if (!q.second.is_primary() || + vinodeno_t(q.second.ino, q.first.snapid) != in->vino()) { + dout(10) << " had bad linkage for " << *dn << ", unlinking " << *in << dendl; + dir->unlink_inode(dn); + } + } else if (dnl->is_remote()) { + if (!q.second.is_remote() || + q.second.remote_ino != dnl->get_remote_ino() || + q.second.remote_d_type != dnl->get_remote_d_type()) { + dout(10) << " had bad linkage for " << *dn << dendl; + dir->unlink_inode(dn); + } + } else if (dnl->is_referent_remote()) { + if constexpr (std::is_same_v) { + if (!d.is_referent_remote() || + d.remote_ino != dnl->get_remote_ino() || + d.remote_d_type != dnl->get_remote_d_type() || + d.referent_ino != dnl->get_referent_ino()) { + dout(10) << " handle_cache_rejoin_ack" << " had bad referent remote linkage for " << *dn << dendl; + dir->unlink_inode(dn); + } + } else { //We shouldn't reach here + dout(10) << " handle_cache_rejoin_ack" << " dnl is referent remote but recevied dn_strong " + << "instead of dn_strong_new " << *dn << dendl; + // If reached, validate remote linkage + if (!q.second.is_remote() || + q.second.remote_ino != dnl->get_remote_ino() || + q.second.remote_d_type != dnl->get_remote_d_type()) { + dout(10) << " handle_cache_rejoin_ack" << " had bad linkage for " << *dn << dendl; + dir->unlink_inode(dn); + } + } + } else { + if (!q.second.is_null()) + dout(10) << " had bad linkage for " << *dn << dendl; + } - // hmm, did we have the proper linkage here? - if (dnl->is_null() && !q.second.is_null()) { - if (q.second.is_remote()) { - dn->dir->link_remote_inode(dn, q.second.remote_ino, q.second.remote_d_type); - } else if (q.second.is_referent_remote()) { - CInode *ref_in = get_inode(q.second.referent_ino, CEPH_NOSNAP); - if (!ref_in) { - // barebones inode; - ref_in = new CInode(this, false, 2, CEPH_NOSNAP); - auto _inode = ref_in->_get_inode(); - _inode->ino = q.second.referent_ino; - _inode->mode = S_IFREG; - _inode->layout = default_file_layout; - add_inode(ref_in); - dout(10) << __func__ << " add inode " << *ref_in << dendl; - } else if (ref_in->get_parent_dn()) { - dout(10) << __func__ << " had bad referent linkage for " << *(ref_in->get_parent_dn()) - << ", unlinking referent inode" << *ref_in << dendl; - ref_in->get_parent_dir()->unlink_inode(ref_in->get_parent_dn()); - } - dn->dir->link_referent_inode(dn, ref_in, q.second.remote_ino, q.second.remote_d_type); - isolated_inodes.erase(ref_in); - } else { - CInode *in = get_inode(q.second.ino, q.first.snapid); - if (!in) { - // barebones inode; assume it's dir, the full inode loop below will clean up. - in = new CInode(this, false, q.second.first, q.first.snapid); - auto _inode = in->_get_inode(); - _inode->ino = q.second.ino; - _inode->mode = S_IFDIR; - _inode->dir_layout.dl_dir_hash = g_conf()->mds_default_dir_hash; - add_inode(in); - dout(10) << " add inode " << *in << dendl; - } else if (in->get_parent_dn()) { - dout(10) << " had bad linkage for " << *(in->get_parent_dn()) - << ", unlinking " << *in << dendl; - in->get_parent_dir()->unlink_inode(in->get_parent_dn()); + // hmm, did we have the proper linkage here? + if (dnl->is_null() && !q.second.is_null()) { + if constexpr (std::is_same_v) { + if (d.is_referent_remote()) { + CInode *ref_in = get_inode(d.referent_ino, CEPH_NOSNAP); + if (!ref_in) { + // barebones inode; + ref_in = new CInode(this, false, 2, CEPH_NOSNAP); + auto _inode = ref_in->_get_inode(); + _inode->ino = d.referent_ino; + _inode->mode = S_IFREG; + _inode->layout = default_file_layout; + add_inode(ref_in); + dout(10) << " handle_cache_rejoin_ack" << " add referent inode " << *ref_in << dendl; + } else if (ref_in->get_parent_dn()) { + dout(10) << " handle_cache_rejoin_ack" << " had bad referent linkage for " << *(ref_in->get_parent_dn()) + << ", unlinking referent inode" << *ref_in << dendl; + ref_in->get_parent_dir()->unlink_inode(ref_in->get_parent_dn()); + } + dn->dir->link_referent_inode(dn, ref_in, d.remote_ino, d.remote_d_type); + isolated_inodes.erase(ref_in); + } + } + if (q.second.is_remote()) { + dn->dir->link_remote_inode(dn, q.second.remote_ino, q.second.remote_d_type); + } else if (q.second.is_primary()) { + CInode *in = get_inode(q.second.ino, q.first.snapid); + if (!in) { + // barebones inode; assume it's dir, the full inode loop below will clean up. + in = new CInode(this, false, q.second.first, q.first.snapid); + auto _inode = in->_get_inode(); + _inode->ino = q.second.ino; + _inode->mode = S_IFDIR; + _inode->dir_layout.dl_dir_hash = g_conf()->mds_default_dir_hash; + add_inode(in); + dout(10) << " add inode " << *in << dendl; + } else if (in->get_parent_dn()) { + dout(10) << " had bad linkage for " << *(in->get_parent_dn()) + << ", unlinking " << *in << dendl; + in->get_parent_dir()->unlink_inode(in->get_parent_dn()); + } + dn->dir->link_primary_inode(dn, in); + isolated_inodes.erase(in); + } } - dn->dir->link_primary_inode(dn, in); - isolated_inodes.erase(in); - } - } - dn->set_replica_nonce(q.second.nonce); - dn->lock.set_state_rejoin(q.second.lock, rejoin_waiters, survivor); - dn->state_clear(CDentry::STATE_REJOINING); - dout(10) << " got " << *dn << dendl; + dn->set_replica_nonce(q.second.nonce); + dn->lock.set_state_rejoin(q.second.lock, rejoin_waiters, survivor); + dn->state_clear(CDentry::STATE_REJOINING); + dout(10) << " got " << *dn << dendl; + }, dns_variant); + } } - } + }, sd_variant); } for (const auto& in : refragged_inodes) { diff --git a/src/messages/MMDSCacheRejoin.h b/src/messages/MMDSCacheRejoin.h index 08872c5c927c0..f9ce46303b967 100644 --- a/src/messages/MMDSCacheRejoin.h +++ b/src/messages/MMDSCacheRejoin.h @@ -108,16 +108,14 @@ public: std::string alternate_name; inodeno_t ino = 0; inodeno_t remote_ino = 0; - inodeno_t referent_ino = 0; unsigned char remote_d_type = 0; uint32_t nonce = 0; int32_t lock = 0; dn_strong() = default; - dn_strong(snapid_t f, std::string_view altn, inodeno_t pi, inodeno_t ri, inodeno_t ref_ino, unsigned char rdt, int n, int l) : - first(f), alternate_name(altn), ino(pi), remote_ino(ri), referent_ino(ref_ino), remote_d_type(rdt), nonce(n), lock(l) {} + dn_strong(snapid_t f, std::string_view altn, inodeno_t pi, inodeno_t ri, unsigned char rdt, int n, int l) : + first(f), alternate_name(altn), ino(pi), remote_ino(ri), remote_d_type(rdt), nonce(n), lock(l) {} bool is_primary() const { return ino > 0; } bool is_remote() const { return remote_ino > 0; } - bool is_referent_remote() const { return remote_ino > 0 && referent_ino > 0; } bool is_null() const { return ino == 0 && remote_ino == 0; } void encode(ceph::buffer::list &bl) const { using ceph::encode; @@ -128,7 +126,6 @@ public: encode(nonce, bl); encode(lock, bl); encode(alternate_name, bl); - encode(referent_ino, bl); } void decode(ceph::buffer::list::const_iterator &bl) { using ceph::decode; @@ -139,17 +136,15 @@ public: decode(nonce, bl); decode(lock, bl); decode(alternate_name, bl); - decode(referent_ino, bl); } static void generate_test_instances(std::list& ls) { ls.push_back(new dn_strong); - ls.push_back(new dn_strong(1, "alternate_name", 2, 3, 4, 5, 6, 7)); + ls.push_back(new dn_strong(1, "alternate_name", 2, 3, 4, 5, 6)); } void dump(ceph::Formatter *f) const { f->dump_unsigned("first", first); f->dump_string("alternate_name", alternate_name); f->dump_unsigned("ino", ino); - f->dump_unsigned("referent_ino", referent_ino); f->dump_unsigned("remote_ino", remote_ino); f->dump_unsigned("remote_d_type", remote_d_type); f->dump_unsigned("nonce", nonce); @@ -158,6 +153,63 @@ public: }; WRITE_CLASS_ENCODER(dn_strong) + struct dn_strong_new { + snapid_t first; + std::string alternate_name; + inodeno_t ino = 0; + inodeno_t remote_ino = 0; + inodeno_t referent_ino = 0; + unsigned char remote_d_type = 0; + uint32_t nonce = 0; + int32_t lock = 0; + dn_strong_new() = default; + dn_strong_new(snapid_t f, std::string_view altn, inodeno_t pi, inodeno_t ri, inodeno_t ref_ino, unsigned char rdt, int n, int l) : + first(f), alternate_name(altn), ino(pi), remote_ino(ri), referent_ino(ref_ino), remote_d_type(rdt), nonce(n), lock(l) {} + bool is_primary() const { return ino > 0; } + bool is_remote() const { return remote_ino > 0 && referent_ino == 0; } + bool is_referent_remote() const { return remote_ino > 0 && referent_ino > 0; } + bool is_null() const { return ino == 0 && remote_ino == 0; } + void encode(ceph::buffer::list &bl) const { + ENCODE_START(1, 1, bl); + encode(first, bl); + encode(ino, bl); + encode(remote_ino, bl); + encode(remote_d_type, bl); + encode(nonce, bl); + encode(lock, bl); + encode(alternate_name, bl); + encode(referent_ino, bl); + ENCODE_FINISH(bl); + } + void decode(ceph::buffer::list::const_iterator &bl) { + DECODE_START(1, bl); + decode(first, bl); + decode(ino, bl); + decode(remote_ino, bl); + decode(remote_d_type, bl); + decode(nonce, bl); + decode(lock, bl); + decode(alternate_name, bl); + decode(referent_ino, bl); + DECODE_FINISH(bl); + } + static void generate_test_instances(std::list& ls) { + ls.push_back(new dn_strong_new); + ls.push_back(new dn_strong_new(1, "alternate_name", 2, 3, 4, 5, 6, 7)); + } + void dump(ceph::Formatter *f) const { + f->dump_unsigned("first", first); + f->dump_string("alternate_name", alternate_name); + f->dump_unsigned("ino", ino); + f->dump_unsigned("referent_ino", referent_ino); + f->dump_unsigned("remote_ino", remote_ino); + f->dump_unsigned("remote_d_type", remote_d_type); + f->dump_unsigned("nonce", nonce); + f->dump_unsigned("lock", lock); + } + }; + WRITE_CLASS_ENCODER(dn_strong_new) + struct dn_weak { snapid_t first; inodeno_t ino = 0; @@ -282,7 +334,9 @@ public: } void add_strong_dentry(dirfrag_t df, std::string_view dname, std::string_view altn, snapid_t first, snapid_t last, inodeno_t pi, inodeno_t ri, inodeno_t ref_ino, unsigned char rdt, int n, int ls) { auto& m = strong_dentries[df]; - m.insert_or_assign(string_snap_t(dname, last), dn_strong(first, altn, pi, ri, ref_ino, rdt, n, ls)); + m.insert_or_assign(string_snap_t(dname, last), dn_strong(first, altn, pi, ri, rdt, n, ls)); + auto& m1 = strong_dentries_new[df]; + m1.insert_or_assign(string_snap_t(dname, last), dn_strong_new(first, altn, pi, ri, ref_ino, rdt, n, ls)); } void add_dentry_authpin(dirfrag_t df, std::string_view dname, snapid_t last, const metareqid_t& ri, __u32 attempt) { @@ -317,6 +371,7 @@ public: encode(authpinned_dentries, payload); encode(xlocked_dentries, payload); encode(client_metadata_map, payload); + encode(strong_dentries_new, payload); } void decode_payload() override { auto p = payload.cbegin(); @@ -343,6 +398,8 @@ public: decode(xlocked_dentries, p); if (header.version >= 2) decode(client_metadata_map, p); + if (header.version >= 3 ) + decode(strong_dentries_new, p); } // -- data -- @@ -357,6 +414,7 @@ public: // strong std::map strong_dirfrags; std::map > strong_dentries; + std::map > strong_dentries_new; std::map strong_inodes; // open @@ -383,7 +441,7 @@ private: template friend MURef crimson::make_message(Args&&... args); - static constexpr int HEAD_VERSION = 2; + static constexpr int HEAD_VERSION = 3; static constexpr int COMPAT_VERSION = 1; MMDSCacheRejoin(int o) : MMDSCacheRejoin() { op = o; } @@ -397,6 +455,7 @@ WRITE_CLASS_ENCODER(MMDSCacheRejoin::dn_strong) WRITE_CLASS_ENCODER(MMDSCacheRejoin::dn_weak) WRITE_CLASS_ENCODER(MMDSCacheRejoin::lock_bls) WRITE_CLASS_ENCODER(MMDSCacheRejoin::peer_reqid) +WRITE_CLASS_ENCODER(MMDSCacheRejoin::dn_strong_new) inline std::ostream& operator<<(std::ostream& out, const MMDSCacheRejoin::peer_reqid& r) { return out << r.reqid << '.' << r.attempt; diff --git a/src/tools/ceph-dencoder/common_types.h b/src/tools/ceph-dencoder/common_types.h index e853321645ba2..37870b6487930 100644 --- a/src/tools/ceph-dencoder/common_types.h +++ b/src/tools/ceph-dencoder/common_types.h @@ -341,6 +341,7 @@ MESSAGE(MMDSCacheRejoin) TYPE(MMDSCacheRejoin::dirfrag_strong) TYPE(MMDSCacheRejoin::dn_strong) TYPE(MMDSCacheRejoin::inode_strong) +TYPE(MMDSCacheRejoin::dn_strong_new) #include "messages/MMDSFindIno.h" MESSAGE(MMDSFindIno) -- 2.39.5