Path: blob/master/tools/testing/selftests/cgroup/test_pids.c
26285 views
// SPDX-License-Identifier: GPL-2.01#define _GNU_SOURCE23#include <errno.h>4#include <linux/limits.h>5#include <signal.h>6#include <string.h>7#include <sys/stat.h>8#include <sys/types.h>9#include <unistd.h>1011#include "../kselftest.h"12#include "cgroup_util.h"1314static int run_success(const char *cgroup, void *arg)15{16return 0;17}1819static int run_pause(const char *cgroup, void *arg)20{21return pause();22}2324/*25* This test checks that pids.max prevents forking new children above the26* specified limit in the cgroup.27*/28static int test_pids_max(const char *root)29{30int ret = KSFT_FAIL;31char *cg_pids;32int pid;3334cg_pids = cg_name(root, "pids_test");35if (!cg_pids)36goto cleanup;3738if (cg_create(cg_pids))39goto cleanup;4041if (cg_read_strcmp(cg_pids, "pids.max", "max\n"))42goto cleanup;4344if (cg_write(cg_pids, "pids.max", "2"))45goto cleanup;4647if (cg_enter_current(cg_pids))48goto cleanup;4950pid = cg_run_nowait(cg_pids, run_pause, NULL);51if (pid < 0)52goto cleanup;5354if (cg_run_nowait(cg_pids, run_success, NULL) != -1 || errno != EAGAIN)55goto cleanup;5657if (kill(pid, SIGINT))58goto cleanup;5960ret = KSFT_PASS;6162cleanup:63cg_enter_current(root);64cg_destroy(cg_pids);65free(cg_pids);6667return ret;68}6970/*71* This test checks that pids.events are counted in cgroup associated with pids.max72*/73static int test_pids_events(const char *root)74{75int ret = KSFT_FAIL;76char *cg_parent = NULL, *cg_child = NULL;77int pid;7879cg_parent = cg_name(root, "pids_parent");80cg_child = cg_name(cg_parent, "pids_child");81if (!cg_parent || !cg_child)82goto cleanup;8384if (cg_create(cg_parent))85goto cleanup;86if (cg_write(cg_parent, "cgroup.subtree_control", "+pids"))87goto cleanup;88if (cg_create(cg_child))89goto cleanup;9091if (cg_write(cg_parent, "pids.max", "2"))92goto cleanup;9394if (cg_read_strcmp(cg_child, "pids.max", "max\n"))95goto cleanup;9697if (cg_enter_current(cg_child))98goto cleanup;99100pid = cg_run_nowait(cg_child, run_pause, NULL);101if (pid < 0)102goto cleanup;103104if (cg_run_nowait(cg_child, run_success, NULL) != -1 || errno != EAGAIN)105goto cleanup;106107if (kill(pid, SIGINT))108goto cleanup;109110if (cg_read_key_long(cg_child, "pids.events", "max ") != 0)111goto cleanup;112if (cg_read_key_long(cg_parent, "pids.events", "max ") != 1)113goto cleanup;114115116ret = KSFT_PASS;117118cleanup:119cg_enter_current(root);120if (cg_child)121cg_destroy(cg_child);122if (cg_parent)123cg_destroy(cg_parent);124free(cg_child);125free(cg_parent);126127return ret;128}129130131132#define T(x) { x, #x }133struct pids_test {134int (*fn)(const char *root);135const char *name;136} tests[] = {137T(test_pids_max),138T(test_pids_events),139};140#undef T141142int main(int argc, char **argv)143{144char root[PATH_MAX];145146ksft_print_header();147ksft_set_plan(ARRAY_SIZE(tests));148if (cg_find_unified_root(root, sizeof(root), NULL))149ksft_exit_skip("cgroup v2 isn't mounted\n");150151/*152* Check that pids controller is available:153* pids is listed in cgroup.controllers154*/155if (cg_read_strstr(root, "cgroup.controllers", "pids"))156ksft_exit_skip("pids controller isn't available\n");157158if (cg_read_strstr(root, "cgroup.subtree_control", "pids"))159if (cg_write(root, "cgroup.subtree_control", "+pids"))160ksft_exit_skip("Failed to set pids controller\n");161162for (int i = 0; i < ARRAY_SIZE(tests); i++) {163switch (tests[i].fn(root)) {164case KSFT_PASS:165ksft_test_result_pass("%s\n", tests[i].name);166break;167case KSFT_SKIP:168ksft_test_result_skip("%s\n", tests[i].name);169break;170default:171ksft_test_result_fail("%s\n", tests[i].name);172break;173}174}175176ksft_finished();177}178179180