xref: /linux/tools/testing/selftests/resctrl/resctrlfs.c (revision 591a6e8588fc1dbdc04355e8ad7b0be43d221c9c)
1*591a6e85SSai Praneeth Prakhya // SPDX-License-Identifier: GPL-2.0
2*591a6e85SSai Praneeth Prakhya /*
3*591a6e85SSai Praneeth Prakhya  * Basic resctrl file system operations
4*591a6e85SSai Praneeth Prakhya  *
5*591a6e85SSai Praneeth Prakhya  * Copyright (C) 2018 Intel Corporation
6*591a6e85SSai Praneeth Prakhya  *
7*591a6e85SSai Praneeth Prakhya  * Authors:
8*591a6e85SSai Praneeth Prakhya  *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9*591a6e85SSai Praneeth Prakhya  *    Fenghua Yu <fenghua.yu@intel.com>
10*591a6e85SSai Praneeth Prakhya  */
11*591a6e85SSai Praneeth Prakhya #include "resctrl.h"
12*591a6e85SSai Praneeth Prakhya 
13*591a6e85SSai Praneeth Prakhya int tests_run;
14*591a6e85SSai Praneeth Prakhya 
15*591a6e85SSai Praneeth Prakhya static int find_resctrl_mount(char *buffer)
16*591a6e85SSai Praneeth Prakhya {
17*591a6e85SSai Praneeth Prakhya 	FILE *mounts;
18*591a6e85SSai Praneeth Prakhya 	char line[256], *fs, *mntpoint;
19*591a6e85SSai Praneeth Prakhya 
20*591a6e85SSai Praneeth Prakhya 	mounts = fopen("/proc/mounts", "r");
21*591a6e85SSai Praneeth Prakhya 	if (!mounts) {
22*591a6e85SSai Praneeth Prakhya 		perror("/proc/mounts");
23*591a6e85SSai Praneeth Prakhya 		return -ENXIO;
24*591a6e85SSai Praneeth Prakhya 	}
25*591a6e85SSai Praneeth Prakhya 	while (!feof(mounts)) {
26*591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, mounts))
27*591a6e85SSai Praneeth Prakhya 			break;
28*591a6e85SSai Praneeth Prakhya 		fs = strtok(line, " \t");
29*591a6e85SSai Praneeth Prakhya 		if (!fs)
30*591a6e85SSai Praneeth Prakhya 			continue;
31*591a6e85SSai Praneeth Prakhya 		mntpoint = strtok(NULL, " \t");
32*591a6e85SSai Praneeth Prakhya 		if (!mntpoint)
33*591a6e85SSai Praneeth Prakhya 			continue;
34*591a6e85SSai Praneeth Prakhya 		fs = strtok(NULL, " \t");
35*591a6e85SSai Praneeth Prakhya 		if (!fs)
36*591a6e85SSai Praneeth Prakhya 			continue;
37*591a6e85SSai Praneeth Prakhya 		if (strcmp(fs, "resctrl"))
38*591a6e85SSai Praneeth Prakhya 			continue;
39*591a6e85SSai Praneeth Prakhya 
40*591a6e85SSai Praneeth Prakhya 		fclose(mounts);
41*591a6e85SSai Praneeth Prakhya 		if (buffer)
42*591a6e85SSai Praneeth Prakhya 			strncpy(buffer, mntpoint, 256);
43*591a6e85SSai Praneeth Prakhya 
44*591a6e85SSai Praneeth Prakhya 		return 0;
45*591a6e85SSai Praneeth Prakhya 	}
46*591a6e85SSai Praneeth Prakhya 
47*591a6e85SSai Praneeth Prakhya 	fclose(mounts);
48*591a6e85SSai Praneeth Prakhya 
49*591a6e85SSai Praneeth Prakhya 	return -ENOENT;
50*591a6e85SSai Praneeth Prakhya }
51*591a6e85SSai Praneeth Prakhya 
52*591a6e85SSai Praneeth Prakhya /*
53*591a6e85SSai Praneeth Prakhya  * remount_resctrlfs - Remount resctrl FS at /sys/fs/resctrl
54*591a6e85SSai Praneeth Prakhya  * @mum_resctrlfs:	Should the resctrl FS be remounted?
55*591a6e85SSai Praneeth Prakhya  *
56*591a6e85SSai Praneeth Prakhya  * If not mounted, mount it.
57*591a6e85SSai Praneeth Prakhya  * If mounted and mum_resctrlfs then remount resctrl FS.
58*591a6e85SSai Praneeth Prakhya  * If mounted and !mum_resctrlfs then noop
59*591a6e85SSai Praneeth Prakhya  *
60*591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
61*591a6e85SSai Praneeth Prakhya  */
62*591a6e85SSai Praneeth Prakhya int remount_resctrlfs(bool mum_resctrlfs)
63*591a6e85SSai Praneeth Prakhya {
64*591a6e85SSai Praneeth Prakhya 	char mountpoint[256];
65*591a6e85SSai Praneeth Prakhya 	int ret;
66*591a6e85SSai Praneeth Prakhya 
67*591a6e85SSai Praneeth Prakhya 	ret = find_resctrl_mount(mountpoint);
68*591a6e85SSai Praneeth Prakhya 	if (ret)
69*591a6e85SSai Praneeth Prakhya 		strcpy(mountpoint, RESCTRL_PATH);
70*591a6e85SSai Praneeth Prakhya 
71*591a6e85SSai Praneeth Prakhya 	if (!ret && mum_resctrlfs && umount(mountpoint)) {
72*591a6e85SSai Praneeth Prakhya 		printf("not ok unmounting \"%s\"\n", mountpoint);
73*591a6e85SSai Praneeth Prakhya 		perror("# umount");
74*591a6e85SSai Praneeth Prakhya 		tests_run++;
75*591a6e85SSai Praneeth Prakhya 	}
76*591a6e85SSai Praneeth Prakhya 
77*591a6e85SSai Praneeth Prakhya 	if (!ret && !mum_resctrlfs)
78*591a6e85SSai Praneeth Prakhya 		return 0;
79*591a6e85SSai Praneeth Prakhya 
80*591a6e85SSai Praneeth Prakhya 	ret = mount("resctrl", RESCTRL_PATH, "resctrl", 0, NULL);
81*591a6e85SSai Praneeth Prakhya 	printf("%sok mounting resctrl to \"%s\"\n", ret ? "not " : "",
82*591a6e85SSai Praneeth Prakhya 	       RESCTRL_PATH);
83*591a6e85SSai Praneeth Prakhya 	if (ret)
84*591a6e85SSai Praneeth Prakhya 		perror("# mount");
85*591a6e85SSai Praneeth Prakhya 
86*591a6e85SSai Praneeth Prakhya 	tests_run++;
87*591a6e85SSai Praneeth Prakhya 
88*591a6e85SSai Praneeth Prakhya 	return ret;
89*591a6e85SSai Praneeth Prakhya }
90*591a6e85SSai Praneeth Prakhya 
91*591a6e85SSai Praneeth Prakhya int umount_resctrlfs(void)
92*591a6e85SSai Praneeth Prakhya {
93*591a6e85SSai Praneeth Prakhya 	if (umount(RESCTRL_PATH)) {
94*591a6e85SSai Praneeth Prakhya 		perror("# Unable to umount resctrl");
95*591a6e85SSai Praneeth Prakhya 
96*591a6e85SSai Praneeth Prakhya 		return errno;
97*591a6e85SSai Praneeth Prakhya 	}
98*591a6e85SSai Praneeth Prakhya 
99*591a6e85SSai Praneeth Prakhya 	return 0;
100*591a6e85SSai Praneeth Prakhya }
101*591a6e85SSai Praneeth Prakhya 
102*591a6e85SSai Praneeth Prakhya /*
103*591a6e85SSai Praneeth Prakhya  * get_resource_id - Get socket number/l3 id for a specified CPU
104*591a6e85SSai Praneeth Prakhya  * @cpu_no:	CPU number
105*591a6e85SSai Praneeth Prakhya  * @resource_id: Socket number or l3_id
106*591a6e85SSai Praneeth Prakhya  *
107*591a6e85SSai Praneeth Prakhya  * Return: >= 0 on success, < 0 on failure.
108*591a6e85SSai Praneeth Prakhya  */
109*591a6e85SSai Praneeth Prakhya int get_resource_id(int cpu_no, int *resource_id)
110*591a6e85SSai Praneeth Prakhya {
111*591a6e85SSai Praneeth Prakhya 	char phys_pkg_path[1024];
112*591a6e85SSai Praneeth Prakhya 	FILE *fp;
113*591a6e85SSai Praneeth Prakhya 
114*591a6e85SSai Praneeth Prakhya 	sprintf(phys_pkg_path, "%s%d/topology/physical_package_id",
115*591a6e85SSai Praneeth Prakhya 		PHYS_ID_PATH, cpu_no);
116*591a6e85SSai Praneeth Prakhya 	fp = fopen(phys_pkg_path, "r");
117*591a6e85SSai Praneeth Prakhya 	if (!fp) {
118*591a6e85SSai Praneeth Prakhya 		perror("Failed to open physical_package_id");
119*591a6e85SSai Praneeth Prakhya 
120*591a6e85SSai Praneeth Prakhya 		return -1;
121*591a6e85SSai Praneeth Prakhya 	}
122*591a6e85SSai Praneeth Prakhya 	if (fscanf(fp, "%d", resource_id) <= 0) {
123*591a6e85SSai Praneeth Prakhya 		perror("Could not get socket number or l3 id");
124*591a6e85SSai Praneeth Prakhya 		fclose(fp);
125*591a6e85SSai Praneeth Prakhya 
126*591a6e85SSai Praneeth Prakhya 		return -1;
127*591a6e85SSai Praneeth Prakhya 	}
128*591a6e85SSai Praneeth Prakhya 	fclose(fp);
129*591a6e85SSai Praneeth Prakhya 
130*591a6e85SSai Praneeth Prakhya 	return 0;
131*591a6e85SSai Praneeth Prakhya }
132*591a6e85SSai Praneeth Prakhya 
133*591a6e85SSai Praneeth Prakhya /*
134*591a6e85SSai Praneeth Prakhya  * taskset_benchmark - Taskset PID (i.e. benchmark) to a specified cpu
135*591a6e85SSai Praneeth Prakhya  * @bm_pid:	PID that should be binded
136*591a6e85SSai Praneeth Prakhya  * @cpu_no:	CPU number at which the PID would be binded
137*591a6e85SSai Praneeth Prakhya  *
138*591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
139*591a6e85SSai Praneeth Prakhya  */
140*591a6e85SSai Praneeth Prakhya int taskset_benchmark(pid_t bm_pid, int cpu_no)
141*591a6e85SSai Praneeth Prakhya {
142*591a6e85SSai Praneeth Prakhya 	cpu_set_t my_set;
143*591a6e85SSai Praneeth Prakhya 
144*591a6e85SSai Praneeth Prakhya 	CPU_ZERO(&my_set);
145*591a6e85SSai Praneeth Prakhya 	CPU_SET(cpu_no, &my_set);
146*591a6e85SSai Praneeth Prakhya 
147*591a6e85SSai Praneeth Prakhya 	if (sched_setaffinity(bm_pid, sizeof(cpu_set_t), &my_set)) {
148*591a6e85SSai Praneeth Prakhya 		perror("Unable to taskset benchmark");
149*591a6e85SSai Praneeth Prakhya 
150*591a6e85SSai Praneeth Prakhya 		return -1;
151*591a6e85SSai Praneeth Prakhya 	}
152*591a6e85SSai Praneeth Prakhya 
153*591a6e85SSai Praneeth Prakhya 	return 0;
154*591a6e85SSai Praneeth Prakhya }
155*591a6e85SSai Praneeth Prakhya 
156*591a6e85SSai Praneeth Prakhya /*
157*591a6e85SSai Praneeth Prakhya  * run_benchmark - Run a specified benchmark or fill_buf (default benchmark)
158*591a6e85SSai Praneeth Prakhya  *		   in specified signal. Direct benchmark stdio to /dev/null.
159*591a6e85SSai Praneeth Prakhya  * @signum:	signal number
160*591a6e85SSai Praneeth Prakhya  * @info:	signal info
161*591a6e85SSai Praneeth Prakhya  * @ucontext:	user context in signal handling
162*591a6e85SSai Praneeth Prakhya  *
163*591a6e85SSai Praneeth Prakhya  * Return: void
164*591a6e85SSai Praneeth Prakhya  */
165*591a6e85SSai Praneeth Prakhya void run_benchmark(int signum, siginfo_t *info, void *ucontext)
166*591a6e85SSai Praneeth Prakhya {
167*591a6e85SSai Praneeth Prakhya 	unsigned long span;
168*591a6e85SSai Praneeth Prakhya 	int operation, ret;
169*591a6e85SSai Praneeth Prakhya 	char **benchmark_cmd;
170*591a6e85SSai Praneeth Prakhya 	FILE *fp;
171*591a6e85SSai Praneeth Prakhya 
172*591a6e85SSai Praneeth Prakhya 	benchmark_cmd = info->si_ptr;
173*591a6e85SSai Praneeth Prakhya 
174*591a6e85SSai Praneeth Prakhya 	/*
175*591a6e85SSai Praneeth Prakhya 	 * Direct stdio of child to /dev/null, so that only parent writes to
176*591a6e85SSai Praneeth Prakhya 	 * stdio (console)
177*591a6e85SSai Praneeth Prakhya 	 */
178*591a6e85SSai Praneeth Prakhya 	fp = freopen("/dev/null", "w", stdout);
179*591a6e85SSai Praneeth Prakhya 	if (!fp)
180*591a6e85SSai Praneeth Prakhya 		PARENT_EXIT("Unable to direct benchmark status to /dev/null");
181*591a6e85SSai Praneeth Prakhya 
182*591a6e85SSai Praneeth Prakhya 	if (strcmp(benchmark_cmd[0], "fill_buf") == 0) {
183*591a6e85SSai Praneeth Prakhya 		/* Execute default fill_buf benchmark */
184*591a6e85SSai Praneeth Prakhya 		span = strtoul(benchmark_cmd[1], NULL, 10);
185*591a6e85SSai Praneeth Prakhya 		operation = atoi(benchmark_cmd[4]);
186*591a6e85SSai Praneeth Prakhya 		if (run_fill_buf(span, 1, 1, operation, NULL))
187*591a6e85SSai Praneeth Prakhya 			fprintf(stderr, "Error in running fill buffer\n");
188*591a6e85SSai Praneeth Prakhya 	} else {
189*591a6e85SSai Praneeth Prakhya 		/* Execute specified benchmark */
190*591a6e85SSai Praneeth Prakhya 		ret = execvp(benchmark_cmd[0], benchmark_cmd);
191*591a6e85SSai Praneeth Prakhya 		if (ret)
192*591a6e85SSai Praneeth Prakhya 			perror("wrong\n");
193*591a6e85SSai Praneeth Prakhya 	}
194*591a6e85SSai Praneeth Prakhya 
195*591a6e85SSai Praneeth Prakhya 	fclose(stdout);
196*591a6e85SSai Praneeth Prakhya 	PARENT_EXIT("Unable to run specified benchmark");
197*591a6e85SSai Praneeth Prakhya }
198*591a6e85SSai Praneeth Prakhya 
199*591a6e85SSai Praneeth Prakhya /*
200*591a6e85SSai Praneeth Prakhya  * create_grp - Create a group only if one doesn't exist
201*591a6e85SSai Praneeth Prakhya  * @grp_name:	Name of the group
202*591a6e85SSai Praneeth Prakhya  * @grp:	Full path and name of the group
203*591a6e85SSai Praneeth Prakhya  * @parent_grp:	Full path and name of the parent group
204*591a6e85SSai Praneeth Prakhya  *
205*591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
206*591a6e85SSai Praneeth Prakhya  */
207*591a6e85SSai Praneeth Prakhya static int create_grp(const char *grp_name, char *grp, const char *parent_grp)
208*591a6e85SSai Praneeth Prakhya {
209*591a6e85SSai Praneeth Prakhya 	int found_grp = 0;
210*591a6e85SSai Praneeth Prakhya 	struct dirent *ep;
211*591a6e85SSai Praneeth Prakhya 	DIR *dp;
212*591a6e85SSai Praneeth Prakhya 
213*591a6e85SSai Praneeth Prakhya 	/* Check if requested grp exists or not */
214*591a6e85SSai Praneeth Prakhya 	dp = opendir(parent_grp);
215*591a6e85SSai Praneeth Prakhya 	if (dp) {
216*591a6e85SSai Praneeth Prakhya 		while ((ep = readdir(dp)) != NULL) {
217*591a6e85SSai Praneeth Prakhya 			if (strcmp(ep->d_name, grp_name) == 0)
218*591a6e85SSai Praneeth Prakhya 				found_grp = 1;
219*591a6e85SSai Praneeth Prakhya 		}
220*591a6e85SSai Praneeth Prakhya 		closedir(dp);
221*591a6e85SSai Praneeth Prakhya 	} else {
222*591a6e85SSai Praneeth Prakhya 		perror("Unable to open resctrl for group");
223*591a6e85SSai Praneeth Prakhya 
224*591a6e85SSai Praneeth Prakhya 		return -1;
225*591a6e85SSai Praneeth Prakhya 	}
226*591a6e85SSai Praneeth Prakhya 
227*591a6e85SSai Praneeth Prakhya 	/* Requested grp doesn't exist, hence create it */
228*591a6e85SSai Praneeth Prakhya 	if (found_grp == 0) {
229*591a6e85SSai Praneeth Prakhya 		if (mkdir(grp, 0) == -1) {
230*591a6e85SSai Praneeth Prakhya 			perror("Unable to create group");
231*591a6e85SSai Praneeth Prakhya 
232*591a6e85SSai Praneeth Prakhya 			return -1;
233*591a6e85SSai Praneeth Prakhya 		}
234*591a6e85SSai Praneeth Prakhya 	}
235*591a6e85SSai Praneeth Prakhya 
236*591a6e85SSai Praneeth Prakhya 	return 0;
237*591a6e85SSai Praneeth Prakhya }
238*591a6e85SSai Praneeth Prakhya 
239*591a6e85SSai Praneeth Prakhya static int write_pid_to_tasks(char *tasks, pid_t pid)
240*591a6e85SSai Praneeth Prakhya {
241*591a6e85SSai Praneeth Prakhya 	FILE *fp;
242*591a6e85SSai Praneeth Prakhya 
243*591a6e85SSai Praneeth Prakhya 	fp = fopen(tasks, "w");
244*591a6e85SSai Praneeth Prakhya 	if (!fp) {
245*591a6e85SSai Praneeth Prakhya 		perror("Failed to open tasks file");
246*591a6e85SSai Praneeth Prakhya 
247*591a6e85SSai Praneeth Prakhya 		return -1;
248*591a6e85SSai Praneeth Prakhya 	}
249*591a6e85SSai Praneeth Prakhya 	if (fprintf(fp, "%d\n", pid) < 0) {
250*591a6e85SSai Praneeth Prakhya 		perror("Failed to wr pid to tasks file");
251*591a6e85SSai Praneeth Prakhya 		fclose(fp);
252*591a6e85SSai Praneeth Prakhya 
253*591a6e85SSai Praneeth Prakhya 		return -1;
254*591a6e85SSai Praneeth Prakhya 	}
255*591a6e85SSai Praneeth Prakhya 	fclose(fp);
256*591a6e85SSai Praneeth Prakhya 
257*591a6e85SSai Praneeth Prakhya 	return 0;
258*591a6e85SSai Praneeth Prakhya }
259*591a6e85SSai Praneeth Prakhya 
260*591a6e85SSai Praneeth Prakhya /*
261*591a6e85SSai Praneeth Prakhya  * write_bm_pid_to_resctrl - Write a PID (i.e. benchmark) to resctrl FS
262*591a6e85SSai Praneeth Prakhya  * @bm_pid:		PID that should be written
263*591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the control monitor group (con_mon grp)
264*591a6e85SSai Praneeth Prakhya  * @mongrp:		Name of the monitor group (mon grp)
265*591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
266*591a6e85SSai Praneeth Prakhya  *
267*591a6e85SSai Praneeth Prakhya  * If a con_mon grp is requested, create it and write pid to it, otherwise
268*591a6e85SSai Praneeth Prakhya  * write pid to root con_mon grp.
269*591a6e85SSai Praneeth Prakhya  * If a mon grp is requested, create it and write pid to it, otherwise
270*591a6e85SSai Praneeth Prakhya  * pid is not written, this means that pid is in con_mon grp and hence
271*591a6e85SSai Praneeth Prakhya  * should consult con_mon grp's mon_data directory for results.
272*591a6e85SSai Praneeth Prakhya  *
273*591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
274*591a6e85SSai Praneeth Prakhya  */
275*591a6e85SSai Praneeth Prakhya int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
276*591a6e85SSai Praneeth Prakhya 			    char *resctrl_val)
277*591a6e85SSai Praneeth Prakhya {
278*591a6e85SSai Praneeth Prakhya 	char controlgroup[128], monitorgroup[512], monitorgroup_p[256];
279*591a6e85SSai Praneeth Prakhya 	char tasks[1024];
280*591a6e85SSai Praneeth Prakhya 	int ret = 0;
281*591a6e85SSai Praneeth Prakhya 
282*591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp))
283*591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp);
284*591a6e85SSai Praneeth Prakhya 	else
285*591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s", RESCTRL_PATH);
286*591a6e85SSai Praneeth Prakhya 
287*591a6e85SSai Praneeth Prakhya 	/* Create control and monitoring group and write pid into it */
288*591a6e85SSai Praneeth Prakhya 	ret = create_grp(ctrlgrp, controlgroup, RESCTRL_PATH);
289*591a6e85SSai Praneeth Prakhya 	if (ret)
290*591a6e85SSai Praneeth Prakhya 		goto out;
291*591a6e85SSai Praneeth Prakhya 	sprintf(tasks, "%s/tasks", controlgroup);
292*591a6e85SSai Praneeth Prakhya 	ret = write_pid_to_tasks(tasks, bm_pid);
293*591a6e85SSai Praneeth Prakhya 	if (ret)
294*591a6e85SSai Praneeth Prakhya 		goto out;
295*591a6e85SSai Praneeth Prakhya 
296*591a6e85SSai Praneeth Prakhya 	/* Create mon grp and write pid into it for "mbm" test */
297*591a6e85SSai Praneeth Prakhya 	if ((strcmp(resctrl_val, "mbm") == 0)) {
298*591a6e85SSai Praneeth Prakhya 		if (mongrp) {
299*591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup_p, "%s/mon_groups", controlgroup);
300*591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp);
301*591a6e85SSai Praneeth Prakhya 			ret = create_grp(mongrp, monitorgroup, monitorgroup_p);
302*591a6e85SSai Praneeth Prakhya 			if (ret)
303*591a6e85SSai Praneeth Prakhya 				goto out;
304*591a6e85SSai Praneeth Prakhya 
305*591a6e85SSai Praneeth Prakhya 			sprintf(tasks, "%s/mon_groups/%s/tasks",
306*591a6e85SSai Praneeth Prakhya 				controlgroup, mongrp);
307*591a6e85SSai Praneeth Prakhya 			ret = write_pid_to_tasks(tasks, bm_pid);
308*591a6e85SSai Praneeth Prakhya 			if (ret)
309*591a6e85SSai Praneeth Prakhya 				goto out;
310*591a6e85SSai Praneeth Prakhya 		}
311*591a6e85SSai Praneeth Prakhya 	}
312*591a6e85SSai Praneeth Prakhya 
313*591a6e85SSai Praneeth Prakhya out:
314*591a6e85SSai Praneeth Prakhya 	printf("%sok writing benchmark parameters to resctrl FS\n",
315*591a6e85SSai Praneeth Prakhya 	       ret ? "not " : "");
316*591a6e85SSai Praneeth Prakhya 	if (ret)
317*591a6e85SSai Praneeth Prakhya 		perror("# writing to resctrlfs");
318*591a6e85SSai Praneeth Prakhya 
319*591a6e85SSai Praneeth Prakhya 	tests_run++;
320*591a6e85SSai Praneeth Prakhya 
321*591a6e85SSai Praneeth Prakhya 	return ret;
322*591a6e85SSai Praneeth Prakhya }
323*591a6e85SSai Praneeth Prakhya 
324*591a6e85SSai Praneeth Prakhya /*
325*591a6e85SSai Praneeth Prakhya  * write_schemata - Update schemata of a con_mon grp
326*591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the con_mon grp
327*591a6e85SSai Praneeth Prakhya  * @schemata:		Schemata that should be updated to
328*591a6e85SSai Praneeth Prakhya  * @cpu_no:		CPU number that the benchmark PID is binded to
329*591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
330*591a6e85SSai Praneeth Prakhya  *
331*591a6e85SSai Praneeth Prakhya  * Update schemata of a con_mon grp *only* if requested resctrl feature is
332*591a6e85SSai Praneeth Prakhya  * allocation type
333*591a6e85SSai Praneeth Prakhya  *
334*591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
335*591a6e85SSai Praneeth Prakhya  */
336*591a6e85SSai Praneeth Prakhya int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
337*591a6e85SSai Praneeth Prakhya {
338*591a6e85SSai Praneeth Prakhya 	char controlgroup[1024], schema[1024], reason[64];
339*591a6e85SSai Praneeth Prakhya 	int resource_id, ret = 0;
340*591a6e85SSai Praneeth Prakhya 	FILE *fp;
341*591a6e85SSai Praneeth Prakhya 
342*591a6e85SSai Praneeth Prakhya 	if (strcmp(resctrl_val, "mba") != 0)
343*591a6e85SSai Praneeth Prakhya 		return -ENOENT;
344*591a6e85SSai Praneeth Prakhya 
345*591a6e85SSai Praneeth Prakhya 	if (!schemata) {
346*591a6e85SSai Praneeth Prakhya 		printf("# Skipping empty schemata update\n");
347*591a6e85SSai Praneeth Prakhya 
348*591a6e85SSai Praneeth Prakhya 		return -1;
349*591a6e85SSai Praneeth Prakhya 	}
350*591a6e85SSai Praneeth Prakhya 
351*591a6e85SSai Praneeth Prakhya 	if (get_resource_id(cpu_no, &resource_id) < 0) {
352*591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to get resource id");
353*591a6e85SSai Praneeth Prakhya 		ret = -1;
354*591a6e85SSai Praneeth Prakhya 
355*591a6e85SSai Praneeth Prakhya 		goto out;
356*591a6e85SSai Praneeth Prakhya 	}
357*591a6e85SSai Praneeth Prakhya 
358*591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp) != 0)
359*591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp);
360*591a6e85SSai Praneeth Prakhya 	else
361*591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/schemata", RESCTRL_PATH);
362*591a6e85SSai Praneeth Prakhya 
363*591a6e85SSai Praneeth Prakhya 	sprintf(schema, "%s%d%c%s", "MB:", resource_id, '=', schemata);
364*591a6e85SSai Praneeth Prakhya 
365*591a6e85SSai Praneeth Prakhya 	fp = fopen(controlgroup, "w");
366*591a6e85SSai Praneeth Prakhya 	if (!fp) {
367*591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to open control group");
368*591a6e85SSai Praneeth Prakhya 		ret = -1;
369*591a6e85SSai Praneeth Prakhya 
370*591a6e85SSai Praneeth Prakhya 		goto out;
371*591a6e85SSai Praneeth Prakhya 	}
372*591a6e85SSai Praneeth Prakhya 
373*591a6e85SSai Praneeth Prakhya 	if (fprintf(fp, "%s\n", schema) < 0) {
374*591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to write schemata in control group");
375*591a6e85SSai Praneeth Prakhya 		fclose(fp);
376*591a6e85SSai Praneeth Prakhya 		ret = -1;
377*591a6e85SSai Praneeth Prakhya 
378*591a6e85SSai Praneeth Prakhya 		goto out;
379*591a6e85SSai Praneeth Prakhya 	}
380*591a6e85SSai Praneeth Prakhya 	fclose(fp);
381*591a6e85SSai Praneeth Prakhya 
382*591a6e85SSai Praneeth Prakhya out:
383*591a6e85SSai Praneeth Prakhya 	printf("%sok Write schema \"%s\" to resctrl FS%s%s\n",
384*591a6e85SSai Praneeth Prakhya 	       ret ? "not " : "", schema, ret ? " # " : "",
385*591a6e85SSai Praneeth Prakhya 	       ret ? reason : "");
386*591a6e85SSai Praneeth Prakhya 	tests_run++;
387*591a6e85SSai Praneeth Prakhya 
388*591a6e85SSai Praneeth Prakhya 	return ret;
389*591a6e85SSai Praneeth Prakhya }
390*591a6e85SSai Praneeth Prakhya 
391*591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str)
392*591a6e85SSai Praneeth Prakhya {
393*591a6e85SSai Praneeth Prakhya 	char line[256];
394*591a6e85SSai Praneeth Prakhya 	int slen = strlen(str);
395*591a6e85SSai Praneeth Prakhya 
396*591a6e85SSai Praneeth Prakhya 	while (!feof(inf)) {
397*591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, inf))
398*591a6e85SSai Praneeth Prakhya 			break;
399*591a6e85SSai Praneeth Prakhya 		if (strncmp(line, str, slen))
400*591a6e85SSai Praneeth Prakhya 			continue;
401*591a6e85SSai Praneeth Prakhya 
402*591a6e85SSai Praneeth Prakhya 		return strdup(line);
403*591a6e85SSai Praneeth Prakhya 	}
404*591a6e85SSai Praneeth Prakhya 
405*591a6e85SSai Praneeth Prakhya 	return NULL;
406*591a6e85SSai Praneeth Prakhya }
407*591a6e85SSai Praneeth Prakhya 
408*591a6e85SSai Praneeth Prakhya /*
409*591a6e85SSai Praneeth Prakhya  * validate_resctrl_feature_request - Check if requested feature is valid.
410*591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Requested feature
411*591a6e85SSai Praneeth Prakhya  *
412*591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
413*591a6e85SSai Praneeth Prakhya  */
414*591a6e85SSai Praneeth Prakhya bool validate_resctrl_feature_request(char *resctrl_val)
415*591a6e85SSai Praneeth Prakhya {
416*591a6e85SSai Praneeth Prakhya 	FILE *inf = fopen("/proc/cpuinfo", "r");
417*591a6e85SSai Praneeth Prakhya 	bool found = false;
418*591a6e85SSai Praneeth Prakhya 	char *res;
419*591a6e85SSai Praneeth Prakhya 
420*591a6e85SSai Praneeth Prakhya 	if (!inf)
421*591a6e85SSai Praneeth Prakhya 		return false;
422*591a6e85SSai Praneeth Prakhya 
423*591a6e85SSai Praneeth Prakhya 	res = fgrep(inf, "flags");
424*591a6e85SSai Praneeth Prakhya 
425*591a6e85SSai Praneeth Prakhya 	if (res) {
426*591a6e85SSai Praneeth Prakhya 		char *s = strchr(res, ':');
427*591a6e85SSai Praneeth Prakhya 
428*591a6e85SSai Praneeth Prakhya 		found = s && !strstr(s, resctrl_val);
429*591a6e85SSai Praneeth Prakhya 		free(res);
430*591a6e85SSai Praneeth Prakhya 	}
431*591a6e85SSai Praneeth Prakhya 	fclose(inf);
432*591a6e85SSai Praneeth Prakhya 
433*591a6e85SSai Praneeth Prakhya 	return found;
434*591a6e85SSai Praneeth Prakhya }
435*591a6e85SSai Praneeth Prakhya 
436*591a6e85SSai Praneeth Prakhya int validate_bw_report_request(char *bw_report)
437*591a6e85SSai Praneeth Prakhya {
438*591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "reads") == 0)
439*591a6e85SSai Praneeth Prakhya 		return 0;
440*591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "writes") == 0)
441*591a6e85SSai Praneeth Prakhya 		return 0;
442*591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "nt-writes") == 0) {
443*591a6e85SSai Praneeth Prakhya 		strcpy(bw_report, "writes");
444*591a6e85SSai Praneeth Prakhya 		return 0;
445*591a6e85SSai Praneeth Prakhya 	}
446*591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "total") == 0)
447*591a6e85SSai Praneeth Prakhya 		return 0;
448*591a6e85SSai Praneeth Prakhya 
449*591a6e85SSai Praneeth Prakhya 	fprintf(stderr, "Requested iMC B/W report type unavailable\n");
450*591a6e85SSai Praneeth Prakhya 
451*591a6e85SSai Praneeth Prakhya 	return -1;
452*591a6e85SSai Praneeth Prakhya }
453*591a6e85SSai Praneeth Prakhya 
454*591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
455*591a6e85SSai Praneeth Prakhya 		    int group_fd, unsigned long flags)
456*591a6e85SSai Praneeth Prakhya {
457*591a6e85SSai Praneeth Prakhya 	int ret;
458*591a6e85SSai Praneeth Prakhya 
459*591a6e85SSai Praneeth Prakhya 	ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
460*591a6e85SSai Praneeth Prakhya 		      group_fd, flags);
461*591a6e85SSai Praneeth Prakhya 	return ret;
462*591a6e85SSai Praneeth Prakhya }
463