# drop cache multiple times to clear replica pins
self._wait_subtrees([], status=self.status, action=_drop)
+ def test_open_file(self):
+ """
+ Test opening a file via a hard link that is not in the same mds as the inode.
+
+ See https://tracker.ceph.com/issues/58411
+ """
+
+ self.mount_a.run_shell_payload("mkdir -p target link")
+ self.mount_a.touch("target/test.txt")
+ self.mount_a.run_shell_payload("ln target/test.txt link/test.txt")
+ self.mount_a.setfattr("target", "ceph.dir.pin", "0")
+ self.mount_a.setfattr("link", "ceph.dir.pin", "1")
+ self._wait_subtrees([("/target", 0), ("/link", 1)], status=self.status)
+
+ # Release client cache, otherwise the bug may not be triggered even if buggy.
+ self.mount_a.remount()
+
+ # Open the file with access mode(O_CREAT|O_WRONLY|O_TRUNC),
+ # this should cause the rank 1 to crash if buggy.
+ # It's OK to use 'truncate -s 0 link/test.txt' here,
+ # its access mode is (O_CREAT|O_WRONLY), it can also trigger this bug.
+ log.info("test open mode (O_CREAT|O_WRONLY|O_TRUNC)")
+ proc = self.mount_a.open_for_writing("link/test.txt")
+ time.sleep(1)
+ success = proc.finished and self.fs.rank_is_running(rank=1)
+
+ # Test other write modes too.
+ if success:
+ self.mount_a.remount()
+ log.info("test open mode (O_WRONLY|O_TRUNC)")
+ proc = self.mount_a.open_for_writing("link/test.txt", creat=False)
+ time.sleep(1)
+ success = proc.finished and self.fs.rank_is_running(rank=1)
+ if success:
+ self.mount_a.remount()
+ log.info("test open mode (O_CREAT|O_WRONLY)")
+ proc = self.mount_a.open_for_writing("link/test.txt", trunc=False)
+ time.sleep(1)
+ success = proc.finished and self.fs.rank_is_running(rank=1)
+
+ # Test open modes too.
+ if success:
+ self.mount_a.remount()
+ log.info("test open mode (O_RDONLY)")
+ proc = self.mount_a.open_for_reading("link/test.txt")
+ time.sleep(1)
+ success = proc.finished and self.fs.rank_is_running(rank=1)
+
+ if success:
+ # All tests done, rank 1 didn't crash.
+ return
+
+ if not proc.finished:
+ log.warning("open operation is blocked, kill it")
+ proc.kill()
+
+ if not self.fs.rank_is_running(rank=1):
+ log.warning("rank 1 crashed")
+
+ self.mount_a.umount_wait(force=True)
+
+ self.assertTrue(success, "open operation failed")
+
class TestEphemeralPins(CephFSTestCase):
MDSS_REQUIRED = 3
CLIENTS_REQUIRED = 1