]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: fix issuing redundant reintegrate/migrate_stray requests 54517/head
authorXiubo Li <xiubli@redhat.com>
Fri, 15 Sep 2023 00:41:35 +0000 (08:41 +0800)
committerXiubo Li <xiubli@redhat.com>
Tue, 5 Dec 2023 06:15:26 +0000 (14:15 +0800)
Just in case a CInode's nlink is 1, and then a unlink request comes
and then early replies and submits to the MDLogs, but just before
the MDlogs are flushed a link request comes, and the link request
also succeeds and early replies to client.

Later when the unlink/link requests' MDLog events are flushed and
the callbacks are called, which will fire a stray denty reintegration.
But it will pick the new dentry, which is from the link's request
and is a remote dentry, to do the reintegration. While in the
'rename' code when traversing the path it will trigger to call the
'dn->link_remote()', which later will fire a new stray dentry
reintegration.

The problem is if the first 'rename' request is retried several
times, and in each time it will fire a new reintegration, which
makes no sense and maybe blocked for a very long time dues to some
reasons and then will be reported as slow request warning.

Fixes: https://tracker.ceph.com/issues/62702
Signed-off-by: Xiubo Li <xiubli@redhat.com>
(cherry picked from commit 53d9e657e42bdf2440cd93a8273eb3ce79d8bd33)

src/mds/CDentry.h
src/mds/StrayManager.cc
src/mds/StrayManager.h

index 6897f1749a2bb38fa093b24bce3bb10180c8db6a..3312c051b0a30967c503a56e855014ccfcf46e8e 100644 (file)
@@ -374,6 +374,8 @@ public:
   mempool::mds_co::map<client_t,ClientLease*> client_lease_map;
   std::map<int, std::unique_ptr<BatchOp>> batch_ops;
 
+  ceph_tid_t reintegration_reqid = 0;
+
 
 protected:
   friend class Migrator;
index 83ab85643b5c9475a4b020c813cd778dc8b3afd2..98764e243bd5d53d8ddd5d901db87d2d91ed3113 100644 (file)
@@ -672,24 +672,41 @@ void StrayManager::reintegrate_stray(CDentry *straydn, CDentry *rdn)
 {
   dout(10) << __func__ << " " << *straydn << " to " << *rdn << dendl;
 
+  if (straydn->reintegration_reqid) {
+    dout(20) << __func__ << ": stray dentry " << *straydn
+             << " is already under reintegrating" << dendl;
+    return;
+  }
+
   logger->inc(l_mdc_strays_reintegrated);
-  
+
   // rename it to remote linkage .
   filepath src(straydn->get_name(), straydn->get_dir()->ino());
   filepath dst(rdn->get_name(), rdn->get_dir()->ino());
 
+  ceph_tid_t tid = mds->issue_tid();
+
   auto req = make_message<MClientRequest>(CEPH_MDS_OP_RENAME);
   req->set_filepath(dst);
   req->set_filepath2(src);
-  req->set_tid(mds->issue_tid());
+  req->set_tid(tid);
+
+  auto ptr = std::make_unique<StrayEvalRequest>(CEPH_MDS_OP_RENAME, tid, straydn);
+  mds->internal_client_requests.emplace(tid, std::move(ptr));
 
   mds->send_message_mds(req, rdn->authority().first);
 }
+
 void StrayManager::migrate_stray(CDentry *dn, mds_rank_t to)
 {
   dout(10) << __func__ << " " << *dn << " to mds." << to << dendl;
 
+  if (dn->reintegration_reqid) {
+    dout(20) << __func__ << ": stray dentry " << *dn
+             << " is already under migrating" << dendl;
+    return;
+  }
+
   logger->inc(l_mdc_strays_migrated);
 
   // rename it to another mds.
@@ -699,10 +716,15 @@ void StrayManager::migrate_stray(CDentry *dn, mds_rank_t to)
   filepath src(dn->get_name(), dirino);
   filepath dst(dn->get_name(), MDS_INO_STRAY(to, MDS_INO_STRAY_INDEX(dirino)));
 
+  ceph_tid_t tid = mds->issue_tid();
+
   auto req = make_message<MClientRequest>(CEPH_MDS_OP_RENAME);
   req->set_filepath(dst);
   req->set_filepath2(src);
-  req->set_tid(mds->issue_tid());
+  req->set_tid(tid);
+
+  auto ptr = std::make_unique<StrayEvalRequest>(CEPH_MDS_OP_RENAME, tid, dn);
+  mds->internal_client_requests.emplace(tid, std::move(ptr));
 
   mds->send_message_mds(req, to);
 }
index 86b6941a513138918e86a389a366405233ef1d7f..874fbbb9a8dcd449375780ac5bbc4d2fddf7a3b4 100644 (file)
 #include <list>
 #include "Mutation.h"
 #include "PurgeQueue.h"
+#include "MDSMetaRequest.h"
+#include "CDentry.h"
 
 class MDSRank;
 class CInode;
-class CDentry;
 
 class StrayManager
 {
   // My public interface is for consumption by MDCache
 public:
+  struct StrayEvalRequest : public MDSMetaRequest {
+    CDentry *dentry;
+  public:
+    explicit StrayEvalRequest(int o, ceph_tid_t t, CDentry *d) :
+      MDSMetaRequest(o, t), dentry(d) {
+      dentry->get(CDentry::PIN_PURGING);
+      dentry->reintegration_reqid = t;
+    }
+    ~StrayEvalRequest() {
+      dentry->reintegration_reqid = 0;
+      dentry->put(CDentry::PIN_PURGING);
+    }
+  };
+
   explicit StrayManager(MDSRank *mds, PurgeQueue &purge_queue_);
   void set_logger(PerfCounters *l) {logger = l;}
   void activate();