From 410dcccc79b5019baeb14768bc0ad10878b25d35 Mon Sep 17 00:00:00 2001 From: Kotresh HR Date: Fri, 28 Feb 2025 00:14:18 +0530 Subject: [PATCH] tools/cephfs-data-scan: Recover referent_inode list The referent_inode list on the primary inode needs to be built on recovery. This PR adds the cability to the 'scan_links' sub command of the cephfs-data-scan tool for the same. Fixes: https://tracker.ceph.com/issues/69338 Signed-off-by: Kotresh HR --- src/tools/cephfs/DataScan.cc | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/tools/cephfs/DataScan.cc b/src/tools/cephfs/DataScan.cc index 5918a229e4eb9..bf710d6f35c0c 100644 --- a/src/tools/cephfs/DataScan.cc +++ b/src/tools/cephfs/DataScan.cc @@ -1052,6 +1052,7 @@ int DataScan::scan_links() interval_set used_inos; map remote_links; + map> referent_inodes; //referent inode list of primary inode map snaps; snapid_t last_snap = 1; snapid_t snaprealm_v2_since = 2; @@ -1064,10 +1065,11 @@ int DataScan::scan_links() int nlink; bool is_dir; map snaps; + vector referent_inodes; link_info_t() : version(0), nlink(0), is_dir(false) {} link_info_t(inodeno_t di, frag_t df, const string& n, const CInode::inode_const_ptr& i) : dirino(di), frag(df), name(n), - version(i->version), nlink(i->nlink), is_dir(S_IFDIR & i->mode) {} + version(i->version), nlink(i->nlink), is_dir(S_IFDIR & i->mode), referent_inodes(i->referent_inodes) {} dirfrag_t dirfrag() const { return dirfrag_t(dirino, frag); } @@ -1203,11 +1205,18 @@ int DataScan::scan_links() nlink = r->second; if (!MDS_INO_IS_STRAY(dir_ino)) nlink++; + if (inode.inode->nlink != nlink) { + if (nlink > 1) + ceph_assert(!referent_inodes[ino].empty()); + ceph_assert(static_cast(nlink) == (referent_inodes[ino].size()+1)); derr << "Bad nlink on " << ino << " expected " << nlink << " has " << inode.inode->nlink << dendl; bad_nlink_inos[ino] = link_info_t(dir_ino, frag_id, dname, inode.inode); bad_nlink_inos[ino].nlink = nlink; + dout(1) << "Bad nlink, adding referent inode list " << referent_inodes[ino] + << " to the primary inode " << ino << dendl; + bad_nlink_inos[ino].referent_inodes = referent_inodes[ino]; } snaps.insert(make_move_iterator(begin(srnode.snaps)), make_move_iterator(end(srnode.snaps))); @@ -1246,6 +1255,12 @@ int DataScan::scan_links() used_inos.insert(referent_ino); dout(20) << "Add referent inode dentry 0x" << std::hex << dir_ino << std::dec << "/" << dname << " to remote_links" << dendl; remote_links[ino]++; + referent_inodes[ino].push_back(referent_ino); + dout(20) << "Added referent inode " << referent_ino << " of dentry 0x" + << std::hex << dir_ino << std::dec << "/" << dname + << " to referent_inodes list of primary inode " << ino + << " referent_inode list after addition " << referent_inodes[ino] + << dendl; } else if (step == CHECK_LINK) { if (dnfirst == CEPH_NOSNAP) { injected_inos.insert({referent_ino, link_info_t(dir_ino, frag_id, dname, inode.inode)}); @@ -1353,10 +1368,16 @@ int DataScan::scan_links() nlink++; if (nlink != newest.nlink) { - derr << "Bad nlink on " << p.first << " expected " << nlink + derr << "Dup primaries - Bad nlink on " << p.first << " expected " << nlink << " has " << newest.nlink << dendl; + if (nlink > 1) + ceph_assert(!referent_inodes[p.first].empty()); + ceph_assert(static_cast(nlink) == (referent_inodes[p.first].size()+1)); bad_nlink_inos[p.first] = newest; bad_nlink_inos[p.first].nlink = nlink; + dout(1) << "Dup primaries - Bad nlink, adding referent inode list " << referent_inodes[p.first] + << " to the primary inode " << p.first << dendl; + bad_nlink_inos[p.first].referent_inodes = referent_inodes[p.first]; } else { bad_nlink_inos.erase(p.first); } @@ -1417,6 +1438,9 @@ int DataScan::scan_links() continue; inode.get_inode()->nlink = p.second.nlink; + inode.get_inode()->referent_inodes = p.second.referent_inodes; + dout(10) << "bad_nlink_inos processing - Injecting referent_inodes " + << p.second.referent_inodes << " to the primary inode " << inode.inode->ino << dendl; r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode, first); if (r < 0) return r; -- 2.39.5