162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#include <stdbool.h> 362306a36Sopenharmony_ci#include <linux/limits.h> 462306a36Sopenharmony_ci#include <sys/ptrace.h> 562306a36Sopenharmony_ci#include <sys/types.h> 662306a36Sopenharmony_ci#include <sys/mman.h> 762306a36Sopenharmony_ci#include <unistd.h> 862306a36Sopenharmony_ci#include <stdio.h> 962306a36Sopenharmony_ci#include <errno.h> 1062306a36Sopenharmony_ci#include <stdlib.h> 1162306a36Sopenharmony_ci#include <string.h> 1262306a36Sopenharmony_ci#include <sys/wait.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include "../kselftest.h" 1562306a36Sopenharmony_ci#include "cgroup_util.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#define DEBUG 1862306a36Sopenharmony_ci#ifdef DEBUG 1962306a36Sopenharmony_ci#define debug(args...) fprintf(stderr, args) 2062306a36Sopenharmony_ci#else 2162306a36Sopenharmony_ci#define debug(args...) 2262306a36Sopenharmony_ci#endif 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * Check if the cgroup is frozen by looking at the cgroup.events::frozen value. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_cistatic int cg_check_frozen(const char *cgroup, bool frozen) 2862306a36Sopenharmony_ci{ 2962306a36Sopenharmony_ci if (frozen) { 3062306a36Sopenharmony_ci if (cg_read_strstr(cgroup, "cgroup.events", "frozen 1") != 0) { 3162306a36Sopenharmony_ci debug("Cgroup %s isn't frozen\n", cgroup); 3262306a36Sopenharmony_ci return -1; 3362306a36Sopenharmony_ci } 3462306a36Sopenharmony_ci } else { 3562306a36Sopenharmony_ci /* 3662306a36Sopenharmony_ci * Check the cgroup.events::frozen value. 3762306a36Sopenharmony_ci */ 3862306a36Sopenharmony_ci if (cg_read_strstr(cgroup, "cgroup.events", "frozen 0") != 0) { 3962306a36Sopenharmony_ci debug("Cgroup %s is frozen\n", cgroup); 4062306a36Sopenharmony_ci return -1; 4162306a36Sopenharmony_ci } 4262306a36Sopenharmony_ci } 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci return 0; 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/* 4862306a36Sopenharmony_ci * Freeze the given cgroup. 4962306a36Sopenharmony_ci */ 5062306a36Sopenharmony_cistatic int cg_freeze_nowait(const char *cgroup, bool freeze) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return cg_write(cgroup, "cgroup.freeze", freeze ? "1" : "0"); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* 5662306a36Sopenharmony_ci * Attach a task to the given cgroup and wait for a cgroup frozen event. 5762306a36Sopenharmony_ci * All transient events (e.g. populated) are ignored. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_cistatic int cg_enter_and_wait_for_frozen(const char *cgroup, int pid, 6062306a36Sopenharmony_ci bool frozen) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci int fd, ret = -1; 6362306a36Sopenharmony_ci int attempts; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci fd = cg_prepare_for_wait(cgroup); 6662306a36Sopenharmony_ci if (fd < 0) 6762306a36Sopenharmony_ci return fd; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci ret = cg_enter(cgroup, pid); 7062306a36Sopenharmony_ci if (ret) 7162306a36Sopenharmony_ci goto out; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci for (attempts = 0; attempts < 10; attempts++) { 7462306a36Sopenharmony_ci ret = cg_wait_for(fd); 7562306a36Sopenharmony_ci if (ret) 7662306a36Sopenharmony_ci break; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci ret = cg_check_frozen(cgroup, frozen); 7962306a36Sopenharmony_ci if (ret) 8062306a36Sopenharmony_ci continue; 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ciout: 8462306a36Sopenharmony_ci close(fd); 8562306a36Sopenharmony_ci return ret; 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* 8962306a36Sopenharmony_ci * Freeze the given cgroup and wait for the inotify signal. 9062306a36Sopenharmony_ci * If there are no events in 10 seconds, treat this as an error. 9162306a36Sopenharmony_ci * Then check that the cgroup is in the desired state. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_cistatic int cg_freeze_wait(const char *cgroup, bool freeze) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci int fd, ret = -1; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci fd = cg_prepare_for_wait(cgroup); 9862306a36Sopenharmony_ci if (fd < 0) 9962306a36Sopenharmony_ci return fd; 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci ret = cg_freeze_nowait(cgroup, freeze); 10262306a36Sopenharmony_ci if (ret) { 10362306a36Sopenharmony_ci debug("Error: cg_freeze_nowait() failed\n"); 10462306a36Sopenharmony_ci goto out; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci ret = cg_wait_for(fd); 10862306a36Sopenharmony_ci if (ret) 10962306a36Sopenharmony_ci goto out; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci ret = cg_check_frozen(cgroup, freeze); 11262306a36Sopenharmony_ciout: 11362306a36Sopenharmony_ci close(fd); 11462306a36Sopenharmony_ci return ret; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* 11862306a36Sopenharmony_ci * A simple process running in a sleep loop until being 11962306a36Sopenharmony_ci * re-parented. 12062306a36Sopenharmony_ci */ 12162306a36Sopenharmony_cistatic int child_fn(const char *cgroup, void *arg) 12262306a36Sopenharmony_ci{ 12362306a36Sopenharmony_ci int ppid = getppid(); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci while (getppid() == ppid) 12662306a36Sopenharmony_ci usleep(1000); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return getppid() == ppid; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci/* 13262306a36Sopenharmony_ci * A simple test for the cgroup freezer: populated the cgroup with 100 13362306a36Sopenharmony_ci * running processes and freeze it. Then unfreeze it. Then it kills all 13462306a36Sopenharmony_ci * processes and destroys the cgroup. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_cistatic int test_cgfreezer_simple(const char *root) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci int ret = KSFT_FAIL; 13962306a36Sopenharmony_ci char *cgroup = NULL; 14062306a36Sopenharmony_ci int i; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci cgroup = cg_name(root, "cg_test_simple"); 14362306a36Sopenharmony_ci if (!cgroup) 14462306a36Sopenharmony_ci goto cleanup; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci if (cg_create(cgroup)) 14762306a36Sopenharmony_ci goto cleanup; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci for (i = 0; i < 100; i++) 15062306a36Sopenharmony_ci cg_run_nowait(cgroup, child_fn, NULL); 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup, 100)) 15362306a36Sopenharmony_ci goto cleanup; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (cg_check_frozen(cgroup, false)) 15662306a36Sopenharmony_ci goto cleanup; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, true)) 15962306a36Sopenharmony_ci goto cleanup; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, false)) 16262306a36Sopenharmony_ci goto cleanup; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci ret = KSFT_PASS; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_cicleanup: 16762306a36Sopenharmony_ci if (cgroup) 16862306a36Sopenharmony_ci cg_destroy(cgroup); 16962306a36Sopenharmony_ci free(cgroup); 17062306a36Sopenharmony_ci return ret; 17162306a36Sopenharmony_ci} 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci/* 17462306a36Sopenharmony_ci * The test creates the following hierarchy: 17562306a36Sopenharmony_ci * A 17662306a36Sopenharmony_ci * / / \ \ 17762306a36Sopenharmony_ci * B E I K 17862306a36Sopenharmony_ci * /\ | 17962306a36Sopenharmony_ci * C D F 18062306a36Sopenharmony_ci * | 18162306a36Sopenharmony_ci * G 18262306a36Sopenharmony_ci * | 18362306a36Sopenharmony_ci * H 18462306a36Sopenharmony_ci * 18562306a36Sopenharmony_ci * with a process in C, H and 3 processes in K. 18662306a36Sopenharmony_ci * Then it tries to freeze and unfreeze the whole tree. 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_cistatic int test_cgfreezer_tree(const char *root) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci char *cgroup[10] = {0}; 19162306a36Sopenharmony_ci int ret = KSFT_FAIL; 19262306a36Sopenharmony_ci int i; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci cgroup[0] = cg_name(root, "cg_test_tree_A"); 19562306a36Sopenharmony_ci if (!cgroup[0]) 19662306a36Sopenharmony_ci goto cleanup; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci cgroup[1] = cg_name(cgroup[0], "B"); 19962306a36Sopenharmony_ci if (!cgroup[1]) 20062306a36Sopenharmony_ci goto cleanup; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci cgroup[2] = cg_name(cgroup[1], "C"); 20362306a36Sopenharmony_ci if (!cgroup[2]) 20462306a36Sopenharmony_ci goto cleanup; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci cgroup[3] = cg_name(cgroup[1], "D"); 20762306a36Sopenharmony_ci if (!cgroup[3]) 20862306a36Sopenharmony_ci goto cleanup; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci cgroup[4] = cg_name(cgroup[0], "E"); 21162306a36Sopenharmony_ci if (!cgroup[4]) 21262306a36Sopenharmony_ci goto cleanup; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci cgroup[5] = cg_name(cgroup[4], "F"); 21562306a36Sopenharmony_ci if (!cgroup[5]) 21662306a36Sopenharmony_ci goto cleanup; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci cgroup[6] = cg_name(cgroup[5], "G"); 21962306a36Sopenharmony_ci if (!cgroup[6]) 22062306a36Sopenharmony_ci goto cleanup; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci cgroup[7] = cg_name(cgroup[6], "H"); 22362306a36Sopenharmony_ci if (!cgroup[7]) 22462306a36Sopenharmony_ci goto cleanup; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci cgroup[8] = cg_name(cgroup[0], "I"); 22762306a36Sopenharmony_ci if (!cgroup[8]) 22862306a36Sopenharmony_ci goto cleanup; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci cgroup[9] = cg_name(cgroup[0], "K"); 23162306a36Sopenharmony_ci if (!cgroup[9]) 23262306a36Sopenharmony_ci goto cleanup; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci for (i = 0; i < 10; i++) 23562306a36Sopenharmony_ci if (cg_create(cgroup[i])) 23662306a36Sopenharmony_ci goto cleanup; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci cg_run_nowait(cgroup[2], child_fn, NULL); 23962306a36Sopenharmony_ci cg_run_nowait(cgroup[7], child_fn, NULL); 24062306a36Sopenharmony_ci cg_run_nowait(cgroup[9], child_fn, NULL); 24162306a36Sopenharmony_ci cg_run_nowait(cgroup[9], child_fn, NULL); 24262306a36Sopenharmony_ci cg_run_nowait(cgroup[9], child_fn, NULL); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* 24562306a36Sopenharmony_ci * Wait until all child processes will enter 24662306a36Sopenharmony_ci * corresponding cgroups. 24762306a36Sopenharmony_ci */ 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup[2], 1) || 25062306a36Sopenharmony_ci cg_wait_for_proc_count(cgroup[7], 1) || 25162306a36Sopenharmony_ci cg_wait_for_proc_count(cgroup[9], 3)) 25262306a36Sopenharmony_ci goto cleanup; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* 25562306a36Sopenharmony_ci * Freeze B. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci if (cg_freeze_wait(cgroup[1], true)) 25862306a36Sopenharmony_ci goto cleanup; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* 26162306a36Sopenharmony_ci * Freeze F. 26262306a36Sopenharmony_ci */ 26362306a36Sopenharmony_ci if (cg_freeze_wait(cgroup[5], true)) 26462306a36Sopenharmony_ci goto cleanup; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* 26762306a36Sopenharmony_ci * Freeze G. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci if (cg_freeze_wait(cgroup[6], true)) 27062306a36Sopenharmony_ci goto cleanup; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci /* 27362306a36Sopenharmony_ci * Check that A and E are not frozen. 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_ci if (cg_check_frozen(cgroup[0], false)) 27662306a36Sopenharmony_ci goto cleanup; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (cg_check_frozen(cgroup[4], false)) 27962306a36Sopenharmony_ci goto cleanup; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci /* 28262306a36Sopenharmony_ci * Freeze A. Check that A, B and E are frozen. 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci if (cg_freeze_wait(cgroup[0], true)) 28562306a36Sopenharmony_ci goto cleanup; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (cg_check_frozen(cgroup[1], true)) 28862306a36Sopenharmony_ci goto cleanup; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (cg_check_frozen(cgroup[4], true)) 29162306a36Sopenharmony_ci goto cleanup; 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * Unfreeze B, F and G 29562306a36Sopenharmony_ci */ 29662306a36Sopenharmony_ci if (cg_freeze_nowait(cgroup[1], false)) 29762306a36Sopenharmony_ci goto cleanup; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (cg_freeze_nowait(cgroup[5], false)) 30062306a36Sopenharmony_ci goto cleanup; 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci if (cg_freeze_nowait(cgroup[6], false)) 30362306a36Sopenharmony_ci goto cleanup; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci /* 30662306a36Sopenharmony_ci * Check that C and H are still frozen. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_ci if (cg_check_frozen(cgroup[2], true)) 30962306a36Sopenharmony_ci goto cleanup; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci if (cg_check_frozen(cgroup[7], true)) 31262306a36Sopenharmony_ci goto cleanup; 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_ci /* 31562306a36Sopenharmony_ci * Unfreeze A. Check that A, C and K are not frozen. 31662306a36Sopenharmony_ci */ 31762306a36Sopenharmony_ci if (cg_freeze_wait(cgroup[0], false)) 31862306a36Sopenharmony_ci goto cleanup; 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci if (cg_check_frozen(cgroup[2], false)) 32162306a36Sopenharmony_ci goto cleanup; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci if (cg_check_frozen(cgroup[9], false)) 32462306a36Sopenharmony_ci goto cleanup; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci ret = KSFT_PASS; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_cicleanup: 32962306a36Sopenharmony_ci for (i = 9; i >= 0 && cgroup[i]; i--) { 33062306a36Sopenharmony_ci cg_destroy(cgroup[i]); 33162306a36Sopenharmony_ci free(cgroup[i]); 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return ret; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/* 33862306a36Sopenharmony_ci * A fork bomb emulator. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_cistatic int forkbomb_fn(const char *cgroup, void *arg) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci int ppid; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci fork(); 34562306a36Sopenharmony_ci fork(); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci ppid = getppid(); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci while (getppid() == ppid) 35062306a36Sopenharmony_ci usleep(1000); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci return getppid() == ppid; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci/* 35662306a36Sopenharmony_ci * The test runs a fork bomb in a cgroup and tries to freeze it. 35762306a36Sopenharmony_ci * Then it kills all processes and checks that cgroup isn't populated 35862306a36Sopenharmony_ci * anymore. 35962306a36Sopenharmony_ci */ 36062306a36Sopenharmony_cistatic int test_cgfreezer_forkbomb(const char *root) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci int ret = KSFT_FAIL; 36362306a36Sopenharmony_ci char *cgroup = NULL; 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_ci cgroup = cg_name(root, "cg_forkbomb_test"); 36662306a36Sopenharmony_ci if (!cgroup) 36762306a36Sopenharmony_ci goto cleanup; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci if (cg_create(cgroup)) 37062306a36Sopenharmony_ci goto cleanup; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci cg_run_nowait(cgroup, forkbomb_fn, NULL); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci usleep(100000); 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, true)) 37762306a36Sopenharmony_ci goto cleanup; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (cg_killall(cgroup)) 38062306a36Sopenharmony_ci goto cleanup; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup, 0)) 38362306a36Sopenharmony_ci goto cleanup; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci ret = KSFT_PASS; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cicleanup: 38862306a36Sopenharmony_ci if (cgroup) 38962306a36Sopenharmony_ci cg_destroy(cgroup); 39062306a36Sopenharmony_ci free(cgroup); 39162306a36Sopenharmony_ci return ret; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci/* 39562306a36Sopenharmony_ci * The test creates a cgroups and freezes it. Then it creates a child cgroup 39662306a36Sopenharmony_ci * and populates it with a task. After that it checks that the child cgroup 39762306a36Sopenharmony_ci * is frozen and the parent cgroup remains frozen too. 39862306a36Sopenharmony_ci */ 39962306a36Sopenharmony_cistatic int test_cgfreezer_mkdir(const char *root) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci int ret = KSFT_FAIL; 40262306a36Sopenharmony_ci char *parent, *child = NULL; 40362306a36Sopenharmony_ci int pid; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci parent = cg_name(root, "cg_test_mkdir_A"); 40662306a36Sopenharmony_ci if (!parent) 40762306a36Sopenharmony_ci goto cleanup; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci child = cg_name(parent, "cg_test_mkdir_B"); 41062306a36Sopenharmony_ci if (!child) 41162306a36Sopenharmony_ci goto cleanup; 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ci if (cg_create(parent)) 41462306a36Sopenharmony_ci goto cleanup; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci if (cg_freeze_wait(parent, true)) 41762306a36Sopenharmony_ci goto cleanup; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci if (cg_create(child)) 42062306a36Sopenharmony_ci goto cleanup; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci pid = cg_run_nowait(child, child_fn, NULL); 42362306a36Sopenharmony_ci if (pid < 0) 42462306a36Sopenharmony_ci goto cleanup; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci if (cg_wait_for_proc_count(child, 1)) 42762306a36Sopenharmony_ci goto cleanup; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci if (cg_check_frozen(child, true)) 43062306a36Sopenharmony_ci goto cleanup; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (cg_check_frozen(parent, true)) 43362306a36Sopenharmony_ci goto cleanup; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci ret = KSFT_PASS; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cicleanup: 43862306a36Sopenharmony_ci if (child) 43962306a36Sopenharmony_ci cg_destroy(child); 44062306a36Sopenharmony_ci free(child); 44162306a36Sopenharmony_ci if (parent) 44262306a36Sopenharmony_ci cg_destroy(parent); 44362306a36Sopenharmony_ci free(parent); 44462306a36Sopenharmony_ci return ret; 44562306a36Sopenharmony_ci} 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci/* 44862306a36Sopenharmony_ci * The test creates two nested cgroups, freezes the parent 44962306a36Sopenharmony_ci * and removes the child. Then it checks that the parent cgroup 45062306a36Sopenharmony_ci * remains frozen and it's possible to create a new child 45162306a36Sopenharmony_ci * without unfreezing. The new child is frozen too. 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_cistatic int test_cgfreezer_rmdir(const char *root) 45462306a36Sopenharmony_ci{ 45562306a36Sopenharmony_ci int ret = KSFT_FAIL; 45662306a36Sopenharmony_ci char *parent, *child = NULL; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci parent = cg_name(root, "cg_test_rmdir_A"); 45962306a36Sopenharmony_ci if (!parent) 46062306a36Sopenharmony_ci goto cleanup; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci child = cg_name(parent, "cg_test_rmdir_B"); 46362306a36Sopenharmony_ci if (!child) 46462306a36Sopenharmony_ci goto cleanup; 46562306a36Sopenharmony_ci 46662306a36Sopenharmony_ci if (cg_create(parent)) 46762306a36Sopenharmony_ci goto cleanup; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci if (cg_create(child)) 47062306a36Sopenharmony_ci goto cleanup; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci if (cg_freeze_wait(parent, true)) 47362306a36Sopenharmony_ci goto cleanup; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci if (cg_destroy(child)) 47662306a36Sopenharmony_ci goto cleanup; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci if (cg_check_frozen(parent, true)) 47962306a36Sopenharmony_ci goto cleanup; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci if (cg_create(child)) 48262306a36Sopenharmony_ci goto cleanup; 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci if (cg_check_frozen(child, true)) 48562306a36Sopenharmony_ci goto cleanup; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci ret = KSFT_PASS; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cicleanup: 49062306a36Sopenharmony_ci if (child) 49162306a36Sopenharmony_ci cg_destroy(child); 49262306a36Sopenharmony_ci free(child); 49362306a36Sopenharmony_ci if (parent) 49462306a36Sopenharmony_ci cg_destroy(parent); 49562306a36Sopenharmony_ci free(parent); 49662306a36Sopenharmony_ci return ret; 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci/* 50062306a36Sopenharmony_ci * The test creates two cgroups: A and B, runs a process in A 50162306a36Sopenharmony_ci * and performs several migrations: 50262306a36Sopenharmony_ci * 1) A (running) -> B (frozen) 50362306a36Sopenharmony_ci * 2) B (frozen) -> A (running) 50462306a36Sopenharmony_ci * 3) A (frozen) -> B (frozen) 50562306a36Sopenharmony_ci * 50662306a36Sopenharmony_ci * On each step it checks the actual state of both cgroups. 50762306a36Sopenharmony_ci */ 50862306a36Sopenharmony_cistatic int test_cgfreezer_migrate(const char *root) 50962306a36Sopenharmony_ci{ 51062306a36Sopenharmony_ci int ret = KSFT_FAIL; 51162306a36Sopenharmony_ci char *cgroup[2] = {0}; 51262306a36Sopenharmony_ci int pid; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci cgroup[0] = cg_name(root, "cg_test_migrate_A"); 51562306a36Sopenharmony_ci if (!cgroup[0]) 51662306a36Sopenharmony_ci goto cleanup; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci cgroup[1] = cg_name(root, "cg_test_migrate_B"); 51962306a36Sopenharmony_ci if (!cgroup[1]) 52062306a36Sopenharmony_ci goto cleanup; 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci if (cg_create(cgroup[0])) 52362306a36Sopenharmony_ci goto cleanup; 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_ci if (cg_create(cgroup[1])) 52662306a36Sopenharmony_ci goto cleanup; 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_ci pid = cg_run_nowait(cgroup[0], child_fn, NULL); 52962306a36Sopenharmony_ci if (pid < 0) 53062306a36Sopenharmony_ci goto cleanup; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup[0], 1)) 53362306a36Sopenharmony_ci goto cleanup; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci /* 53662306a36Sopenharmony_ci * Migrate from A (running) to B (frozen) 53762306a36Sopenharmony_ci */ 53862306a36Sopenharmony_ci if (cg_freeze_wait(cgroup[1], true)) 53962306a36Sopenharmony_ci goto cleanup; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (cg_enter_and_wait_for_frozen(cgroup[1], pid, true)) 54262306a36Sopenharmony_ci goto cleanup; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (cg_check_frozen(cgroup[0], false)) 54562306a36Sopenharmony_ci goto cleanup; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci /* 54862306a36Sopenharmony_ci * Migrate from B (frozen) to A (running) 54962306a36Sopenharmony_ci */ 55062306a36Sopenharmony_ci if (cg_enter_and_wait_for_frozen(cgroup[0], pid, false)) 55162306a36Sopenharmony_ci goto cleanup; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci if (cg_check_frozen(cgroup[1], true)) 55462306a36Sopenharmony_ci goto cleanup; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci /* 55762306a36Sopenharmony_ci * Migrate from A (frozen) to B (frozen) 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_ci if (cg_freeze_wait(cgroup[0], true)) 56062306a36Sopenharmony_ci goto cleanup; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (cg_enter_and_wait_for_frozen(cgroup[1], pid, true)) 56362306a36Sopenharmony_ci goto cleanup; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci if (cg_check_frozen(cgroup[0], true)) 56662306a36Sopenharmony_ci goto cleanup; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci ret = KSFT_PASS; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_cicleanup: 57162306a36Sopenharmony_ci if (cgroup[0]) 57262306a36Sopenharmony_ci cg_destroy(cgroup[0]); 57362306a36Sopenharmony_ci free(cgroup[0]); 57462306a36Sopenharmony_ci if (cgroup[1]) 57562306a36Sopenharmony_ci cg_destroy(cgroup[1]); 57662306a36Sopenharmony_ci free(cgroup[1]); 57762306a36Sopenharmony_ci return ret; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci/* 58162306a36Sopenharmony_ci * The test checks that ptrace works with a tracing process in a frozen cgroup. 58262306a36Sopenharmony_ci */ 58362306a36Sopenharmony_cistatic int test_cgfreezer_ptrace(const char *root) 58462306a36Sopenharmony_ci{ 58562306a36Sopenharmony_ci int ret = KSFT_FAIL; 58662306a36Sopenharmony_ci char *cgroup = NULL; 58762306a36Sopenharmony_ci siginfo_t siginfo; 58862306a36Sopenharmony_ci int pid; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci cgroup = cg_name(root, "cg_test_ptrace"); 59162306a36Sopenharmony_ci if (!cgroup) 59262306a36Sopenharmony_ci goto cleanup; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci if (cg_create(cgroup)) 59562306a36Sopenharmony_ci goto cleanup; 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci pid = cg_run_nowait(cgroup, child_fn, NULL); 59862306a36Sopenharmony_ci if (pid < 0) 59962306a36Sopenharmony_ci goto cleanup; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup, 1)) 60262306a36Sopenharmony_ci goto cleanup; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, true)) 60562306a36Sopenharmony_ci goto cleanup; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci if (ptrace(PTRACE_SEIZE, pid, NULL, NULL)) 60862306a36Sopenharmony_ci goto cleanup; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (ptrace(PTRACE_INTERRUPT, pid, NULL, NULL)) 61162306a36Sopenharmony_ci goto cleanup; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci waitpid(pid, NULL, 0); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /* 61662306a36Sopenharmony_ci * Cgroup has to remain frozen, however the test task 61762306a36Sopenharmony_ci * is in traced state. 61862306a36Sopenharmony_ci */ 61962306a36Sopenharmony_ci if (cg_check_frozen(cgroup, true)) 62062306a36Sopenharmony_ci goto cleanup; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo)) 62362306a36Sopenharmony_ci goto cleanup; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) 62662306a36Sopenharmony_ci goto cleanup; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci if (cg_check_frozen(cgroup, true)) 62962306a36Sopenharmony_ci goto cleanup; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci ret = KSFT_PASS; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cicleanup: 63462306a36Sopenharmony_ci if (cgroup) 63562306a36Sopenharmony_ci cg_destroy(cgroup); 63662306a36Sopenharmony_ci free(cgroup); 63762306a36Sopenharmony_ci return ret; 63862306a36Sopenharmony_ci} 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci/* 64162306a36Sopenharmony_ci * Check if the process is stopped. 64262306a36Sopenharmony_ci */ 64362306a36Sopenharmony_cistatic int proc_check_stopped(int pid) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci char buf[PAGE_SIZE]; 64662306a36Sopenharmony_ci int len; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci len = proc_read_text(pid, 0, "stat", buf, sizeof(buf)); 64962306a36Sopenharmony_ci if (len == -1) { 65062306a36Sopenharmony_ci debug("Can't get %d stat\n", pid); 65162306a36Sopenharmony_ci return -1; 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci if (strstr(buf, "(test_freezer) T ") == NULL) { 65562306a36Sopenharmony_ci debug("Process %d in the unexpected state: %s\n", pid, buf); 65662306a36Sopenharmony_ci return -1; 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci return 0; 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci/* 66362306a36Sopenharmony_ci * Test that it's possible to freeze a cgroup with a stopped process. 66462306a36Sopenharmony_ci */ 66562306a36Sopenharmony_cistatic int test_cgfreezer_stopped(const char *root) 66662306a36Sopenharmony_ci{ 66762306a36Sopenharmony_ci int pid, ret = KSFT_FAIL; 66862306a36Sopenharmony_ci char *cgroup = NULL; 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci cgroup = cg_name(root, "cg_test_stopped"); 67162306a36Sopenharmony_ci if (!cgroup) 67262306a36Sopenharmony_ci goto cleanup; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (cg_create(cgroup)) 67562306a36Sopenharmony_ci goto cleanup; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci pid = cg_run_nowait(cgroup, child_fn, NULL); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup, 1)) 68062306a36Sopenharmony_ci goto cleanup; 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci if (kill(pid, SIGSTOP)) 68362306a36Sopenharmony_ci goto cleanup; 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci if (cg_check_frozen(cgroup, false)) 68662306a36Sopenharmony_ci goto cleanup; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, true)) 68962306a36Sopenharmony_ci goto cleanup; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, false)) 69262306a36Sopenharmony_ci goto cleanup; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (proc_check_stopped(pid)) 69562306a36Sopenharmony_ci goto cleanup; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci ret = KSFT_PASS; 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_cicleanup: 70062306a36Sopenharmony_ci if (cgroup) 70162306a36Sopenharmony_ci cg_destroy(cgroup); 70262306a36Sopenharmony_ci free(cgroup); 70362306a36Sopenharmony_ci return ret; 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci/* 70762306a36Sopenharmony_ci * Test that it's possible to freeze a cgroup with a ptraced process. 70862306a36Sopenharmony_ci */ 70962306a36Sopenharmony_cistatic int test_cgfreezer_ptraced(const char *root) 71062306a36Sopenharmony_ci{ 71162306a36Sopenharmony_ci int pid, ret = KSFT_FAIL; 71262306a36Sopenharmony_ci char *cgroup = NULL; 71362306a36Sopenharmony_ci siginfo_t siginfo; 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci cgroup = cg_name(root, "cg_test_ptraced"); 71662306a36Sopenharmony_ci if (!cgroup) 71762306a36Sopenharmony_ci goto cleanup; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci if (cg_create(cgroup)) 72062306a36Sopenharmony_ci goto cleanup; 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci pid = cg_run_nowait(cgroup, child_fn, NULL); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup, 1)) 72562306a36Sopenharmony_ci goto cleanup; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci if (ptrace(PTRACE_SEIZE, pid, NULL, NULL)) 72862306a36Sopenharmony_ci goto cleanup; 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci if (ptrace(PTRACE_INTERRUPT, pid, NULL, NULL)) 73162306a36Sopenharmony_ci goto cleanup; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci waitpid(pid, NULL, 0); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci if (cg_check_frozen(cgroup, false)) 73662306a36Sopenharmony_ci goto cleanup; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, true)) 73962306a36Sopenharmony_ci goto cleanup; 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci /* 74262306a36Sopenharmony_ci * cg_check_frozen(cgroup, true) will fail here, 74362306a36Sopenharmony_ci * because the task in in the TRACEd state. 74462306a36Sopenharmony_ci */ 74562306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, false)) 74662306a36Sopenharmony_ci goto cleanup; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci if (ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo)) 74962306a36Sopenharmony_ci goto cleanup; 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) 75262306a36Sopenharmony_ci goto cleanup; 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci ret = KSFT_PASS; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_cicleanup: 75762306a36Sopenharmony_ci if (cgroup) 75862306a36Sopenharmony_ci cg_destroy(cgroup); 75962306a36Sopenharmony_ci free(cgroup); 76062306a36Sopenharmony_ci return ret; 76162306a36Sopenharmony_ci} 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_cistatic int vfork_fn(const char *cgroup, void *arg) 76462306a36Sopenharmony_ci{ 76562306a36Sopenharmony_ci int pid = vfork(); 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci if (pid == 0) 76862306a36Sopenharmony_ci while (true) 76962306a36Sopenharmony_ci sleep(1); 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci return pid; 77262306a36Sopenharmony_ci} 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci/* 77562306a36Sopenharmony_ci * Test that it's possible to freeze a cgroup with a process, 77662306a36Sopenharmony_ci * which called vfork() and is waiting for a child. 77762306a36Sopenharmony_ci */ 77862306a36Sopenharmony_cistatic int test_cgfreezer_vfork(const char *root) 77962306a36Sopenharmony_ci{ 78062306a36Sopenharmony_ci int ret = KSFT_FAIL; 78162306a36Sopenharmony_ci char *cgroup = NULL; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci cgroup = cg_name(root, "cg_test_vfork"); 78462306a36Sopenharmony_ci if (!cgroup) 78562306a36Sopenharmony_ci goto cleanup; 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci if (cg_create(cgroup)) 78862306a36Sopenharmony_ci goto cleanup; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci cg_run_nowait(cgroup, vfork_fn, NULL); 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci if (cg_wait_for_proc_count(cgroup, 2)) 79362306a36Sopenharmony_ci goto cleanup; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci if (cg_freeze_wait(cgroup, true)) 79662306a36Sopenharmony_ci goto cleanup; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci ret = KSFT_PASS; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_cicleanup: 80162306a36Sopenharmony_ci if (cgroup) 80262306a36Sopenharmony_ci cg_destroy(cgroup); 80362306a36Sopenharmony_ci free(cgroup); 80462306a36Sopenharmony_ci return ret; 80562306a36Sopenharmony_ci} 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci#define T(x) { x, #x } 80862306a36Sopenharmony_cistruct cgfreezer_test { 80962306a36Sopenharmony_ci int (*fn)(const char *root); 81062306a36Sopenharmony_ci const char *name; 81162306a36Sopenharmony_ci} tests[] = { 81262306a36Sopenharmony_ci T(test_cgfreezer_simple), 81362306a36Sopenharmony_ci T(test_cgfreezer_tree), 81462306a36Sopenharmony_ci T(test_cgfreezer_forkbomb), 81562306a36Sopenharmony_ci T(test_cgfreezer_mkdir), 81662306a36Sopenharmony_ci T(test_cgfreezer_rmdir), 81762306a36Sopenharmony_ci T(test_cgfreezer_migrate), 81862306a36Sopenharmony_ci T(test_cgfreezer_ptrace), 81962306a36Sopenharmony_ci T(test_cgfreezer_stopped), 82062306a36Sopenharmony_ci T(test_cgfreezer_ptraced), 82162306a36Sopenharmony_ci T(test_cgfreezer_vfork), 82262306a36Sopenharmony_ci}; 82362306a36Sopenharmony_ci#undef T 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ciint main(int argc, char *argv[]) 82662306a36Sopenharmony_ci{ 82762306a36Sopenharmony_ci char root[PATH_MAX]; 82862306a36Sopenharmony_ci int i, ret = EXIT_SUCCESS; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci if (cg_find_unified_root(root, sizeof(root))) 83162306a36Sopenharmony_ci ksft_exit_skip("cgroup v2 isn't mounted\n"); 83262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(tests); i++) { 83362306a36Sopenharmony_ci switch (tests[i].fn(root)) { 83462306a36Sopenharmony_ci case KSFT_PASS: 83562306a36Sopenharmony_ci ksft_test_result_pass("%s\n", tests[i].name); 83662306a36Sopenharmony_ci break; 83762306a36Sopenharmony_ci case KSFT_SKIP: 83862306a36Sopenharmony_ci ksft_test_result_skip("%s\n", tests[i].name); 83962306a36Sopenharmony_ci break; 84062306a36Sopenharmony_ci default: 84162306a36Sopenharmony_ci ret = EXIT_FAILURE; 84262306a36Sopenharmony_ci ksft_test_result_fail("%s\n", tests[i].name); 84362306a36Sopenharmony_ci break; 84462306a36Sopenharmony_ci } 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci return ret; 84862306a36Sopenharmony_ci} 849