pyscript = dedent(script_builder).format(path=path)
- log.info("lock file {0}".format(basename))
+ log.info("lock_background file {0}".format(basename))
rproc = self._run_python(pyscript)
self.background_procs.append(rproc)
return rproc
+ def lock_and_release(self, basename="background_file"):
+ assert(self.is_mounted())
+
+ path = os.path.join(self.mountpoint, basename)
+
+ script = """
+ import time
+ import fcntl
+ import struct
+ f1 = open("{path}-1", 'w')
+ fcntl.flock(f1, fcntl.LOCK_EX)
+ f2 = open("{path}-2", 'w')
+ lockdata = struct.pack('hhllhh', fcntl.F_WRLCK, 0, 0, 0, 0, 0)
+ fcntl.fcntl(f2, fcntl.F_SETLK, lockdata)
+ """
+ pyscript = dedent(script).format(path=path)
+
+ log.info("lock_and_release file {0}".format(basename))
+ return self._run_python(pyscript)
+
def check_filelock(self, basename="background_file", do_flock=True):
assert(self.is_mounted())
count, num_caps
))
- def test_filelock(self):
- """
- Check that file lock doesn't get lost after an MDS restart
- """
+ def _is_flockable(self):
a_version_str = get_package_version(self.mount_a.client_remote, "fuse")
b_version_str = get_package_version(self.mount_b.client_remote, "fuse")
flock_version_str = "2.9"
b_version = version.StrictVersion(b_result.group())
flock_version=version.StrictVersion(flock_version_str)
- flockable = False
if (a_version >= flock_version and b_version >= flock_version):
- log.info("testing flock locks")
- flockable = True
+ log.info("flock locks are available")
+ return True
else:
log.info("not testing flock locks, machines have versions {av} and {bv}".format(
av=a_version_str,bv=b_version_str))
+ return False
+
+ def test_filelock(self):
+ """
+ Check that file lock doesn't get lost after an MDS restart
+ """
+ flockable = self._is_flockable()
lock_holder = self.mount_a.lock_background(do_flock=flockable)
self.mount_b.wait_for_visible("background_file-2")
# We killed it, so it raises an error
pass
+ def test_filelock_eviction(self):
+ """
+ Check that file lock held by evicted client is given to
+ waiting client.
+ """
+ if not self._is_flockable():
+ self.skipTest("flock is not available")
+
+ lock_holder = self.mount_a.lock_background()
+ self.mount_b.wait_for_visible("background_file-2")
+ self.mount_b.check_filelock()
+
+ lock_taker = self.mount_b.lock_and_release()
+ # Check the taker is waiting (doesn't get it immediately)
+ time.sleep(2)
+ self.assertFalse(lock_holder.finished)
+ self.assertFalse(lock_taker.finished)
+
+ mount_a_client_id = self.mount_a.get_global_id()
+ self.fs.mds_asok(['session', 'evict', "%s" % mount_a_client_id])
+
+ # Evicting mount_a should let mount_b's attepmt to take the lock
+ # suceed
+ self.wait_until_true(
+ lambda: lock_taker.finished,
+ timeout=10)
+
def test_dir_fsync(self):
self._test_fsync(True);