2015-03-26 17:52:10 +00:00
|
|
|
|
2014-11-03 15:38:57 +00:00
|
|
|
from textwrap import dedent
|
2015-03-26 17:52:10 +00:00
|
|
|
from tasks.cephfs.cephfs_test_case import CephFSTestCase
|
|
|
|
from tasks.cephfs.filesystem import ObjectNotFound, ROOT_INO
|
2014-11-03 15:38:57 +00:00
|
|
|
|
|
|
|
|
|
|
|
class TestFlush(CephFSTestCase):
|
|
|
|
def test_flush(self):
|
2014-12-18 13:03:40 +00:00
|
|
|
self.mount_a.run_shell(["mkdir", "mydir"])
|
|
|
|
self.mount_a.run_shell(["touch", "mydir/alpha"])
|
|
|
|
dir_ino = self.mount_a.path_to_ino("mydir")
|
|
|
|
file_ino = self.mount_a.path_to_ino("mydir/alpha")
|
2014-11-03 15:38:57 +00:00
|
|
|
|
|
|
|
# Unmount the client so that it isn't still holding caps
|
2014-12-18 13:03:40 +00:00
|
|
|
self.mount_a.umount_wait()
|
2014-11-03 15:38:57 +00:00
|
|
|
|
|
|
|
# Before flush, the dirfrag object does not exist
|
|
|
|
with self.assertRaises(ObjectNotFound):
|
|
|
|
self.fs.list_dirfrag(dir_ino)
|
|
|
|
|
|
|
|
# Before flush, the file's backtrace has not been written
|
|
|
|
with self.assertRaises(ObjectNotFound):
|
|
|
|
self.fs.read_backtrace(file_ino)
|
|
|
|
|
|
|
|
# Before flush, there are no dentries in the root
|
|
|
|
self.assertEqual(self.fs.list_dirfrag(ROOT_INO), [])
|
|
|
|
|
|
|
|
# Execute flush
|
|
|
|
flush_data = self.fs.mds_asok(["flush", "journal"])
|
|
|
|
self.assertEqual(flush_data['return_code'], 0)
|
|
|
|
|
|
|
|
# After flush, the dirfrag object has been created
|
|
|
|
dir_list = self.fs.list_dirfrag(dir_ino)
|
|
|
|
self.assertEqual(dir_list, ["alpha_head"])
|
|
|
|
|
|
|
|
# And the 'mydir' dentry is in the root
|
|
|
|
self.assertEqual(self.fs.list_dirfrag(ROOT_INO), ['mydir_head'])
|
|
|
|
|
|
|
|
# ...and the data object has its backtrace
|
|
|
|
backtrace = self.fs.read_backtrace(file_ino)
|
|
|
|
self.assertEqual(['alpha', 'mydir'], [a['dname'] for a in backtrace['ancestors']])
|
|
|
|
self.assertEqual([dir_ino, 1], [a['dirino'] for a in backtrace['ancestors']])
|
|
|
|
self.assertEqual(file_ino, backtrace['ino'])
|
|
|
|
|
|
|
|
# ...and the journal is truncated to just a single subtreemap from the
|
|
|
|
# newly created segment
|
2015-02-23 13:43:13 +00:00
|
|
|
summary_output = self.fs.journal_tool(["event", "get", "summary"])
|
|
|
|
try:
|
|
|
|
self.assertEqual(summary_output,
|
|
|
|
dedent(
|
|
|
|
"""
|
|
|
|
Events by type:
|
|
|
|
SUBTREEMAP: 1
|
|
|
|
Errors: 0
|
|
|
|
"""
|
|
|
|
).strip())
|
|
|
|
except AssertionError:
|
|
|
|
# In some states, flushing the journal will leave you
|
|
|
|
# an extra event from locks a client held. This is
|
|
|
|
# correct behaviour: the MDS is flushing the journal,
|
|
|
|
# it's just that new events are getting added too.
|
|
|
|
# In this case, we should nevertheless see a fully
|
|
|
|
# empty journal after a second flush.
|
|
|
|
self.assertEqual(summary_output,
|
|
|
|
dedent(
|
|
|
|
"""
|
|
|
|
Events by type:
|
|
|
|
SUBTREEMAP: 1
|
|
|
|
UPDATE: 1
|
|
|
|
Errors: 0
|
|
|
|
"""
|
|
|
|
).strip())
|
|
|
|
flush_data = self.fs.mds_asok(["flush", "journal"])
|
|
|
|
self.assertEqual(flush_data['return_code'], 0)
|
|
|
|
self.assertEqual(self.fs.journal_tool(["event", "get", "summary"]),
|
|
|
|
dedent(
|
|
|
|
"""
|
|
|
|
Events by type:
|
|
|
|
SUBTREEMAP: 1
|
|
|
|
Errors: 0
|
|
|
|
"""
|
|
|
|
).strip())
|
2014-11-03 15:38:57 +00:00
|
|
|
|
|
|
|
# Now for deletion!
|
2015-02-19 09:12:38 +00:00
|
|
|
# We will count the RADOS deletions and MDS file purges, to verify that
|
|
|
|
# the expected behaviour is happening as a result of the purge
|
|
|
|
initial_dels = self.fs.mds_asok(['perf', 'dump', 'objecter'])['objecter']['osdop_delete']
|
|
|
|
initial_purges = self.fs.mds_asok(['perf', 'dump', 'mds_cache'])['mds_cache']['strays_purged']
|
|
|
|
|
|
|
|
# Use a client to delete a file
|
2014-12-18 13:03:40 +00:00
|
|
|
self.mount_a.mount()
|
|
|
|
self.mount_a.wait_until_mounted()
|
|
|
|
self.mount_a.run_shell(["rm", "-rf", "mydir"])
|
2014-11-03 15:38:57 +00:00
|
|
|
|
2015-02-19 09:12:38 +00:00
|
|
|
# Flush the journal so that the directory inode can be purged
|
2014-11-03 15:38:57 +00:00
|
|
|
flush_data = self.fs.mds_asok(["flush", "journal"])
|
|
|
|
self.assertEqual(flush_data['return_code'], 0)
|
|
|
|
|
2015-01-19 21:32:50 +00:00
|
|
|
# We expect to see a single file purge
|
|
|
|
self.wait_until_true(
|
2015-02-19 09:12:38 +00:00
|
|
|
lambda: self.fs.mds_asok(['perf', 'dump', 'mds_cache'])['mds_cache']['strays_purged'] - initial_purges >= 2,
|
2015-01-19 21:32:50 +00:00
|
|
|
60)
|
|
|
|
|
2014-11-03 15:38:57 +00:00
|
|
|
# We expect two deletions, one of the dirfrag and one of the backtrace
|
2014-12-18 12:50:16 +00:00
|
|
|
self.wait_until_true(
|
2015-02-19 09:12:38 +00:00
|
|
|
lambda: self.fs.mds_asok(['perf', 'dump', 'objecter'])['objecter']['osdop_delete'] - initial_dels >= 2,
|
2015-01-07 13:08:30 +00:00
|
|
|
60) # timeout is fairly long to allow for tick+rados latencies
|
2014-11-03 15:38:57 +00:00
|
|
|
|
|
|
|
with self.assertRaises(ObjectNotFound):
|
|
|
|
self.fs.list_dirfrag(dir_ino)
|
|
|
|
with self.assertRaises(ObjectNotFound):
|
|
|
|
self.fs.read_backtrace(file_ino)
|
|
|
|
self.assertEqual(self.fs.list_dirfrag(ROOT_INO), [])
|