diff --git a/tests/functional/pyocf/types/volume.py b/tests/functional/pyocf/types/volume.py index 09d5224..9ef59c8 100644 --- a/tests/functional/pyocf/types/volume.py +++ b/tests/functional/pyocf/types/volume.py @@ -431,12 +431,19 @@ class RamVolume(Volume): class ErrorDevice(Volume): def __init__( - self, vol, error_sectors: set = None, error_seq_no: dict = None, armed=True, uuid=None, + self, + vol, + error_sectors: set = None, + error_seq_no: dict = None, + data_only=False, + armed=True, + uuid=None, ): self.vol = vol super().__init__(uuid) - self.error_sectors = error_sectors - self.error_seq_no = error_seq_no + self.error_sectors = error_sectors or set() + self.error_seq_no = error_seq_no or {IoDir.WRITE: -1, IoDir.READ: -1} + self.data_only = data_only self.armed = armed self.io_seq_no = {IoDir.WRITE: 0, IoDir.READ: 0} self.error = False @@ -444,32 +451,44 @@ class ErrorDevice(Volume): def set_mapping(self, error_sectors: set): self.error_sectors = error_sectors - def do_submit_io(self, io): + def should_forward_io(self, io): if not self.armed: - self.vol.do_submit_io(io) - return + return True direction = IoDir(io.contents._dir) seq_no_match = ( - self.error_seq_no is not None - and direction in self.error_seq_no + self.error_seq_no[direction] >= 0 and self.error_seq_no[direction] <= self.io_seq_no[direction] ) - sector_match = self.error_sectors is not None and io.contents._addr in self.error_sectors + sector_match = io.contents._addr in self.error_sectors self.io_seq_no[direction] += 1 - error = True - if self.error_seq_no is not None and not seq_no_match: - error = False - if self.error_sectors is not None and not sector_match: - error = False - if error: - self.error = True - io.contents._end(io, -OcfErrorCode.OCF_ERR_IO) - self.stats["errors"][direction] += 1 - else: + return not seq_no_match and not sector_match + + def complete_with_error(self, io): + self.error = True + direction = IoDir(io.contents._dir) + self.stats["errors"][direction] += 1 + io.contents._end(io, -OcfErrorCode.OCF_ERR_IO) + + def do_submit_io(self, io): + if self.should_forward_io(io): self.vol.do_submit_io(io) + else: + self.complete_with_error(io) + + def do_submit_flush(self, flush): + if self.data_only and self.should_forward_io(flush): + self.vol.do_submit_flush(flush) + else: + self.complete_with_error(flush) + + def do_submit_discard(self, discard): + if self.data_only and self.should_forward_io(discard): + self.vol.do_submit_discard(discard) + else: + self.complete_with_error(discard) def arm(self): self.armed = True @@ -491,12 +510,6 @@ class ErrorDevice(Volume): def get_max_io_size(self): return self.vol.get_max_io_size() - def do_submit_flush(self, flush): - return self.vol.do_submit_flush(flush) - - def do_submit_discard(self, discard): - return self.vol.do_submit_discard(discard) - def dump(self, offset=0, size=0, ignore=VOLUME_POISON, **kwargs): return self.vol.dump(offset, size, ignore=ignore, **kwargs) diff --git a/tests/functional/tests/surprise_shutdown/test_management_surprise_shutdown.py b/tests/functional/tests/surprise_shutdown/test_management_surprise_shutdown.py index f1e0c8d..7037262 100644 --- a/tests/functional/tests/surprise_shutdown/test_management_surprise_shutdown.py +++ b/tests/functional/tests/surprise_shutdown/test_management_surprise_shutdown.py @@ -70,7 +70,10 @@ def prepare_failover(pyocf_2_ctx, cache_backend_vol, error_io_seq_no): error_io = {IoDir.WRITE: error_io_seq_no} - err_vol = ErrorDevice(cache2_exp_obj_vol, error_seq_no=error_io, armed=False) + # TODO: Adjust tests to work with error injection for flushes and discards (data_only=False + # below). Currently the test fails with data_only=False as it assumes metadata is not updated + # if error had been injected, which is not true in case of error in flush. + err_vol = ErrorDevice(cache2_exp_obj_vol, error_seq_no=error_io, data_only=True, armed=False) cache = Cache.start_on_device(err_vol, cache_mode=CacheMode.WB, owner=ctx1) return cache, cache2, err_vol @@ -81,7 +84,7 @@ def prepare_normal(pyocf_2_ctx, cache_backend_vol, error_io_seq_no): error_io = {IoDir.WRITE: error_io_seq_no} - err_vol = ErrorDevice(cache_backend_vol, error_seq_no=error_io, armed=False) + err_vol = ErrorDevice(cache_backend_vol, error_seq_no=error_io, data_only=True, armed=False) cache = Cache.start_on_device(err_vol, cache_mode=CacheMode.WB, owner=ctx1) return cache, err_vol @@ -330,9 +333,11 @@ def test_surprise_shutdown_start_cache(pyocf_2_ctx, failover): cache2.start_cache() cache2.standby_attach(ramdisk) cache2_exp_obj_vol = CacheVolume(cache2, open=True) - err_device = ErrorDevice(cache2_exp_obj_vol, error_seq_no=error_io, armed=True) + err_device = ErrorDevice( + cache2_exp_obj_vol, error_seq_no=error_io, data_only=True, armed=True + ) else: - err_device = ErrorDevice(ramdisk, error_seq_no=error_io, armed=True) + err_device = ErrorDevice(ramdisk, error_seq_no=error_io, data_only=True, armed=True) # call tested management function try: @@ -808,7 +813,7 @@ def test_surprise_shutdown_standby_activate(pyocf_ctx): # Start cache device without error injection error_io = {IoDir.WRITE: error_io_seq_no} ramdisk = RamVolume(mngmt_op_surprise_shutdown_test_cache_size) - device = ErrorDevice(ramdisk, error_seq_no=error_io, armed=False) + device = ErrorDevice(ramdisk, error_seq_no=error_io, data_only=True, rmed=False) core_device = RamVolume(S.from_MiB(10)) device.disarm() @@ -882,7 +887,7 @@ def test_surprise_shutdown_standby_init_clean(pyocf_ctx): # Start cache device without error injection error_io = {IoDir.WRITE: error_io_seq_no} ramdisk = RamVolume(mngmt_op_surprise_shutdown_test_cache_size) - device = ErrorDevice(ramdisk, error_seq_no=error_io, armed=True) + device = ErrorDevice(ramdisk, error_seq_no=error_io, data_only=True, armed=True) cache = Cache(owner=OcfCtx.get_default()) cache.start_cache() @@ -942,7 +947,7 @@ def test_surprise_shutdown_standby_init_force_1(pyocf_ctx): # Start cache device without error injection error_io = {IoDir.WRITE: error_io_seq_no} ramdisk = RamVolume(mngmt_op_surprise_shutdown_test_cache_size) - device = ErrorDevice(ramdisk, error_seq_no=error_io, armed=False) + device = ErrorDevice(ramdisk, error_seq_no=error_io, data_only=True, armed=False) # start and stop cache with cacheline inserted cache = Cache.start_on_device(device, cache_mode=CacheMode.WB) @@ -1032,7 +1037,7 @@ def test_surprise_shutdown_standby_init_force_2(pyocf_ctx): # Start cache device without error injection error_io = {IoDir.WRITE: error_io_seq_no} ramdisk = RamVolume(mngmt_op_surprise_shutdown_test_cache_size) - device = ErrorDevice(ramdisk, error_seq_no=error_io, armed=False) + device = ErrorDevice(ramdisk, error_seq_no=error_io, data_only=True, armed=False) # start and stop cache with cacheline inserted cache = Cache.start_on_device(device, cache_mode=CacheMode.WB)