]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/cephfs-journal-tool: Recover referent hardlink dentry
authorKotresh HR <khiremat@redhat.com>
Thu, 27 Feb 2025 20:57:20 +0000 (02:27 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 06:20:47 +0000 (11:50 +0530)
Recover hardlink dentry with referent inode with
the following command.

cephfs-journal-tool --rank={fs}:{rank} event recover_dentries
list|summary

Fixes: https://tracker.ceph.com/issues/69338
Signed-off-by: Kotresh HR <khiremat@redhat.com>
src/tools/cephfs/JournalTool.cc
src/tools/cephfs/JournalTool.h

index 58f08a9886f55369524443003d7f1e969ea60617..0c970bd7bae2abdbab10024ce2ef30c56f767f80 100644 (file)
@@ -945,6 +945,12 @@ int JournalTool::recover_dentries(
                << "' with lump fnode version " << lump.fnode->version
                << "vs existing fnode version " << old_fnode_version << dendl;
           write_dentry = old_fnode_version < lump.fnode->version;
+       } else if (dentry_type == 'R' || dentry_type == 'r') {
+          dout(10) << "Existing hardlink referent full inode in slot to be (maybe) "
+               << "written by a remote inode from the journal dn '" << rb.dn.c_str()
+               << "' with lump fnode version " << lump.fnode->version
+               << "vs existing fnode version " << old_fnode_version << dendl;
+          write_dentry = old_fnode_version < lump.fnode->version;
         } else if (dentry_type == 'I' || dentry_type == 'i') {
           dout(10) << "Existing full inode in slot to be (maybe) written "
                << "by a remote inode from the journal dn '" << rb.dn.c_str()
@@ -959,22 +965,46 @@ int JournalTool::recover_dentries(
       }
 
       if ((other_pool || write_dentry) && !dry_run) {
-        dout(4) << "writing L dentry " << key << " into frag "
-          << frag_oid.name << dendl;
-
-        // Compose: Dentry format is dnfirst, [I|L], ino, d_type, alternate_name
-        bufferlist dentry_bl;
-        encode(rb.dnfirst, dentry_bl);
-        encode('l', dentry_bl);
-        ENCODE_START(2, 1, dentry_bl);
-        encode(rb.ino, dentry_bl);
-        encode(rb.d_type, dentry_bl);
-        encode(rb.alternate_name, dentry_bl);
-        ENCODE_FINISH(dentry_bl);
-
-        // Record for writing to RADOS
-        write_vals[key] = dentry_bl;
-        consumed_inos->insert(rb.ino);
+        dout(4) << "writing r|l (referent|just remote) dentry " << key
+         << " into frag " << frag_oid.name << " rb.referent_ino "
+          << rb.referent_ino << " referent_inode " << rb.referent_inode
+         << "rb.ino " << rb.ino << dendl;
+
+       if (rb.referent_ino != 0) {
+          dout(4) << "writing 'r' (referent remote) dentry " << key
+           << " into frag " << frag_oid.name << dendl;
+
+          // Compose: Dentry format is dnfirst, r, alternate_name, InodeStore
+          bufferlist dentry_bl;
+          encode(rb.dnfirst, dentry_bl);
+          encode('r', dentry_bl);
+          ENCODE_START(2, 1, dentry_bl);
+          encode(rb.alternate_name, dentry_bl);
+         encode_remotebit_as_referent_inode(rb, &dentry_bl);
+          ENCODE_FINISH(dentry_bl);
+
+          // Record for writing to RADOS
+          write_vals[key] = dentry_bl;
+          consumed_inos->insert(rb.referent_ino);
+          consumed_inos->insert(rb.ino);
+       } else {
+          dout(4) << "writing l dentry " << key << " into frag "
+            << frag_oid.name << dendl;
+
+          // Compose: Dentry format is dnfirst, l, ino, d_type, alternate_name
+          bufferlist dentry_bl;
+          encode(rb.dnfirst, dentry_bl);
+          encode('l', dentry_bl);
+          ENCODE_START(2, 1, dentry_bl);
+          encode(rb.ino, dentry_bl);
+          encode(rb.d_type, dentry_bl);
+          encode(rb.alternate_name, dentry_bl);
+          ENCODE_FINISH(dentry_bl);
+
+          // Record for writing to RADOS
+          write_vals[key] = dentry_bl;
+          consumed_inos->insert(rb.ino);
+       }
       }
     }
 
@@ -1219,6 +1249,20 @@ void JournalTool::encode_fullbit_as_inode(
   new_inode.encode(*out_bl, CEPH_FEATURES_SUPPORTED_DEFAULT);
 }
 
+void JournalTool::encode_remotebit_as_referent_inode(
+  const EMetaBlob::remotebit &rb,
+  bufferlist *out_bl)
+{
+  ceph_assert(out_bl != NULL);
+
+  // Compose InodeStore
+  InodeStore new_inode;
+  new_inode.inode = rb.referent_inode;
+
+  // Serialize InodeStore
+  new_inode.encode(*out_bl, CEPH_FEATURES_SUPPORTED_DEFAULT);
+}
+
 /**
  * Given a list of inode numbers known to be in use by
  * inodes in the backing store, ensure that none of these
index ac4258b89e43986676f0c0b08ad740f193cd5215..9a5edac5bafb51b26e185eb5c7c027240b3f0d3b 100644 (file)
@@ -79,6 +79,9 @@ class JournalTool : public MDSUtility
     void encode_fullbit_as_inode(
         const EMetaBlob::fullbit &fb,
         bufferlist *out_bl);
+    void encode_remotebit_as_referent_inode(
+        const EMetaBlob::remotebit &rb,
+        bufferlist *out_bl);
     int consume_inos(const std::set<inodeno_t> &inos);
 
     //validate type