1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2020 Red Hat, Inc.
4*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2020 Li Wang <[email protected]>
5*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2020-2021 SUSE LLC <[email protected]>
6*49cdfc7eSAndroid Build Coastguard Worker */
7*49cdfc7eSAndroid Build Coastguard Worker
8*49cdfc7eSAndroid Build Coastguard Worker #define TST_NO_DEFAULT_MAIN
9*49cdfc7eSAndroid Build Coastguard Worker
10*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <stddef.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <stdlib.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <mntent.h>
14*49cdfc7eSAndroid Build Coastguard Worker
15*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
16*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/fcntl.h"
17*49cdfc7eSAndroid Build Coastguard Worker #include "lapi/mount.h"
18*49cdfc7eSAndroid Build Coastguard Worker #include "tst_safe_file_at.h"
19*49cdfc7eSAndroid Build Coastguard Worker
20*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root;
21*49cdfc7eSAndroid Build Coastguard Worker
22*49cdfc7eSAndroid Build Coastguard Worker /* A node in a single CGroup hierarchy. It exists mainly for
23*49cdfc7eSAndroid Build Coastguard Worker * convenience so that we do not have to traverse the CGroup structure
24*49cdfc7eSAndroid Build Coastguard Worker * for frequent operations.
25*49cdfc7eSAndroid Build Coastguard Worker *
26*49cdfc7eSAndroid Build Coastguard Worker * This is actually a single-linked list not a tree. We only need to
27*49cdfc7eSAndroid Build Coastguard Worker * traverse from leaf towards root.
28*49cdfc7eSAndroid Build Coastguard Worker */
29*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir {
30*49cdfc7eSAndroid Build Coastguard Worker const char *dir_name;
31*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_dir *dir_parent;
32*49cdfc7eSAndroid Build Coastguard Worker
33*49cdfc7eSAndroid Build Coastguard Worker /* Shortcut to root */
34*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_root *dir_root;
35*49cdfc7eSAndroid Build Coastguard Worker
36*49cdfc7eSAndroid Build Coastguard Worker /* Subsystems (controllers) bit field. Only controllers which
37*49cdfc7eSAndroid Build Coastguard Worker * were required and configured for this node are added to
38*49cdfc7eSAndroid Build Coastguard Worker * this field. So it may be different from root->css_field.
39*49cdfc7eSAndroid Build Coastguard Worker */
40*49cdfc7eSAndroid Build Coastguard Worker uint32_t ctrl_field;
41*49cdfc7eSAndroid Build Coastguard Worker
42*49cdfc7eSAndroid Build Coastguard Worker /* In general we avoid having sprintfs everywhere and use
43*49cdfc7eSAndroid Build Coastguard Worker * openat, linkat, etc.
44*49cdfc7eSAndroid Build Coastguard Worker */
45*49cdfc7eSAndroid Build Coastguard Worker int dir_fd;
46*49cdfc7eSAndroid Build Coastguard Worker
47*49cdfc7eSAndroid Build Coastguard Worker int we_created_it:1;
48*49cdfc7eSAndroid Build Coastguard Worker };
49*49cdfc7eSAndroid Build Coastguard Worker
50*49cdfc7eSAndroid Build Coastguard Worker /* The root of a CGroup hierarchy/tree */
51*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root {
52*49cdfc7eSAndroid Build Coastguard Worker enum tst_cg_ver ver;
53*49cdfc7eSAndroid Build Coastguard Worker /* A mount path */
54*49cdfc7eSAndroid Build Coastguard Worker char mnt_path[PATH_MAX];
55*49cdfc7eSAndroid Build Coastguard Worker /* Subsystems (controllers) bit field. Includes all
56*49cdfc7eSAndroid Build Coastguard Worker * controllers found while scanning this root.
57*49cdfc7eSAndroid Build Coastguard Worker */
58*49cdfc7eSAndroid Build Coastguard Worker uint32_t ctrl_field;
59*49cdfc7eSAndroid Build Coastguard Worker
60*49cdfc7eSAndroid Build Coastguard Worker /* CGroup hierarchy: mnt -> ltp -> {drain, test -> ??? } We
61*49cdfc7eSAndroid Build Coastguard Worker * keep a flat reference to ltp, drain and test for
62*49cdfc7eSAndroid Build Coastguard Worker * convenience.
63*49cdfc7eSAndroid Build Coastguard Worker */
64*49cdfc7eSAndroid Build Coastguard Worker
65*49cdfc7eSAndroid Build Coastguard Worker /* Mount directory */
66*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir mnt_dir;
67*49cdfc7eSAndroid Build Coastguard Worker /* LTP CGroup directory, contains drain and test dirs */
68*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir ltp_dir;
69*49cdfc7eSAndroid Build Coastguard Worker /* Drain CGroup, see cgroup_cleanup */
70*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir drain_dir;
71*49cdfc7eSAndroid Build Coastguard Worker /* CGroup for current test. Which may have children. */
72*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir test_dir;
73*49cdfc7eSAndroid Build Coastguard Worker
74*49cdfc7eSAndroid Build Coastguard Worker int nsdelegate:1;
75*49cdfc7eSAndroid Build Coastguard Worker
76*49cdfc7eSAndroid Build Coastguard Worker int we_mounted_it:1;
77*49cdfc7eSAndroid Build Coastguard Worker /* cpuset is in compatability mode */
78*49cdfc7eSAndroid Build Coastguard Worker int no_cpuset_prefix:1;
79*49cdfc7eSAndroid Build Coastguard Worker };
80*49cdfc7eSAndroid Build Coastguard Worker
81*49cdfc7eSAndroid Build Coastguard Worker /* Controller sub-systems */
82*49cdfc7eSAndroid Build Coastguard Worker enum cgroup_ctrl_indx {
83*49cdfc7eSAndroid Build Coastguard Worker CTRL_MEMORY = 1,
84*49cdfc7eSAndroid Build Coastguard Worker CTRL_CPU,
85*49cdfc7eSAndroid Build Coastguard Worker CTRL_CPUSET,
86*49cdfc7eSAndroid Build Coastguard Worker CTRL_IO,
87*49cdfc7eSAndroid Build Coastguard Worker CTRL_PIDS,
88*49cdfc7eSAndroid Build Coastguard Worker CTRL_HUGETLB,
89*49cdfc7eSAndroid Build Coastguard Worker CTRL_CPUACCT,
90*49cdfc7eSAndroid Build Coastguard Worker CTRL_DEVICES,
91*49cdfc7eSAndroid Build Coastguard Worker CTRL_FREEZER,
92*49cdfc7eSAndroid Build Coastguard Worker CTRL_NETCLS,
93*49cdfc7eSAndroid Build Coastguard Worker CTRL_NETPRIO,
94*49cdfc7eSAndroid Build Coastguard Worker CTRL_BLKIO,
95*49cdfc7eSAndroid Build Coastguard Worker CTRL_MISC,
96*49cdfc7eSAndroid Build Coastguard Worker CTRL_PERFEVENT,
97*49cdfc7eSAndroid Build Coastguard Worker CTRL_DEBUG,
98*49cdfc7eSAndroid Build Coastguard Worker CTRL_RDMA,
99*49cdfc7eSAndroid Build Coastguard Worker CTRL_BASE
100*49cdfc7eSAndroid Build Coastguard Worker };
101*49cdfc7eSAndroid Build Coastguard Worker #define CTRLS_MAX CTRL_BASE
102*49cdfc7eSAndroid Build Coastguard Worker
103*49cdfc7eSAndroid Build Coastguard Worker /* At most we can have one cgroup V1 tree for each controller and one
104*49cdfc7eSAndroid Build Coastguard Worker * (empty) v2 tree.
105*49cdfc7eSAndroid Build Coastguard Worker */
106*49cdfc7eSAndroid Build Coastguard Worker #define ROOTS_MAX (CTRLS_MAX + 1)
107*49cdfc7eSAndroid Build Coastguard Worker
108*49cdfc7eSAndroid Build Coastguard Worker /* Describes a controller file or knob
109*49cdfc7eSAndroid Build Coastguard Worker *
110*49cdfc7eSAndroid Build Coastguard Worker * The primary purpose of this is to map V2 names to V1
111*49cdfc7eSAndroid Build Coastguard Worker * names.
112*49cdfc7eSAndroid Build Coastguard Worker */
113*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_file {
114*49cdfc7eSAndroid Build Coastguard Worker /* Canonical name. Is the V2 name unless an item is V1 only */
115*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name;
116*49cdfc7eSAndroid Build Coastguard Worker /* V1 name or NULL if item is V2 only */
117*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name_v1;
118*49cdfc7eSAndroid Build Coastguard Worker
119*49cdfc7eSAndroid Build Coastguard Worker /* The controller this item belongs to or zero for
120*49cdfc7eSAndroid Build Coastguard Worker * 'cgroup.<item>'.
121*49cdfc7eSAndroid Build Coastguard Worker */
122*49cdfc7eSAndroid Build Coastguard Worker const enum cgroup_ctrl_indx ctrl_indx;
123*49cdfc7eSAndroid Build Coastguard Worker };
124*49cdfc7eSAndroid Build Coastguard Worker
125*49cdfc7eSAndroid Build Coastguard Worker /* Describes a Controller or subsystem
126*49cdfc7eSAndroid Build Coastguard Worker *
127*49cdfc7eSAndroid Build Coastguard Worker * Internally the kernel seems to call controllers subsystems and uses
128*49cdfc7eSAndroid Build Coastguard Worker * the abbreviations subsys and css.
129*49cdfc7eSAndroid Build Coastguard Worker */
130*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_ctrl {
131*49cdfc7eSAndroid Build Coastguard Worker /* Userland name of the controller (e.g. 'memory' not 'memcg') */
132*49cdfc7eSAndroid Build Coastguard Worker const char *const ctrl_name;
133*49cdfc7eSAndroid Build Coastguard Worker /* List of files belonging to this controller */
134*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_file *const files;
135*49cdfc7eSAndroid Build Coastguard Worker /* Our index for the controller */
136*49cdfc7eSAndroid Build Coastguard Worker const enum cgroup_ctrl_indx ctrl_indx;
137*49cdfc7eSAndroid Build Coastguard Worker
138*49cdfc7eSAndroid Build Coastguard Worker /* Runtime; hierarchy the controller is attached to */
139*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *ctrl_root;
140*49cdfc7eSAndroid Build Coastguard Worker /* Runtime; whether we required the controller */
141*49cdfc7eSAndroid Build Coastguard Worker int we_require_it:1;
142*49cdfc7eSAndroid Build Coastguard Worker };
143*49cdfc7eSAndroid Build Coastguard Worker
144*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group {
145*49cdfc7eSAndroid Build Coastguard Worker char group_name[NAME_MAX + 1];
146*49cdfc7eSAndroid Build Coastguard Worker /* Maps controller ID to the tree which contains it. The V2
147*49cdfc7eSAndroid Build Coastguard Worker * tree is at zero even if it contains no controllers.
148*49cdfc7eSAndroid Build Coastguard Worker */
149*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *dirs_by_ctrl[ROOTS_MAX];
150*49cdfc7eSAndroid Build Coastguard Worker /* NULL terminated list of trees */
151*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *dirs[ROOTS_MAX + 1];
152*49cdfc7eSAndroid Build Coastguard Worker };
153*49cdfc7eSAndroid Build Coastguard Worker
154*49cdfc7eSAndroid Build Coastguard Worker /* If controllers are required via the tst_test struct then this is
155*49cdfc7eSAndroid Build Coastguard Worker * populated with the test's CGroup.
156*49cdfc7eSAndroid Build Coastguard Worker */
157*49cdfc7eSAndroid Build Coastguard Worker static struct tst_cg_group test_group;
158*49cdfc7eSAndroid Build Coastguard Worker static struct tst_cg_group drain_group;
159*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *const tst_cg = &test_group;
160*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *const tst_cg_drain = &drain_group;
161*49cdfc7eSAndroid Build Coastguard Worker
162*49cdfc7eSAndroid Build Coastguard Worker /* Always use first item for unified hierarchy */
163*49cdfc7eSAndroid Build Coastguard Worker static struct cgroup_root roots[ROOTS_MAX + 1];
164*49cdfc7eSAndroid Build Coastguard Worker
165*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file cgroup_ctrl_files[] = {
166*49cdfc7eSAndroid Build Coastguard Worker /* procs exists on V1, however it was read-only until kernel v3.0. */
167*49cdfc7eSAndroid Build Coastguard Worker { "cgroup.procs", "tasks", 0 },
168*49cdfc7eSAndroid Build Coastguard Worker { "cgroup.controllers", NULL, 0 },
169*49cdfc7eSAndroid Build Coastguard Worker { "cgroup.subtree_control", NULL, 0 },
170*49cdfc7eSAndroid Build Coastguard Worker { "cgroup.clone_children", "cgroup.clone_children", 0 },
171*49cdfc7eSAndroid Build Coastguard Worker { "cgroup.kill", NULL, 0 },
172*49cdfc7eSAndroid Build Coastguard Worker { }
173*49cdfc7eSAndroid Build Coastguard Worker };
174*49cdfc7eSAndroid Build Coastguard Worker
175*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file memory_ctrl_files[] = {
176*49cdfc7eSAndroid Build Coastguard Worker { "memory.current", "memory.usage_in_bytes", CTRL_MEMORY },
177*49cdfc7eSAndroid Build Coastguard Worker { "memory.events", NULL, CTRL_MEMORY },
178*49cdfc7eSAndroid Build Coastguard Worker { "memory.low", NULL, CTRL_MEMORY },
179*49cdfc7eSAndroid Build Coastguard Worker { "memory.min", NULL, CTRL_MEMORY },
180*49cdfc7eSAndroid Build Coastguard Worker { "memory.max", "memory.limit_in_bytes", CTRL_MEMORY },
181*49cdfc7eSAndroid Build Coastguard Worker { "memory.stat", "memory.stat", CTRL_MEMORY },
182*49cdfc7eSAndroid Build Coastguard Worker { "memory.swappiness", "memory.swappiness", CTRL_MEMORY },
183*49cdfc7eSAndroid Build Coastguard Worker { "memory.swap.current", "memory.memsw.usage_in_bytes", CTRL_MEMORY },
184*49cdfc7eSAndroid Build Coastguard Worker { "memory.swap.max", "memory.memsw.limit_in_bytes", CTRL_MEMORY },
185*49cdfc7eSAndroid Build Coastguard Worker { "memory.kmem.usage_in_bytes", "memory.kmem.usage_in_bytes", CTRL_MEMORY },
186*49cdfc7eSAndroid Build Coastguard Worker { "memory.kmem.limit_in_bytes", "memory.kmem.limit_in_bytes", CTRL_MEMORY },
187*49cdfc7eSAndroid Build Coastguard Worker { }
188*49cdfc7eSAndroid Build Coastguard Worker };
189*49cdfc7eSAndroid Build Coastguard Worker
190*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file cpu_ctrl_files[] = {
191*49cdfc7eSAndroid Build Coastguard Worker /* The V1 quota and period files were combined in the V2 max
192*49cdfc7eSAndroid Build Coastguard Worker * file. The quota is in the first column and if we just print
193*49cdfc7eSAndroid Build Coastguard Worker * a single value to the file, it will be treated as the
194*49cdfc7eSAndroid Build Coastguard Worker * quota. To get or set the period we need to branch on the
195*49cdfc7eSAndroid Build Coastguard Worker * API version.
196*49cdfc7eSAndroid Build Coastguard Worker */
197*49cdfc7eSAndroid Build Coastguard Worker { "cpu.max", "cpu.cfs_quota_us", CTRL_CPU },
198*49cdfc7eSAndroid Build Coastguard Worker { "cpu.cfs_period_us", "cpu.cfs_period_us", CTRL_CPU },
199*49cdfc7eSAndroid Build Coastguard Worker { }
200*49cdfc7eSAndroid Build Coastguard Worker };
201*49cdfc7eSAndroid Build Coastguard Worker
202*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file cpuset_ctrl_files[] = {
203*49cdfc7eSAndroid Build Coastguard Worker { "cpuset.cpus", "cpuset.cpus", CTRL_CPUSET },
204*49cdfc7eSAndroid Build Coastguard Worker { "cpuset.mems", "cpuset.mems", CTRL_CPUSET },
205*49cdfc7eSAndroid Build Coastguard Worker { "cpuset.memory_migrate", "cpuset.memory_migrate", CTRL_CPUSET },
206*49cdfc7eSAndroid Build Coastguard Worker { }
207*49cdfc7eSAndroid Build Coastguard Worker };
208*49cdfc7eSAndroid Build Coastguard Worker
209*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file io_ctrl_files[] = {
210*49cdfc7eSAndroid Build Coastguard Worker { "io.stat", NULL, CTRL_IO },
211*49cdfc7eSAndroid Build Coastguard Worker { }
212*49cdfc7eSAndroid Build Coastguard Worker };
213*49cdfc7eSAndroid Build Coastguard Worker
214*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file pids_ctrl_files[] = {
215*49cdfc7eSAndroid Build Coastguard Worker { "pids.max", "pids.max", CTRL_PIDS },
216*49cdfc7eSAndroid Build Coastguard Worker { "pids.current", "pids.current", CTRL_PIDS },
217*49cdfc7eSAndroid Build Coastguard Worker { }
218*49cdfc7eSAndroid Build Coastguard Worker };
219*49cdfc7eSAndroid Build Coastguard Worker
220*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file hugetlb_ctrl_files[] = {
221*49cdfc7eSAndroid Build Coastguard Worker { }
222*49cdfc7eSAndroid Build Coastguard Worker };
223*49cdfc7eSAndroid Build Coastguard Worker
224*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file cpuacct_ctrl_files[] = {
225*49cdfc7eSAndroid Build Coastguard Worker { }
226*49cdfc7eSAndroid Build Coastguard Worker };
227*49cdfc7eSAndroid Build Coastguard Worker
228*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file devices_ctrl_files[] = {
229*49cdfc7eSAndroid Build Coastguard Worker { }
230*49cdfc7eSAndroid Build Coastguard Worker };
231*49cdfc7eSAndroid Build Coastguard Worker
232*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file freezer_ctrl_files[] = {
233*49cdfc7eSAndroid Build Coastguard Worker { }
234*49cdfc7eSAndroid Build Coastguard Worker };
235*49cdfc7eSAndroid Build Coastguard Worker
236*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file net_cls_ctrl_files[] = {
237*49cdfc7eSAndroid Build Coastguard Worker { }
238*49cdfc7eSAndroid Build Coastguard Worker };
239*49cdfc7eSAndroid Build Coastguard Worker
240*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file net_prio_ctrl_files[] = {
241*49cdfc7eSAndroid Build Coastguard Worker { }
242*49cdfc7eSAndroid Build Coastguard Worker };
243*49cdfc7eSAndroid Build Coastguard Worker
244*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file blkio_ctrl_files[] = {
245*49cdfc7eSAndroid Build Coastguard Worker { }
246*49cdfc7eSAndroid Build Coastguard Worker };
247*49cdfc7eSAndroid Build Coastguard Worker
248*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file misc_ctrl_files[] = {
249*49cdfc7eSAndroid Build Coastguard Worker { }
250*49cdfc7eSAndroid Build Coastguard Worker };
251*49cdfc7eSAndroid Build Coastguard Worker
252*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file perf_event_ctrl_files[] = {
253*49cdfc7eSAndroid Build Coastguard Worker { }
254*49cdfc7eSAndroid Build Coastguard Worker };
255*49cdfc7eSAndroid Build Coastguard Worker
256*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file debug_ctrl_files[] = {
257*49cdfc7eSAndroid Build Coastguard Worker { }
258*49cdfc7eSAndroid Build Coastguard Worker };
259*49cdfc7eSAndroid Build Coastguard Worker
260*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file rdma_ctrl_files[] = {
261*49cdfc7eSAndroid Build Coastguard Worker { }
262*49cdfc7eSAndroid Build Coastguard Worker };
263*49cdfc7eSAndroid Build Coastguard Worker
264*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file base_ctrl_files[] = {
265*49cdfc7eSAndroid Build Coastguard Worker { }
266*49cdfc7eSAndroid Build Coastguard Worker };
267*49cdfc7eSAndroid Build Coastguard Worker
268*49cdfc7eSAndroid Build Coastguard Worker #define CTRL_NAME_MAX 31
269*49cdfc7eSAndroid Build Coastguard Worker #define CGROUP_CTRL_MEMBER(x, y)[y] = { .ctrl_name = #x, .files = \
270*49cdfc7eSAndroid Build Coastguard Worker x ## _ctrl_files, .ctrl_indx = y, NULL, 0 }
271*49cdfc7eSAndroid Build Coastguard Worker
272*49cdfc7eSAndroid Build Coastguard Worker /* Lookup tree for item names. */
273*49cdfc7eSAndroid Build Coastguard Worker static struct cgroup_ctrl controllers[] = {
274*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(cgroup, 0),
275*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(memory, CTRL_MEMORY),
276*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(cpu, CTRL_CPU),
277*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(cpuset, CTRL_CPUSET),
278*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(io, CTRL_IO),
279*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(pids, CTRL_PIDS),
280*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(hugetlb, CTRL_HUGETLB),
281*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(cpuacct, CTRL_CPUACCT),
282*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(devices, CTRL_DEVICES),
283*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(freezer, CTRL_FREEZER),
284*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(net_cls, CTRL_NETCLS),
285*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(net_prio, CTRL_NETPRIO),
286*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(blkio, CTRL_BLKIO),
287*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(misc, CTRL_MISC),
288*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(perf_event, CTRL_PERFEVENT),
289*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(debug, CTRL_DEBUG),
290*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(rdma, CTRL_RDMA),
291*49cdfc7eSAndroid Build Coastguard Worker CGROUP_CTRL_MEMBER(base, CTRL_BASE),
292*49cdfc7eSAndroid Build Coastguard Worker { }
293*49cdfc7eSAndroid Build Coastguard Worker };
294*49cdfc7eSAndroid Build Coastguard Worker
295*49cdfc7eSAndroid Build Coastguard Worker /* We should probably allow these to be set in environment
296*49cdfc7eSAndroid Build Coastguard Worker * variables
297*49cdfc7eSAndroid Build Coastguard Worker */
298*49cdfc7eSAndroid Build Coastguard Worker static const char *cgroup_ltp_dir = "ltp";
299*49cdfc7eSAndroid Build Coastguard Worker static const char *cgroup_ltp_drain_dir = "drain";
300*49cdfc7eSAndroid Build Coastguard Worker static char cgroup_test_dir[NAME_MAX + 1];
301*49cdfc7eSAndroid Build Coastguard Worker static const char *cgroup_mount_ltp_prefix = "cgroup_";
302*49cdfc7eSAndroid Build Coastguard Worker static const char *cgroup_v2_ltp_mount = "unified";
303*49cdfc7eSAndroid Build Coastguard Worker
304*49cdfc7eSAndroid Build Coastguard Worker #define first_root \
305*49cdfc7eSAndroid Build Coastguard Worker (roots[0].ver ? roots : roots + 1)
306*49cdfc7eSAndroid Build Coastguard Worker #define for_each_root(r) \
307*49cdfc7eSAndroid Build Coastguard Worker for ((r) = first_root; (r)->ver; (r)++)
308*49cdfc7eSAndroid Build Coastguard Worker #define for_each_v1_root(r) \
309*49cdfc7eSAndroid Build Coastguard Worker for ((r) = roots + 1; (r)->ver; (r)++)
310*49cdfc7eSAndroid Build Coastguard Worker #define for_each_ctrl(ctrl) \
311*49cdfc7eSAndroid Build Coastguard Worker for ((ctrl) = controllers; (ctrl)->ctrl_name; (ctrl)++)
312*49cdfc7eSAndroid Build Coastguard Worker
313*49cdfc7eSAndroid Build Coastguard Worker /* In all cases except one, this only loops once.
314*49cdfc7eSAndroid Build Coastguard Worker *
315*49cdfc7eSAndroid Build Coastguard Worker * If (ctrl) == 0 and multiple V1 (and a V2) hierarchies are mounted,
316*49cdfc7eSAndroid Build Coastguard Worker * then we need to loop over multiple directories. For example if we
317*49cdfc7eSAndroid Build Coastguard Worker * need to write to "tasks"/"cgroup.procs" which exists for each
318*49cdfc7eSAndroid Build Coastguard Worker * hierarchy.
319*49cdfc7eSAndroid Build Coastguard Worker */
320*49cdfc7eSAndroid Build Coastguard Worker #define for_each_dir(cg, ctrl, t) \
321*49cdfc7eSAndroid Build Coastguard Worker for ((t) = (ctrl) ? (cg)->dirs_by_ctrl + (ctrl) : (cg)->dirs; \
322*49cdfc7eSAndroid Build Coastguard Worker *(t); \
323*49cdfc7eSAndroid Build Coastguard Worker (t) = (ctrl) ? (cg)->dirs + ROOTS_MAX : (t) + 1)
324*49cdfc7eSAndroid Build Coastguard Worker
325*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull))
has_ctrl(const uint32_t ctrl_field,const struct cgroup_ctrl * const ctrl)326*49cdfc7eSAndroid Build Coastguard Worker static int has_ctrl(const uint32_t ctrl_field,
327*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_ctrl *const ctrl)
328*49cdfc7eSAndroid Build Coastguard Worker {
329*49cdfc7eSAndroid Build Coastguard Worker return !!(ctrl_field & (1 << ctrl->ctrl_indx));
330*49cdfc7eSAndroid Build Coastguard Worker }
331*49cdfc7eSAndroid Build Coastguard Worker
332*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull))
add_ctrl(uint32_t * const ctrl_field,const struct cgroup_ctrl * const ctrl)333*49cdfc7eSAndroid Build Coastguard Worker static void add_ctrl(uint32_t *const ctrl_field,
334*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_ctrl *const ctrl)
335*49cdfc7eSAndroid Build Coastguard Worker {
336*49cdfc7eSAndroid Build Coastguard Worker *ctrl_field |= 1 << ctrl->ctrl_indx;
337*49cdfc7eSAndroid Build Coastguard Worker }
338*49cdfc7eSAndroid Build Coastguard Worker
cgroup_v2_mounted(void)339*49cdfc7eSAndroid Build Coastguard Worker static int cgroup_v2_mounted(void)
340*49cdfc7eSAndroid Build Coastguard Worker {
341*49cdfc7eSAndroid Build Coastguard Worker return !!roots[0].ver;
342*49cdfc7eSAndroid Build Coastguard Worker }
343*49cdfc7eSAndroid Build Coastguard Worker
cgroup_v1_mounted(void)344*49cdfc7eSAndroid Build Coastguard Worker static int cgroup_v1_mounted(void)
345*49cdfc7eSAndroid Build Coastguard Worker {
346*49cdfc7eSAndroid Build Coastguard Worker return !!roots[1].ver;
347*49cdfc7eSAndroid Build Coastguard Worker }
348*49cdfc7eSAndroid Build Coastguard Worker
cgroup_v2_nsdelegate(void)349*49cdfc7eSAndroid Build Coastguard Worker static int cgroup_v2_nsdelegate(void)
350*49cdfc7eSAndroid Build Coastguard Worker {
351*49cdfc7eSAndroid Build Coastguard Worker return !!roots[0].nsdelegate;
352*49cdfc7eSAndroid Build Coastguard Worker }
353*49cdfc7eSAndroid Build Coastguard Worker
cgroup_mounted(void)354*49cdfc7eSAndroid Build Coastguard Worker static int cgroup_mounted(void)
355*49cdfc7eSAndroid Build Coastguard Worker {
356*49cdfc7eSAndroid Build Coastguard Worker return cgroup_v2_mounted() || cgroup_v1_mounted();
357*49cdfc7eSAndroid Build Coastguard Worker }
358*49cdfc7eSAndroid Build Coastguard Worker
359*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull, warn_unused_result))
cgroup_ctrl_on_v2(const struct cgroup_ctrl * const ctrl)360*49cdfc7eSAndroid Build Coastguard Worker static int cgroup_ctrl_on_v2(const struct cgroup_ctrl *const ctrl)
361*49cdfc7eSAndroid Build Coastguard Worker {
362*49cdfc7eSAndroid Build Coastguard Worker return ctrl->ctrl_root && ctrl->ctrl_root->ver == TST_CG_V2;
363*49cdfc7eSAndroid Build Coastguard Worker }
364*49cdfc7eSAndroid Build Coastguard Worker
365*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull))
cgroup_dir_mk(const struct cgroup_dir * const parent,const char * const dir_name,struct cgroup_dir * const new)366*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_dir_mk(const struct cgroup_dir *const parent,
367*49cdfc7eSAndroid Build Coastguard Worker const char *const dir_name,
368*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const new)
369*49cdfc7eSAndroid Build Coastguard Worker {
370*49cdfc7eSAndroid Build Coastguard Worker const char *dpath;
371*49cdfc7eSAndroid Build Coastguard Worker mode_t old_umask = umask(0);
372*49cdfc7eSAndroid Build Coastguard Worker
373*49cdfc7eSAndroid Build Coastguard Worker new->dir_root = parent->dir_root;
374*49cdfc7eSAndroid Build Coastguard Worker new->dir_name = dir_name;
375*49cdfc7eSAndroid Build Coastguard Worker new->dir_parent = parent;
376*49cdfc7eSAndroid Build Coastguard Worker new->ctrl_field = parent->ctrl_field;
377*49cdfc7eSAndroid Build Coastguard Worker new->we_created_it = 0;
378*49cdfc7eSAndroid Build Coastguard Worker
379*49cdfc7eSAndroid Build Coastguard Worker if (!mkdirat(parent->dir_fd, dir_name, 0777)) {
380*49cdfc7eSAndroid Build Coastguard Worker new->we_created_it = 1;
381*49cdfc7eSAndroid Build Coastguard Worker goto opendir;
382*49cdfc7eSAndroid Build Coastguard Worker }
383*49cdfc7eSAndroid Build Coastguard Worker
384*49cdfc7eSAndroid Build Coastguard Worker if (errno == EEXIST)
385*49cdfc7eSAndroid Build Coastguard Worker goto opendir;
386*49cdfc7eSAndroid Build Coastguard Worker
387*49cdfc7eSAndroid Build Coastguard Worker dpath = tst_decode_fd(parent->dir_fd);
388*49cdfc7eSAndroid Build Coastguard Worker
389*49cdfc7eSAndroid Build Coastguard Worker if (errno == EACCES) {
390*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF | TERRNO,
391*49cdfc7eSAndroid Build Coastguard Worker "Lack permission to make '%s/%s'; premake it or run as root",
392*49cdfc7eSAndroid Build Coastguard Worker dpath, dir_name);
393*49cdfc7eSAndroid Build Coastguard Worker } else if (errno == EROFS) {
394*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF | TERRNO, "'%s/%s' must not be read-only",
395*49cdfc7eSAndroid Build Coastguard Worker dpath, dir_name);
396*49cdfc7eSAndroid Build Coastguard Worker } else {
397*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO,
398*49cdfc7eSAndroid Build Coastguard Worker "mkdirat(%d<%s>, '%s', 0777)",
399*49cdfc7eSAndroid Build Coastguard Worker parent->dir_fd, dpath, dir_name);
400*49cdfc7eSAndroid Build Coastguard Worker }
401*49cdfc7eSAndroid Build Coastguard Worker
402*49cdfc7eSAndroid Build Coastguard Worker opendir:
403*49cdfc7eSAndroid Build Coastguard Worker new->dir_fd = SAFE_OPENAT(parent->dir_fd, dir_name,
404*49cdfc7eSAndroid Build Coastguard Worker O_PATH | O_DIRECTORY);
405*49cdfc7eSAndroid Build Coastguard Worker umask(old_umask);
406*49cdfc7eSAndroid Build Coastguard Worker }
407*49cdfc7eSAndroid Build Coastguard Worker
408*49cdfc7eSAndroid Build Coastguard Worker #define PATH_MAX_STRLEN 4095
409*49cdfc7eSAndroid Build Coastguard Worker #define CONFIG_HEADER "ctrl_name ver we_require_it mnt_path we_mounted_it ltp_dir.we_created_it test_dir.dir_name"
410*49cdfc7eSAndroid Build Coastguard Worker #define CONFIG_FORMAT "%" TST_TO_STR(CTRL_NAME_MAX) "s\t%d\t%d\t%" TST_TO_STR(PATH_MAX_STRLEN) "s\t%d\t%d\t%" TST_TO_STR(NAME_MAX) "s"
411*49cdfc7eSAndroid Build Coastguard Worker /* Prints out the state associated with each controller to be consumed by
412*49cdfc7eSAndroid Build Coastguard Worker * tst_cg_load_config.
413*49cdfc7eSAndroid Build Coastguard Worker *
414*49cdfc7eSAndroid Build Coastguard Worker * The config keeps track of the minimal state needed for tst_cg_cleanup
415*49cdfc7eSAndroid Build Coastguard Worker * to cleanup mounts and directories made by tst_cg_require.
416*49cdfc7eSAndroid Build Coastguard Worker */
tst_cg_print_config(void)417*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_print_config(void)
418*49cdfc7eSAndroid Build Coastguard Worker {
419*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_ctrl *ctrl;
420*49cdfc7eSAndroid Build Coastguard Worker
421*49cdfc7eSAndroid Build Coastguard Worker printf("%s\n", CONFIG_HEADER);
422*49cdfc7eSAndroid Build Coastguard Worker
423*49cdfc7eSAndroid Build Coastguard Worker for_each_ctrl(ctrl) {
424*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *root = ctrl->ctrl_root;
425*49cdfc7eSAndroid Build Coastguard Worker
426*49cdfc7eSAndroid Build Coastguard Worker if (!root)
427*49cdfc7eSAndroid Build Coastguard Worker continue;
428*49cdfc7eSAndroid Build Coastguard Worker
429*49cdfc7eSAndroid Build Coastguard Worker printf("%s\t%d\t%d\t%s\t%d\t%d\t%s\n",
430*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_name,
431*49cdfc7eSAndroid Build Coastguard Worker root->ver,
432*49cdfc7eSAndroid Build Coastguard Worker ctrl->we_require_it,
433*49cdfc7eSAndroid Build Coastguard Worker root->mnt_path,
434*49cdfc7eSAndroid Build Coastguard Worker root->we_mounted_it,
435*49cdfc7eSAndroid Build Coastguard Worker root->ltp_dir.we_created_it,
436*49cdfc7eSAndroid Build Coastguard Worker root->test_dir.dir_name ? root->test_dir.dir_name : "NULL");
437*49cdfc7eSAndroid Build Coastguard Worker }
438*49cdfc7eSAndroid Build Coastguard Worker }
439*49cdfc7eSAndroid Build Coastguard Worker
440*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull, warn_unused_result))
cgroup_find_ctrl(const char * const ctrl_name,unsigned int strict)441*49cdfc7eSAndroid Build Coastguard Worker static struct cgroup_ctrl *cgroup_find_ctrl(const char *const ctrl_name,
442*49cdfc7eSAndroid Build Coastguard Worker unsigned int strict)
443*49cdfc7eSAndroid Build Coastguard Worker {
444*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_ctrl *ctrl;
445*49cdfc7eSAndroid Build Coastguard Worker int l = 0;
446*49cdfc7eSAndroid Build Coastguard Worker char c = ctrl_name[l];
447*49cdfc7eSAndroid Build Coastguard Worker
448*49cdfc7eSAndroid Build Coastguard Worker while (c == '_' || (c >= 'a' && c <= 'z'))
449*49cdfc7eSAndroid Build Coastguard Worker c = ctrl_name[++l];
450*49cdfc7eSAndroid Build Coastguard Worker
451*49cdfc7eSAndroid Build Coastguard Worker if (l > 32 && strict)
452*49cdfc7eSAndroid Build Coastguard Worker tst_res(TWARN, "Subsys name len greater than max known value of MAX_CGROUP_TYPE_NAMELEN: %d > 32", l);
453*49cdfc7eSAndroid Build Coastguard Worker
454*49cdfc7eSAndroid Build Coastguard Worker if (!(c == '\n' || c == '\0')) {
455*49cdfc7eSAndroid Build Coastguard Worker if (!strict)
456*49cdfc7eSAndroid Build Coastguard Worker return NULL;
457*49cdfc7eSAndroid Build Coastguard Worker
458*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Unexpected char in %s: %c", ctrl_name, c);
459*49cdfc7eSAndroid Build Coastguard Worker }
460*49cdfc7eSAndroid Build Coastguard Worker
461*49cdfc7eSAndroid Build Coastguard Worker for_each_ctrl(ctrl) {
462*49cdfc7eSAndroid Build Coastguard Worker if (!strncmp(ctrl_name, ctrl->ctrl_name, l))
463*49cdfc7eSAndroid Build Coastguard Worker return ctrl;
464*49cdfc7eSAndroid Build Coastguard Worker }
465*49cdfc7eSAndroid Build Coastguard Worker
466*49cdfc7eSAndroid Build Coastguard Worker return NULL;
467*49cdfc7eSAndroid Build Coastguard Worker }
468*49cdfc7eSAndroid Build Coastguard Worker
cgroup_find_root(const char * const mnt_path)469*49cdfc7eSAndroid Build Coastguard Worker static struct cgroup_root *cgroup_find_root(const char *const mnt_path)
470*49cdfc7eSAndroid Build Coastguard Worker {
471*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *root;
472*49cdfc7eSAndroid Build Coastguard Worker
473*49cdfc7eSAndroid Build Coastguard Worker for_each_root(root) {
474*49cdfc7eSAndroid Build Coastguard Worker if (!strcmp(root->mnt_path, mnt_path))
475*49cdfc7eSAndroid Build Coastguard Worker return root;
476*49cdfc7eSAndroid Build Coastguard Worker }
477*49cdfc7eSAndroid Build Coastguard Worker
478*49cdfc7eSAndroid Build Coastguard Worker return NULL;
479*49cdfc7eSAndroid Build Coastguard Worker }
480*49cdfc7eSAndroid Build Coastguard Worker
cgroup_parse_config_line(const char * const config_entry)481*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_parse_config_line(const char *const config_entry)
482*49cdfc7eSAndroid Build Coastguard Worker {
483*49cdfc7eSAndroid Build Coastguard Worker char ctrl_name[CTRL_NAME_MAX + 1], mnt_path[PATH_MAX_STRLEN + 1], test_dir_name[NAME_MAX + 1];
484*49cdfc7eSAndroid Build Coastguard Worker int ver, we_require_it, we_mounted_it, ltp_dir_we_created_it, vars_read;
485*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *root;
486*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_ctrl *ctrl;
487*49cdfc7eSAndroid Build Coastguard Worker
488*49cdfc7eSAndroid Build Coastguard Worker vars_read = sscanf(config_entry, CONFIG_FORMAT,
489*49cdfc7eSAndroid Build Coastguard Worker ctrl_name, &ver, &we_require_it, mnt_path, &we_mounted_it,
490*49cdfc7eSAndroid Build Coastguard Worker <p_dir_we_created_it, test_dir_name);
491*49cdfc7eSAndroid Build Coastguard Worker
492*49cdfc7eSAndroid Build Coastguard Worker if (vars_read != 7)
493*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Incorrect number of vars read from config. Config possibly malformed?");
494*49cdfc7eSAndroid Build Coastguard Worker
495*49cdfc7eSAndroid Build Coastguard Worker ctrl = cgroup_find_ctrl(ctrl_name, 1);
496*49cdfc7eSAndroid Build Coastguard Worker if (!ctrl)
497*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Could not find ctrl from config. Ctrls changing between calls?");
498*49cdfc7eSAndroid Build Coastguard Worker
499*49cdfc7eSAndroid Build Coastguard Worker ctrl->we_require_it = we_require_it;
500*49cdfc7eSAndroid Build Coastguard Worker
501*49cdfc7eSAndroid Build Coastguard Worker root = cgroup_find_root(mnt_path);
502*49cdfc7eSAndroid Build Coastguard Worker if (!root)
503*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Could not find root from config. Config possibly malformed?");
504*49cdfc7eSAndroid Build Coastguard Worker
505*49cdfc7eSAndroid Build Coastguard Worker if (we_mounted_it)
506*49cdfc7eSAndroid Build Coastguard Worker root->we_mounted_it = 1;
507*49cdfc7eSAndroid Build Coastguard Worker
508*49cdfc7eSAndroid Build Coastguard Worker if (!root->ltp_dir.dir_name) {
509*49cdfc7eSAndroid Build Coastguard Worker cgroup_dir_mk(&root->mnt_dir, cgroup_ltp_dir, &root->ltp_dir);
510*49cdfc7eSAndroid Build Coastguard Worker cgroup_dir_mk(&root->ltp_dir, cgroup_ltp_drain_dir, &root->drain_dir);
511*49cdfc7eSAndroid Build Coastguard Worker if (ltp_dir_we_created_it) {
512*49cdfc7eSAndroid Build Coastguard Worker root->ltp_dir.we_created_it = 1;
513*49cdfc7eSAndroid Build Coastguard Worker root->drain_dir.we_created_it = 1;
514*49cdfc7eSAndroid Build Coastguard Worker }
515*49cdfc7eSAndroid Build Coastguard Worker }
516*49cdfc7eSAndroid Build Coastguard Worker
517*49cdfc7eSAndroid Build Coastguard Worker if (!root->test_dir.dir_name && strcmp(test_dir_name, "NULL")) {
518*49cdfc7eSAndroid Build Coastguard Worker strncpy(cgroup_test_dir, test_dir_name, NAME_MAX + 1);
519*49cdfc7eSAndroid Build Coastguard Worker cgroup_dir_mk(&root->ltp_dir, cgroup_test_dir, &root->test_dir);
520*49cdfc7eSAndroid Build Coastguard Worker root->test_dir.we_created_it = 1;
521*49cdfc7eSAndroid Build Coastguard Worker }
522*49cdfc7eSAndroid Build Coastguard Worker }
523*49cdfc7eSAndroid Build Coastguard Worker
524*49cdfc7eSAndroid Build Coastguard Worker /* Load the test state config provided by tst_cg_print_config
525*49cdfc7eSAndroid Build Coastguard Worker *
526*49cdfc7eSAndroid Build Coastguard Worker * This will reload some internal tst_cgroup state given by the config
527*49cdfc7eSAndroid Build Coastguard Worker * that might otherwise have been lost between calls or between different
528*49cdfc7eSAndroid Build Coastguard Worker * processes. In particular this is used by testcases/lib/tst_cgctl to
529*49cdfc7eSAndroid Build Coastguard Worker * provide access to this C api to shell scripts.
530*49cdfc7eSAndroid Build Coastguard Worker *
531*49cdfc7eSAndroid Build Coastguard Worker * The config keeps track of the minimal state needed for tst_cg_cleanup
532*49cdfc7eSAndroid Build Coastguard Worker * to cleanup mounts and directories created by tst_cg_require.
533*49cdfc7eSAndroid Build Coastguard Worker */
tst_cg_load_config(const char * const config)534*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_load_config(const char *const config)
535*49cdfc7eSAndroid Build Coastguard Worker {
536*49cdfc7eSAndroid Build Coastguard Worker char temp_config[BUFSIZ];
537*49cdfc7eSAndroid Build Coastguard Worker char *line;
538*49cdfc7eSAndroid Build Coastguard Worker const size_t config_len = strlen(config) + 1;
539*49cdfc7eSAndroid Build Coastguard Worker
540*49cdfc7eSAndroid Build Coastguard Worker if (config_len >= BUFSIZ)
541*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Config has exceeded buffer size?");
542*49cdfc7eSAndroid Build Coastguard Worker
543*49cdfc7eSAndroid Build Coastguard Worker memcpy(temp_config, config, config_len);
544*49cdfc7eSAndroid Build Coastguard Worker temp_config[config_len] = '\0';
545*49cdfc7eSAndroid Build Coastguard Worker
546*49cdfc7eSAndroid Build Coastguard Worker line = strtok(temp_config, "\n");
547*49cdfc7eSAndroid Build Coastguard Worker /* Make sure to consume the header. */
548*49cdfc7eSAndroid Build Coastguard Worker for (line = strtok(NULL, "\n"); line; line = strtok(NULL, "\n"))
549*49cdfc7eSAndroid Build Coastguard Worker cgroup_parse_config_line(line);
550*49cdfc7eSAndroid Build Coastguard Worker }
551*49cdfc7eSAndroid Build Coastguard Worker
552*49cdfc7eSAndroid Build Coastguard Worker /* Determine if a mounted cgroup hierarchy is unique and record it if so.
553*49cdfc7eSAndroid Build Coastguard Worker *
554*49cdfc7eSAndroid Build Coastguard Worker * For CGroups V2 this is very simple as there is only one
555*49cdfc7eSAndroid Build Coastguard Worker * hierarchy. We just record which controllers are available and check
556*49cdfc7eSAndroid Build Coastguard Worker * if this matches what we read from any previous mount points.
557*49cdfc7eSAndroid Build Coastguard Worker *
558*49cdfc7eSAndroid Build Coastguard Worker * For V1 the set of controllers S is partitioned into sets {P_1, P_2,
559*49cdfc7eSAndroid Build Coastguard Worker * ..., P_n} with one or more controllers in each partion. Each
560*49cdfc7eSAndroid Build Coastguard Worker * partition P_n can be mounted multiple times, but the same
561*49cdfc7eSAndroid Build Coastguard Worker * controller can not appear in more than one partition. Usually each
562*49cdfc7eSAndroid Build Coastguard Worker * partition contains a single controller, but, for example, cpu and
563*49cdfc7eSAndroid Build Coastguard Worker * cpuacct are often mounted together in the same partiion.
564*49cdfc7eSAndroid Build Coastguard Worker *
565*49cdfc7eSAndroid Build Coastguard Worker * Each controller partition has its own hierarchy (root) which we
566*49cdfc7eSAndroid Build Coastguard Worker * must track and update independently.
567*49cdfc7eSAndroid Build Coastguard Worker */
568*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull))
cgroup_root_scan(const char * const mnt_type,const char * const mnt_dir,char * const mnt_opts)569*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_root_scan(const char *const mnt_type,
570*49cdfc7eSAndroid Build Coastguard Worker const char *const mnt_dir,
571*49cdfc7eSAndroid Build Coastguard Worker char *const mnt_opts)
572*49cdfc7eSAndroid Build Coastguard Worker {
573*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *root = roots;
574*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_ctrl *const_ctrl;
575*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_ctrl *ctrl;
576*49cdfc7eSAndroid Build Coastguard Worker uint32_t ctrl_field = 0;
577*49cdfc7eSAndroid Build Coastguard Worker int no_prefix = 0;
578*49cdfc7eSAndroid Build Coastguard Worker int nsdelegate = 0;
579*49cdfc7eSAndroid Build Coastguard Worker char buf[BUFSIZ];
580*49cdfc7eSAndroid Build Coastguard Worker char *tok;
581*49cdfc7eSAndroid Build Coastguard Worker const int mnt_dfd = SAFE_OPEN(mnt_dir, O_PATH | O_DIRECTORY);
582*49cdfc7eSAndroid Build Coastguard Worker
583*49cdfc7eSAndroid Build Coastguard Worker if (!strcmp(mnt_type, "cgroup"))
584*49cdfc7eSAndroid Build Coastguard Worker goto v1;
585*49cdfc7eSAndroid Build Coastguard Worker
586*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_READAT(mnt_dfd, "cgroup.controllers", buf, sizeof(buf));
587*49cdfc7eSAndroid Build Coastguard Worker
588*49cdfc7eSAndroid Build Coastguard Worker for (tok = strtok(buf, " "); tok; tok = strtok(NULL, " ")) {
589*49cdfc7eSAndroid Build Coastguard Worker const_ctrl = cgroup_find_ctrl(tok, 1);
590*49cdfc7eSAndroid Build Coastguard Worker if (const_ctrl)
591*49cdfc7eSAndroid Build Coastguard Worker add_ctrl(&ctrl_field, const_ctrl);
592*49cdfc7eSAndroid Build Coastguard Worker }
593*49cdfc7eSAndroid Build Coastguard Worker for (tok = strtok(mnt_opts, ","); tok; tok = strtok(NULL, ",")) {
594*49cdfc7eSAndroid Build Coastguard Worker nsdelegate |= !strcmp("nsdelegate", tok);
595*49cdfc7eSAndroid Build Coastguard Worker }
596*49cdfc7eSAndroid Build Coastguard Worker
597*49cdfc7eSAndroid Build Coastguard Worker if (root->ver && ctrl_field == root->ctrl_field)
598*49cdfc7eSAndroid Build Coastguard Worker goto discard;
599*49cdfc7eSAndroid Build Coastguard Worker
600*49cdfc7eSAndroid Build Coastguard Worker if (root->ctrl_field)
601*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Available V2 controllers are changing between scans?");
602*49cdfc7eSAndroid Build Coastguard Worker
603*49cdfc7eSAndroid Build Coastguard Worker root->ver = TST_CG_V2;
604*49cdfc7eSAndroid Build Coastguard Worker
605*49cdfc7eSAndroid Build Coastguard Worker goto backref;
606*49cdfc7eSAndroid Build Coastguard Worker
607*49cdfc7eSAndroid Build Coastguard Worker v1:
608*49cdfc7eSAndroid Build Coastguard Worker for (tok = strtok(mnt_opts, ","); tok; tok = strtok(NULL, ",")) {
609*49cdfc7eSAndroid Build Coastguard Worker const_ctrl = cgroup_find_ctrl(tok, 0);
610*49cdfc7eSAndroid Build Coastguard Worker if (const_ctrl)
611*49cdfc7eSAndroid Build Coastguard Worker add_ctrl(&ctrl_field, const_ctrl);
612*49cdfc7eSAndroid Build Coastguard Worker
613*49cdfc7eSAndroid Build Coastguard Worker no_prefix |= !strcmp("noprefix", tok);
614*49cdfc7eSAndroid Build Coastguard Worker }
615*49cdfc7eSAndroid Build Coastguard Worker
616*49cdfc7eSAndroid Build Coastguard Worker if (!ctrl_field)
617*49cdfc7eSAndroid Build Coastguard Worker goto discard;
618*49cdfc7eSAndroid Build Coastguard Worker
619*49cdfc7eSAndroid Build Coastguard Worker for_each_v1_root(root) {
620*49cdfc7eSAndroid Build Coastguard Worker if (!(ctrl_field & root->ctrl_field))
621*49cdfc7eSAndroid Build Coastguard Worker continue;
622*49cdfc7eSAndroid Build Coastguard Worker
623*49cdfc7eSAndroid Build Coastguard Worker if (ctrl_field == root->ctrl_field)
624*49cdfc7eSAndroid Build Coastguard Worker goto discard;
625*49cdfc7eSAndroid Build Coastguard Worker
626*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK,
627*49cdfc7eSAndroid Build Coastguard Worker "The intersection of two distinct sets of mounted controllers should be null? "
628*49cdfc7eSAndroid Build Coastguard Worker "Check '%s' and '%s'", root->mnt_path, mnt_dir);
629*49cdfc7eSAndroid Build Coastguard Worker }
630*49cdfc7eSAndroid Build Coastguard Worker
631*49cdfc7eSAndroid Build Coastguard Worker if (root >= roots + ROOTS_MAX) {
632*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK,
633*49cdfc7eSAndroid Build Coastguard Worker "Unique controller mounts have exceeded our limit %d?",
634*49cdfc7eSAndroid Build Coastguard Worker ROOTS_MAX);
635*49cdfc7eSAndroid Build Coastguard Worker }
636*49cdfc7eSAndroid Build Coastguard Worker
637*49cdfc7eSAndroid Build Coastguard Worker root->ver = TST_CG_V1;
638*49cdfc7eSAndroid Build Coastguard Worker
639*49cdfc7eSAndroid Build Coastguard Worker backref:
640*49cdfc7eSAndroid Build Coastguard Worker strcpy(root->mnt_path, mnt_dir);
641*49cdfc7eSAndroid Build Coastguard Worker root->mnt_dir.dir_root = root;
642*49cdfc7eSAndroid Build Coastguard Worker root->mnt_dir.dir_name = root->mnt_path;
643*49cdfc7eSAndroid Build Coastguard Worker root->mnt_dir.dir_fd = mnt_dfd;
644*49cdfc7eSAndroid Build Coastguard Worker root->ctrl_field = ctrl_field;
645*49cdfc7eSAndroid Build Coastguard Worker root->no_cpuset_prefix = no_prefix;
646*49cdfc7eSAndroid Build Coastguard Worker root->nsdelegate = nsdelegate;
647*49cdfc7eSAndroid Build Coastguard Worker
648*49cdfc7eSAndroid Build Coastguard Worker for_each_ctrl(ctrl) {
649*49cdfc7eSAndroid Build Coastguard Worker if (has_ctrl(root->ctrl_field, ctrl))
650*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_root = root;
651*49cdfc7eSAndroid Build Coastguard Worker }
652*49cdfc7eSAndroid Build Coastguard Worker
653*49cdfc7eSAndroid Build Coastguard Worker return;
654*49cdfc7eSAndroid Build Coastguard Worker
655*49cdfc7eSAndroid Build Coastguard Worker discard:
656*49cdfc7eSAndroid Build Coastguard Worker close(mnt_dfd);
657*49cdfc7eSAndroid Build Coastguard Worker }
658*49cdfc7eSAndroid Build Coastguard Worker
tst_cg_scan(void)659*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_scan(void)
660*49cdfc7eSAndroid Build Coastguard Worker {
661*49cdfc7eSAndroid Build Coastguard Worker struct mntent *mnt;
662*49cdfc7eSAndroid Build Coastguard Worker FILE *f = setmntent("/proc/self/mounts", "r");
663*49cdfc7eSAndroid Build Coastguard Worker
664*49cdfc7eSAndroid Build Coastguard Worker if (!f) {
665*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "Can't open /proc/self/mounts");
666*49cdfc7eSAndroid Build Coastguard Worker return;
667*49cdfc7eSAndroid Build Coastguard Worker }
668*49cdfc7eSAndroid Build Coastguard Worker
669*49cdfc7eSAndroid Build Coastguard Worker mnt = getmntent(f);
670*49cdfc7eSAndroid Build Coastguard Worker if (!mnt) {
671*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "Can't read mounts or no mounts?");
672*49cdfc7eSAndroid Build Coastguard Worker return;
673*49cdfc7eSAndroid Build Coastguard Worker }
674*49cdfc7eSAndroid Build Coastguard Worker
675*49cdfc7eSAndroid Build Coastguard Worker do {
676*49cdfc7eSAndroid Build Coastguard Worker if (strncmp(mnt->mnt_type, "cgroup", 6))
677*49cdfc7eSAndroid Build Coastguard Worker continue;
678*49cdfc7eSAndroid Build Coastguard Worker
679*49cdfc7eSAndroid Build Coastguard Worker cgroup_root_scan(mnt->mnt_type, mnt->mnt_dir, mnt->mnt_opts);
680*49cdfc7eSAndroid Build Coastguard Worker } while ((mnt = getmntent(f)));
681*49cdfc7eSAndroid Build Coastguard Worker }
682*49cdfc7eSAndroid Build Coastguard Worker
cgroup_mount_v2(void)683*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_mount_v2(void)
684*49cdfc7eSAndroid Build Coastguard Worker {
685*49cdfc7eSAndroid Build Coastguard Worker int ret;
686*49cdfc7eSAndroid Build Coastguard Worker char mnt_path[PATH_MAX];
687*49cdfc7eSAndroid Build Coastguard Worker const char *tmpdir = tst_get_tmpdir_root();
688*49cdfc7eSAndroid Build Coastguard Worker
689*49cdfc7eSAndroid Build Coastguard Worker sprintf(mnt_path, "%s/%s%s",
690*49cdfc7eSAndroid Build Coastguard Worker tmpdir, cgroup_mount_ltp_prefix, cgroup_v2_ltp_mount);
691*49cdfc7eSAndroid Build Coastguard Worker
692*49cdfc7eSAndroid Build Coastguard Worker if (!mkdir(mnt_path, 0777)) {
693*49cdfc7eSAndroid Build Coastguard Worker roots[0].mnt_dir.we_created_it = 1;
694*49cdfc7eSAndroid Build Coastguard Worker goto mount;
695*49cdfc7eSAndroid Build Coastguard Worker }
696*49cdfc7eSAndroid Build Coastguard Worker
697*49cdfc7eSAndroid Build Coastguard Worker if (errno == EEXIST)
698*49cdfc7eSAndroid Build Coastguard Worker goto mount;
699*49cdfc7eSAndroid Build Coastguard Worker
700*49cdfc7eSAndroid Build Coastguard Worker if (errno == EACCES) {
701*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO | TERRNO,
702*49cdfc7eSAndroid Build Coastguard Worker "Lack permission to make %s, premake it or run as root",
703*49cdfc7eSAndroid Build Coastguard Worker mnt_path);
704*49cdfc7eSAndroid Build Coastguard Worker return;
705*49cdfc7eSAndroid Build Coastguard Worker }
706*49cdfc7eSAndroid Build Coastguard Worker
707*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "mkdir(%s, 0777)", mnt_path);
708*49cdfc7eSAndroid Build Coastguard Worker return;
709*49cdfc7eSAndroid Build Coastguard Worker
710*49cdfc7eSAndroid Build Coastguard Worker mount:
711*49cdfc7eSAndroid Build Coastguard Worker ret = mount("cgroup2", mnt_path, "cgroup2",
712*49cdfc7eSAndroid Build Coastguard Worker 0, "memory_recursiveprot");
713*49cdfc7eSAndroid Build Coastguard Worker
714*49cdfc7eSAndroid Build Coastguard Worker if (ret && errno == EINVAL)
715*49cdfc7eSAndroid Build Coastguard Worker ret = mount("cgroup2", mnt_path, "cgroup2", 0, NULL);
716*49cdfc7eSAndroid Build Coastguard Worker
717*49cdfc7eSAndroid Build Coastguard Worker if (!ret) {
718*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Mounted V2 CGroups on %s", mnt_path);
719*49cdfc7eSAndroid Build Coastguard Worker tst_cg_scan();
720*49cdfc7eSAndroid Build Coastguard Worker roots[0].we_mounted_it = 1;
721*49cdfc7eSAndroid Build Coastguard Worker return;
722*49cdfc7eSAndroid Build Coastguard Worker }
723*49cdfc7eSAndroid Build Coastguard Worker
724*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO | TERRNO, "Could not mount V2 CGroups on %s", mnt_path);
725*49cdfc7eSAndroid Build Coastguard Worker
726*49cdfc7eSAndroid Build Coastguard Worker if (roots[0].mnt_dir.we_created_it) {
727*49cdfc7eSAndroid Build Coastguard Worker roots[0].mnt_dir.we_created_it = 0;
728*49cdfc7eSAndroid Build Coastguard Worker SAFE_RMDIR(mnt_path);
729*49cdfc7eSAndroid Build Coastguard Worker }
730*49cdfc7eSAndroid Build Coastguard Worker }
731*49cdfc7eSAndroid Build Coastguard Worker
732*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull))
cgroup_mount_v1(struct cgroup_ctrl * const ctrl)733*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_mount_v1(struct cgroup_ctrl *const ctrl)
734*49cdfc7eSAndroid Build Coastguard Worker {
735*49cdfc7eSAndroid Build Coastguard Worker char mnt_path[PATH_MAX];
736*49cdfc7eSAndroid Build Coastguard Worker int made_dir = 0;
737*49cdfc7eSAndroid Build Coastguard Worker const char *tmpdir = tst_get_tmpdir_root();
738*49cdfc7eSAndroid Build Coastguard Worker
739*49cdfc7eSAndroid Build Coastguard Worker if (ctrl->ctrl_indx == CTRL_BLKIO && controllers[CTRL_IO].ctrl_root) {
740*49cdfc7eSAndroid Build Coastguard Worker tst_res(TCONF,
741*49cdfc7eSAndroid Build Coastguard Worker "IO controller found on V2 root, skipping blkio mount that would unmount IO controller");
742*49cdfc7eSAndroid Build Coastguard Worker return;
743*49cdfc7eSAndroid Build Coastguard Worker }
744*49cdfc7eSAndroid Build Coastguard Worker
745*49cdfc7eSAndroid Build Coastguard Worker sprintf(mnt_path, "%s/%s%s",
746*49cdfc7eSAndroid Build Coastguard Worker tmpdir, cgroup_mount_ltp_prefix, ctrl->ctrl_name);
747*49cdfc7eSAndroid Build Coastguard Worker
748*49cdfc7eSAndroid Build Coastguard Worker if (!mkdir(mnt_path, 0777)) {
749*49cdfc7eSAndroid Build Coastguard Worker made_dir = 1;
750*49cdfc7eSAndroid Build Coastguard Worker goto mount;
751*49cdfc7eSAndroid Build Coastguard Worker }
752*49cdfc7eSAndroid Build Coastguard Worker
753*49cdfc7eSAndroid Build Coastguard Worker if (errno == EEXIST)
754*49cdfc7eSAndroid Build Coastguard Worker goto mount;
755*49cdfc7eSAndroid Build Coastguard Worker
756*49cdfc7eSAndroid Build Coastguard Worker if (errno == EACCES) {
757*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO | TERRNO,
758*49cdfc7eSAndroid Build Coastguard Worker "Lack permission to make %s, premake it or run as root",
759*49cdfc7eSAndroid Build Coastguard Worker mnt_path);
760*49cdfc7eSAndroid Build Coastguard Worker return;
761*49cdfc7eSAndroid Build Coastguard Worker }
762*49cdfc7eSAndroid Build Coastguard Worker
763*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "mkdir(%s, 0777)", mnt_path);
764*49cdfc7eSAndroid Build Coastguard Worker return;
765*49cdfc7eSAndroid Build Coastguard Worker
766*49cdfc7eSAndroid Build Coastguard Worker mount:
767*49cdfc7eSAndroid Build Coastguard Worker if (mount(ctrl->ctrl_name, mnt_path, "cgroup", 0, ctrl->ctrl_name)) {
768*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO | TERRNO,
769*49cdfc7eSAndroid Build Coastguard Worker "Could not mount V1 CGroup on %s", mnt_path);
770*49cdfc7eSAndroid Build Coastguard Worker
771*49cdfc7eSAndroid Build Coastguard Worker if (made_dir)
772*49cdfc7eSAndroid Build Coastguard Worker SAFE_RMDIR(mnt_path);
773*49cdfc7eSAndroid Build Coastguard Worker return;
774*49cdfc7eSAndroid Build Coastguard Worker }
775*49cdfc7eSAndroid Build Coastguard Worker
776*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Mounted V1 %s CGroup on %s", ctrl->ctrl_name, mnt_path);
777*49cdfc7eSAndroid Build Coastguard Worker tst_cg_scan();
778*49cdfc7eSAndroid Build Coastguard Worker if (!ctrl->ctrl_root)
779*49cdfc7eSAndroid Build Coastguard Worker return;
780*49cdfc7eSAndroid Build Coastguard Worker
781*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_root->we_mounted_it = 1;
782*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_root->mnt_dir.we_created_it = made_dir;
783*49cdfc7eSAndroid Build Coastguard Worker
784*49cdfc7eSAndroid Build Coastguard Worker if (ctrl->ctrl_indx == CTRL_MEMORY) {
785*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTFAT(ctrl->ctrl_root->mnt_dir.dir_fd,
786*49cdfc7eSAndroid Build Coastguard Worker "memory.use_hierarchy", "%d", 1);
787*49cdfc7eSAndroid Build Coastguard Worker }
788*49cdfc7eSAndroid Build Coastguard Worker }
789*49cdfc7eSAndroid Build Coastguard Worker
790*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull))
cgroup_copy_cpuset(const struct cgroup_root * const root)791*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_copy_cpuset(const struct cgroup_root *const root)
792*49cdfc7eSAndroid Build Coastguard Worker {
793*49cdfc7eSAndroid Build Coastguard Worker char knob_val[BUFSIZ];
794*49cdfc7eSAndroid Build Coastguard Worker int i;
795*49cdfc7eSAndroid Build Coastguard Worker const char *const n0[] = {"mems", "cpus"};
796*49cdfc7eSAndroid Build Coastguard Worker const char *const n1[] = {"cpuset.mems", "cpuset.cpus"};
797*49cdfc7eSAndroid Build Coastguard Worker const char *const *const fname = root->no_cpuset_prefix ? n0 : n1;
798*49cdfc7eSAndroid Build Coastguard Worker
799*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < 2; i++) {
800*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_READAT(root->mnt_dir.dir_fd,
801*49cdfc7eSAndroid Build Coastguard Worker fname[i], knob_val, sizeof(knob_val));
802*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTFAT(root->ltp_dir.dir_fd,
803*49cdfc7eSAndroid Build Coastguard Worker fname[i], "%s", knob_val);
804*49cdfc7eSAndroid Build Coastguard Worker }
805*49cdfc7eSAndroid Build Coastguard Worker }
806*49cdfc7eSAndroid Build Coastguard Worker
807*49cdfc7eSAndroid Build Coastguard Worker /* Ensure the specified controller is available.
808*49cdfc7eSAndroid Build Coastguard Worker *
809*49cdfc7eSAndroid Build Coastguard Worker * First we check if the specified controller has a known mount point,
810*49cdfc7eSAndroid Build Coastguard Worker * if not then we scan the system. If we find it then we goto ensuring
811*49cdfc7eSAndroid Build Coastguard Worker * the LTP group exists in the hierarchy the controller is using.
812*49cdfc7eSAndroid Build Coastguard Worker *
813*49cdfc7eSAndroid Build Coastguard Worker * If we can't find the controller, then we try to create it. First we
814*49cdfc7eSAndroid Build Coastguard Worker * check if the V2 hierarchy/tree is mounted. If it isn't then we try
815*49cdfc7eSAndroid Build Coastguard Worker * mounting it and look for the controller. If it is already mounted
816*49cdfc7eSAndroid Build Coastguard Worker * then we know the controller is not available on V2 on this system.
817*49cdfc7eSAndroid Build Coastguard Worker *
818*49cdfc7eSAndroid Build Coastguard Worker * If we can't mount V2 or the controller is not on V2, then we try
819*49cdfc7eSAndroid Build Coastguard Worker * mounting it on its own V1 tree.
820*49cdfc7eSAndroid Build Coastguard Worker *
821*49cdfc7eSAndroid Build Coastguard Worker * Once we have mounted the controller somehow, we create a hierarchy
822*49cdfc7eSAndroid Build Coastguard Worker * of cgroups. If we are on V2 we first need to enable the controller
823*49cdfc7eSAndroid Build Coastguard Worker * for all children of root. Then we create hierarchy described in
824*49cdfc7eSAndroid Build Coastguard Worker * tst_cgroup.h.
825*49cdfc7eSAndroid Build Coastguard Worker *
826*49cdfc7eSAndroid Build Coastguard Worker * If we are using V1 cpuset then we copy the available mems and cpus
827*49cdfc7eSAndroid Build Coastguard Worker * from root to the ltp group and set clone_children on the ltp group
828*49cdfc7eSAndroid Build Coastguard Worker * to distribute these settings to the test cgroups. This means the
829*49cdfc7eSAndroid Build Coastguard Worker * test author does not have to copy these settings before using the
830*49cdfc7eSAndroid Build Coastguard Worker * cpuset.
831*49cdfc7eSAndroid Build Coastguard Worker *
832*49cdfc7eSAndroid Build Coastguard Worker */
tst_cg_require(const char * const ctrl_name,const struct tst_cg_opts * options)833*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_require(const char *const ctrl_name,
834*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_opts *options)
835*49cdfc7eSAndroid Build Coastguard Worker {
836*49cdfc7eSAndroid Build Coastguard Worker const char *const cgsc = "cgroup.subtree_control";
837*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_ctrl *const ctrl = cgroup_find_ctrl(ctrl_name, 1);
838*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *root;
839*49cdfc7eSAndroid Build Coastguard Worker int base = !strcmp(ctrl->ctrl_name, "base");
840*49cdfc7eSAndroid Build Coastguard Worker
841*49cdfc7eSAndroid Build Coastguard Worker if (base && options->needs_ver != TST_CG_V2)
842*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "Base control only support needs_ver TST_CG_V2!");
843*49cdfc7eSAndroid Build Coastguard Worker
844*49cdfc7eSAndroid Build Coastguard Worker if (!ctrl) {
845*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "'%s' controller is unknown to LTP", ctrl_name);
846*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "Calling %s in cleanup?", __func__);
847*49cdfc7eSAndroid Build Coastguard Worker return;
848*49cdfc7eSAndroid Build Coastguard Worker }
849*49cdfc7eSAndroid Build Coastguard Worker
850*49cdfc7eSAndroid Build Coastguard Worker if (ctrl->we_require_it)
851*49cdfc7eSAndroid Build Coastguard Worker tst_res(TWARN, "Duplicate %s(%s, )", __func__, ctrl->ctrl_name);
852*49cdfc7eSAndroid Build Coastguard Worker
853*49cdfc7eSAndroid Build Coastguard Worker ctrl->we_require_it = 1;
854*49cdfc7eSAndroid Build Coastguard Worker
855*49cdfc7eSAndroid Build Coastguard Worker if (ctrl->ctrl_root)
856*49cdfc7eSAndroid Build Coastguard Worker goto mkdirs;
857*49cdfc7eSAndroid Build Coastguard Worker
858*49cdfc7eSAndroid Build Coastguard Worker tst_cg_scan();
859*49cdfc7eSAndroid Build Coastguard Worker
860*49cdfc7eSAndroid Build Coastguard Worker if (ctrl->ctrl_root)
861*49cdfc7eSAndroid Build Coastguard Worker goto mkdirs;
862*49cdfc7eSAndroid Build Coastguard Worker
863*49cdfc7eSAndroid Build Coastguard Worker if (!cgroup_v2_mounted() && options->needs_ver != TST_CG_V1)
864*49cdfc7eSAndroid Build Coastguard Worker cgroup_mount_v2();
865*49cdfc7eSAndroid Build Coastguard Worker
866*49cdfc7eSAndroid Build Coastguard Worker if (ctrl->ctrl_root)
867*49cdfc7eSAndroid Build Coastguard Worker goto mkdirs;
868*49cdfc7eSAndroid Build Coastguard Worker
869*49cdfc7eSAndroid Build Coastguard Worker if (options->needs_ver != TST_CG_V2)
870*49cdfc7eSAndroid Build Coastguard Worker cgroup_mount_v1(ctrl);
871*49cdfc7eSAndroid Build Coastguard Worker
872*49cdfc7eSAndroid Build Coastguard Worker if (base)
873*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_root = roots;
874*49cdfc7eSAndroid Build Coastguard Worker
875*49cdfc7eSAndroid Build Coastguard Worker if (!ctrl->ctrl_root) {
876*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF,
877*49cdfc7eSAndroid Build Coastguard Worker "'%s' controller required, but not available",
878*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_name);
879*49cdfc7eSAndroid Build Coastguard Worker return;
880*49cdfc7eSAndroid Build Coastguard Worker }
881*49cdfc7eSAndroid Build Coastguard Worker
882*49cdfc7eSAndroid Build Coastguard Worker mkdirs:
883*49cdfc7eSAndroid Build Coastguard Worker root = ctrl->ctrl_root;
884*49cdfc7eSAndroid Build Coastguard Worker
885*49cdfc7eSAndroid Build Coastguard Worker if (options->needs_nsdelegate && cgroup_v2_mounted() && !cgroup_v2_nsdelegate())
886*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "Requires cgroup2 to be mounted with nsdelegate");
887*49cdfc7eSAndroid Build Coastguard Worker
888*49cdfc7eSAndroid Build Coastguard Worker add_ctrl(&root->mnt_dir.ctrl_field, ctrl);
889*49cdfc7eSAndroid Build Coastguard Worker
890*49cdfc7eSAndroid Build Coastguard Worker if (cgroup_ctrl_on_v2(ctrl) && options->needs_ver == TST_CG_V1) {
891*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF,
892*49cdfc7eSAndroid Build Coastguard Worker "V1 '%s' controller required, but it's mounted on V2",
893*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_name);
894*49cdfc7eSAndroid Build Coastguard Worker }
895*49cdfc7eSAndroid Build Coastguard Worker if (!cgroup_ctrl_on_v2(ctrl) && options->needs_ver == TST_CG_V2) {
896*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF,
897*49cdfc7eSAndroid Build Coastguard Worker "V2 '%s' controller required, but it's mounted on V1",
898*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_name);
899*49cdfc7eSAndroid Build Coastguard Worker }
900*49cdfc7eSAndroid Build Coastguard Worker
901*49cdfc7eSAndroid Build Coastguard Worker if (cgroup_ctrl_on_v2(ctrl) && !base) {
902*49cdfc7eSAndroid Build Coastguard Worker if (root->we_mounted_it) {
903*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTFAT(root->mnt_dir.dir_fd,
904*49cdfc7eSAndroid Build Coastguard Worker cgsc, "+%s", ctrl->ctrl_name);
905*49cdfc7eSAndroid Build Coastguard Worker } else {
906*49cdfc7eSAndroid Build Coastguard Worker tst_file_printfat(root->mnt_dir.dir_fd,
907*49cdfc7eSAndroid Build Coastguard Worker cgsc, "+%s", ctrl->ctrl_name);
908*49cdfc7eSAndroid Build Coastguard Worker }
909*49cdfc7eSAndroid Build Coastguard Worker }
910*49cdfc7eSAndroid Build Coastguard Worker
911*49cdfc7eSAndroid Build Coastguard Worker if (!root->ltp_dir.dir_fd)
912*49cdfc7eSAndroid Build Coastguard Worker cgroup_dir_mk(&root->mnt_dir, cgroup_ltp_dir, &root->ltp_dir);
913*49cdfc7eSAndroid Build Coastguard Worker else
914*49cdfc7eSAndroid Build Coastguard Worker root->ltp_dir.ctrl_field |= root->mnt_dir.ctrl_field;
915*49cdfc7eSAndroid Build Coastguard Worker
916*49cdfc7eSAndroid Build Coastguard Worker if (!base) {
917*49cdfc7eSAndroid Build Coastguard Worker if (cgroup_ctrl_on_v2(ctrl)) {
918*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTFAT(root->ltp_dir.dir_fd,
919*49cdfc7eSAndroid Build Coastguard Worker cgsc, "+%s", ctrl->ctrl_name);
920*49cdfc7eSAndroid Build Coastguard Worker } else {
921*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTFAT(root->ltp_dir.dir_fd,
922*49cdfc7eSAndroid Build Coastguard Worker "cgroup.clone_children", "%d", 1);
923*49cdfc7eSAndroid Build Coastguard Worker
924*49cdfc7eSAndroid Build Coastguard Worker if (ctrl->ctrl_indx == CTRL_CPUSET)
925*49cdfc7eSAndroid Build Coastguard Worker cgroup_copy_cpuset(root);
926*49cdfc7eSAndroid Build Coastguard Worker }
927*49cdfc7eSAndroid Build Coastguard Worker }
928*49cdfc7eSAndroid Build Coastguard Worker
929*49cdfc7eSAndroid Build Coastguard Worker cgroup_dir_mk(&root->ltp_dir, cgroup_ltp_drain_dir, &root->drain_dir);
930*49cdfc7eSAndroid Build Coastguard Worker
931*49cdfc7eSAndroid Build Coastguard Worker if (options->test_pid)
932*49cdfc7eSAndroid Build Coastguard Worker sprintf(cgroup_test_dir, "test-%d", options->test_pid);
933*49cdfc7eSAndroid Build Coastguard Worker else
934*49cdfc7eSAndroid Build Coastguard Worker sprintf(cgroup_test_dir, "test-%d", getpid());
935*49cdfc7eSAndroid Build Coastguard Worker
936*49cdfc7eSAndroid Build Coastguard Worker cgroup_dir_mk(&root->ltp_dir, cgroup_test_dir, &root->test_dir);
937*49cdfc7eSAndroid Build Coastguard Worker }
938*49cdfc7eSAndroid Build Coastguard Worker
cgroup_drain(const enum tst_cg_ver ver,const int source_dfd,const int dest_dfd)939*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_drain(const enum tst_cg_ver ver,
940*49cdfc7eSAndroid Build Coastguard Worker const int source_dfd, const int dest_dfd)
941*49cdfc7eSAndroid Build Coastguard Worker {
942*49cdfc7eSAndroid Build Coastguard Worker char pid_list[BUFSIZ];
943*49cdfc7eSAndroid Build Coastguard Worker char *tok;
944*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name =
945*49cdfc7eSAndroid Build Coastguard Worker ver == TST_CG_V1 ? "tasks" : "cgroup.procs";
946*49cdfc7eSAndroid Build Coastguard Worker int fd;
947*49cdfc7eSAndroid Build Coastguard Worker ssize_t ret;
948*49cdfc7eSAndroid Build Coastguard Worker
949*49cdfc7eSAndroid Build Coastguard Worker ret = SAFE_FILE_READAT(source_dfd, file_name,
950*49cdfc7eSAndroid Build Coastguard Worker pid_list, sizeof(pid_list));
951*49cdfc7eSAndroid Build Coastguard Worker if (ret < 0)
952*49cdfc7eSAndroid Build Coastguard Worker return;
953*49cdfc7eSAndroid Build Coastguard Worker
954*49cdfc7eSAndroid Build Coastguard Worker fd = SAFE_OPENAT(dest_dfd, file_name, O_WRONLY);
955*49cdfc7eSAndroid Build Coastguard Worker if (fd < 0)
956*49cdfc7eSAndroid Build Coastguard Worker return;
957*49cdfc7eSAndroid Build Coastguard Worker
958*49cdfc7eSAndroid Build Coastguard Worker for (tok = strtok(pid_list, "\n"); tok; tok = strtok(NULL, "\n")) {
959*49cdfc7eSAndroid Build Coastguard Worker ret = dprintf(fd, "%s", tok);
960*49cdfc7eSAndroid Build Coastguard Worker
961*49cdfc7eSAndroid Build Coastguard Worker if (ret < (ssize_t)strlen(tok))
962*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "Failed to drain %s", tok);
963*49cdfc7eSAndroid Build Coastguard Worker }
964*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(fd);
965*49cdfc7eSAndroid Build Coastguard Worker }
966*49cdfc7eSAndroid Build Coastguard Worker
967*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull))
close_path_fds(struct cgroup_root * const root)968*49cdfc7eSAndroid Build Coastguard Worker static void close_path_fds(struct cgroup_root *const root)
969*49cdfc7eSAndroid Build Coastguard Worker {
970*49cdfc7eSAndroid Build Coastguard Worker if (root->test_dir.dir_fd > 0)
971*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(root->test_dir.dir_fd);
972*49cdfc7eSAndroid Build Coastguard Worker if (root->ltp_dir.dir_fd > 0)
973*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(root->ltp_dir.dir_fd);
974*49cdfc7eSAndroid Build Coastguard Worker if (root->drain_dir.dir_fd > 0)
975*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(root->drain_dir.dir_fd);
976*49cdfc7eSAndroid Build Coastguard Worker if (root->mnt_dir.dir_fd > 0)
977*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(root->mnt_dir.dir_fd);
978*49cdfc7eSAndroid Build Coastguard Worker }
979*49cdfc7eSAndroid Build Coastguard Worker
980*49cdfc7eSAndroid Build Coastguard Worker /* Maybe remove CGroups used during testing and clear our data
981*49cdfc7eSAndroid Build Coastguard Worker *
982*49cdfc7eSAndroid Build Coastguard Worker * This will never remove CGroups we did not create to allow tests to
983*49cdfc7eSAndroid Build Coastguard Worker * be run in parallel.
984*49cdfc7eSAndroid Build Coastguard Worker *
985*49cdfc7eSAndroid Build Coastguard Worker * Each test process is given its own unique CGroup. Unless we want to
986*49cdfc7eSAndroid Build Coastguard Worker * stress test the CGroup system. We should at least remove these
987*49cdfc7eSAndroid Build Coastguard Worker * unique per test CGroups.
988*49cdfc7eSAndroid Build Coastguard Worker *
989*49cdfc7eSAndroid Build Coastguard Worker * We probably also want to remove the LTP parent CGroup, although
990*49cdfc7eSAndroid Build Coastguard Worker * this may have been created by the system manager or another test
991*49cdfc7eSAndroid Build Coastguard Worker * (see notes on parallel testing).
992*49cdfc7eSAndroid Build Coastguard Worker *
993*49cdfc7eSAndroid Build Coastguard Worker * On systems with no initial CGroup setup we may try to destroy the
994*49cdfc7eSAndroid Build Coastguard Worker * CGroup roots we mounted so that they can be recreated by another
995*49cdfc7eSAndroid Build Coastguard Worker * test. Note that successfully unmounting a CGroup root does not
996*49cdfc7eSAndroid Build Coastguard Worker * necessarily indicate that it was destroyed.
997*49cdfc7eSAndroid Build Coastguard Worker *
998*49cdfc7eSAndroid Build Coastguard Worker * The ltp/drain CGroup is required for cleaning up test CGroups when
999*49cdfc7eSAndroid Build Coastguard Worker * we can not move them to the root CGroup. CGroups can only be
1000*49cdfc7eSAndroid Build Coastguard Worker * removed when they have no members and only leaf or root CGroups may
1001*49cdfc7eSAndroid Build Coastguard Worker * have processes within them. As test processes create and destroy
1002*49cdfc7eSAndroid Build Coastguard Worker * their own CGroups they must move themselves either to root or
1003*49cdfc7eSAndroid Build Coastguard Worker * another leaf CGroup. So we move them to drain while destroying the
1004*49cdfc7eSAndroid Build Coastguard Worker * unique test CGroup.
1005*49cdfc7eSAndroid Build Coastguard Worker *
1006*49cdfc7eSAndroid Build Coastguard Worker * If we have access to root and created the LTP CGroup we then move
1007*49cdfc7eSAndroid Build Coastguard Worker * the test process to root and destroy the drain and LTP
1008*49cdfc7eSAndroid Build Coastguard Worker * CGroups. Otherwise we just leave the test process to die in the
1009*49cdfc7eSAndroid Build Coastguard Worker * drain, much like many a unwanted terrapin.
1010*49cdfc7eSAndroid Build Coastguard Worker *
1011*49cdfc7eSAndroid Build Coastguard Worker * Finally we clear any data we have collected on CGroups. This will
1012*49cdfc7eSAndroid Build Coastguard Worker * happen regardless of whether anything was removed.
1013*49cdfc7eSAndroid Build Coastguard Worker */
tst_cg_cleanup(void)1014*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_cleanup(void)
1015*49cdfc7eSAndroid Build Coastguard Worker {
1016*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *root;
1017*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_ctrl *ctrl;
1018*49cdfc7eSAndroid Build Coastguard Worker
1019*49cdfc7eSAndroid Build Coastguard Worker if (!cgroup_mounted())
1020*49cdfc7eSAndroid Build Coastguard Worker goto clear_data;
1021*49cdfc7eSAndroid Build Coastguard Worker
1022*49cdfc7eSAndroid Build Coastguard Worker for_each_root(root) {
1023*49cdfc7eSAndroid Build Coastguard Worker if (!root->test_dir.dir_name)
1024*49cdfc7eSAndroid Build Coastguard Worker continue;
1025*49cdfc7eSAndroid Build Coastguard Worker
1026*49cdfc7eSAndroid Build Coastguard Worker cgroup_drain(root->ver,
1027*49cdfc7eSAndroid Build Coastguard Worker root->test_dir.dir_fd, root->drain_dir.dir_fd);
1028*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINKAT(root->ltp_dir.dir_fd, root->test_dir.dir_name,
1029*49cdfc7eSAndroid Build Coastguard Worker AT_REMOVEDIR);
1030*49cdfc7eSAndroid Build Coastguard Worker }
1031*49cdfc7eSAndroid Build Coastguard Worker
1032*49cdfc7eSAndroid Build Coastguard Worker for_each_root(root) {
1033*49cdfc7eSAndroid Build Coastguard Worker if (!root->ltp_dir.we_created_it)
1034*49cdfc7eSAndroid Build Coastguard Worker continue;
1035*49cdfc7eSAndroid Build Coastguard Worker
1036*49cdfc7eSAndroid Build Coastguard Worker cgroup_drain(root->ver,
1037*49cdfc7eSAndroid Build Coastguard Worker root->drain_dir.dir_fd, root->mnt_dir.dir_fd);
1038*49cdfc7eSAndroid Build Coastguard Worker
1039*49cdfc7eSAndroid Build Coastguard Worker if (root->drain_dir.dir_name) {
1040*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINKAT(root->ltp_dir.dir_fd,
1041*49cdfc7eSAndroid Build Coastguard Worker root->drain_dir.dir_name, AT_REMOVEDIR);
1042*49cdfc7eSAndroid Build Coastguard Worker }
1043*49cdfc7eSAndroid Build Coastguard Worker
1044*49cdfc7eSAndroid Build Coastguard Worker if (root->ltp_dir.dir_name) {
1045*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINKAT(root->mnt_dir.dir_fd,
1046*49cdfc7eSAndroid Build Coastguard Worker root->ltp_dir.dir_name, AT_REMOVEDIR);
1047*49cdfc7eSAndroid Build Coastguard Worker }
1048*49cdfc7eSAndroid Build Coastguard Worker }
1049*49cdfc7eSAndroid Build Coastguard Worker
1050*49cdfc7eSAndroid Build Coastguard Worker for_each_ctrl(ctrl) {
1051*49cdfc7eSAndroid Build Coastguard Worker if (!cgroup_ctrl_on_v2(ctrl) || !ctrl->ctrl_root->we_mounted_it
1052*49cdfc7eSAndroid Build Coastguard Worker || !strcmp(ctrl->ctrl_name, "base"))
1053*49cdfc7eSAndroid Build Coastguard Worker continue;
1054*49cdfc7eSAndroid Build Coastguard Worker
1055*49cdfc7eSAndroid Build Coastguard Worker SAFE_FILE_PRINTFAT(ctrl->ctrl_root->mnt_dir.dir_fd,
1056*49cdfc7eSAndroid Build Coastguard Worker "cgroup.subtree_control",
1057*49cdfc7eSAndroid Build Coastguard Worker "-%s", ctrl->ctrl_name);
1058*49cdfc7eSAndroid Build Coastguard Worker }
1059*49cdfc7eSAndroid Build Coastguard Worker
1060*49cdfc7eSAndroid Build Coastguard Worker for_each_root(root) {
1061*49cdfc7eSAndroid Build Coastguard Worker if (!root->we_mounted_it)
1062*49cdfc7eSAndroid Build Coastguard Worker continue;
1063*49cdfc7eSAndroid Build Coastguard Worker
1064*49cdfc7eSAndroid Build Coastguard Worker /* This probably does not result in the CGroup root
1065*49cdfc7eSAndroid Build Coastguard Worker * being destroyed
1066*49cdfc7eSAndroid Build Coastguard Worker */
1067*49cdfc7eSAndroid Build Coastguard Worker if (umount2(root->mnt_path, MNT_DETACH))
1068*49cdfc7eSAndroid Build Coastguard Worker continue;
1069*49cdfc7eSAndroid Build Coastguard Worker
1070*49cdfc7eSAndroid Build Coastguard Worker SAFE_RMDIR(root->mnt_path);
1071*49cdfc7eSAndroid Build Coastguard Worker }
1072*49cdfc7eSAndroid Build Coastguard Worker
1073*49cdfc7eSAndroid Build Coastguard Worker clear_data:
1074*49cdfc7eSAndroid Build Coastguard Worker for_each_ctrl(ctrl) {
1075*49cdfc7eSAndroid Build Coastguard Worker ctrl->ctrl_root = NULL;
1076*49cdfc7eSAndroid Build Coastguard Worker ctrl->we_require_it = 0;
1077*49cdfc7eSAndroid Build Coastguard Worker }
1078*49cdfc7eSAndroid Build Coastguard Worker
1079*49cdfc7eSAndroid Build Coastguard Worker for_each_root(root)
1080*49cdfc7eSAndroid Build Coastguard Worker close_path_fds(root);
1081*49cdfc7eSAndroid Build Coastguard Worker
1082*49cdfc7eSAndroid Build Coastguard Worker memset(roots, 0, sizeof(roots));
1083*49cdfc7eSAndroid Build Coastguard Worker }
1084*49cdfc7eSAndroid Build Coastguard Worker
1085*49cdfc7eSAndroid Build Coastguard Worker __attribute__((nonnull(2, 3)))
cgroup_group_add_dir(const struct tst_cg_group * const parent,struct tst_cg_group * const cg,struct cgroup_dir * const dir)1086*49cdfc7eSAndroid Build Coastguard Worker static void cgroup_group_add_dir(const struct tst_cg_group *const parent,
1087*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group *const cg,
1088*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const dir)
1089*49cdfc7eSAndroid Build Coastguard Worker {
1090*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_ctrl *ctrl;
1091*49cdfc7eSAndroid Build Coastguard Worker int i;
1092*49cdfc7eSAndroid Build Coastguard Worker
1093*49cdfc7eSAndroid Build Coastguard Worker if (dir->dir_root->ver != TST_CG_V1)
1094*49cdfc7eSAndroid Build Coastguard Worker cg->dirs_by_ctrl[0] = dir;
1095*49cdfc7eSAndroid Build Coastguard Worker
1096*49cdfc7eSAndroid Build Coastguard Worker for_each_ctrl(ctrl) {
1097*49cdfc7eSAndroid Build Coastguard Worker if (!has_ctrl(dir->ctrl_field, ctrl))
1098*49cdfc7eSAndroid Build Coastguard Worker continue;
1099*49cdfc7eSAndroid Build Coastguard Worker
1100*49cdfc7eSAndroid Build Coastguard Worker cg->dirs_by_ctrl[ctrl->ctrl_indx] = dir;
1101*49cdfc7eSAndroid Build Coastguard Worker
1102*49cdfc7eSAndroid Build Coastguard Worker if (!parent || dir->dir_root->ver == TST_CG_V1)
1103*49cdfc7eSAndroid Build Coastguard Worker continue;
1104*49cdfc7eSAndroid Build Coastguard Worker
1105*49cdfc7eSAndroid Build Coastguard Worker if (strcmp(ctrl->ctrl_name, "base")) {
1106*49cdfc7eSAndroid Build Coastguard Worker SAFE_CG_PRINTF(parent, "cgroup.subtree_control",
1107*49cdfc7eSAndroid Build Coastguard Worker "+%s", ctrl->ctrl_name);
1108*49cdfc7eSAndroid Build Coastguard Worker }
1109*49cdfc7eSAndroid Build Coastguard Worker }
1110*49cdfc7eSAndroid Build Coastguard Worker
1111*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; cg->dirs[i]; i++)
1112*49cdfc7eSAndroid Build Coastguard Worker ;
1113*49cdfc7eSAndroid Build Coastguard Worker cg->dirs[i] = dir;
1114*49cdfc7eSAndroid Build Coastguard Worker }
1115*49cdfc7eSAndroid Build Coastguard Worker
1116*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group *
tst_cg_group_mk(const struct tst_cg_group * const parent,const char * const group_name_fmt,...)1117*49cdfc7eSAndroid Build Coastguard Worker tst_cg_group_mk(const struct tst_cg_group *const parent,
1118*49cdfc7eSAndroid Build Coastguard Worker const char *const group_name_fmt, ...)
1119*49cdfc7eSAndroid Build Coastguard Worker {
1120*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group *cg;
1121*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const *dir;
1122*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *new_dir;
1123*49cdfc7eSAndroid Build Coastguard Worker va_list ap;
1124*49cdfc7eSAndroid Build Coastguard Worker size_t name_len;
1125*49cdfc7eSAndroid Build Coastguard Worker
1126*49cdfc7eSAndroid Build Coastguard Worker cg = SAFE_MALLOC(sizeof(*cg));
1127*49cdfc7eSAndroid Build Coastguard Worker memset(cg, 0, sizeof(*cg));
1128*49cdfc7eSAndroid Build Coastguard Worker
1129*49cdfc7eSAndroid Build Coastguard Worker va_start(ap, group_name_fmt);
1130*49cdfc7eSAndroid Build Coastguard Worker name_len = vsnprintf(cg->group_name, NAME_MAX,
1131*49cdfc7eSAndroid Build Coastguard Worker group_name_fmt, ap);
1132*49cdfc7eSAndroid Build Coastguard Worker va_end(ap);
1133*49cdfc7eSAndroid Build Coastguard Worker
1134*49cdfc7eSAndroid Build Coastguard Worker if (name_len >= NAME_MAX)
1135*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK, "CGroup name is too long");
1136*49cdfc7eSAndroid Build Coastguard Worker
1137*49cdfc7eSAndroid Build Coastguard Worker for_each_dir(parent, 0, dir) {
1138*49cdfc7eSAndroid Build Coastguard Worker new_dir = SAFE_MALLOC(sizeof(*new_dir));
1139*49cdfc7eSAndroid Build Coastguard Worker cgroup_dir_mk(*dir, cg->group_name, new_dir);
1140*49cdfc7eSAndroid Build Coastguard Worker cgroup_group_add_dir(parent, cg, new_dir);
1141*49cdfc7eSAndroid Build Coastguard Worker }
1142*49cdfc7eSAndroid Build Coastguard Worker
1143*49cdfc7eSAndroid Build Coastguard Worker return cg;
1144*49cdfc7eSAndroid Build Coastguard Worker }
1145*49cdfc7eSAndroid Build Coastguard Worker
tst_cg_group_name(const struct tst_cg_group * const cg)1146*49cdfc7eSAndroid Build Coastguard Worker const char *tst_cg_group_name(const struct tst_cg_group *const cg)
1147*49cdfc7eSAndroid Build Coastguard Worker {
1148*49cdfc7eSAndroid Build Coastguard Worker return cg->group_name;
1149*49cdfc7eSAndroid Build Coastguard Worker }
1150*49cdfc7eSAndroid Build Coastguard Worker
tst_cg_group_unified_dir_fd(const struct tst_cg_group * const cg)1151*49cdfc7eSAndroid Build Coastguard Worker int tst_cg_group_unified_dir_fd(const struct tst_cg_group *const cg)
1152*49cdfc7eSAndroid Build Coastguard Worker {
1153*49cdfc7eSAndroid Build Coastguard Worker if(cg->dirs_by_ctrl[0])
1154*49cdfc7eSAndroid Build Coastguard Worker return cg->dirs_by_ctrl[0]->dir_fd;
1155*49cdfc7eSAndroid Build Coastguard Worker
1156*49cdfc7eSAndroid Build Coastguard Worker return -1;
1157*49cdfc7eSAndroid Build Coastguard Worker }
1158*49cdfc7eSAndroid Build Coastguard Worker
tst_cg_group_rm(struct tst_cg_group * const cg)1159*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group *tst_cg_group_rm(struct tst_cg_group *const cg)
1160*49cdfc7eSAndroid Build Coastguard Worker {
1161*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir **dir;
1162*49cdfc7eSAndroid Build Coastguard Worker
1163*49cdfc7eSAndroid Build Coastguard Worker for_each_dir(cg, 0, dir) {
1164*49cdfc7eSAndroid Build Coastguard Worker close((*dir)->dir_fd);
1165*49cdfc7eSAndroid Build Coastguard Worker SAFE_UNLINKAT((*dir)->dir_parent->dir_fd,
1166*49cdfc7eSAndroid Build Coastguard Worker (*dir)->dir_name,
1167*49cdfc7eSAndroid Build Coastguard Worker AT_REMOVEDIR);
1168*49cdfc7eSAndroid Build Coastguard Worker free(*dir);
1169*49cdfc7eSAndroid Build Coastguard Worker }
1170*49cdfc7eSAndroid Build Coastguard Worker
1171*49cdfc7eSAndroid Build Coastguard Worker free(cg);
1172*49cdfc7eSAndroid Build Coastguard Worker return NULL;
1173*49cdfc7eSAndroid Build Coastguard Worker }
1174*49cdfc7eSAndroid Build Coastguard Worker
1175*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull, warn_unused_result))
cgroup_file_find(const char * const file,const int lineno,const char * const file_name)1176*49cdfc7eSAndroid Build Coastguard Worker static const struct cgroup_file *cgroup_file_find(const char *const file,
1177*49cdfc7eSAndroid Build Coastguard Worker const int lineno,
1178*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name)
1179*49cdfc7eSAndroid Build Coastguard Worker {
1180*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_file *cfile;
1181*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_ctrl *ctrl;
1182*49cdfc7eSAndroid Build Coastguard Worker char ctrl_name[CTRL_NAME_MAX + 1];
1183*49cdfc7eSAndroid Build Coastguard Worker const char *const sep = strchr(file_name, '.');
1184*49cdfc7eSAndroid Build Coastguard Worker size_t len;
1185*49cdfc7eSAndroid Build Coastguard Worker
1186*49cdfc7eSAndroid Build Coastguard Worker if (!sep) {
1187*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK,
1188*49cdfc7eSAndroid Build Coastguard Worker "Invalid file name '%s'; did not find controller separator '.'",
1189*49cdfc7eSAndroid Build Coastguard Worker file_name);
1190*49cdfc7eSAndroid Build Coastguard Worker return NULL;
1191*49cdfc7eSAndroid Build Coastguard Worker }
1192*49cdfc7eSAndroid Build Coastguard Worker
1193*49cdfc7eSAndroid Build Coastguard Worker len = sep - file_name;
1194*49cdfc7eSAndroid Build Coastguard Worker memcpy(ctrl_name, file_name, len);
1195*49cdfc7eSAndroid Build Coastguard Worker ctrl_name[len] = '\0';
1196*49cdfc7eSAndroid Build Coastguard Worker
1197*49cdfc7eSAndroid Build Coastguard Worker ctrl = cgroup_find_ctrl(ctrl_name, 1);
1198*49cdfc7eSAndroid Build Coastguard Worker
1199*49cdfc7eSAndroid Build Coastguard Worker if (!ctrl) {
1200*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK,
1201*49cdfc7eSAndroid Build Coastguard Worker "Did not find controller '%s'\n", ctrl_name);
1202*49cdfc7eSAndroid Build Coastguard Worker return NULL;
1203*49cdfc7eSAndroid Build Coastguard Worker }
1204*49cdfc7eSAndroid Build Coastguard Worker
1205*49cdfc7eSAndroid Build Coastguard Worker for (cfile = ctrl->files; cfile->file_name; cfile++) {
1206*49cdfc7eSAndroid Build Coastguard Worker if (!strcmp(file_name, cfile->file_name))
1207*49cdfc7eSAndroid Build Coastguard Worker break;
1208*49cdfc7eSAndroid Build Coastguard Worker }
1209*49cdfc7eSAndroid Build Coastguard Worker
1210*49cdfc7eSAndroid Build Coastguard Worker if (!cfile->file_name) {
1211*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK,
1212*49cdfc7eSAndroid Build Coastguard Worker "Did not find '%s' in '%s'\n",
1213*49cdfc7eSAndroid Build Coastguard Worker file_name, ctrl->ctrl_name);
1214*49cdfc7eSAndroid Build Coastguard Worker return NULL;
1215*49cdfc7eSAndroid Build Coastguard Worker }
1216*49cdfc7eSAndroid Build Coastguard Worker
1217*49cdfc7eSAndroid Build Coastguard Worker return cfile;
1218*49cdfc7eSAndroid Build Coastguard Worker }
1219*49cdfc7eSAndroid Build Coastguard Worker
tst_cg_ver(const char * const file,const int lineno,const struct tst_cg_group * const cg,const char * const ctrl_name)1220*49cdfc7eSAndroid Build Coastguard Worker enum tst_cg_ver tst_cg_ver(const char *const file, const int lineno,
1221*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *const cg,
1222*49cdfc7eSAndroid Build Coastguard Worker const char *const ctrl_name)
1223*49cdfc7eSAndroid Build Coastguard Worker {
1224*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_ctrl *const ctrl = cgroup_find_ctrl(ctrl_name, 1);
1225*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_dir *dir;
1226*49cdfc7eSAndroid Build Coastguard Worker
1227*49cdfc7eSAndroid Build Coastguard Worker if (!strcmp(ctrl_name, "cgroup")) {
1228*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno,
1229*49cdfc7eSAndroid Build Coastguard Worker TBROK,
1230*49cdfc7eSAndroid Build Coastguard Worker "cgroup may be present on both V1 and V2 hierarchies");
1231*49cdfc7eSAndroid Build Coastguard Worker return 0;
1232*49cdfc7eSAndroid Build Coastguard Worker }
1233*49cdfc7eSAndroid Build Coastguard Worker
1234*49cdfc7eSAndroid Build Coastguard Worker if (!ctrl) {
1235*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno,
1236*49cdfc7eSAndroid Build Coastguard Worker TBROK, "Unknown controller '%s'", ctrl_name);
1237*49cdfc7eSAndroid Build Coastguard Worker return 0;
1238*49cdfc7eSAndroid Build Coastguard Worker }
1239*49cdfc7eSAndroid Build Coastguard Worker
1240*49cdfc7eSAndroid Build Coastguard Worker dir = cg->dirs_by_ctrl[ctrl->ctrl_indx];
1241*49cdfc7eSAndroid Build Coastguard Worker
1242*49cdfc7eSAndroid Build Coastguard Worker if (!dir) {
1243*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno,
1244*49cdfc7eSAndroid Build Coastguard Worker TBROK, "%s controller not attached to CGroup %s",
1245*49cdfc7eSAndroid Build Coastguard Worker ctrl_name, cg->group_name);
1246*49cdfc7eSAndroid Build Coastguard Worker return 0;
1247*49cdfc7eSAndroid Build Coastguard Worker }
1248*49cdfc7eSAndroid Build Coastguard Worker
1249*49cdfc7eSAndroid Build Coastguard Worker return dir->dir_root->ver;
1250*49cdfc7eSAndroid Build Coastguard Worker }
1251*49cdfc7eSAndroid Build Coastguard Worker
1252*49cdfc7eSAndroid Build Coastguard Worker __attribute__ ((nonnull, warn_unused_result))
cgroup_file_alias(const struct cgroup_file * const cfile,const struct cgroup_dir * const dir)1253*49cdfc7eSAndroid Build Coastguard Worker static const char *cgroup_file_alias(const struct cgroup_file *const cfile,
1254*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_dir *const dir)
1255*49cdfc7eSAndroid Build Coastguard Worker {
1256*49cdfc7eSAndroid Build Coastguard Worker if (dir->dir_root->ver != TST_CG_V1)
1257*49cdfc7eSAndroid Build Coastguard Worker return cfile->file_name;
1258*49cdfc7eSAndroid Build Coastguard Worker
1259*49cdfc7eSAndroid Build Coastguard Worker if (cfile->ctrl_indx == CTRL_CPUSET &&
1260*49cdfc7eSAndroid Build Coastguard Worker dir->dir_root->no_cpuset_prefix &&
1261*49cdfc7eSAndroid Build Coastguard Worker cfile->file_name_v1) {
1262*49cdfc7eSAndroid Build Coastguard Worker return strchr(cfile->file_name_v1, '.') + 1;
1263*49cdfc7eSAndroid Build Coastguard Worker }
1264*49cdfc7eSAndroid Build Coastguard Worker
1265*49cdfc7eSAndroid Build Coastguard Worker return cfile->file_name_v1;
1266*49cdfc7eSAndroid Build Coastguard Worker }
1267*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_has(const char * const file,const int lineno,const struct tst_cg_group * cg,const char * const file_name)1268*49cdfc7eSAndroid Build Coastguard Worker int safe_cg_has(const char *const file, const int lineno,
1269*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *cg,
1270*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name)
1271*49cdfc7eSAndroid Build Coastguard Worker {
1272*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_file *const cfile =
1273*49cdfc7eSAndroid Build Coastguard Worker cgroup_file_find(file, lineno, file_name);
1274*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const *dir;
1275*49cdfc7eSAndroid Build Coastguard Worker const char *alias;
1276*49cdfc7eSAndroid Build Coastguard Worker
1277*49cdfc7eSAndroid Build Coastguard Worker if (!cfile)
1278*49cdfc7eSAndroid Build Coastguard Worker return 0;
1279*49cdfc7eSAndroid Build Coastguard Worker
1280*49cdfc7eSAndroid Build Coastguard Worker for_each_dir(cg, cfile->ctrl_indx, dir) {
1281*49cdfc7eSAndroid Build Coastguard Worker alias = cgroup_file_alias(cfile, *dir);
1282*49cdfc7eSAndroid Build Coastguard Worker if (!alias)
1283*49cdfc7eSAndroid Build Coastguard Worker continue;
1284*49cdfc7eSAndroid Build Coastguard Worker
1285*49cdfc7eSAndroid Build Coastguard Worker if (!faccessat((*dir)->dir_fd, alias, F_OK, 0))
1286*49cdfc7eSAndroid Build Coastguard Worker return 1;
1287*49cdfc7eSAndroid Build Coastguard Worker
1288*49cdfc7eSAndroid Build Coastguard Worker if (errno == ENOENT)
1289*49cdfc7eSAndroid Build Coastguard Worker continue;
1290*49cdfc7eSAndroid Build Coastguard Worker
1291*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
1292*49cdfc7eSAndroid Build Coastguard Worker "faccessat(%d<%s>, %s, F_OK, 0)",
1293*49cdfc7eSAndroid Build Coastguard Worker (*dir)->dir_fd, tst_decode_fd((*dir)->dir_fd), alias);
1294*49cdfc7eSAndroid Build Coastguard Worker }
1295*49cdfc7eSAndroid Build Coastguard Worker
1296*49cdfc7eSAndroid Build Coastguard Worker return 0;
1297*49cdfc7eSAndroid Build Coastguard Worker }
1298*49cdfc7eSAndroid Build Coastguard Worker
group_from_roots(struct tst_cg_group * const cg)1299*49cdfc7eSAndroid Build Coastguard Worker static void group_from_roots(struct tst_cg_group *const cg)
1300*49cdfc7eSAndroid Build Coastguard Worker {
1301*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_root *root;
1302*49cdfc7eSAndroid Build Coastguard Worker
1303*49cdfc7eSAndroid Build Coastguard Worker if (cg->group_name[0]) {
1304*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK,
1305*49cdfc7eSAndroid Build Coastguard Worker "%s CGroup already initialized",
1306*49cdfc7eSAndroid Build Coastguard Worker cg == &test_group ? "Test" : "Drain");
1307*49cdfc7eSAndroid Build Coastguard Worker }
1308*49cdfc7eSAndroid Build Coastguard Worker
1309*49cdfc7eSAndroid Build Coastguard Worker for_each_root(root) {
1310*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *dir =
1311*49cdfc7eSAndroid Build Coastguard Worker cg == &test_group ? &root->test_dir : &root->drain_dir;
1312*49cdfc7eSAndroid Build Coastguard Worker
1313*49cdfc7eSAndroid Build Coastguard Worker if (dir->ctrl_field)
1314*49cdfc7eSAndroid Build Coastguard Worker cgroup_group_add_dir(NULL, cg, dir);
1315*49cdfc7eSAndroid Build Coastguard Worker }
1316*49cdfc7eSAndroid Build Coastguard Worker
1317*49cdfc7eSAndroid Build Coastguard Worker if (cg->dirs[0]) {
1318*49cdfc7eSAndroid Build Coastguard Worker strncpy(cg->group_name, cg->dirs[0]->dir_name, NAME_MAX);
1319*49cdfc7eSAndroid Build Coastguard Worker return;
1320*49cdfc7eSAndroid Build Coastguard Worker }
1321*49cdfc7eSAndroid Build Coastguard Worker
1322*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK,
1323*49cdfc7eSAndroid Build Coastguard Worker "No CGroups found; maybe you forgot to call tst_cg_require?");
1324*49cdfc7eSAndroid Build Coastguard Worker }
1325*49cdfc7eSAndroid Build Coastguard Worker
tst_cg_init(void)1326*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_init(void)
1327*49cdfc7eSAndroid Build Coastguard Worker {
1328*49cdfc7eSAndroid Build Coastguard Worker group_from_roots(&test_group);
1329*49cdfc7eSAndroid Build Coastguard Worker group_from_roots(&drain_group);
1330*49cdfc7eSAndroid Build Coastguard Worker }
1331*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_read(const char * const file,const int lineno,const struct tst_cg_group * const cg,const char * const file_name,char * const out,const size_t len)1332*49cdfc7eSAndroid Build Coastguard Worker ssize_t safe_cg_read(const char *const file, const int lineno,
1333*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *const cg,
1334*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name,
1335*49cdfc7eSAndroid Build Coastguard Worker char *const out, const size_t len)
1336*49cdfc7eSAndroid Build Coastguard Worker {
1337*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_file *const cfile =
1338*49cdfc7eSAndroid Build Coastguard Worker cgroup_file_find(file, lineno, file_name);
1339*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const *dir;
1340*49cdfc7eSAndroid Build Coastguard Worker const char *alias;
1341*49cdfc7eSAndroid Build Coastguard Worker size_t prev_len = 0;
1342*49cdfc7eSAndroid Build Coastguard Worker char prev_buf[BUFSIZ];
1343*49cdfc7eSAndroid Build Coastguard Worker ssize_t read_ret = 0;
1344*49cdfc7eSAndroid Build Coastguard Worker
1345*49cdfc7eSAndroid Build Coastguard Worker for_each_dir(cg, cfile->ctrl_indx, dir) {
1346*49cdfc7eSAndroid Build Coastguard Worker alias = cgroup_file_alias(cfile, *dir);
1347*49cdfc7eSAndroid Build Coastguard Worker if (!alias)
1348*49cdfc7eSAndroid Build Coastguard Worker continue;
1349*49cdfc7eSAndroid Build Coastguard Worker
1350*49cdfc7eSAndroid Build Coastguard Worker if (prev_len)
1351*49cdfc7eSAndroid Build Coastguard Worker memcpy(prev_buf, out, prev_len);
1352*49cdfc7eSAndroid Build Coastguard Worker
1353*49cdfc7eSAndroid Build Coastguard Worker read_ret = safe_file_readat(file, lineno,
1354*49cdfc7eSAndroid Build Coastguard Worker (*dir)->dir_fd, alias, out, len);
1355*49cdfc7eSAndroid Build Coastguard Worker if (read_ret < 0)
1356*49cdfc7eSAndroid Build Coastguard Worker continue;
1357*49cdfc7eSAndroid Build Coastguard Worker
1358*49cdfc7eSAndroid Build Coastguard Worker if (prev_len && memcmp(out, prev_buf, prev_len)) {
1359*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK,
1360*49cdfc7eSAndroid Build Coastguard Worker "%s has different value across roots",
1361*49cdfc7eSAndroid Build Coastguard Worker file_name);
1362*49cdfc7eSAndroid Build Coastguard Worker break;
1363*49cdfc7eSAndroid Build Coastguard Worker }
1364*49cdfc7eSAndroid Build Coastguard Worker
1365*49cdfc7eSAndroid Build Coastguard Worker prev_len = MIN(sizeof(prev_buf), (size_t)read_ret);
1366*49cdfc7eSAndroid Build Coastguard Worker }
1367*49cdfc7eSAndroid Build Coastguard Worker
1368*49cdfc7eSAndroid Build Coastguard Worker out[MAX(read_ret, (ssize_t)0)] = '\0';
1369*49cdfc7eSAndroid Build Coastguard Worker
1370*49cdfc7eSAndroid Build Coastguard Worker return read_ret;
1371*49cdfc7eSAndroid Build Coastguard Worker }
1372*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_printf(const char * const file,const int lineno,const struct tst_cg_group * cg,const char * const file_name,const char * const fmt,...)1373*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_printf(const char *const file, const int lineno,
1374*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *cg,
1375*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name,
1376*49cdfc7eSAndroid Build Coastguard Worker const char *const fmt, ...)
1377*49cdfc7eSAndroid Build Coastguard Worker {
1378*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_file *const cfile =
1379*49cdfc7eSAndroid Build Coastguard Worker cgroup_file_find(file, lineno, file_name);
1380*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const *dir;
1381*49cdfc7eSAndroid Build Coastguard Worker const char *alias;
1382*49cdfc7eSAndroid Build Coastguard Worker va_list va;
1383*49cdfc7eSAndroid Build Coastguard Worker
1384*49cdfc7eSAndroid Build Coastguard Worker for_each_dir(cg, cfile->ctrl_indx, dir) {
1385*49cdfc7eSAndroid Build Coastguard Worker alias = cgroup_file_alias(cfile, *dir);
1386*49cdfc7eSAndroid Build Coastguard Worker if (!alias)
1387*49cdfc7eSAndroid Build Coastguard Worker continue;
1388*49cdfc7eSAndroid Build Coastguard Worker
1389*49cdfc7eSAndroid Build Coastguard Worker va_start(va, fmt);
1390*49cdfc7eSAndroid Build Coastguard Worker safe_file_vprintfat(file, lineno,
1391*49cdfc7eSAndroid Build Coastguard Worker (*dir)->dir_fd, alias, fmt, va);
1392*49cdfc7eSAndroid Build Coastguard Worker va_end(va);
1393*49cdfc7eSAndroid Build Coastguard Worker }
1394*49cdfc7eSAndroid Build Coastguard Worker }
1395*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_open(const char * const file,const int lineno,const struct tst_cg_group * cg,const char * const file_name,int flags,int * fds)1396*49cdfc7eSAndroid Build Coastguard Worker int safe_cg_open(const char *const file, const int lineno,
1397*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *cg,
1398*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name, int flags, int *fds)
1399*49cdfc7eSAndroid Build Coastguard Worker {
1400*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_file *const cfile =
1401*49cdfc7eSAndroid Build Coastguard Worker cgroup_file_find(file, lineno, file_name);
1402*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const *dir;
1403*49cdfc7eSAndroid Build Coastguard Worker const char *alias;
1404*49cdfc7eSAndroid Build Coastguard Worker int i = 0;
1405*49cdfc7eSAndroid Build Coastguard Worker
1406*49cdfc7eSAndroid Build Coastguard Worker for_each_dir(cg, cfile->ctrl_indx, dir) {
1407*49cdfc7eSAndroid Build Coastguard Worker alias = cgroup_file_alias(cfile, *dir);
1408*49cdfc7eSAndroid Build Coastguard Worker if (!alias)
1409*49cdfc7eSAndroid Build Coastguard Worker continue;
1410*49cdfc7eSAndroid Build Coastguard Worker
1411*49cdfc7eSAndroid Build Coastguard Worker fds[i++] = safe_openat(file, lineno, (*dir)->dir_fd, alias, flags);
1412*49cdfc7eSAndroid Build Coastguard Worker }
1413*49cdfc7eSAndroid Build Coastguard Worker
1414*49cdfc7eSAndroid Build Coastguard Worker return i;
1415*49cdfc7eSAndroid Build Coastguard Worker }
1416*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_fchown(const char * const file,const int lineno,const struct tst_cg_group * cg,const char * const file_name,uid_t owner,gid_t group)1417*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_fchown(const char *const file, const int lineno,
1418*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *cg,
1419*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name,
1420*49cdfc7eSAndroid Build Coastguard Worker uid_t owner, gid_t group)
1421*49cdfc7eSAndroid Build Coastguard Worker {
1422*49cdfc7eSAndroid Build Coastguard Worker const struct cgroup_file *const cfile =
1423*49cdfc7eSAndroid Build Coastguard Worker cgroup_file_find(file, lineno, file_name);
1424*49cdfc7eSAndroid Build Coastguard Worker struct cgroup_dir *const *dir;
1425*49cdfc7eSAndroid Build Coastguard Worker const char *alias;
1426*49cdfc7eSAndroid Build Coastguard Worker
1427*49cdfc7eSAndroid Build Coastguard Worker for_each_dir(cg, cfile->ctrl_indx, dir) {
1428*49cdfc7eSAndroid Build Coastguard Worker alias = cgroup_file_alias(cfile, *dir);
1429*49cdfc7eSAndroid Build Coastguard Worker if (!alias)
1430*49cdfc7eSAndroid Build Coastguard Worker continue;
1431*49cdfc7eSAndroid Build Coastguard Worker
1432*49cdfc7eSAndroid Build Coastguard Worker safe_fchownat(file, lineno, (*dir)->dir_fd, alias, owner, group, 0);
1433*49cdfc7eSAndroid Build Coastguard Worker }
1434*49cdfc7eSAndroid Build Coastguard Worker }
1435*49cdfc7eSAndroid Build Coastguard Worker
1436*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_scanf(const char * const file,const int lineno,const struct tst_cg_group * const cg,const char * const file_name,const char * const fmt,...)1437*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_scanf(const char *const file, const int lineno,
1438*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *const cg,
1439*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name,
1440*49cdfc7eSAndroid Build Coastguard Worker const char *const fmt, ...)
1441*49cdfc7eSAndroid Build Coastguard Worker {
1442*49cdfc7eSAndroid Build Coastguard Worker va_list va;
1443*49cdfc7eSAndroid Build Coastguard Worker char buf[BUFSIZ];
1444*49cdfc7eSAndroid Build Coastguard Worker ssize_t len = safe_cg_read(file, lineno,
1445*49cdfc7eSAndroid Build Coastguard Worker cg, file_name, buf, sizeof(buf));
1446*49cdfc7eSAndroid Build Coastguard Worker const int conv_cnt = tst_count_scanf_conversions(fmt);
1447*49cdfc7eSAndroid Build Coastguard Worker int ret;
1448*49cdfc7eSAndroid Build Coastguard Worker
1449*49cdfc7eSAndroid Build Coastguard Worker if (len < 1)
1450*49cdfc7eSAndroid Build Coastguard Worker return;
1451*49cdfc7eSAndroid Build Coastguard Worker
1452*49cdfc7eSAndroid Build Coastguard Worker va_start(va, fmt);
1453*49cdfc7eSAndroid Build Coastguard Worker ret = vsscanf(buf, fmt, va);
1454*49cdfc7eSAndroid Build Coastguard Worker if (ret < 1) {
1455*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK | TERRNO,
1456*49cdfc7eSAndroid Build Coastguard Worker "'%s': vsscanf('%s', '%s', ...)", file_name, buf, fmt);
1457*49cdfc7eSAndroid Build Coastguard Worker }
1458*49cdfc7eSAndroid Build Coastguard Worker va_end(va);
1459*49cdfc7eSAndroid Build Coastguard Worker
1460*49cdfc7eSAndroid Build Coastguard Worker if (conv_cnt == ret)
1461*49cdfc7eSAndroid Build Coastguard Worker return;
1462*49cdfc7eSAndroid Build Coastguard Worker
1463*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK,
1464*49cdfc7eSAndroid Build Coastguard Worker "'%s': vsscanf('%s', '%s', ..): Less conversions than expected: %d != %d",
1465*49cdfc7eSAndroid Build Coastguard Worker file_name, buf, fmt, ret, conv_cnt);
1466*49cdfc7eSAndroid Build Coastguard Worker }
1467*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_lines_scanf(const char * const file,const int lineno,const struct tst_cg_group * const cg,const char * const file_name,const char * const fmt,...)1468*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_lines_scanf(const char *const file, const int lineno,
1469*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *const cg,
1470*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name,
1471*49cdfc7eSAndroid Build Coastguard Worker const char *const fmt, ...)
1472*49cdfc7eSAndroid Build Coastguard Worker {
1473*49cdfc7eSAndroid Build Coastguard Worker va_list va;
1474*49cdfc7eSAndroid Build Coastguard Worker char buf[BUFSIZ];
1475*49cdfc7eSAndroid Build Coastguard Worker ssize_t len = safe_cg_read(file, lineno,
1476*49cdfc7eSAndroid Build Coastguard Worker cg, file_name, buf, sizeof(buf));
1477*49cdfc7eSAndroid Build Coastguard Worker const int conv_cnt = tst_count_scanf_conversions(fmt);
1478*49cdfc7eSAndroid Build Coastguard Worker int ret = 0;
1479*49cdfc7eSAndroid Build Coastguard Worker char *line, *buf_ptr;
1480*49cdfc7eSAndroid Build Coastguard Worker
1481*49cdfc7eSAndroid Build Coastguard Worker if (len < 1)
1482*49cdfc7eSAndroid Build Coastguard Worker return;
1483*49cdfc7eSAndroid Build Coastguard Worker
1484*49cdfc7eSAndroid Build Coastguard Worker line = strtok_r(buf, "\n", &buf_ptr);
1485*49cdfc7eSAndroid Build Coastguard Worker while (line && ret != conv_cnt) {
1486*49cdfc7eSAndroid Build Coastguard Worker va_start(va, fmt);
1487*49cdfc7eSAndroid Build Coastguard Worker ret = vsscanf(line, fmt, va);
1488*49cdfc7eSAndroid Build Coastguard Worker va_end(va);
1489*49cdfc7eSAndroid Build Coastguard Worker
1490*49cdfc7eSAndroid Build Coastguard Worker line = strtok_r(NULL, "\n", &buf_ptr);
1491*49cdfc7eSAndroid Build Coastguard Worker }
1492*49cdfc7eSAndroid Build Coastguard Worker
1493*49cdfc7eSAndroid Build Coastguard Worker if (conv_cnt == ret)
1494*49cdfc7eSAndroid Build Coastguard Worker return;
1495*49cdfc7eSAndroid Build Coastguard Worker
1496*49cdfc7eSAndroid Build Coastguard Worker tst_brk_(file, lineno, TBROK,
1497*49cdfc7eSAndroid Build Coastguard Worker "'%s': vsscanf('%s', '%s', ..): Less conversions than expected: %d != %d",
1498*49cdfc7eSAndroid Build Coastguard Worker file_name, buf, fmt, ret, conv_cnt);
1499*49cdfc7eSAndroid Build Coastguard Worker }
1500*49cdfc7eSAndroid Build Coastguard Worker
safe_cg_occursin(const char * const file,const int lineno,const struct tst_cg_group * const cg,const char * const file_name,const char * const needle)1501*49cdfc7eSAndroid Build Coastguard Worker int safe_cg_occursin(const char *const file, const int lineno,
1502*49cdfc7eSAndroid Build Coastguard Worker const struct tst_cg_group *const cg,
1503*49cdfc7eSAndroid Build Coastguard Worker const char *const file_name,
1504*49cdfc7eSAndroid Build Coastguard Worker const char *const needle)
1505*49cdfc7eSAndroid Build Coastguard Worker {
1506*49cdfc7eSAndroid Build Coastguard Worker char buf[BUFSIZ];
1507*49cdfc7eSAndroid Build Coastguard Worker
1508*49cdfc7eSAndroid Build Coastguard Worker safe_cg_read(file, lineno, cg, file_name, buf, sizeof(buf));
1509*49cdfc7eSAndroid Build Coastguard Worker
1510*49cdfc7eSAndroid Build Coastguard Worker return !!strstr(buf, needle);
1511*49cdfc7eSAndroid Build Coastguard Worker }
1512