]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mds: rdlock file/nest lock when accumulating stats of subtree dirfrags
authorSimon Gao <simon29rock@gmail.com>
Wed, 3 Jun 2020 03:04:25 +0000 (11:04 +0800)
committerYan, Zheng <zyan@redhat.com>
Mon, 16 Nov 2020 01:02:17 +0000 (09:02 +0800)
Signed-off-by: Simon Gao <simon29rock@gmail.com>
Signed-off-by: "Yan, Zheng" <zyan@redhat.com>
src/include/ceph_fs.h
src/mds/CInode.cc
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/MDSContinuation.h

index fe98eef8924286f2ad1630bec882a73402476c9b..f0cac9e1a0db253ca6e4e05326c93200416ee7eb 100644 (file)
@@ -415,6 +415,7 @@ enum {
        CEPH_MDS_OP_ENQUEUE_SCRUB  = 0x01503,
        CEPH_MDS_OP_REPAIR_FRAGSTATS = 0x01504,
        CEPH_MDS_OP_REPAIR_INODESTATS = 0x01505,
+       CEPH_MDS_OP_RDLOCK_FRAGSSTATS = 0x01507
 };
 
 extern const char *ceph_mds_op_name(int op);
index 3e771e30429a01ab9756618b3c03223132e7dcb6..601a144e8c5639820b64ef7d2ce7211025b7ae87 100644 (file)
@@ -4811,7 +4811,12 @@ next:
     }
 
     bool check_dirfrag_rstats() {
-      return immediate(DIRFRAGS, 0);
+      if (in->has_subtree_root_dirfrag()) {
+       in->mdcache->rdlock_dirfrags_stats(in, get_internal_callback(DIRFRAGS));
+       return false;
+      } else {
+       return immediate(DIRFRAGS, 0);
+      }
     }
 
     bool _dirfrags(int rval) {
index 234c630bef3ccfc1f30b37c5e083bad8e637af53..ade41bcb8f8a1d643086f584aa00c3f35490860d 100644 (file)
@@ -9650,6 +9650,9 @@ void MDCache::dispatch_request(MDRequestRef& mdr)
     case CEPH_MDS_OP_REPAIR_INODESTATS:
       repair_inode_stats_work(mdr);
       break;
+    case CEPH_MDS_OP_RDLOCK_FRAGSSTATS:
+      rdlock_dirfrags_stats_work(mdr);
+      break;
     default:
       ceph_abort();
     }
@@ -13056,6 +13059,40 @@ do_rdlocks:
   mds->server->respond_to_request(mdr, 0);
 }
 
+void MDCache::rdlock_dirfrags_stats(CInode *diri, MDSInternalContext* fin)
+{
+  MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_RDLOCK_FRAGSSTATS);
+  mdr->pin(diri);
+  mdr->internal_op_private = diri;
+  mdr->internal_op_finish = fin;
+  return rdlock_dirfrags_stats_work(mdr);
+}
+
+void MDCache::rdlock_dirfrags_stats_work(MDRequestRef& mdr)
+{
+  CInode *diri = static_cast<CInode*>(mdr->internal_op_private);
+  dout(10) << __func__ << " " << *diri << dendl;
+  if (!diri->is_auth()) {
+    mds->server->respond_to_request(mdr, -ESTALE);
+    return;
+  }
+  if (!diri->is_dir()) {
+    mds->server->respond_to_request(mdr, -ENOTDIR);
+    return;
+  }
+
+  MutationImpl::LockOpVec lov;
+  lov.add_rdlock(&diri->dirfragtreelock);
+  lov.add_rdlock(&diri->nestlock);
+  lov.add_rdlock(&diri->filelock);
+  if (!mds->locker->acquire_locks(mdr, lov))
+    return;
+  dout(10) << __func__ << " start dirfrags : " << *diri << dendl;
+
+  mds->server->respond_to_request(mdr, 0);
+  return;
+}
+
 void MDCache::flush_dentry(std::string_view path, Context *fin)
 {
   if (is_readonly()) {
index 8c0957646ad4e8dccc81057a6fb62633b37af53c..2db916d70a73c74254e438eb78b926408abf3072 100644 (file)
@@ -940,6 +940,7 @@ class MDCache {
                     Formatter *f, Context *fin);
   void repair_inode_stats(CInode *diri);
   void repair_dirfrag_stats(CDir *dir);
+  void rdlock_dirfrags_stats(CInode *diri, MDSInternalContext *fin);
 
   // my leader
   MDSRank *mds;
@@ -1125,6 +1126,7 @@ class MDCache {
   void enqueue_scrub_work(MDRequestRef& mdr);
   void repair_inode_stats_work(MDRequestRef& mdr);
   void repair_dirfrag_stats_work(MDRequestRef& mdr);
+  void rdlock_dirfrags_stats_work(MDRequestRef& mdr);
 
   ceph::unordered_map<inodeno_t,CInode*> inode_map;  // map of head inodes by ino
   map<vinodeno_t, CInode*> snap_inode_map;  // map of snap inodes by ino
index 97bae912a2a4be9071f243ee5634dd545f35b9cb..e01522522556d3e7bf5737c67f5c70a863f285f6 100644 (file)
@@ -21,7 +21,7 @@
 class MDSContinuation : public Continuation {
 protected:
   Server *server;
-  MDSContext *get_internal_callback(int stage) {
+  MDSInternalContext *get_internal_callback(int stage) {
     return new MDSInternalContextWrapper(server->mds, get_callback(stage));
   }
   MDSIOContextBase *get_io_callback(int stage) {