]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: Fix MMDSCacheRejoin::dn_strong version check failure 61945/head
authorKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 16:18:57 +0000 (21:48 +0530)
committerKotresh HR <khiremat@redhat.com>
Wed, 5 Mar 2025 11:32:40 +0000 (17:02 +0530)
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 <khiremat@redhat.com>
src/mds/MDCache.cc
src/messages/MMDSCacheRejoin.h
src/tools/ceph-dencoder/common_types.h

index 166f90e3054d69d517cde691df2337926f8424c9..c432fe4beb3b195c0738e5e5449a7084965cf66a 100644 (file)
 
 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_t<MMDSC
        
        if (dn->is_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<MMDSCacheRejoin> &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<decltype(strong_dentries)>;
+      if constexpr (std::is_same_v<Tp, decltype(MMDSCacheRejoin::strong_dentries_new)>) {
+        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<decltype(d)>;
+            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<T, MMDSCacheRejoin::dn_strong_new>) {
+               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<MMDSCacheRejoin> &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<decltype(strong_dentries)>;
+      if constexpr (std::is_same_v<Tp, decltype(MMDSCacheRejoin::strong_dentries_new)>) {
+        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<decltype(d)>;
+            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<T, MMDSCacheRejoin::dn_strong_new>) {
+               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<T, MMDSCacheRejoin::dn_strong_new>) {
+               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) {
index 08872c5c927c09269a4983bc93bb4332c9b9e289..f9ce46303b9677c41ffab338298318dacff16ffd 100644 (file)
@@ -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<dn_strong*>& 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<dn_strong_new*>& 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<dirfrag_t, dirfrag_strong> strong_dirfrags;
   std::map<dirfrag_t, std::map<string_snap_t, dn_strong> > strong_dentries;
+  std::map<dirfrag_t, std::map<string_snap_t, dn_strong_new> > strong_dentries_new;
   std::map<vinodeno_t, inode_strong> strong_inodes;
 
   // open
@@ -383,7 +441,7 @@ private:
   template<class T, typename... Args>
   friend MURef<T> 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;
index e853321645ba2d5ea74251aeb280864ca224a849..37870b648793036709f7b274eb2c471ce79bf94e 100644 (file)
@@ -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)