4 from textwrap import dedent
5 from unittest import SkipTest
6 from tasks.cephfs.fuse_mount import FuseMount
7 from tasks.cephfs.cephfs_test_case import CephFSTestCase, for_teuthology
9 class TestCapFlush(CephFSTestCase):
11 def test_replay_create(self):
13 MDS starts to handle client caps when it enters clientreplay stage.
14 When handling a client cap in clientreplay stage, it's possible that
15 corresponding inode does not exist because the client request which
16 creates inode hasn't been replayed.
19 if not isinstance(self.mount_a, FuseMount):
20 raise SkipTest("Require FUSE client to inject client release failure")
22 dir_path = os.path.join(self.mount_a.mountpoint, "testdir")
23 py_script = dedent("""
26 fd = os.open("{0}", os.O_RDONLY)
30 self.mount_a.run_python(py_script)
32 self.fs.mds_asok(["flush", "journal"])
34 # client will only get unsafe replay
35 self.fs.mds_asok(["config", "set", "mds_log_pause", "1"])
37 file_name = "testfile"
38 file_path = dir_path + "/" + file_name
40 # Create a file and modify its mode. ceph-fuse will mark Ax cap dirty
41 py_script = dedent("""
46 fd = os.open("{1}", os.O_CREAT | os.O_RDWR, 0644)
48 """).format(dir_path, file_name)
49 self.mount_a.run_python(py_script)
51 # Modify file mode by different user. ceph-fuse will send a setattr request
52 self.mount_a.run_shell(["chmod", "600", file_path], wait=False)
56 # Restart mds. Client will re-send the unsafe request and cap flush
58 self.fs.mds_fail_restart()
59 self.fs.wait_for_daemons()
61 mode = self.mount_a.run_shell(['stat', '-c' '%a', file_path]).stdout.getvalue().strip()
62 # If the cap flush get dropped, mode should be 0644.
63 # (Ax cap stays in dirty state, which prevents setattr reply from updating file mode)
64 self.assertEqual(mode, "600")