From: Yan, Zheng Date: Fri, 7 Jul 2017 06:03:15 +0000 (+0800) Subject: tools/cephfs: handle removed dentries when replaying journal X-Git-Tag: ses5-milestone9~1^2~22^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=6055e4fb2675016cb0e8890e30aefba444dbcb2a;p=ceph.git tools/cephfs: handle removed dentries when replaying journal Fixes: http://tracker.ceph.com/issues/20440 Signed-off-by: "Yan, Zheng" --- diff --git a/src/tools/cephfs/JournalTool.cc b/src/tools/cephfs/JournalTool.cc index 057e79cb86bf..20c83acecf3d 100644 --- a/src/tools/cephfs/JournalTool.cc +++ b/src/tools/cephfs/JournalTool.cc @@ -720,6 +720,15 @@ int JournalTool::recover_dentries( read_keys.insert(key); } + list const &nb_list = lump.get_dnull(); + for (auto& nb : nb_list) { + // Get a key like "foobar_head" + std::string key; + dentry_key_t dn_key(nb.dnlast, nb.dn.c_str()); + dn_key.encode(key); + read_keys.insert(key); + } + // Perform bulk read of existing dentries std::map read_vals; r = input.omap_get_vals_by_keys(frag_oid.name, read_keys, &read_vals); @@ -866,6 +875,48 @@ int JournalTool::recover_dentries( } } + std::set null_vals; + for (auto& nb : nb_list) { + std::string key; + dentry_key_t dn_key(nb.dnlast, nb.dn.c_str()); + dn_key.encode(key); + + dout(4) << "inspecting nullbit " << frag_oid.name << "/" << nb.dn + << dendl; + + auto it = read_vals.find(key); + if (it != read_vals.end()) { + dout(4) << "dentry exists, will remove" << dendl; + + bufferlist::iterator q = it->second.begin(); + snapid_t dnfirst; + ::decode(dnfirst, q); + char dentry_type; + ::decode(dentry_type, q); + + bool remove_dentry = false; + if (dentry_type == 'L') { + dout(10) << "Existing hardlink inode in slot to be (maybe) removed " + << "by null journal dn '" << nb.dn.c_str() + << "' with lump fnode version " << lump.fnode.version + << "vs existing fnode version " << old_fnode_version << dendl; + remove_dentry = old_fnode_version < lump.fnode.version; + } else if (dentry_type == 'I') { + dout(10) << "Existing full inode in slot to be (maybe) removed " + << "by null journal dn '" << nb.dn.c_str() + << "' with lump fnode version " << lump.fnode.version + << "vs existing fnode version " << old_fnode_version << dendl; + remove_dentry = old_fnode_version < lump.fnode.version; + } else { + dout(4) << "corrupt dentry in backing store, will remove" << dendl; + remove_dentry = true; + } + + if (remove_dentry) + null_vals.insert(key); + } + } + // Write back any new/changed dentries if (!write_vals.empty()) { r = output.omap_set(frag_oid.name, write_vals); @@ -875,6 +926,16 @@ int JournalTool::recover_dentries( return r; } } + + // remove any null dentries + if (!null_vals.empty()) { + r = output.omap_rm_keys(frag_oid.name, null_vals); + if (r != 0) { + derr << "error removing dentries from " << frag_oid.name + << ": " << cpp_strerror(r) << dendl; + return r; + } + } } /* Now that we've looked at the dirlumps, we finally pay attention to