Commit b0d1e540 by Kirill Smelkov

bigfile/tests/thread: Don't invalidate exactly same page to test general virtmem deadlock on loadblk

The main deadlock described in f49c11a3 (bigfile/virtmem: Do loadblk()
with virtmem lock released) (V,Z in T1; Z,V in T2) can happen if in T2 V
is taken for whatever reason - e.g. for invalidating completely
unrelated page to what is being loaded in T1.

For invalidation of the same page we have explicit separate
test_thread_load_vs_invalidate() which verifies how loadblk handles this
situation.

This patch prepares general test_thread_lock_vs_virtmem_lock() to also
test V vs Z deadlock for storeblk() case - when it will be called with
virtmem lock released: for storeblk it will be forbidden by virtmem
rules to invalidate pages of fileh for which writeout is in progress.

Updates: #6
1 parent 8bb7f2f2
......@@ -68,7 +68,7 @@ PS = 2*MB
# V -> loadblk
# Z <- ClientStorage.invalidateTransaction()
# Z -> zeo.load
# V <- fileh_invalidate_page
# V <- fileh_invalidate_page (possibly of unrelated page)
def test_thread_lock_vs_virtmem_lock():
Z = Lock()
c12 = NotifyChannel() # T1 -> T2
......@@ -77,26 +77,24 @@ def test_thread_lock_vs_virtmem_lock():
class ZLockBigFile(BigFile):
def __new__(cls, blksize):
obj = BigFile.__new__(cls, blksize)
obj.cycle = 0
return obj
def loadblk(self, blk, buf):
tell, wait = c12.tell, c21.wait
# on the first cycle we synchronize with invalidate in T2
if self.cycle == 0:
tell('T1-V-under')
wait('T2-Z-taken')
# synchronize with invalidate in T2
tell('T1-V-under')
wait('T2-Z-taken')
# this will deadlock, if V is plain lock and calling from under-virtmem
# is done with V held
Z.acquire()
Z.release()
# this will deadlock, if V is plain lock and calling from under-virtmem
# is done with V held
Z.acquire()
Z.release()
self.cycle += 1
f = ZLockBigFile(PS)
fh = f.fileh_open()
fh2 = f.fileh_open()
vma = fh.mmap(0, 1)
m = memoryview(vma)
......@@ -111,7 +109,7 @@ def test_thread_lock_vs_virtmem_lock():
Z.acquire()
tell('T2-Z-taken')
fh.invalidate_page(0)
fh2.invalidate_page(0) # NOTE invalidating page _not_ of fh
Z.release()
......@@ -185,7 +183,7 @@ def test_thread_multiaccess_parallel():
t1.join(); t2.join()
# loading vs invalidate in another thread
# loading vs invalidate of same page in another thread
def test_thread_load_vs_invalidate():
c12 = NotifyChannel() # T1 -> T2
c21 = NotifyChannel() # T2 -> T1
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!