Commit b0d1e540 authored by Kirill Smelkov's avatar Kirill Smelkov

bigfile/tests/thread: Don't invalidate exactly same page to test general...

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