]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds/migration: Handle referent inode during subtree migration
authorKotresh HR <khiremat@redhat.com>
Thu, 20 Feb 2025 19:59:48 +0000 (01:29 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 06:20:47 +0000 (11:50 +0530)
The referent inode should be considered while migrating
the subtree. This patch takes care of migrating the
referent inode.

Fixes: https://tracker.ceph.com/issues/54205
Signed-off-by: Kotresh HR <khiremat@redhat.com>
src/mds/Migrator.cc

index 2d182b4aecdfb26bde299fbb708c162488e2c58f..328ccf3a92ba70214072fecf0e06d867deb4937e 100644 (file)
@@ -1805,6 +1805,7 @@ void Migrator::encode_export_dir(bufferlist& exportbl,
   for (auto &p : *dir) {
     CDentry *dn = p.second;
     CInode *in = dn->get_linkage()->get_inode();
+    CInode *ref_in = dn->get_linkage()->get_referent_inode();
 
     num_exported++;
     
@@ -1835,6 +1836,16 @@ void Migrator::encode_export_dir(bufferlist& exportbl,
       continue;
     }
 
+    if (dn->get_linkage()->is_referent_remote()) {
+      // referent inode
+      ceph_assert(ref_in);
+      exportbl.append("r", 1);    // referent inode dentry
+      ENCODE_START(2, 1, exportbl);
+      encode_export_inode(ref_in, exportbl, exported_client_map, exported_client_metadata_map);  // encode, and (update state for) export
+      encode(dn->alternate_name, exportbl);
+      ENCODE_FINISH(exportbl);
+      continue;
+    }
     // primary link
     // -- inode
     exportbl.append("i", 1);    // inode dentry
@@ -1902,6 +1913,10 @@ void Migrator::finish_export_dir(CDir *dir, mds_rank_t peer,
       // subdirs?
       auto&& dirs = in->get_nested_dirfrags();
       subdirs.insert(std::end(subdirs), std::begin(dirs), std::end(dirs));
+    } else if (dn->get_linkage()->is_referent_remote()) { //referent inode ?
+      CInode *ref_in = dn->get_linkage()->get_referent_inode();
+      finish_export_inode(ref_in, peer, peer_imported[ref_in->ino()], finished);
+      // referent inode - no subdirs
     }
 
     mdcache->touch_dentry_bottom(dn); // move dentry to tail of LRU
@@ -3345,7 +3360,18 @@ void Migrator::decode_import_inode(CDentry *dn, bufferlist::const_iterator& blp,
   }
 
   // link before state  -- or not!  -sage
-  if (dn->get_linkage()->get_inode() != in) {
+  if (in->get_remote_ino()) { //referent inode ?
+    dout(20) << __func__ << " linking decoded referent_inode="  << *in << " remote_inode=" << in->get_remote_ino() << dendl;
+    if (dn->get_linkage()->get_referent_inode() != in) {
+      ceph_assert(!dn->get_linkage()->get_referent_inode());
+      dout(20) << __func__ << " null dentry_linkage, linking decode referent_inode, linkage referent_inode=" << dn->get_linkage()->get_referent_inode() << dendl;
+      dn->dir->link_referent_inode(dn, in, in->get_remote_ino(), in->d_type());
+    } else {
+      dout(20) << __func__ << " non-null dentry_linkage, validating decoded referent_inode against existing" << dendl;
+      ceph_assert(dn->get_linkage()->get_remote_ino() == in->get_remote_ino());
+      ceph_assert(dn->get_linkage()->get_referent_ino() == in->ino());
+    }
+  } else if (dn->get_linkage()->get_inode() != in) {
     ceph_assert(!dn->get_linkage()->get_inode());
     dn->dir->link_primary_inode(dn, in);
   }
@@ -3596,6 +3622,21 @@ void Migrator::decode_import_dir(bufferlist::const_iterator& blp,
                             peer_exports, updated_scatterlocks);
       }
     }
+    else if (icode == 'R' || icode == 'r') {
+      // remote link with referent inode
+      ceph_assert(le);
+      if (icode == 'r') {
+        DECODE_START(2, blp);
+        decode_import_inode(dn, blp, oldauth, ls,
+                            peer_exports, updated_scatterlocks);
+        ceph_assert(!dn->is_projected());
+        decode(dn->alternate_name, blp);
+        DECODE_FINISH(blp);
+      } else {
+        decode_import_inode(dn, blp, oldauth, ls,
+                            peer_exports, updated_scatterlocks);
+      }
+    }
     
     // add dentry to journal entry
     if (le)