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):
"""
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()
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):
"""
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
;
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
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;
}
}
- 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) {
}
return;
} else {
- dout(5) << __func__ << ": fully quiesced " << *diri << dendl;
+ dout(5) << __func__ << ": fully quiesced " << *rooti << dendl;
mdr->mark_event("quiesce complete");
}