def test_ioclass_directory_file_operations(filesystem): """ Test if directory classification works properly after file operations like move or rename. The operations themselves should not cause reclassification but IO after those operations should be reclassified to proper IO class. """ def check_occupancy(expected: Size, actual: Size): if expected != actual: pytest.xfail("Occupancy check failed!\n" f"Expected: {expected}, actual: {actual}") cache, core = prepare() Udev.disable() test_dir_path = f"{mountpoint}/test_dir" nested_dir_path = f"{test_dir_path}/nested_dir" dd_blocks = random.randint(5, 50) ioclass_id = random.randint(1, ioclass_config.MAX_IO_CLASS_ID) # directory IO class ioclass_config.add_ioclass( ioclass_id=ioclass_id, eviction_priority=1, allocation=True, rule=f"directory:{test_dir_path}", ioclass_config_path=ioclass_config_path, ) casadm.load_io_classes(cache_id=cache.cache_id, file=ioclass_config_path) TestRun.LOGGER.info(f"Preparing {filesystem.name} filesystem " f"and mounting {core.system_path} at {mountpoint}") core.create_filesystem(fs_type=filesystem) core.mount(mount_point=mountpoint) sync() TestRun.LOGGER.info(f"Creating directory {nested_dir_path}") Directory.create_directory(path=nested_dir_path, parents=True) sync() drop_caches(DropCachesMode.ALL) TestRun.LOGGER.info("Creating test file") classified_before = cache.get_statistics_deprecated( io_class_id=ioclass_id)["occupancy"] file_path = f"{test_dir_path}/test_file" (Dd().input("/dev/urandom").output(file_path).oflag("sync").block_size( Size(1, Unit.MebiByte)).count(dd_blocks).run()) sync() drop_caches(DropCachesMode.ALL) test_file = File(file_path).refresh_item() TestRun.LOGGER.info("Checking classified occupancy") classified_after = cache.get_statistics_deprecated( io_class_id=ioclass_id)["occupancy"] check_occupancy(classified_before + test_file.size, classified_after) TestRun.LOGGER.info("Moving test file out of classified directory") classified_before = classified_after non_classified_before = cache.get_statistics_deprecated( io_class_id=0)["occupancy"] test_file.move(destination=mountpoint) sync() drop_caches(DropCachesMode.ALL) TestRun.LOGGER.info("Checking classified occupancy") classified_after = cache.get_statistics_deprecated( io_class_id=ioclass_id)["occupancy"] check_occupancy(classified_before, classified_after) TestRun.LOGGER.info("Checking non-classified occupancy") non_classified_after = cache.get_statistics_deprecated( io_class_id=0)["occupancy"] check_occupancy(non_classified_before, non_classified_after) TestRun.LOGGER.info("Reading test file") classified_before = classified_after non_classified_before = non_classified_after (Dd().input(test_file.full_path).output("/dev/null").block_size( Size(1, Unit.MebiByte)).run()) TestRun.LOGGER.info("Checking classified occupancy") classified_after = cache.get_statistics_deprecated( io_class_id=ioclass_id)["occupancy"] check_occupancy(classified_before - test_file.size, classified_after) TestRun.LOGGER.info("Checking non-classified occupancy") non_classified_after = cache.get_statistics_deprecated( io_class_id=0)["occupancy"] check_occupancy(non_classified_before + test_file.size, non_classified_after) TestRun.LOGGER.info(f"Moving test file to {nested_dir_path}") classified_before = classified_after non_classified_before = non_classified_after test_file.move(destination=nested_dir_path) sync() drop_caches(DropCachesMode.ALL) TestRun.LOGGER.info("Checking classified occupancy") classified_after = cache.get_statistics_deprecated( io_class_id=ioclass_id)["occupancy"] check_occupancy(classified_before, classified_after) TestRun.LOGGER.info("Checking non-classified occupancy") non_classified_after = cache.get_statistics_deprecated( io_class_id=0)["occupancy"] check_occupancy(non_classified_before, non_classified_after) TestRun.LOGGER.info("Reading test file") classified_before = classified_after non_classified_before = non_classified_after (Dd().input(test_file.full_path).output("/dev/null").block_size( Size(1, Unit.MebiByte)).run()) TestRun.LOGGER.info("Checking classified occupancy") classified_after = cache.get_statistics_deprecated( io_class_id=ioclass_id)["occupancy"] check_occupancy(classified_before + test_file.size, classified_after) TestRun.LOGGER.info("Checking non-classified occupancy") non_classified_after = cache.get_statistics_deprecated( io_class_id=0)["occupancy"] check_occupancy(non_classified_before - test_file.size, non_classified_after)
def test_ioclass_directory_file_operations(filesystem): """ title: Test IO classification by file operations. description: | Test if directory classification works properly after file operations like move or rename. pass_criteria: - No kernel bug. - The operations themselves should not cause reclassification but IO after those operations should be reclassified to proper IO class. """ test_dir_path = f"{mountpoint}/test_dir" nested_dir_path = f"{test_dir_path}/nested_dir" dd_blocks = random.randint(5, 50) with TestRun.step("Prepare cache and core."): cache, core = prepare() Udev.disable() with TestRun.step("Create and load IO class config file."): ioclass_id = random.randint(1, ioclass_config.MAX_IO_CLASS_ID) # directory IO class ioclass_config.add_ioclass( ioclass_id=ioclass_id, eviction_priority=1, allocation=True, rule=f"directory:{test_dir_path}", ioclass_config_path=ioclass_config_path, ) casadm.load_io_classes(cache_id=cache.cache_id, file=ioclass_config_path) with TestRun.step(f"Prepare {filesystem.name} filesystem " f"and mounting {core.system_path} at {mountpoint}."): core.create_filesystem(fs_type=filesystem) core.mount(mount_point=mountpoint) sync() with TestRun.step(f"Create directory {nested_dir_path}."): Directory.create_directory(path=nested_dir_path, parents=True) sync() drop_caches(DropCachesMode.ALL) with TestRun.step("Create test file."): classified_before = cache.get_io_class_statistics( io_class_id=ioclass_id).usage_stats.occupancy file_path = f"{test_dir_path}/test_file" (Dd().input("/dev/urandom").output(file_path).oflag("sync").block_size( Size(1, Unit.MebiByte)).count(dd_blocks).run()) sync() drop_caches(DropCachesMode.ALL) test_file = File(file_path).refresh_item() with TestRun.step("Check classified occupancy."): classified_after = cache.get_io_class_statistics( io_class_id=ioclass_id).usage_stats.occupancy check_occupancy(classified_before + test_file.size, classified_after) with TestRun.step("Move test file out of classified directory."): classified_before = classified_after non_classified_before = cache.get_io_class_statistics( io_class_id=0).usage_stats.occupancy test_file.move(destination=mountpoint) sync() drop_caches(DropCachesMode.ALL) with TestRun.step("Check classified occupancy."): classified_after = cache.get_io_class_statistics( io_class_id=ioclass_id).usage_stats.occupancy check_occupancy(classified_before, classified_after) TestRun.LOGGER.info("Checking non-classified occupancy") non_classified_after = cache.get_io_class_statistics( io_class_id=0).usage_stats.occupancy check_occupancy(non_classified_before, non_classified_after) with TestRun.step("Read test file."): classified_before = classified_after non_classified_before = non_classified_after (Dd().input(test_file.full_path).output("/dev/null").block_size( Size(1, Unit.MebiByte)).run()) with TestRun.step("Check classified occupancy."): classified_after = cache.get_io_class_statistics( io_class_id=ioclass_id).usage_stats.occupancy check_occupancy(classified_before - test_file.size, classified_after) TestRun.LOGGER.info("Checking non-classified occupancy") non_classified_after = cache.get_io_class_statistics( io_class_id=0).usage_stats.occupancy check_occupancy(non_classified_before + test_file.size, non_classified_after) with TestRun.step(f"Move test file to {nested_dir_path}."): classified_before = classified_after non_classified_before = non_classified_after test_file.move(destination=nested_dir_path) sync() drop_caches(DropCachesMode.ALL) with TestRun.step("Check classified occupancy."): classified_after = cache.get_io_class_statistics( io_class_id=ioclass_id).usage_stats.occupancy check_occupancy(classified_before, classified_after) TestRun.LOGGER.info("Checking non-classified occupancy") non_classified_after = cache.get_io_class_statistics( io_class_id=0).usage_stats.occupancy check_occupancy(non_classified_before, non_classified_after) with TestRun.step("Read test file."): classified_before = classified_after non_classified_before = non_classified_after (Dd().input(test_file.full_path).output("/dev/null").block_size( Size(1, Unit.MebiByte)).run()) with TestRun.step("Check classified occupancy."): classified_after = cache.get_io_class_statistics( io_class_id=ioclass_id).usage_stats.occupancy check_occupancy(classified_before + test_file.size, classified_after) with TestRun.step("Check non-classified occupancy."): non_classified_after = cache.get_io_class_statistics( io_class_id=0).usage_stats.occupancy check_occupancy(non_classified_before - test_file.size, non_classified_after)