def test_ioclass_pid(prepare_and_cleanup):
    cache, core = prepare()

    ioclass_id = 1
    iterations = 20
    dd_count = 100
    dd_size = Size(4, Unit.KibiByte)

    Udev.disable()

    # Since 'dd' has to be executed right after writing pid to 'ns_last_pid',
    # 'dd' command is created and is appended to 'echo' command instead of running it
    dd_command = str(Dd().input("/dev/zero").output(
        core.system_path).count(dd_count).block_size(dd_size))

    for i in range(iterations):
        cache.flush_cache()

        output = TestProperties.executor.execute(
            "cat /proc/sys/kernel/ns_last_pid")
        if output.exit_code != 0:
            raise Exception(
                f"Failed to retrieve pid. stdout: {output.stdout} \n stderr :{output.stderr}"
            )

        # Few pids might be used by system during test preparation
        pid = int(output.stdout) + 50

        ioclass_config.add_ioclass(
            ioclass_id=ioclass_id,
            eviction_priority=1,
            allocation=True,
            rule=f"pid:eq:{pid}&done",
            ioclass_config_path=ioclass_config_path,
        )
        casadm.load_io_classes(cache_id=cache.cache_id,
                               file=ioclass_config_path)

        TestProperties.LOGGER.info(f"Running dd with pid {pid}")
        # pid saved in 'ns_last_pid' has to be smaller by one than target dd pid
        dd_and_pid_command = (
            f"echo {pid-1} > /proc/sys/kernel/ns_last_pid && {dd_command}")
        output = TestProperties.executor.execute(dd_and_pid_command)
        if output.exit_code != 0:
            raise Exception(
                f"Failed to run dd with target pid. "
                f"stdout: {output.stdout} \n stderr :{output.stderr}")
        sync()
        stats = cache.get_cache_statistics(per_io_class=True,
                                           io_class_id=ioclass_id)
        assert stats["dirty"].get_value(Unit.Blocks4096) == dd_count

        ioclass_config.remove_ioclass(ioclass_id)
Exemplo n.º 2
0
def test_ioclass_pid():
    """
        title: Test IO classification by process id.
        description: Check if data generated by process with particular id is cached.
        pass_criteria:
          - No kernel bug.
          - IO is classified properly based on process generating IO id.
    """
    ioclass_id = 1
    iterations = 20
    dd_count = 100
    dd_size = Size(4, Unit.KibiByte)

    with TestRun.step("Prepare cache, core and disable udev."):
        cache, core = prepare()
        Udev.disable()

    with TestRun.step("Prepare dd command."):
        # Since 'dd' has to be executed right after writing pid to 'ns_last_pid',
        # 'dd' command is created and is appended to 'echo' command instead of running it
        dd_command = str(Dd().input("/dev/zero").output(
            core.path).count(dd_count).block_size(dd_size))

    for _ in TestRun.iteration(range(iterations)):
        with TestRun.step("Flush cache."):
            cache.flush_cache()

        with TestRun.step("Prepare and load IO class config."):
            output = TestRun.executor.run("cat /proc/sys/kernel/ns_last_pid")
            if output.exit_code != 0:
                raise Exception(
                    f"Failed to retrieve pid. stdout: {output.stdout} \n stderr :{output.stderr}"
                )

            # Few pids might be used by system during test preparation
            pid = int(output.stdout) + 50

            ioclass_config.add_ioclass(
                ioclass_id=ioclass_id,
                eviction_priority=1,
                allocation="1.00",
                rule=f"pid:eq:{pid}&done",
                ioclass_config_path=ioclass_config_path,
            )
            casadm.load_io_classes(cache_id=cache.cache_id,
                                   file=ioclass_config_path)

        with TestRun.step(f"Run dd with pid {pid}."):
            # pid saved in 'ns_last_pid' has to be smaller by one than target dd pid
            dd_and_pid_command = (
                f"echo {pid-1} > /proc/sys/kernel/ns_last_pid && {dd_command}")
            output = TestRun.executor.run(dd_and_pid_command)
            if output.exit_code != 0:
                raise Exception(
                    f"Failed to run dd with target pid. "
                    f"stdout: {output.stdout} \n stderr :{output.stderr}")
            sync()
        with TestRun.step("Check if data was cached properly."):
            dirty = cache.get_io_class_statistics(
                io_class_id=ioclass_id).usage_stats.dirty
            if dirty.get_value(Unit.Blocks4096) != dd_count:
                TestRun.LOGGER.error(f"Wrong amount of dirty data ({dirty}).")
            ioclass_config.remove_ioclass(ioclass_id)