diff --git a/inc/ocf_err.h b/inc/ocf_err.h index 9af69b1..68d6a05 100644 --- a/inc/ocf_err.h +++ b/inc/ocf_err.h @@ -143,6 +143,9 @@ typedef enum { /** Invalid operation for cache in standby state. */ OCF_ERR_CACHE_STANDBY, + /** Size of core volume doesn't match the size stored in cache metadata */ + OCF_ERR_CORE_SIZE_MISMATCH, + /** Operation invalid with cache drive atatched in failover standby */ OCF_ERR_STANDBY_ATTACHED, diff --git a/src/mngt/ocf_mngt_cache.c b/src/mngt/ocf_mngt_cache.c index e1ffe3a..e42ab8d 100644 --- a/src/mngt/ocf_mngt_cache.c +++ b/src/mngt/ocf_mngt_cache.c @@ -353,6 +353,7 @@ static void _ocf_mngt_load_add_cores(ocf_pipeline_t pipeline, int ret = -1; uint64_t hd_lines = 0; uint64_t length; + ocf_error_t error = -OCF_ERR_START_CACHE_FAIL; OCF_ASSERT_PLUGGED(cache); @@ -435,10 +436,11 @@ static void _ocf_mngt_load_add_cores(ocf_pipeline_t pipeline, length = ocf_volume_get_length(&core->volume); if (length != core->conf_meta->length) { - ocf_cache_log(cache, log_err, + ocf_core_log(core, log_err, "Size of core volume doesn't match with" " the size stored in cache metadata!"); - goto err; + error = -OCF_ERR_CORE_SIZE_MISMATCH; + goto err; } hd_lines = ocf_bytes_2_lines(cache, length); @@ -455,7 +457,7 @@ static void _ocf_mngt_load_add_cores(ocf_pipeline_t pipeline, err: _ocf_mngt_close_all_uninitialized_cores(context); - OCF_PL_FINISH_RET(pipeline, -OCF_ERR_START_CACHE_FAIL); + OCF_PL_FINISH_RET(pipeline, error); } typedef void (*ocf_mngt_rebuild_metadata_end_t)(void *priv, int error); diff --git a/src/mngt/ocf_mngt_core.c b/src/mngt/ocf_mngt_core.c index 64f30b7..ac8d306 100644 --- a/src/mngt/ocf_mngt_core.c +++ b/src/mngt/ocf_mngt_core.c @@ -305,7 +305,7 @@ static void ocf_mngt_cache_try_add_core_insert(ocf_pipeline_t pipeline, ocf_cache_log(cache, log_err, "Size of core volume doesn't match with" " the size stored in cache metadata!\n"); - result = -OCF_ERR_CORE_NOT_AVAIL; + result = -OCF_ERR_CORE_SIZE_MISMATCH; goto error_after_open; } diff --git a/tests/functional/pyocf/types/shared.py b/tests/functional/pyocf/types/shared.py index 51ef230..27c4c08 100644 --- a/tests/functional/pyocf/types/shared.py +++ b/tests/functional/pyocf/types/shared.py @@ -54,6 +54,7 @@ class OcfErrorCode(IntEnum): OCF_ERR_METADATA_LAYOUT_MISMATCH = auto() OCF_ERR_CACHE_LINE_SIZE_MISMATCH = auto() OCF_ERR_CACHE_STANDBY = auto() + OCF_ERR_CORE_SIZE_MISMATCH = auto() OCF_ERR_STANDBY_ATTACHED = auto() diff --git a/tests/functional/pyocf/types/volume.py b/tests/functional/pyocf/types/volume.py index c983c60..8384742 100644 --- a/tests/functional/pyocf/types/volume.py +++ b/tests/functional/pyocf/types/volume.py @@ -256,6 +256,12 @@ class Volume(Structure): def get_length(self): return self.size + def resize(self, size): + self.size = size + self.data = create_string_buffer(int(self.size)) + memset(self.data, self.VOLUME_POISON, self.size) + self._storage = cast(self.data, c_void_p) + def get_max_io_size(self): return S.from_KiB(128) diff --git a/tests/functional/tests/management/test_add_remove.py b/tests/functional/tests/management/test_add_remove.py index d071989..95cfc32 100644 --- a/tests/functional/tests/management/test_add_remove.py +++ b/tests/functional/tests/management/test_add_remove.py @@ -313,3 +313,69 @@ def _io_to_core(exported_obj: Core, data: Data): completion.wait() assert completion.results["err"] == 0, "IO to exported object completion" + + +@pytest.mark.xfail +@pytest.mark.parametrize("cache_mode", CacheMode) +@pytest.mark.parametrize("cls", CacheLineSize) +def test_try_add_with_changed_core_size(pyocf_ctx, cache_mode, cls): + """ + Test changing volume size before load + :param pyocf_ctx: basic pyocf context fixture + :param cm: cache mode we start with + :param cls: cache line size we start with + """ + # Start cache device + cache_device = Volume(S.from_MiB(50)) + cache = Cache.start_on_device( + cache_device, cache_mode=cache_mode, cache_line_size=cls + ) + + # Add core to cache + core_device = Volume(S.from_MiB(10)) + core = Core.using_device(core_device) + cache.add_core(core) + + # Stop cache + cache.stop() + + # Change core device size + core_device.resize(S.from_MiB(12)) + + # Load cache with changed core size + cache = Cache.load_from_device(cache_device, open_cores=False) + core = Core(device=core_device, try_add=True) + + with pytest.raises(OcfError, match="OCF_ERR_CORE_SIZE_MISMATCH"): + cache.add_core(core) + + +@pytest.mark.parametrize("cache_mode", CacheMode) +@pytest.mark.parametrize("cls", CacheLineSize) +def test_load_with_changed_core_size(pyocf_ctx, cache_mode, cls): + """ + Test changing volume size before load + :param pyocf_ctx: basic pyocf context fixture + :param cm: cache mode we start with + :param cls: cache line size we start with + """ + # Start cache device + cache_device = Volume(S.from_MiB(50)) + cache = Cache.start_on_device( + cache_device, cache_mode=cache_mode, cache_line_size=cls + ) + + # Add core to cache + core_device = Volume(S.from_MiB(10)) + core = Core.using_device(core_device) + cache.add_core(core) + + # Stop cache + cache.stop() + + # Change core device size + core_device.resize(S.from_MiB(12)) + + # Load cache with changed core size + with pytest.raises(OcfError, match="OCF_ERR_CORE_SIZE_MISMATCH"): + cache = Cache.load_from_device(cache_device)