Resctrl CAT selftests have been limited to mainly testing performance. In order to validate the kernel side behavior better, add a functional test that validates .../tasks file content while performing moves of the task to different control groups.
Signed-off-by: Ilpo Järvinen <ilpo.jarvi...@linux.intel.com> --- tools/testing/selftests/resctrl/cat_test.c | 84 +++++++++++++++++++ tools/testing/selftests/resctrl/resctrl.h | 2 + .../testing/selftests/resctrl/resctrl_tests.c | 1 + tools/testing/selftests/resctrl/resctrlfs.c | 48 +++++++++++ 4 files changed, 135 insertions(+) diff --git a/tools/testing/selftests/resctrl/cat_test.c b/tools/testing/selftests/resctrl/cat_test.c index 94cfdba5308d..78cb9ac90bb1 100644 --- a/tools/testing/selftests/resctrl/cat_test.c +++ b/tools/testing/selftests/resctrl/cat_test.c @@ -376,6 +376,82 @@ static bool noncont_cat_feature_check(const struct resctrl_test *test) return resource_info_file_exists(test->resource, "sparse_masks"); } +static int cat_ctrlgrp_tasks_test(const struct resctrl_test *test, + const struct user_params *uparams) +{ + cpu_set_t old_affinity; + pid_t bm_pid; + int ret; + + bm_pid = getpid(); + + ret = resctrl_grp_has_task(NULL, bm_pid); + if (ret < 0) + return ret; + if (!ret) { + ksft_print_msg("PID not found in the root group\n"); + return 1; + } + + /* Taskset benchmark to specified CPU */ + ret = taskset_benchmark(bm_pid, uparams->cpu, &old_affinity); + if (ret) + return ret; + ret = resctrl_grp_has_task(NULL, bm_pid); + if (ret < 0) + goto reset_affinity; + if (!ret) { + ksft_print_msg("PID not found in the root group\n"); + ret = 1; + goto reset_affinity; + } + + ret = write_bm_pid_to_resctrl(bm_pid, "c1", NULL); + if (ret) + goto reset_affinity; + ret = resctrl_grp_has_task("c1", bm_pid); + if (ret < 0) + goto reset_affinity; + if (!ret) { + ksft_print_msg("PID not found in the control group\n"); + ret = 1; + goto reset_affinity; + } + ret = resctrl_grp_has_task(NULL, bm_pid); + if (ret < 0) + goto reset_affinity; + if (ret) { + ksft_print_msg("PID duplicate remains in the root group\n"); + ret = 1; + goto reset_affinity; + } + + ret = write_bm_pid_to_resctrl(bm_pid, "c2", NULL); + if (ret) + goto reset_affinity; + ret = resctrl_grp_has_task("c2", bm_pid); + if (ret < 0) + goto reset_affinity; + if (!ret) { + ksft_print_msg("PID not found in the new control group\n"); + ret = 1; + goto reset_affinity; + } + ret = resctrl_grp_has_task("c1", bm_pid); + if (ret < 0) + goto reset_affinity; + if (ret) { + ksft_print_msg("PID duplicate remains in the old control group\n"); + ret = 1; + goto reset_affinity; + } + +reset_affinity: + taskset_restore(bm_pid, &old_affinity); + + return ret; +} + struct resctrl_test l3_cat_test = { .name = "L3_CAT", .group = "CAT", @@ -400,3 +476,11 @@ struct resctrl_test l2_noncont_cat_test = { .feature_check = noncont_cat_feature_check, .run_test = noncont_cat_run_test, }; + +struct resctrl_test cat_grp_tasks_test = { + .name = "CAT_GROUP_TASKS", + .group = "CAT", + .resource = "L3", + .feature_check = test_resource_feature_check, + .run_test = cat_ctrlgrp_tasks_test, +}; diff --git a/tools/testing/selftests/resctrl/resctrl.h b/tools/testing/selftests/resctrl/resctrl.h index cd3adfc14969..d25f83d0a54d 100644 --- a/tools/testing/selftests/resctrl/resctrl.h +++ b/tools/testing/selftests/resctrl/resctrl.h @@ -174,6 +174,7 @@ bool resctrl_mon_feature_exists(const char *resource, const char *feature); bool resource_info_file_exists(const char *resource, const char *file); bool test_resource_feature_check(const struct resctrl_test *test); char *fgrep(FILE *inf, const char *str); +int resctrl_grp_has_task(const char *grp, pid_t bm_pid); int taskset_benchmark(pid_t bm_pid, int cpu_no, cpu_set_t *old_affinity); int taskset_restore(pid_t bm_pid, cpu_set_t *old_affinity); int write_schemata(const char *ctrlgrp, char *schemata, int cpu_no, @@ -241,6 +242,7 @@ static inline unsigned long cache_portion_size(unsigned long cache_size, extern struct resctrl_test mbm_test; extern struct resctrl_test mba_test; extern struct resctrl_test cmt_test; +extern struct resctrl_test cat_grp_tasks_test; extern struct resctrl_test l3_cat_test; extern struct resctrl_test l3_noncont_cat_test; extern struct resctrl_test l2_noncont_cat_test; diff --git a/tools/testing/selftests/resctrl/resctrl_tests.c b/tools/testing/selftests/resctrl/resctrl_tests.c index 5154ffd821c4..71b7cd846dc1 100644 --- a/tools/testing/selftests/resctrl/resctrl_tests.c +++ b/tools/testing/selftests/resctrl/resctrl_tests.c @@ -18,6 +18,7 @@ static struct resctrl_test *resctrl_tests[] = { &mbm_test, &mba_test, &cmt_test, + &cat_grp_tasks_test, &l3_cat_test, &l3_noncont_cat_test, &l2_noncont_cat_test, diff --git a/tools/testing/selftests/resctrl/resctrlfs.c b/tools/testing/selftests/resctrl/resctrlfs.c index 195f04c4d158..0bc92eee0080 100644 --- a/tools/testing/selftests/resctrl/resctrlfs.c +++ b/tools/testing/selftests/resctrl/resctrlfs.c @@ -601,6 +601,54 @@ static int create_grp(const char *grp_name, char *grp, const char *parent_grp) return 0; } +/* + * resctrl_grp_has_task - Check if group tasks include a PID + * @grp: Name of the group (use NULL for root group) + * @bm_id: PID that should be checked + * + * Return: 1 if PID is a task in @grp, 0 if not, and <0 on error. + */ +int resctrl_grp_has_task(const char *grp, pid_t bm_pid) +{ + unsigned long tasks_pid; + char tasks[PATH_MAX]; + int ret = 0; + FILE *fp; + + if (grp) + snprintf(tasks, sizeof(tasks), "%s/%s/tasks", RESCTRL_PATH, grp); + else + snprintf(tasks, sizeof(tasks), "%s/tasks", RESCTRL_PATH); + + fp = fopen(tasks, "r"); + if (!fp) { + ksft_print_msg("Error opening %s: %m\n", tasks); + return -EIO; + } + while (1) { + ret = fscanf(fp, "%lu", &tasks_pid); + if (ret == EOF) { + if (errno) { + ksft_print_msg("Error reading %s: %m\n", tasks); + ret = -EIO; + } else { + ret = 0; + } + break; + } + if (!ret) + break; + + if (tasks_pid == bm_pid) { + ret = 1; + break; + } + } + + fclose(fp); + return ret; +} + static int write_pid_to_tasks(char *tasks, pid_t pid) { FILE *fp; -- 2.39.5