]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mds: add debug "lock path" command
authorPatrick Donnelly <pdonnell@redhat.com>
Tue, 16 Apr 2024 15:44:49 +0000 (11:44 -0400)
committerPatrick Donnelly <pdonnell@ibm.com>
Thu, 9 Jan 2025 19:50:56 +0000 (14:50 -0500)
So we can have a long-running lock on an inode for certain tests.

Signed-off-by: Patrick Donnelly <pdonnell@redhat.com>
(cherry picked from commit 7f1d066756383adae37d61cc2b2f5d99bc167f65)

Conflicts:
src/include/ceph_fs.h: missing quiesce code
src/mds/MDCache.cc: missing quiesce code
src/mds/MDCache.h: missing quiesce code
src/mds/MDSRank.cc: missing quiesce code
src/mds/MDSRank.h: missing quiesce code

src/include/ceph_fs.h
src/mds/MDCache.cc
src/mds/MDCache.h
src/mds/MDSDaemon.cc
src/mds/MDSRank.cc
src/mds/MDSRank.h

index 4c56d7b7f54e4ca663d6d8cf938d9d4b6c788b2e..ad604fe9f0e3339e5e0c7cda0043be7c37f08e51 100644 (file)
@@ -430,7 +430,10 @@ 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
+       CEPH_MDS_OP_RDLOCK_FRAGSSTATS = 0x01507,
+       CEPH_MDS_OP_QUIESCE_PATH = 0x01508,
+       CEPH_MDS_OP_QUIESCE_INODE = 0x01509,
+       CEPH_MDS_OP_LOCK_PATH = 0x0150a,
 };
 
 #define IS_CEPH_MDS_OP_NEWINODE(op) (op == CEPH_MDS_OP_CREATE     || \
index cd4f8c4f015de64a9488491d42787e8ba348fe48..34d83d50de3704ddc380d4d5c24e3f2bdb2a8e1e 100644 (file)
@@ -115,6 +115,10 @@ public:
   explicit MDCacheLogContext(MDCache *mdc_) : mdcache(mdc_) {}
 };
 
+struct LockPathState {
+  std::vector<std::string> locks;
+};
+
 MDCache::MDCache(MDSRank *m, PurgeQueue &purge_queue_) :
   mds(m),
   open_file_table(m),
@@ -9758,6 +9762,9 @@ void MDCache::dispatch_request(MDRequestRef& mdr)
     mds->server->dispatch_peer_request(mdr);
   } else {
     switch (mdr->internal_op) {
+    case CEPH_MDS_OP_LOCK_PATH:
+      dispatch_lock_path(mdr);
+      break;
     case CEPH_MDS_OP_FRAGMENTDIR:
       dispatch_fragment_dir(mdr);
       break;
@@ -9875,7 +9882,7 @@ void MDCache::request_cleanup(MDRequestRef& mdr)
       mdr->clear_ambiguous_auth();
     if (!mdr->more()->waiting_for_finish.empty())
       mds->queue_waiters(mdr->more()->waiting_for_finish);
-  }
+   }
 
   request_drop_locks(mdr);
 
@@ -13441,6 +13448,98 @@ void MDCache::clear_dirty_bits_for_stray(CInode* diri) {
   }
 }
 
