From: Patrick Donnelly Date: Mon, 27 Jan 2025 22:03:47 +0000 (-0500) Subject: tools/cephfs/DataScan: skip linkages that have been removed X-Git-Tag: v20.0.0~226^2~3 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=a66a68bfa5388e04afe3a8dcd58a08c3138e0b28;p=ceph.git tools/cephfs/DataScan: skip linkages that have been removed 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 --- diff --git a/src/tools/cephfs/DataScan.cc b/src/tools/cephfs/DataScan.cc index 1a0c75f5dac7..0da8ff9dede9 100644 --- a/src/tools/cephfs/DataScan.cc +++ b/src/tools/cephfs/DataScan.cc @@ -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 > dup_primaries; map bad_nlink_inos; - map injected_inos; + multimap injected_inos; map > 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();