]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/cephfs/DataScan: skip linkages that have been removed
authorPatrick Donnelly <pdonnell@ibm.com>
Mon, 27 Jan 2025 22:03:47 +0000 (17:03 -0500)
committerPatrick Donnelly <pdonnell@ibm.com>
Thu, 30 Jan 2025 04:19:53 +0000 (23:19 -0500)
Also: injected_inos may need to store multiple injected primary links found in
the metadata pool. This is especially true now that we may have multiple
primary links to a directory due to prior commit

    tools/cephfs/DataScan: create all ancestors during scan_inodes

Fixes: https://tracker.ceph.com/issues/63301
Signed-off-by: Patrick Donnelly <pdonnell@ibm.com>
src/tools/cephfs/DataScan.cc

index 1a0c75f5dac7cad1648c52b733319280a9eecac1..0da8ff9dede910a39b520c2c25aeccf298c3044d 100644 (file)
@@ -1068,10 +1068,18 @@ int DataScan::scan_links()
     dirfrag_t dirfrag() const {
       return dirfrag_t(dirino, frag);
     }
+    void print(std::ostream& os) const {
+      os << "link_info_t(diri=" << dirino << "." << frag << " name=" << name << " v=" << version << " l=" << nlink << ")";
+    }
+    bool operator==(const link_info_t& o) const {
+      return dirino == o.dirino
+             && frag == o.frag
+             && name == o.name;
+    }
   };
   map<inodeno_t, list<link_info_t> > dup_primaries;
   map<inodeno_t, link_info_t> bad_nlink_inos;
-  map<inodeno_t, link_info_t> injected_inos;
+  multimap<inodeno_t, link_info_t> injected_inos;
 
   map<dirfrag_t, set<string> > to_remove;
 
@@ -1202,7 +1210,7 @@ int DataScan::scan_links()
                             make_move_iterator(end(srnode.snaps)));
              }
              if (dnfirst == CEPH_NOSNAP) {
-                injected_inos[ino] = link_info_t(dir_ino, frag_id, dname, inode.inode);
+                injected_inos.insert({ino, link_info_t(dir_ino, frag_id, dname, inode.inode)});
                 dout(20) << "adding " << ino << " for future processing to fix dnfirst" << dendl;
               }
            }
@@ -1270,6 +1278,7 @@ int DataScan::scan_links()
 
     link_info_t newest;
     for (auto& q : p.second) {
+      dout(10) << " primary: " << q << dendl;
       if (q.version > newest.version) {
        newest = q;
       } else if (q.version == newest.version &&
@@ -1278,6 +1287,7 @@ int DataScan::scan_links()
        newest = q;
       }
     }
+    dout(10) << "newest is: " << newest << dendl;
 
     for (auto& q : p.second) {
       // in the middle of dir fragmentation?
@@ -1293,6 +1303,17 @@ int DataScan::scan_links()
       to_remove[q.dirfrag()].insert(key);
       derr << "Remove duplicated ino 0x" << p.first << " from "
           << q.dirfrag() << "/" << q.name << dendl;
+      {
+        /* we've removed the injected linkage: don't fix it later */
+        auto range = injected_inos.equal_range(p.first);
+        for (auto it = range.first; it != range.second; ) {
+          if (it->second == q) {
+            it = injected_inos.erase(it);
+          } else {
+            ++it;
+          }
+        }
+      }
     }
 
     int nlink = 0;
@@ -1307,6 +1328,8 @@ int DataScan::scan_links()
           << " has " << newest.nlink << dendl;
       bad_nlink_inos[p.first] = newest;
       bad_nlink_inos[p.first].nlink = nlink;
+    } else {
+      bad_nlink_inos.erase(p.first);
     }
   }
   dup_primaries.clear();