+void MDCache::dispatch_lock_path(MDRequestRef& mdr)
+{
+  CInode* in = nullptr;
+  CF_MDS_RetryRequestFactory cf(this, mdr, true);
+  static const int ptflags = 0
+    | MDS_TRAVERSE_DISCOVER
+    | MDS_TRAVERSE_RDLOCK_PATH
+    | MDS_TRAVERSE_WANT_INODE
+    ;
+  int r = path_traverse(mdr, cf, mdr->get_filepath(), ptflags, nullptr, &in);
+  if (r > 0)
+    return;
+  if (r < 0) {
+    mds->server->respond_to_request(mdr, r);
+    return;
+  }
+
+  auto& lps = *static_cast<LockPathState*>(mdr->internal_op_private);
+
+  MutationImpl::LockOpVec lov;
+  for (const auto &lock : lps.locks) {
+    auto colonps = lock.find(':');
+    if (colonps == std::string::npos) {
+      mds->server->respond_to_request(mdr, -CEPHFS_EINVAL);
+      return;
+    }
+    auto lock_type = lock.substr(0, colonps);
+    auto lock_kind = lock.substr(colonps+1, lock.size());
+    dout(20) << "lock: " << lock_type << " " << lock_kind << dendl;
+
+    SimpleLock* l;
+    if (lock_type == "snap") {
+      l = &in->snaplock;
+    } else if (lock_type == "policy") {
+      l = &in->policylock;
+    } else if (lock_type == "file") {
+      l = &in->filelock;
+    } else if (lock_type == "nest") {
+      l = &in->nestlock;
+    } else if (lock_type == "dft") {
+      l = &in->dirfragtreelock;
+    } else if (lock_type == "auth") {
+      l = &in->authlock;
+    } else if (lock_type == "link") {
+      l = &in->linklock;
+    } else if (lock_type == "xattr") {
+      l = &in->xattrlock;
+    } else if (lock_type == "flock") {
+      l = &in->flocklock;
+    } else {
+      mds->server->respond_to_request(mdr, -CEPHFS_EINVAL);
+      return;
+    }
+
+    if (lock_kind.size() != 1) {
+      mds->server->respond_to_request(mdr, -CEPHFS_EINVAL);
+      return;
+    }
+
+    switch (lock_kind[0]) {
+      case 'r':
+        lov.add_rdlock(l);
+        break;
+      case 'w':
+        lov.add_wrlock(l);
+        break;
+      case 'x':
+        lov.add_xlock(l);
+        break;
+      default:
+        mds->server->respond_to_request(mdr, -CEPHFS_EINVAL);
+        return;
+    }
+  }
+
+  if (!mds->locker->acquire_locks(mdr, lov, nullptr, false)) {
+    return;
+  }
+
+  /* deliberately leak until killed */
+}
+
+MDRequestRef MDCache::lock_path(filepath p, std::vector<std::string> locks)
+{
+  MDRequestRef mdr = request_start_internal(CEPH_MDS_OP_LOCK_PATH);
+  mdr->set_filepath(p);
+  mdr->internal_op_finish = new LambdaContext([](int r) {});
+  mdr->internal_op_private = new LockPathState{locks};
+  dispatch_request(mdr);
+  return mdr;
+}
+
 bool MDCache::dump_inode(Formatter *f, uint64_t number) {
   CInode *in = get_inode(number);
   if (!in) {
index d773b5fcfaf4af75653550d086e699995f65b23c..d1daa251be52ed94421ab5ad84d09fb1a35914e2 100644 (file)
@@ -527,6 +527,8 @@ class MDCache {
                               std::map<dirfrag_t,std::vector<dirfrag_t> >& subtrees);
   ESubtreeMap *create_subtree_map();
 
+  MDRequestRef lock_path(filepath p, std::vector<std::string> locks);
+
   void clean_open_file_lists();
   void dump_openfiles(Formatter *f);
   bool dump_inode(Formatter *f, uint64_t number);
@@ -1351,6 +1353,8 @@ class MDCache {
   void finish_uncommitted_fragment(dirfrag_t basedirfrag, int op);
   void rollback_uncommitted_fragment(dirfrag_t basedirfrag, frag_vec_t&& old_frags);
 
+  void dispatch_lock_path(MDRequestRef& mdr);
+
   void upkeep_main(void);
 
   bool is_ready_to_trim_cache(void);
index debd6a46cca3ba869945241c2c1ddc0d1e80247c..374c5e9a17d1d8852d842733c48e08c9d26f956f 100644 (file)
@@ -336,6 +336,12 @@ void MDSDaemon::set_up_admin_socket()
                                     asok_hook,
                                     "trim cache and optionally request client to release all caps and flush the journal");
   ceph_assert(r == 0);
+  r = admin_socket->register_command("lock path"
+                                     " name=path,type=CephString,req=true"
+                                     " name=locks,type=CephString,n=N,req=false"
+                                    ,asok_hook
+                                    ,"lock a path");
+  ceph_assert(r == 0);
   r = admin_socket->register_command("cache status",
                                      asok_hook,
                                      "show cache status");
index 7d089e89b9cfd947f0342d3d7f3491c38225a6ba..491940639a42a744b5e9b233329ac78b8e8641c5 100644 (file)
@@ -2899,6 +2899,8 @@ void MDSRankDispatcher::handle_asok_command(
   } else if (command == "cache status") {
     std::lock_guard l(mds_lock);
     mdcache->cache_status(f);
+  } else if (command == "lock path") {
+    r = command_lock_path(f, cmdmap, *css);
   } else if (command == "dump tree") {
     command_dump_tree(cmdmap, *css, f);
   } else if (command == "dump loads") {
@@ -3362,6 +3364,30 @@ void MDSRank::command_openfiles_ls(Formatter *f)
   mdcache->dump_openfiles(f);
 }
 
+int MDSRank::command_lock_path(Formatter* f, const cmdmap_t& cmdmap, std::ostream& ss)
+{
+  std::string path;
+  {
+    bool got = cmd_getval(cmdmap, "path", path);
+    if (!got) {
+      ss << "missing path";
+      return -CEPHFS_EINVAL;
+    }
+  }
+
+  std::vector<std::string> locks;
+  cmd_getval(cmdmap, "locks", locks);
+
+  f->open_object_section("lock");
+  {
+    std::lock_guard l(mds_lock);
+    auto mdr = mdcache->lock_path(filepath(path), locks);
+    f->dump_object("op", *mdr);
+  }
+  f->close_section();
+  return 0;
+}
+
 void MDSRank::command_dump_inode(Formatter *f, const cmdmap_t &cmdmap, std::ostream &ss)
 {
   std::lock_guard l(mds_lock);
index a9e8da1817a26368aa6a4b9db2d9abd64115d5bb..23c3b37f8d4bfea6d17c51deb8e7a19e45487301 100644 (file)
@@ -525,6 +525,7 @@ class MDSRank {
         std::ostream &ss);
     void command_openfiles_ls(Formatter *f);
     void command_dump_tree(const cmdmap_t &cmdmap, std::ostream &ss, Formatter *f);
+    int command_lock_path(Formatter *f, const cmdmap_t &cmdmap, std::ostream &ss);
     void command_dump_inode(Formatter *f, const cmdmap_t &cmdmap, std::ostream &ss);
     void command_dump_dir(Formatter *f, const cmdmap_t &cmdmap, std::ostream &ss);
     void command_cache_drop(uint64_t timeout, Formatter *f, Context *on_finish);