def test_start_write_first_and_check_mode(pyocf_ctx, mode: CacheMode, cls: CacheLineSize): """Test starting cache in different modes with different cache line sizes. After start check proper cache mode behaviour, starting with write operation. """ cache_device = Volume(Size.from_MiB(40)) core_device = Volume(Size.from_MiB(10)) cache = Cache.start_on_device(cache_device, cache_mode=mode, cache_line_size=cls) core_exported = Core.using_device(core_device) cache.add_core(core_exported) logger.info("[STAGE] Initial write to exported object") cache_device.reset_stats() core_device.reset_stats() test_data = Data.from_string("This is test data") io_to_core(core_exported, test_data, Size.from_sector(1).B) check_stats_write_empty(core_exported, mode, cls) logger.info("[STAGE] Read from exported object after initial write") io_from_exported_object(core_exported, test_data.size, Size.from_sector(1).B) check_stats_read_after_write(core_exported, mode, cls, True) logger.info("[STAGE] Write to exported object after read") cache_device.reset_stats() core_device.reset_stats() test_data = Data.from_string("Changed test data") io_to_core(core_exported, test_data, Size.from_sector(1).B) check_stats_write_after_read(core_exported, mode, cls) check_md5_sums(core_exported, mode)
def test_simple_wt_write(pyocf_ctx): cache_device = Volume(S.from_MiB(30)) core_device = Volume(S.from_MiB(30)) cache = Cache.start_on_device(cache_device) core = Core.using_device(core_device) cache.add_core(core) cache_device.reset_stats() core_device.reset_stats() write_data = Data.from_string("This is test data") io = core.new_io(cache.get_default_queue(), S.from_sector(1).B, write_data.size, IoDir.WRITE, 0, 0) io.set_data(write_data) cmpl = OcfCompletion([("err", c_int)]) io.callback = cmpl.callback io.submit() cmpl.wait() assert cmpl.results["err"] == 0 assert cache_device.get_stats()[IoDir.WRITE] == 1 stats = cache.get_stats() assert stats["req"]["wr_full_misses"]["value"] == 1 assert stats["usage"]["occupancy"]["value"] == 1 assert core.exp_obj_md5() == core_device.md5() cache.stop()
def test_10add_remove_with_io(pyocf_ctx): # Start cache device cache_device = Volume(S.from_MiB(30)) cache = Cache.start_on_device(cache_device) # Create core device core_device = Volume(S.from_MiB(10)) core = Core.using_device(core_device) # Add and remove core 10 times in a loop with io in between for i in range(0, 10): cache.add_core(core) stats = cache.get_stats() assert stats["conf"]["core_count"] == 1 write_data = Data.from_string("Test data") io = core.new_io() io.set_data(write_data) io.configure(20, write_data.size, IoDir.WRITE, 0, 0) io.set_queue(cache.get_default_queue()) cmpl = OcfCompletion([("err", c_int)]) io.callback = cmpl.callback io.submit() cmpl.wait() cache.remove_core(core) stats = cache.get_stats() assert stats["conf"]["core_count"] == 0
def test_simple_wt_write(pyocf_ctx): cache_device = Volume(S.from_MiB(100)) core_device = Volume(S.from_MiB(200)) cache = Cache.start_on_device(cache_device) core = Core.using_device(core_device) queue = Queue(cache) cache.add_core(core) cache_device.reset_stats() core_device.reset_stats() write_data = Data.from_string("This is test data") io = core.new_io() io.set_data(write_data) io.configure(20, write_data.size, IoDir.WRITE, 0, 0) io.set_queue(queue) io.submit() assert cache_device.get_stats()[IoDir.WRITE] == 1 stats = cache.get_stats() assert stats["req"]["wr_full_misses"]["value"] == 1 assert stats["usage"]["occupancy"]["value"] == 1 assert core.exp_obj_md5() == core_device.md5()
def test_start_read_first_and_check_mode(pyocf_ctx, mode: CacheMode, cls: CacheLineSize): """Starting cache in different modes with different cache line sizes. After start check proper cache mode behaviour, starting with read operation. """ cache_device = RamVolume(Size.from_MiB(50)) core_device = RamVolume(Size.from_MiB(5)) cache = Cache.start_on_device(cache_device, cache_mode=mode, cache_line_size=cls) core = Core.using_device(core_device) cache.add_core(core) front_vol = CoreVolume(core, open=True) bottom_vol = core.get_volume() queue = cache.get_default_queue() logger.info("[STAGE] Initial write to core device") test_data = Data.from_string("This is test data") io_to_core(bottom_vol, queue, test_data, Size.from_sector(1).B) cache_device.reset_stats() core_device.reset_stats() logger.info("[STAGE] Initial read from exported object") io_from_exported_object(front_vol, queue, test_data.size, Size.from_sector(1).B) check_stats_read_empty(core, mode, cls) logger.info("[STAGE] Write to exported object after initial read") cache_device.reset_stats() core_device.reset_stats() test_data = Data.from_string("Changed test data") io_to_core(front_vol, queue, test_data, Size.from_sector(1).B) check_stats_write_after_read(core, mode, cls, True) logger.info("[STAGE] Read from exported object after write") io_from_exported_object(front_vol, queue, test_data.size, Size.from_sector(1).B) check_stats_read_after_write(core, mode, cls) check_md5_sums(core, mode)
def run_io_and_cache_data_if_possible(exported_obj, mode, cls): test_data = Data.from_string("This is test data") if mode in {CacheMode.WI, CacheMode.WA}: logger.info("[STAGE] Write to core device") io_to_core(exported_obj, test_data, 20, True) logger.info("[STAGE] Read from exported object") io_from_exported_object(exported_obj, test_data.size, 20) else: logger.info("[STAGE] Write to exported object") io_to_core(exported_obj, test_data, 20) stats = exported_obj.cache.get_stats() assert stats["usage"]["occupancy"]["value"] == \ ((cls / CacheLineSize.LINE_4KiB) if mode != CacheMode.PT else 0), "Occupancy"
def test_load_cache_with_cores(pyocf_ctx, open_cores): cache_device = RamVolume(S.from_MiB(40)) core_device = RamVolume(S.from_MiB(40)) cache = Cache.start_on_device(cache_device) core = Core.using_device(core_device, name="test_core") cache.add_core(core) vol = CoreVolume(core, open=True) write_data = Data.from_string("This is test data") io = vol.new_io(cache.get_default_queue(), S.from_sector(3).B, write_data.size, IoDir.WRITE, 0, 0) io.set_data(write_data) cmpl = OcfCompletion([("err", c_int)]) io.callback = cmpl.callback io.submit() cmpl.wait() cache.stop() cache = Cache.load_from_device(cache_device, open_cores=open_cores) if not open_cores: cache.add_core(core, try_add=True) else: core = cache.get_core_by_name("test_core") vol = CoreVolume(core, open=True) read_data = Data(write_data.size) io = vol.new_io(cache.get_default_queue(), S.from_sector(3).B, read_data.size, IoDir.READ, 0, 0) io.set_data(read_data) cmpl = OcfCompletion([("err", c_int)]) io.callback = cmpl.callback io.submit() cmpl.wait() assert read_data.md5() == write_data.md5() assert vol.md5() == core_device.md5()
def test_secure_erase_simple_io_read_misses(cache_mode): """ Perform simple IO which will trigger read misses, which in turn should trigger backfill. Track all the data locked/copied for backfill and make sure OCF calls secure erase and unlock on them. """ ctx = OcfCtx( OcfLib.getInstance(), b"Security tests ctx", DefaultLogger(LogLevel.WARN), DataCopyTracer, MetadataUpdater, Cleaner, ) ctx.register_volume_type(Volume) cache_device = Volume(S.from_MiB(30)) cache = Cache.start_on_device(cache_device, cache_mode=cache_mode) core_device = Volume(S.from_MiB(50)) core = Core.using_device(core_device) cache.add_core(core) write_data = Data.from_string("This is test data") io = core.new_io() io.set_data(write_data) io.configure(20, write_data.size, IoDir.WRITE, 0, 0) io.set_queue(cache.get_default_queue()) cmpl = OcfCompletion([("err", c_int)]) io.callback = cmpl.callback io.submit() cmpl.wait() cmpls = [] for i in range(100): read_data = Data(500) io = core.new_io() io.set_data(read_data) io.configure( (i * 1259) % int(core_device.size), read_data.size, IoDir.READ, 0, 0 ) io.set_queue(cache.get_default_queue()) cmpl = OcfCompletion([("err", c_int)]) io.callback = cmpl.callback cmpls.append(cmpl) io.submit() for c in cmpls: c.wait() write_data = Data.from_string("TEST DATA" * 100) io = core.new_io() io.set_data(write_data) io.configure(500, write_data.size, IoDir.WRITE, 0, 0) io.set_queue(cache.get_default_queue()) cmpl = OcfCompletion([("err", c_int)]) io.callback = cmpl.callback io.submit() cmpl.wait() stats = cache.get_stats() ctx.exit() assert ( len(DataCopyTracer.needs_erase) == 0 ), "Not all locked Data instances were secure erased!" assert ( len(DataCopyTracer.locked_instances) == 0 ), "Not all locked Data instances were unlocked!" assert ( stats["req"]["rd_partial_misses"]["value"] + stats["req"]["rd_full_misses"]["value"] ) > 0