]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: Handle referent remote similar to remote
authorKotresh HR <khiremat@redhat.com>
Thu, 20 Feb 2025 11:20:31 +0000 (16:50 +0530)
committerKotresh HR <khiremat@redhat.com>
Tue, 4 Mar 2025 06:20:47 +0000 (11:50 +0530)
In multiple places in the code, the referent remote
needs to be handled similar to remote e.g rstats and
dirfrags check etc.

This patch adds the check in all the places so the
existing functionality doesn't break.

The changes are done in the following functions.

CDir::encode_lock_state
CDir::check_rstats
CDir::adjust_dentry_lru
CDir::steal_dentry
CDir::verify_fragstat
ScrubStack::scrub_dirfrag
Migrator::maybe_split_export
Server::reply_client_request
Server::build_snap_diff
MDCache::journal_cow_dentry
MDCache::path_traverse
MDCache::get_dentry_inode
MDCache::_open_remote_dentry_finish
MDCache::repair_dirfrag_stats_work

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

index 555fe090a8737d938c10e060092e991254ce5e4e..4a432c5f2a24accbd088c6a8eb6043ab3dee2e8b 100644 (file)
@@ -494,7 +494,7 @@ void CDentry::encode_lock_state(int type, bufferlist& bl)
     encode(c, bl);
     encode(linkage.get_inode()->ino(), bl);
   }
-  else if (linkage.is_remote()) {
+  else if (linkage.is_remote() || linkage.is_referent_remote()) {
     c = 2;
     encode(c, bl);
     encode(linkage.get_remote_ino(), bl);
index d117507b861ca6303c39b2b3269665913740021f..a4827086257aa7a6c1d6e40239234dc455c5aee4 100644 (file)
@@ -250,7 +250,7 @@ bool CDir::check_rstats(bool scrub)
        frag_info.nsubdirs++;
       else
        frag_info.nfiles++;
-    } else if (dnl->is_remote())
+    } else if (dnl->is_remote() || dnl->is_referent_remote())
       frag_info.nfiles++;
   }
 
@@ -343,7 +343,7 @@ void CDir::adjust_dentry_lru(CDentry *dn)
   bool bottom_lru;
   if (dn->get_linkage()->is_primary()) {
     bottom_lru = !is_auth() && inode->is_stray();
-  } else if (dn->get_linkage()->is_remote()) {
+  } else if (dn->get_linkage()->is_remote() || dn->get_linkage()->is_referent_remote()) { //TODO Is this right for referent remote?
     bottom_lru = false;
   } else {
     bottom_lru = !is_auth();
@@ -1007,7 +1007,7 @@ void CDir::steal_dentry(CDentry *dn)
       // move dirty inode rstat to new dirfrag
       if (in->is_dirty_rstat())
        dirty_rstat_inodes.push_back(&in->dirty_rstat_item);
-    } else if (dn->get_linkage()->is_remote()) {
+    } else if (dn->get_linkage()->is_remote() || dn->get_linkage()->is_referent_remote()) {
       if (dn->get_linkage()->get_remote_d_type() == DT_DIR)
        _fnode->fragstat.nsubdirs++;
       else
@@ -3488,7 +3488,7 @@ void CDir::verify_fragstat()
       else
        c.nfiles++;
     }
