]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
squid: mds/quiesce: accept a regular file as the quiesce root
authorLeonid Usov <leonid.usov@ibm.com>
Wed, 22 May 2024 09:19:08 +0000 (12:19 +0300)
committerLeonid Usov <leonid.usov@ibm.com>
Tue, 28 May 2024 18:59:57 +0000 (21:59 +0300)
Signed-off-by: Leonid Usov <leonid.usov@ibm.com>
(cherry picked from commit f706ae8c2d1993ba11fe32f6cfa87154c7d2b39b)
Fixes: https://tracker.ceph.com/issues/66258
qa/tasks/cephfs/test_quiesce.py
src/mds/MDCache.cc

index a93dcc758e26004ef7b49c65e45950035184e53d..c29ad8971059bcb28510128eedbeb2dc21fe1723 100644 (file)
@@ -461,18 +461,28 @@ class TestQuiesce(QuiesceTestCase):
 
     def test_quiesce_path_link_terminal(self):
         """
-        That quiesce on path with an terminal link fails with ENOTDIR even
-        pointing to a valid subvolume.
+        That quiesce on path with an terminal link quiesces just the link inode
         """
 
         self._configure_subvolume()
 
-        self.mount_a.run_shell_payload("ln -s ../.. subvol_quiesce")
-        path = self.mount_a.cephfs_mntpt + "/subvol_quiesce"
+        self.mount_a.run_shell_payload("mkdir -p dir/")
+        self.mount_a.write_file("dir/afile", "I'm a file")
+        self.mount_a.run_shell_payload("ln -s dir symlink_to_dir")
+        path = self.mount_a.cephfs_mntpt + "/symlink_to_dir"
 
-        J = self.fs.rank_tell(["quiesce", "path", path, '--await'], check_status=False)
-        log.debug(f"{J}")
-        self.assertEqual(J['op']['result'], -20) # ENOTDIR: the link is not a directory
+        # MDS doesn't treat symlinks differently from regular inodes,
+        # so quiescing one is allowed
+        self.quiesce_and_verify(path)
+
+        # however, this also means that the directory this symlink points to isn't quiesced
+        ops = self.fs.get_ops()
+        quiesce_inode = 0
+        for op in ops['ops']:
+            op_name = op['type_data'].get('op_name', None)
+            if op_name == "quiesce_inode":
+                quiesce_inode += 1
+        self.assertEqual(1, quiesce_inode)
 
     def test_quiesce_path_link_intermediate(self):
         """
@@ -505,7 +515,7 @@ class TestQuiesce(QuiesceTestCase):
 
     def test_quiesce_path_regfile(self):
         """
-        That quiesce on a regular file fails with ENOTDIR.
+        That quiesce on a regular file is possible.
         """
 
         self._configure_subvolume()
@@ -515,7 +525,7 @@ class TestQuiesce(QuiesceTestCase):
 
         J = self.fs.rank_tell(["quiesce", "path", path, '--await'], check_status=False)
         log.debug(f"{J}")
-        self.assertEqual(J['op']['result'], -20) # ENOTDIR
+        self.assertEqual(J['op']['result'], 0)
 
     def test_quiesce_path_dup(self):
         """
index 772a0e9fd589b61ff8e4e83ff63f06eb02a3631e..690db14d9405422057f2c570d19d16bced33a9b0 100644 (file)
@@ -13831,7 +13831,7 @@ void MDCache::dispatch_quiesce_path(const MDRequestRef& mdr)
   QuiesceInodeStateRef qis = std::make_shared<QuiesceInodeState>();
   *qis = {mdr, qfinisher->qs, delay, splitauth};
 
-  CInode* diri = nullptr;
+  CInode* rooti = nullptr;
   CF_MDS_RetryRequestFactory cf(this, mdr, true);
   static const int ptflags = 0
     | MDS_TRAVERSE_DISCOVER
@@ -13840,7 +13840,7 @@ void MDCache::dispatch_quiesce_path(const MDRequestRef& mdr)
     ;
 
   CDir* curdir = nullptr;
-  int r = path_traverse(mdr, cf, mdr->get_filepath(), ptflags, nullptr, &diri, &curdir);
+  int r = path_traverse(mdr, cf, mdr->get_filepath(), ptflags, nullptr, &rooti, &curdir);
   if (r > 0) {
     // we must abort asyncrhonously, since we may be on the unfreeze waiter list,
     // which whill be flushed syncrhonously with the abort
@@ -13851,13 +13851,7 @@ void MDCache::dispatch_quiesce_path(const MDRequestRef& mdr)
     return;
   }
 
-  auto dirino = diri->ino();
-
-  if (!diri->is_dir()) {
-    dout(5) << __func__ << ": file is not a directory" << dendl;
-    mds->server->respond_to_request(mdr, -CEPHFS_ENOTDIR);
-    return;
-  }
+  auto rootino = rooti->ino();
 
   qfinisher->mdr = mdr;
 
@@ -13873,16 +13867,16 @@ void MDCache::dispatch_quiesce_path(const MDRequestRef& mdr)
     }
   }
 
-  if (!diri->is_auth() && !splitauth) {
+  if (!rooti->is_auth() && !splitauth) {
     dout(5) << __func__ << ": skipping recursive quiesce of path for non-auth inode" << dendl;
     mdr->mark_event("quiesce complete for non-auth tree");
-  } else if (auto& qops = mdr->more()->quiesce_ops; qops.count(dirino) == 0) {
+  } else if (auto& qops = mdr->more()->quiesce_ops; qops.count(rootino) == 0) {
     mdr->mark_event("quiescing root");
     MDRequestRef qimdr = request_start_internal(CEPH_MDS_OP_QUIESCE_INODE);
-    qimdr->set_filepath(filepath(dirino));
+    qimdr->set_filepath(filepath(rootino));
     qimdr->internal_op_finish = new C_MDS_RetryRequest(this, mdr);
     qimdr->internal_op_private = new QuiesceInodeStateRef(qis);
-    qops[dirino] = qimdr->reqid;
+    qops[rootino] = qimdr->reqid;
     qs.inc_inodes();
     if (delay > 0ms) {
       mds->timer.add_event_after(delay, new LambdaContext([cache=this,qimdr](int r) {
@@ -13893,7 +13887,7 @@ void MDCache::dispatch_quiesce_path(const MDRequestRef& mdr)
     }
     return;
   } else {
-    dout(5) << __func__ << ": fully quiesced "  << *diri << dendl;
+    dout(5) << __func__ << ": fully quiesced "  << *rooti << dendl;
     mdr->mark_event("quiesce complete");
   }