From: Yan, Zheng Date: Fri, 15 Nov 2019 15:59:44 +0000 (+0800) Subject: tools/cephfs: make 'cephfs-data-scan scan_links' fix dentry's first X-Git-Tag: v15.1.0~660^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=16fc2c392b0a4de13dbe4dfcc7dad01d8e58ce40;p=ceph.git tools/cephfs: make 'cephfs-data-scan scan_links' fix dentry's first Dentries injected by 'cephfs-data-scan foo' have 'first == CEPH_NOSNAP'. This confuses mimic and later version MDS, and can cause them to crash. Signed-off-by: "Yan, Zheng" Fixes: https://tracker.ceph.com/issues/42829 --- diff --git a/src/tools/cephfs/DataScan.cc b/src/tools/cephfs/DataScan.cc index 4dfbe48ccd9f..8fb670ad08e6 100644 --- a/src/tools/cephfs/DataScan.cc +++ b/src/tools/cephfs/DataScan.cc @@ -931,6 +931,7 @@ int DataScan::scan_links() }; map > dup_primaries; map bad_nlink_inos; + map injected_inos; map > to_remove; @@ -973,8 +974,11 @@ int DataScan::scan_links() snapid_t last; dentry_key_t::decode_helper(p.first, dname, last); - if (last != CEPH_NOSNAP) + if (last != CEPH_NOSNAP) { + if (last > last_snap) + last_snap = last; continue; + } try { snapid_t dnfirst; @@ -1040,6 +1044,8 @@ int DataScan::scan_links() snaps.insert(make_move_iterator(begin(srnode.snaps)), make_move_iterator(end(srnode.snaps))); } + if (dnfirst == CEPH_NOSNAP) + injected_inos[ino] = link_info_t(dir_ino, frag_id, dname, inode.inode); } } else if (dentry_type == 'L') { inodeno_t ino; @@ -1142,6 +1148,23 @@ int DataScan::scan_links() dup_primaries.clear(); remote_links.clear(); + { + objecter->with_osdmap([&](const OSDMap& o) { + for (auto p : data_pools) { + const pg_pool_t *pi = o.get_pg_pool(p); + if (!pi) + continue; + if (pi->snap_seq > last_snap) + last_snap = pi->snap_seq; + } + }); + + if (!snaps.empty()) { + if (snaps.rbegin()->first > last_snap) + last_snap = snaps.rbegin()->first; + } + } + for (auto& p : to_remove) { object_t frag_oid = InodeStore::get_object_name(p.first.ino, p.first.frag, ""); @@ -1155,7 +1178,8 @@ int DataScan::scan_links() for (auto &p : bad_nlink_inos) { InodeStore inode; - int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode); + snapid_t first; + int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode, &first); if (r < 0) { derr << "Unexpected error reading dentry " << p.second.dirfrag() << "/" << p.second.name @@ -1167,7 +1191,27 @@ int DataScan::scan_links() continue; inode.inode.nlink = p.second.nlink; - r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode); + r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode, first); + if (r < 0) + return r; + } + + for (auto &p : injected_inos) { + InodeStore inode; + snapid_t first; + int r = read_dentry(p.second.dirino, p.second.frag, p.second.name, &inode, &first); + if (r < 0) { + derr << "Unexpected error reading dentry " + << p.second.dirfrag() << "/" << p.second.name + << ": " << cpp_strerror(r) << dendl; + return r; + } + + if (first != CEPH_NOSNAP) + continue; + + first = last_snap + 1; + r = metadata_driver->inject_linkage(p.second.dirino, p.second.name, p.second.frag, inode, first); if (r < 0) return r; } @@ -1191,21 +1235,6 @@ int DataScan::scan_links() } { - objecter->with_osdmap([&](const OSDMap& o) { - for (auto p : data_pools) { - const pg_pool_t *pi = o.get_pg_pool(p); - if (!pi) - continue; - if (pi->snap_seq > last_snap) - last_snap = pi->snap_seq; - } - }); - - if (!snaps.empty()) { - if (snaps.rbegin()->first > last_snap) - last_snap = snaps.rbegin()->first; - } - SnapServer snaptable; snaptable.set_rank(0); bool dirty = false; @@ -1410,11 +1439,10 @@ int MetadataTool::read_fnode( } int MetadataTool::read_dentry(inodeno_t parent_ino, frag_t frag, - const std::string &dname, InodeStore *inode) + const std::string &dname, InodeStore *inode, snapid_t *dnfirst) { ceph_assert(inode != NULL); - std::string key; dentry_key_t dn_key(CEPH_NOSNAP, dname.c_str()); dn_key.encode(key); @@ -1439,18 +1467,19 @@ int MetadataTool::read_dentry(inodeno_t parent_ino, frag_t frag, try { auto q = vals[key].cbegin(); - snapid_t dnfirst; - decode(dnfirst, q); + snapid_t first; + decode(first, q); char dentry_type; decode(dentry_type, q); if (dentry_type == 'I') { inode->decode_bare(q); - return 0; } else { dout(20) << "dentry type '" << dentry_type << "': cannot" "read an inode out of that" << dendl; return -EINVAL; } + if (dnfirst) + *dnfirst = first; } catch (const buffer::error &err) { dout(20) << "encoding error in dentry 0x" << std::hex << parent_ino << std::dec << "/" << dname << dendl; @@ -1913,20 +1942,16 @@ int MetadataDriver::find_or_create_dirfrag( int MetadataDriver::inject_linkage( inodeno_t dir_ino, const std::string &dname, - const frag_t fragment, const InodeStore &inode) + const frag_t fragment, const InodeStore &inode, const snapid_t dnfirst) { - // We have no information about snapshots, so everything goes - // in as CEPH_NOSNAP - snapid_t snap = CEPH_NOSNAP; - object_t frag_oid = InodeStore::get_object_name(dir_ino, fragment, ""); std::string key; - dentry_key_t dn_key(snap, dname.c_str()); + dentry_key_t dn_key(CEPH_NOSNAP, dname.c_str()); dn_key.encode(key); bufferlist dentry_bl; - encode(snap, dentry_bl); + encode(dnfirst, dentry_bl); encode('I', dentry_bl); inode.encode_bare(dentry_bl, CEPH_FEATURES_SUPPORTED_DEFAULT); diff --git a/src/tools/cephfs/DataScan.h b/src/tools/cephfs/DataScan.h index dd064492d01e..5c87fe2bdec4 100644 --- a/src/tools/cephfs/DataScan.h +++ b/src/tools/cephfs/DataScan.h @@ -174,7 +174,7 @@ class MetadataTool * Try and read a dentry from a dirfrag */ int read_dentry(inodeno_t parent_ino, frag_t frag, - const std::string &dname, InodeStore *inode); + const std::string &dname, InodeStore *inode, snapid_t *dnfirst=nullptr); }; /** @@ -220,7 +220,7 @@ class MetadataDriver : public RecoveryDriver, public MetadataTool int inject_linkage( inodeno_t dir_ino, const std::string &dname, - const frag_t fragment, const InodeStore &inode); + const frag_t fragment, const InodeStore &inode, snapid_t dnfirst=CEPH_NOSNAP); int inject_with_backtrace( const inode_backtrace_t &bt,