xref: /aosp_15_r20/external/ltp/include/tst_cgroup.h (revision 49cdfc7efb34551c7342be41a7384b9c40d7cab7)
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  * [Description]
9*49cdfc7eSAndroid Build Coastguard Worker  *
10*49cdfc7eSAndroid Build Coastguard Worker  * The LTP CGroups API tries to present a consistent interface to the
11*49cdfc7eSAndroid Build Coastguard Worker  * many possible CGroup configurations a system could have.
12*49cdfc7eSAndroid Build Coastguard Worker  *
13*49cdfc7eSAndroid Build Coastguard Worker  * You may ask; "Why don't you just mount a simple CGroup hierarchy,
14*49cdfc7eSAndroid Build Coastguard Worker  * instead of scanning the current setup?". The short answer is that
15*49cdfc7eSAndroid Build Coastguard Worker  * it is not possible unless no CGroups are currently active and
16*49cdfc7eSAndroid Build Coastguard Worker  * almost all of our users will have CGroups active. Even if
17*49cdfc7eSAndroid Build Coastguard Worker  * unmounting the current CGroup hierarchy is a reasonable thing to do
18*49cdfc7eSAndroid Build Coastguard Worker  * to the sytem manager, it is highly unlikely the CGroup hierarchy
19*49cdfc7eSAndroid Build Coastguard Worker  * will be destroyed. So users would be forced to remove their CGroup
20*49cdfc7eSAndroid Build Coastguard Worker  * configuration and reboot the system.
21*49cdfc7eSAndroid Build Coastguard Worker  *
22*49cdfc7eSAndroid Build Coastguard Worker  * The core library tries to ensure an LTP CGroup exists on each
23*49cdfc7eSAndroid Build Coastguard Worker  * hierarchy root. Inside the LTP group it ensures a 'drain' group
24*49cdfc7eSAndroid Build Coastguard Worker  * exists and creats a test group for the current test. In the worst
25*49cdfc7eSAndroid Build Coastguard Worker  * case we end up with a set of hierarchies like the follwoing. Where
26*49cdfc7eSAndroid Build Coastguard Worker  * existing system-manager-created CGroups have been omitted.
27*49cdfc7eSAndroid Build Coastguard Worker  *
28*49cdfc7eSAndroid Build Coastguard Worker  *	(V2 Root)	(V1 Root 1)	...	(V1 Root N)
29*49cdfc7eSAndroid Build Coastguard Worker  *	    |		     |			     |
30*49cdfc7eSAndroid Build Coastguard Worker  *	  (ltp)		   (ltp)	...	   (ltp)
31*49cdfc7eSAndroid Build Coastguard Worker  *	 /     \	  /	\		  /	\
32*49cdfc7eSAndroid Build Coastguard Worker  *  (drain) (test-n) (drain)  (test-n)  ...  (drain)  (test-n)
33*49cdfc7eSAndroid Build Coastguard Worker  *
34*49cdfc7eSAndroid Build Coastguard Worker  * V2 CGroup controllers use a single unified hierarchy on a single
35*49cdfc7eSAndroid Build Coastguard Worker  * root. Two or more V1 controllers may share a root or have their own
36*49cdfc7eSAndroid Build Coastguard Worker  * root. However there may exist only one instance of a controller.
37*49cdfc7eSAndroid Build Coastguard Worker  * So you can not have the same V1 controller on multiple roots.
38*49cdfc7eSAndroid Build Coastguard Worker  *
39*49cdfc7eSAndroid Build Coastguard Worker  * It is possible to have both a V2 hierarchy and V1 hierarchies
40*49cdfc7eSAndroid Build Coastguard Worker  * active at the same time. Which is what is shown above. Any
41*49cdfc7eSAndroid Build Coastguard Worker  * controllers attached to V1 hierarchies will not be available in the
42*49cdfc7eSAndroid Build Coastguard Worker  * V2 hierarchy. The reverse is also true.
43*49cdfc7eSAndroid Build Coastguard Worker  *
44*49cdfc7eSAndroid Build Coastguard Worker  * Note that a single hierarchy may be mounted multiple
45*49cdfc7eSAndroid Build Coastguard Worker  * times. Allowing it to be accessed at different locations. However
46*49cdfc7eSAndroid Build Coastguard Worker  * subsequent mount operations will fail if the mount options are
47*49cdfc7eSAndroid Build Coastguard Worker  * different from the first.
48*49cdfc7eSAndroid Build Coastguard Worker  *
49*49cdfc7eSAndroid Build Coastguard Worker  * The user may pre-create the CGroup hierarchies and the ltp CGroup,
50*49cdfc7eSAndroid Build Coastguard Worker  * otherwise the library will try to create them. If the ltp group
51*49cdfc7eSAndroid Build Coastguard Worker  * already exists and has appropriate permissions, then admin
52*49cdfc7eSAndroid Build Coastguard Worker  * privileges will not be required to run the tests.
53*49cdfc7eSAndroid Build Coastguard Worker  *
54*49cdfc7eSAndroid Build Coastguard Worker  * Because the test may not have access to the CGroup root(s), the
55*49cdfc7eSAndroid Build Coastguard Worker  * drain CGroup is created. This can be used to store processes which
56*49cdfc7eSAndroid Build Coastguard Worker  * would otherwise block the destruction of the individual test CGroup
57*49cdfc7eSAndroid Build Coastguard Worker  * or one of its descendants.
58*49cdfc7eSAndroid Build Coastguard Worker  *
59*49cdfc7eSAndroid Build Coastguard Worker  * The test author may create child CGroups within the test CGroup
60*49cdfc7eSAndroid Build Coastguard Worker  * using the CGroup Item API. The library will create the new CGroup
61*49cdfc7eSAndroid Build Coastguard Worker  * in all the relevant hierarchies.
62*49cdfc7eSAndroid Build Coastguard Worker  *
63*49cdfc7eSAndroid Build Coastguard Worker  * There are many differences between the V1 and V2 CGroup APIs. If a
64*49cdfc7eSAndroid Build Coastguard Worker  * controller is on both V1 and V2, it may have different parameters
65*49cdfc7eSAndroid Build Coastguard Worker  * and control files. Some of these control files have a different
66*49cdfc7eSAndroid Build Coastguard Worker  * name, but similar functionality. In this case the Item API uses
67*49cdfc7eSAndroid Build Coastguard Worker  * the V2 names and aliases them to the V1 name when appropriate.
68*49cdfc7eSAndroid Build Coastguard Worker  *
69*49cdfc7eSAndroid Build Coastguard Worker  * Some control files only exist on one of the versions or they can be
70*49cdfc7eSAndroid Build Coastguard Worker  * missing due to other reasons. The Item API allows the user to check
71*49cdfc7eSAndroid Build Coastguard Worker  * if the file exists before trying to use it.
72*49cdfc7eSAndroid Build Coastguard Worker  *
73*49cdfc7eSAndroid Build Coastguard Worker  * Often a control file has almost the same functionality between V1
74*49cdfc7eSAndroid Build Coastguard Worker  * and V2. Which means it can be used in the same way most of the
75*49cdfc7eSAndroid Build Coastguard Worker  * time, but not all. For now this is handled by exposing the API
76*49cdfc7eSAndroid Build Coastguard Worker  * version a controller is using to allow the test author to handle
77*49cdfc7eSAndroid Build Coastguard Worker  * edge cases. (e.g. V2 memory.swap.max accepts "max", but V1
78*49cdfc7eSAndroid Build Coastguard Worker  * memory.memsw.limit_in_bytes does not).
79*49cdfc7eSAndroid Build Coastguard Worker  */
80*49cdfc7eSAndroid Build Coastguard Worker 
81*49cdfc7eSAndroid Build Coastguard Worker #ifndef TST_CGROUP_H
82*49cdfc7eSAndroid Build Coastguard Worker #define TST_CGROUP_H
83*49cdfc7eSAndroid Build Coastguard Worker 
84*49cdfc7eSAndroid Build Coastguard Worker #include <sys/types.h>
85*49cdfc7eSAndroid Build Coastguard Worker 
86*49cdfc7eSAndroid Build Coastguard Worker /* CGroups Kernel API version */
87*49cdfc7eSAndroid Build Coastguard Worker enum tst_cg_ver {
88*49cdfc7eSAndroid Build Coastguard Worker 	TST_CG_V1 = 1,
89*49cdfc7eSAndroid Build Coastguard Worker 	TST_CG_V2 = 2,
90*49cdfc7eSAndroid Build Coastguard Worker };
91*49cdfc7eSAndroid Build Coastguard Worker 
92*49cdfc7eSAndroid Build Coastguard Worker /* This value is greater than ROOTS_MAX in tst_cgroup.c. */
93*49cdfc7eSAndroid Build Coastguard Worker #define TST_CG_ROOTS_MAX 32
94*49cdfc7eSAndroid Build Coastguard Worker 
95*49cdfc7eSAndroid Build Coastguard Worker /* Used to specify CGroup hierarchy configuration options, allowing a
96*49cdfc7eSAndroid Build Coastguard Worker  * test to request a particular CGroup structure.
97*49cdfc7eSAndroid Build Coastguard Worker  */
98*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_opts {
99*49cdfc7eSAndroid Build Coastguard Worker 	/* Call tst_brk with TCONF if the controller is not on this
100*49cdfc7eSAndroid Build Coastguard Worker 	 * version. Defautls to zero to accept any version.
101*49cdfc7eSAndroid Build Coastguard Worker 	 */
102*49cdfc7eSAndroid Build Coastguard Worker 	enum tst_cg_ver needs_ver;
103*49cdfc7eSAndroid Build Coastguard Worker 	/* Pass in a specific pid to create and identify the test
104*49cdfc7eSAndroid Build Coastguard Worker 	 * directory as opposed to the default pid of the calling process.
105*49cdfc7eSAndroid Build Coastguard Worker 	 */
106*49cdfc7eSAndroid Build Coastguard Worker 	int test_pid;
107*49cdfc7eSAndroid Build Coastguard Worker 	int needs_nsdelegate;
108*49cdfc7eSAndroid Build Coastguard Worker };
109*49cdfc7eSAndroid Build Coastguard Worker 
110*49cdfc7eSAndroid Build Coastguard Worker /* A Control Group in LTP's aggregated hierarchy */
111*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group;
112*49cdfc7eSAndroid Build Coastguard Worker 
113*49cdfc7eSAndroid Build Coastguard Worker /* Populated with a reference to this tests's CGroup */
114*49cdfc7eSAndroid Build Coastguard Worker extern const struct tst_cg_group *const tst_cg;
115*49cdfc7eSAndroid Build Coastguard Worker extern const struct tst_cg_group *const tst_cg_drain;
116*49cdfc7eSAndroid Build Coastguard Worker 
117*49cdfc7eSAndroid Build Coastguard Worker /* Search the system for mounted cgroups and available
118*49cdfc7eSAndroid Build Coastguard Worker  * controllers. Called automatically by tst_cg_require.
119*49cdfc7eSAndroid Build Coastguard Worker  */
120*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_scan(void);
121*49cdfc7eSAndroid Build Coastguard Worker /* Print the config detected by tst_cg_scan and print the internal
122*49cdfc7eSAndroid Build Coastguard Worker  * state associated with each controller. Output can be passed to
123*49cdfc7eSAndroid Build Coastguard Worker  * tst_cg_load_config to configure the internal state to that of the
124*49cdfc7eSAndroid Build Coastguard Worker  * config between program invocations.
125*49cdfc7eSAndroid Build Coastguard Worker  */
126*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_print_config(void);
127*49cdfc7eSAndroid Build Coastguard Worker 
128*49cdfc7eSAndroid Build Coastguard Worker /* Load the config printed out by tst_cg_print_config and configure the internal
129*49cdfc7eSAndroid Build Coastguard Worker  * libary state to match the config. Used to allow tst_cg_cleanup to properly
130*49cdfc7eSAndroid Build Coastguard Worker  * cleanup mounts and directories created by tst_cg_require between program
131*49cdfc7eSAndroid Build Coastguard Worker  * invocations.
132*49cdfc7eSAndroid Build Coastguard Worker  */
133*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_load_config(const char *const config);
134*49cdfc7eSAndroid Build Coastguard Worker 
135*49cdfc7eSAndroid Build Coastguard Worker /* Ensure the specified controller is available in the test's default
136*49cdfc7eSAndroid Build Coastguard Worker  * CGroup, mounting/enabling it if necessary. Usually this is not
137*49cdfc7eSAndroid Build Coastguard Worker  * necessary use tst_test.needs_cgroup_ctrls instead.
138*49cdfc7eSAndroid Build Coastguard Worker  */
139*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_require(const char *const ctrl_name,
140*49cdfc7eSAndroid Build Coastguard Worker 			const struct tst_cg_opts *const options)
141*49cdfc7eSAndroid Build Coastguard Worker 			__attribute__ ((nonnull));
142*49cdfc7eSAndroid Build Coastguard Worker 
143*49cdfc7eSAndroid Build Coastguard Worker /* Tear down any CGroups created by calls to tst_cg_require */
144*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_cleanup(void);
145*49cdfc7eSAndroid Build Coastguard Worker 
146*49cdfc7eSAndroid Build Coastguard Worker /* Call this in setup after you call tst_cg_require and want to
147*49cdfc7eSAndroid Build Coastguard Worker  * initialize tst_cg and tst_cg_drain. See tst_cg_require.
148*49cdfc7eSAndroid Build Coastguard Worker  */
149*49cdfc7eSAndroid Build Coastguard Worker void tst_cg_init(void);
150*49cdfc7eSAndroid Build Coastguard Worker 
151*49cdfc7eSAndroid Build Coastguard Worker /* Create a descendant CGroup */
152*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group *
153*49cdfc7eSAndroid Build Coastguard Worker tst_cg_group_mk(const struct tst_cg_group *const parent,
154*49cdfc7eSAndroid Build Coastguard Worker 		    const char *const group_name_fmt, ...)
155*49cdfc7eSAndroid Build Coastguard Worker 	    __attribute__ ((nonnull, warn_unused_result, format (printf, 2, 3)));
156*49cdfc7eSAndroid Build Coastguard Worker 
157*49cdfc7eSAndroid Build Coastguard Worker const char *
158*49cdfc7eSAndroid Build Coastguard Worker tst_cg_group_name(const struct tst_cg_group *const cg)
159*49cdfc7eSAndroid Build Coastguard Worker 		      __attribute__ ((nonnull, warn_unused_result));
160*49cdfc7eSAndroid Build Coastguard Worker 
161*49cdfc7eSAndroid Build Coastguard Worker /* This call returns a fd pointing to a v2 directory */
162*49cdfc7eSAndroid Build Coastguard Worker int tst_cg_group_unified_dir_fd(const struct tst_cg_group *const cg)
163*49cdfc7eSAndroid Build Coastguard Worker 		      __attribute__ ((nonnull, warn_unused_result));
164*49cdfc7eSAndroid Build Coastguard Worker 
165*49cdfc7eSAndroid Build Coastguard Worker /* Remove a descendant CGroup */
166*49cdfc7eSAndroid Build Coastguard Worker struct tst_cg_group *
167*49cdfc7eSAndroid Build Coastguard Worker tst_cg_group_rm(struct tst_cg_group *const cg)
168*49cdfc7eSAndroid Build Coastguard Worker 		    __attribute__ ((nonnull, warn_unused_result));
169*49cdfc7eSAndroid Build Coastguard Worker 
170*49cdfc7eSAndroid Build Coastguard Worker #define TST_CG_VER(cg, ctrl_name) \
171*49cdfc7eSAndroid Build Coastguard Worker 	tst_cg_ver(__FILE__, __LINE__, (cg), (ctrl_name))
172*49cdfc7eSAndroid Build Coastguard Worker 
173*49cdfc7eSAndroid Build Coastguard Worker enum tst_cg_ver tst_cg_ver(const char *const file, const int lineno,
174*49cdfc7eSAndroid Build Coastguard Worker 				   const struct tst_cg_group *const cg,
175*49cdfc7eSAndroid Build Coastguard Worker 				   const char *const ctrl_name)
176*49cdfc7eSAndroid Build Coastguard Worker 				   __attribute__ ((nonnull, warn_unused_result));
177*49cdfc7eSAndroid Build Coastguard Worker 
178*49cdfc7eSAndroid Build Coastguard Worker #define TST_CG_VER_IS_V1(cg, ctrl_name) \
179*49cdfc7eSAndroid Build Coastguard Worker 	(TST_CG_VER((cg), (ctrl_name)) == TST_CG_V1)
180*49cdfc7eSAndroid Build Coastguard Worker 
181*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_HAS(cg, file_name) \
182*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_has(__FILE__, __LINE__, (cg), (file_name))
183*49cdfc7eSAndroid Build Coastguard Worker 
184*49cdfc7eSAndroid Build Coastguard Worker int safe_cg_has(const char *const file, const int lineno,
185*49cdfc7eSAndroid Build Coastguard Worker 		    const struct tst_cg_group *const cg,
186*49cdfc7eSAndroid Build Coastguard Worker 		    const char *const file_name)
187*49cdfc7eSAndroid Build Coastguard Worker 		    __attribute__ ((nonnull, warn_unused_result));
188*49cdfc7eSAndroid Build Coastguard Worker 
189*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_READ(cg, file_name, out, len)			\
190*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_read(__FILE__, __LINE__,				\
191*49cdfc7eSAndroid Build Coastguard Worker 			 (cg), (file_name), (out), (len))
192*49cdfc7eSAndroid Build Coastguard Worker 
193*49cdfc7eSAndroid Build Coastguard Worker ssize_t safe_cg_read(const char *const file, const int lineno,
194*49cdfc7eSAndroid Build Coastguard Worker 			 const struct tst_cg_group *const cg,
195*49cdfc7eSAndroid Build Coastguard Worker 			 const char *const file_name,
196*49cdfc7eSAndroid Build Coastguard Worker 			 char *const out, const size_t len)
197*49cdfc7eSAndroid Build Coastguard Worker 			 __attribute__ ((nonnull));
198*49cdfc7eSAndroid Build Coastguard Worker 
199*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_PRINTF(cg, file_name, fmt, ...)			\
200*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_printf(__FILE__, __LINE__,				\
201*49cdfc7eSAndroid Build Coastguard Worker 			   (cg), (file_name), (fmt), __VA_ARGS__)
202*49cdfc7eSAndroid Build Coastguard Worker 
203*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_PRINT(cg, file_name, str)				\
204*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_printf(__FILE__, __LINE__, (cg), (file_name), "%s", (str))
205*49cdfc7eSAndroid Build Coastguard Worker 
206*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_printf(const char *const file, const int lineno,
207*49cdfc7eSAndroid Build Coastguard Worker 			const struct tst_cg_group *const cg,
208*49cdfc7eSAndroid Build Coastguard Worker 			const char *const file_name,
209*49cdfc7eSAndroid Build Coastguard Worker 			const char *const fmt, ...)
210*49cdfc7eSAndroid Build Coastguard Worker 			__attribute__ ((format (printf, 5, 6), nonnull));
211*49cdfc7eSAndroid Build Coastguard Worker 
212*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_OPEN(cg, file_name, flags, fds)			\
213*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_open(__FILE__, __LINE__, (cg), (file_name), (flags), (fds))
214*49cdfc7eSAndroid Build Coastguard Worker 
215*49cdfc7eSAndroid Build Coastguard Worker int safe_cg_open(const char *const file, const int lineno,
216*49cdfc7eSAndroid Build Coastguard Worker 			const struct tst_cg_group *const cg,
217*49cdfc7eSAndroid Build Coastguard Worker 			const char *const file_name,
218*49cdfc7eSAndroid Build Coastguard Worker 			int flags, int *fds)
219*49cdfc7eSAndroid Build Coastguard Worker 			__attribute__ ((nonnull));
220*49cdfc7eSAndroid Build Coastguard Worker 
221*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_FCHOWN(cg, file_name, owner, group)		\
222*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_fchown(__FILE__, __LINE__, (cg), (file_name), (owner), (group))
223*49cdfc7eSAndroid Build Coastguard Worker 
224*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_fchown(const char *const file, const int lineno,
225*49cdfc7eSAndroid Build Coastguard Worker 			const struct tst_cg_group *const cg,
226*49cdfc7eSAndroid Build Coastguard Worker 			const char *const file_name,
227*49cdfc7eSAndroid Build Coastguard Worker 			uid_t owner, gid_t group)
228*49cdfc7eSAndroid Build Coastguard Worker 			__attribute__ ((nonnull));
229*49cdfc7eSAndroid Build Coastguard Worker 
230*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_SCANF(cg, file_name, fmt, ...)			\
231*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_scanf(__FILE__, __LINE__,				\
232*49cdfc7eSAndroid Build Coastguard Worker 			  (cg), (file_name), (fmt), __VA_ARGS__)
233*49cdfc7eSAndroid Build Coastguard Worker 
234*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_scanf(const char *file, const int lineno,
235*49cdfc7eSAndroid Build Coastguard Worker 		       const struct tst_cg_group *const cg,
236*49cdfc7eSAndroid Build Coastguard Worker 		       const char *const file_name,
237*49cdfc7eSAndroid Build Coastguard Worker 		       const char *const fmt, ...)
238*49cdfc7eSAndroid Build Coastguard Worker 		       __attribute__ ((format (scanf, 5, 6), nonnull));
239*49cdfc7eSAndroid Build Coastguard Worker 
240*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_LINES_SCANF(cg, file_name, fmt, ...)		\
241*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_lines_scanf(__FILE__, __LINE__,			\
242*49cdfc7eSAndroid Build Coastguard Worker 				(cg), (file_name), (fmt), __VA_ARGS__)
243*49cdfc7eSAndroid Build Coastguard Worker 
244*49cdfc7eSAndroid Build Coastguard Worker void safe_cg_lines_scanf(const char *const file, const int lineno,
245*49cdfc7eSAndroid Build Coastguard Worker 			     const struct tst_cg_group *const cg,
246*49cdfc7eSAndroid Build Coastguard Worker 			     const char *const file_name,
247*49cdfc7eSAndroid Build Coastguard Worker 			     const char *const fmt, ...)
248*49cdfc7eSAndroid Build Coastguard Worker 			__attribute__ ((format (scanf, 5, 6), nonnull));
249*49cdfc7eSAndroid Build Coastguard Worker 
250*49cdfc7eSAndroid Build Coastguard Worker #define SAFE_CG_OCCURSIN(cg, file_name, needle)		\
251*49cdfc7eSAndroid Build Coastguard Worker 	safe_cg_occursin(__FILE__, __LINE__,		\
252*49cdfc7eSAndroid Build Coastguard Worker 			     (cg), (file_name), (needle))
253*49cdfc7eSAndroid Build Coastguard Worker 
254*49cdfc7eSAndroid Build Coastguard Worker int safe_cg_occursin(const char *file, const int lineno,
255*49cdfc7eSAndroid Build Coastguard Worker 			 const struct tst_cg_group *const cg,
256*49cdfc7eSAndroid Build Coastguard Worker 			 const char *const file_name,
257*49cdfc7eSAndroid Build Coastguard Worker 			 const char *const needle);
258*49cdfc7eSAndroid Build Coastguard Worker 
259*49cdfc7eSAndroid Build Coastguard Worker #endif /* TST_CGROUP_H */
260