Commit 87bf4908 authored by Kirill Smelkov's avatar Kirill Smelkov

bigfile/virtmem: Don't forget to release fileh->writeout_inprogress on storeblk error

Commit fb4bfb32 (bigfile/virtmem: Do storeblk() with virtmem lock
released) added bug-protection to fileh_dirty_writeout() so that it could
not be called twice at the same time or in parallel with other functions
which modify pages.

However it missed the code path when storeblk() call returned with error
and whole writeout was thus erroring out, but with fileh->writeout_inprogress
still left set to 1 incorrectly.

This was leading to things like

    bigfile/virtmem.c:419: fileh_dirty_discard: Assertion `!(fileh->writeout_inprogress)' failed.

and crashes.

Fix it.
parent 63ec659f
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
# See COPYING file for full licensing terms. # See COPYING file for full licensing terms.
# TODO description # TODO description
from wendelin.bigfile import BigFile, WRITEOUT_STORE, WRITEOUT_MARKSTORED from wendelin.bigfile import BigFile, WRITEOUT_STORE, WRITEOUT_MARKSTORED
from wendelin.lib.mem import bzero
import struct import struct
import weakref import weakref
import sys import sys
...@@ -343,3 +344,35 @@ def test_gc_from_sighandler(): ...@@ -343,3 +344,35 @@ def test_gc_from_sighandler():
assert f3.marker_list == [] assert f3.marker_list == []
m3[0] m3[0]
assert f3.marker_list == [2] assert f3.marker_list == [2]
# test that there is no crash after first store error on writeout
class StoreError(Exception):
pass
class StoreErrBigFile(BigFile):
def __new__(cls, blksize):
return BigFile.__new__(cls, blksize)
# load: just return all zero
def loadblk(self, blk, buf):
bzero(buf)
# store: always error
def storeblk(self, blk, buf):
raise StoreError("store blk #%d: error " % blk)
def test_writeout_err_notfatal():
f = StoreErrBigFile(PS)
fh = f.fileh_open()
vma = fh.mmap(0, 1)
m = memoryview(vma)
m[0] = bord_py3(b'A') # load + set dirty
# call writeout 2 times as previously upon error it was leaving internal
# flag set that writeout was still in progress and second call to writeout
# was leading to BUG and thus process crash.
raises(StoreError, "fh.dirty_writeout(WRITEOUT_STORE)")
raises(StoreError, "fh.dirty_writeout(WRITEOUT_STORE)")
...@@ -397,9 +397,9 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags) ...@@ -397,9 +397,9 @@ int fileh_dirty_writeout(BigFileH *fileh, enum WriteoutFlags flags)
if (flags & WRITEOUT_MARKSTORED) if (flags & WRITEOUT_MARKSTORED)
BUG_ON(!list_empty(&fileh->dirty_pages)); BUG_ON(!list_empty(&fileh->dirty_pages));
out:
fileh->writeout_inprogress = 0; fileh->writeout_inprogress = 0;
out:
virt_unlock(); virt_unlock();
sigsegv_restore(&save_sigset); sigsegv_restore(&save_sigset);
return err; return err;
......
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