REQUIRE_KCLIENT_REMOTE = True
CLIENTS_REQUIRED = 2
- def _test_client_pin(self, use_subdir):
+ def _test_client_pin(self, use_subdir, open_files):
"""
When a client pins an inode in its cache, for example because the file is held open,
it should reject requests from the MDS to trim these caps. The MDS should complain
:param use_subdir: whether to put test files in a subdir or use root
"""
- cache_size = 100
- open_files = 200
+ cache_size = open_files/2
self.set_conf('mds', 'mds cache size', cache_size)
+ self.set_conf('mds', 'mds_recall_max_caps', open_files/2)
+ self.set_conf('mds', 'mds_recall_warning_threshold', open_files)
self.fs.mds_fail_restart()
self.fs.wait_for_daemons()
+ mds_min_caps_per_client = int(self.fs.get_config("mds_min_caps_per_client"))
+ mds_recall_warning_decay_rate = self.fs.get_config("mds_recall_warning_decay_rate")
+ self.assertTrue(open_files >= mds_min_caps_per_client)
+
mount_a_client_id = self.mount_a.get_global_id()
path = "subdir/mount_a" if use_subdir else "mount_a"
open_proc = self.mount_a.open_n_background(path, open_files)
# MDS should not be happy about that, as the client is failing to comply
# with the SESSION_RECALL messages it is being sent
- mds_recall_state_timeout = int(self.fs.get_config("mds_recall_state_timeout"))
- self.wait_for_health("failing to respond to cache pressure",
- mds_recall_state_timeout + 10)
+ self.wait_for_health("MDS_CLIENT_RECALL", mds_recall_warning_decay_rate*2)
# We can also test that the MDS health warning for oversized
# cache is functioning as intended.
- self.wait_for_health("Too many inodes in cache",
- mds_recall_state_timeout + 10)
+ self.wait_for_health("MDS_CACHE_OVERSIZED", mds_recall_warning_decay_rate*2)
# When the client closes the files, it should retain only as many caps as allowed
# under the SESSION_RECALL policy
pass
# The remaining caps should comply with the numbers sent from MDS in SESSION_RECALL message,
- # which depend on the cache size and overall ratio
- self.wait_until_equal(
- lambda: self.get_session(mount_a_client_id)['num_caps'],
- int(cache_size * 0.8),
- timeout=600,
- reject_fn=lambda x: x < int(cache_size*.8))
+ # which depend on the caps outstanding, cache size and overall ratio
+ def expected_caps():
+ num_caps = self.get_session(mount_a_client_id)['num_caps']
+ if num_caps <= mds_min_caps_per_client:
+ return True
+ elif num_caps < cache_size:
+ return True
+ else:
+ return False
+
+ self.wait_until_true(expected_caps, timeout=60)
@needs_trimming
def test_client_pin_root(self):
- self._test_client_pin(False)
+ self._test_client_pin(False, 400)
@needs_trimming
def test_client_pin(self):
- self._test_client_pin(True)
+ self._test_client_pin(True, 800)
+
+ @needs_trimming
+ def test_client_pin_mincaps(self):
+ self._test_client_pin(True, 200)
def test_client_release_bug(self):
"""
# Client B tries to stat the file that client A created
rproc = self.mount_b.write_background("file1")
- # After mds_revoke_cap_timeout, we should see a health warning (extra lag from
+ # After session_timeout, we should see a health warning (extra lag from
# MDS beacon period)
- mds_revoke_cap_timeout = int(self.fs.get_config("mds_revoke_cap_timeout"))
- self.wait_for_health("failing to respond to capability release", mds_revoke_cap_timeout + 10)
+ session_timeout = self.fs.get_var("session_timeout")
+ self.wait_for_health("MDS_CLIENT_LATE_RELEASE", session_timeout + 10)
# Client B should still be stuck
self.assertFalse(rproc.finished)
self.mount_a.create_n_files("testdir/file2", 5, True)
# Wait for the health warnings. Assume mds can handle 10 request per second at least
- self.wait_for_health("failing to advance its oldest client/flush tid", max_requests / 10)
+ self.wait_for_health("MDS_CLIENT_OLDEST_TID", max_requests / 10)
def _test_client_cache_size(self, mount_subdir):
"""
def test_client_cache_size(self):
self._test_client_cache_size(False)
self._test_client_cache_size(True)
+
+ def test_client_max_caps(self):
+ """
+ That the MDS will not let a client sit above mds_max_caps_per_client caps.
+ """
+
+ mds_min_caps_per_client = int(self.fs.get_config("mds_min_caps_per_client"))
+ mds_max_caps_per_client = 2*mds_min_caps_per_client
+ self.set_conf('mds', 'mds_max_caps_per_client', mds_max_caps_per_client)
+ self.fs.mds_fail_restart()
+ self.fs.wait_for_daemons()
+
+ self.mount_a.create_n_files("foo/", 3*mds_max_caps_per_client, sync=True)
+
+ mount_a_client_id = self.mount_a.get_global_id()
+ def expected_caps():
+ num_caps = self.get_session(mount_a_client_id)['num_caps']
+ if num_caps <= mds_max_caps_per_client:
+ return True
+ else:
+ return False
+
+ self.wait_until_true(expected_caps, timeout=60)