From: Leonid Usov Date: Wed, 22 May 2024 09:19:08 +0000 (+0300) Subject: squid: mds/quiesce: accept a regular file as the quiesce root X-Git-Tag: v19.1.1~299^2~10 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=6191e750c20ef47cc1ee171c9910ad4aaca3fa9e;p=ceph.git squid: mds/quiesce: accept a regular file as the quiesce root Signed-off-by: Leonid Usov (cherry picked from commit f706ae8c2d1993ba11fe32f6cfa87154c7d2b39b) Fixes: https://tracker.ceph.com/issues/66258 --- diff --git a/qa/tasks/cephfs/test_quiesce.py b/qa/tasks/cephfs/test_quiesce.py index a93dcc758e260..c29ad8971059b 100644 --- a/qa/tasks/cephfs/test_quiesce.py +++ b/qa/tasks/cephfs/test_quiesce.py @@ -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): """ diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index 772a0e9fd589b..690db14d94054 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -13831,7 +13831,7 @@ void MDCache::dispatch_quiesce_path(const MDRequestRef& mdr) QuiesceInodeStateRef qis = std::make_shared(); *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"); }