-    if (dn->is_remote()) {
+    if (dn->is_remote() || dn->is_referent_remote()) {
       if (dn->get_remote_d_type() == DT_DIR)
        c.nsubdirs++;
       else
index 65f4b83f8889a8b04c5496d13c5deb9b533f1f09..08cbbc2ccaa4902975b3f3c052f223c2cac14a04 100644 (file)
@@ -1665,7 +1665,14 @@ void MDCache::journal_cow_dentry(MutationImpl *mut, EMetaBlob *metablob,
        dn->first = dir_follows+1;
        if (realm->has_snaps_in_range(oldfirst, dir_follows)) {
          CDir *dir = dn->dir;
-          // TODO: What does this mean for referent inode ?? Passing nullptr for now.
+          /* TODO: No need to cow referent inode. So just the remote dentry is prepared,
+           * journalled and added to dirty_cow_dentries list. But when the journal is
+           * replayed. How does this play out ? Test this out.
+          */
+         if (mds->mdsmap->allow_referent_inodes()) {
+            dout(10) << __func__ << " lookout-1 - Adding dentry as remote for journal when referent inode feature is enabled !!! "
+                    << " dentry " << *dn << " first " << oldfirst << " last " << dir_follows << dendl;
+         }
          CDentry *olddn = dir->add_remote_dentry(dn->get_name(), nullptr, in->ino(), in->d_type(), dn->alternate_name, oldfirst, dir_follows);
          dout(10) << " olddn " << *olddn << dendl;
          ceph_assert(dir->is_projected());
@@ -1751,8 +1758,15 @@ void MDCache::journal_cow_dentry(MutationImpl *mut, EMetaBlob *metablob,
       metablob->add_primary_dentry(olddn, 0, true, false, false, need_snapflush);
       mut->add_cow_dentry(olddn);
     } else {
-      ceph_assert(dnl->is_remote());
-      //No need to journal referent inode for cow
+      ceph_assert(dnl->is_remote() || dnl->is_referent_remote());
+      /* TODO: No need to cow referent inode. So just the remote dentry is prepared,
+       * journalled and added to dirty_cow_dentries list. But when the journal is
+       * replayed. How does this play out ? Test this out.
+       */
+      if (mds->mdsmap->allow_referent_inodes()) {
+        dout(10) << __func__ << " lookout-2 - Adding dentry as remote for journal when referent inode feature is enabled !!! "
+                << " dentry " << *dn << " first " << oldfirst << " last " << follows << dendl;
+      }
       CDentry *olddn = dir->add_remote_dentry(dn->get_name(), nullptr, dnl->get_remote_ino(), dnl->get_remote_d_type(), dn->alternate_name, oldfirst, follows);
       dout(10) << " olddn " << *olddn << dendl;
 
@@ -8568,7 +8582,7 @@ int MDCache::path_traverse(const MDRequestRef& mdr, MDSContextFactory& cf,
       // do we have inode?
       CInode *in = dnl->get_inode();
       if (!in) {
-        ceph_assert(dnl->is_remote());
+        ceph_assert(dnl->is_remote() || dnl->is_referent_remote());
         // do i have it?
         in = get_inode(dnl->get_remote_ino());
         if (in) {
@@ -8857,11 +8871,19 @@ CInode *MDCache::get_dentry_inode(CDentry *dn, const MDRequestRef& mdr, bool pro
   if (dnl->is_primary())
     return dnl->inode;
 
-  ceph_assert(dnl->is_remote());
+  ceph_assert(dnl->is_remote() || dnl->is_referent_remote());
   CInode *in = get_inode(dnl->get_remote_ino());
   if (in) {
-    dout(7) << "get_dentry_inode linking in remote in " << *in << dendl;
-    dn->link_remote(dnl, in);
+    CInode *ref_in = dnl->get_referent_inode();
+    if (dnl->is_referent_remote())
+      ceph_assert(ref_in);
+    if (ref_in) {
+      dout(7) << __func__ << " linking in referent remote in " << *in << "referent " << *ref_in << dendl;
+      dn->link_remote(dnl, in, ref_in);
+    } else {
+      dout(7) << __func__ << " linking in remote in " << *in << dendl;
+      dn->link_remote(dnl, in);
+    }
     return in;
   } else {
     dout(10) << "get_dentry_inode on remote dn, opening inode for " << *dn << dendl;
@@ -8900,7 +8922,7 @@ void MDCache::_open_remote_dentry_finish(CDentry *dn, inodeno_t ino, MDSContext
 {
   if (r < 0) {
     CDentry::linkage_t *dnl = dn->get_projected_linkage();
-    if (dnl->is_remote() && dnl->get_remote_ino() == ino) {
+    if ((dnl->is_remote() || dnl->is_referent_remote()) && dnl->get_remote_ino() == ino) {
       dout(0) << "open_remote_dentry_finish bad remote dentry " << *dn << dendl;
       dn->state_set(CDentry::STATE_BADREMOTEINO);
 
@@ -13452,7 +13474,7 @@ void MDCache::repair_dirfrag_stats_work(const MDRequestRef& mdr)
        frag_info.nsubdirs++;
       else
        frag_info.nfiles++;
-    } else if (dnl->is_remote())
+    } else if (dnl->is_remote() || dnl->is_referent_remote())
       frag_info.nfiles++;
   }
 
index 82950a07c576a2e5d16e3618c95ef2ebae53004e..2d182b4aecdfb26bde299fbb708c162488e2c58f 100644 (file)
@@ -935,7 +935,7 @@ void Migrator::maybe_split_export(CDir* dir, uint64_t max_size, bool null_okay,
        dirfrag_size += null_size;
        continue;
       }
-      if (dn->get_linkage()->is_remote()) {
+      if (dn->get_linkage()->is_remote() || dn->get_linkage()->is_referent_remote()) {
        dirfrag_size += remote_size;
        continue;
       }
index cc84a1866ef26f62080734431878cb5dab6993ec..a0d168b023bd6c81eba1caf0d9dc5feec2935849 100644 (file)
@@ -521,7 +521,7 @@ void ScrubStack::scrub_dirfrag(CDir *dir, bool *done)
       }
       if (dnl->is_primary()) {
        _enqueue(dnl->get_inode(), header, false);
-      } else if (dnl->is_remote()) {
+      } else if (dnl->is_remote() || dnl->is_referent_remote()) {
        // TODO: check remote linkage
       }
     }
index a77ca844afb0dee612082a159d9007dcde4dc35f..2ea3559731aa3e8ecfc7faddc65bd9e24d30c303 100644 (file)
@@ -2423,7 +2423,7 @@ void Server::reply_client_request(const MDRequestRef& mdr, const ref_t<MClientRe
   // take a closer look at tracei, if it happens to be a remote link
   if (tracei && 
       tracedn &&
-      tracedn->get_projected_linkage()->is_remote()) {
+      (tracedn->get_projected_linkage()->is_remote() || tracedn->get_projected_linkage()->is_referent_remote())) {
     mdcache->eval_remote(tracedn);
   }
 }
@@ -12058,7 +12058,7 @@ bool Server::build_snap_diff(
 
     // remote link?
     // better for the MDS to do the work, if we think the client will stat any of these files.
-    if (dnl->is_remote() && !in) {
+    if ((dnl->is_remote() || dnl->is_referent_remote()) && !in) {
       in = mdcache->get_inode(dnl->get_remote_ino());
       dout(20) << __func__ << " remote in: " << *in << " ino " << std::hex << dnl->get_remote_ino() << std::dec << dendl;
       if (in) {