xref: /linux/tools/testing/selftests/resctrl/resctrlfs.c (revision c0327e1d7c42adb31a9541de6812f740893177a1)
1591a6e85SSai Praneeth Prakhya // SPDX-License-Identifier: GPL-2.0
2591a6e85SSai Praneeth Prakhya /*
3591a6e85SSai Praneeth Prakhya  * Basic resctrl file system operations
4591a6e85SSai Praneeth Prakhya  *
5591a6e85SSai Praneeth Prakhya  * Copyright (C) 2018 Intel Corporation
6591a6e85SSai Praneeth Prakhya  *
7591a6e85SSai Praneeth Prakhya  * Authors:
8591a6e85SSai Praneeth Prakhya  *    Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>,
9591a6e85SSai Praneeth Prakhya  *    Fenghua Yu <fenghua.yu@intel.com>
10591a6e85SSai Praneeth Prakhya  */
11591a6e85SSai Praneeth Prakhya #include "resctrl.h"
12591a6e85SSai Praneeth Prakhya 
13591a6e85SSai Praneeth Prakhya int tests_run;
14591a6e85SSai Praneeth Prakhya 
15591a6e85SSai Praneeth Prakhya static int find_resctrl_mount(char *buffer)
16591a6e85SSai Praneeth Prakhya {
17591a6e85SSai Praneeth Prakhya 	FILE *mounts;
18591a6e85SSai Praneeth Prakhya 	char line[256], *fs, *mntpoint;
19591a6e85SSai Praneeth Prakhya 
20591a6e85SSai Praneeth Prakhya 	mounts = fopen("/proc/mounts", "r");
21591a6e85SSai Praneeth Prakhya 	if (!mounts) {
22591a6e85SSai Praneeth Prakhya 		perror("/proc/mounts");
23591a6e85SSai Praneeth Prakhya 		return -ENXIO;
24591a6e85SSai Praneeth Prakhya 	}
25591a6e85SSai Praneeth Prakhya 	while (!feof(mounts)) {
26591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, mounts))
27591a6e85SSai Praneeth Prakhya 			break;
28591a6e85SSai Praneeth Prakhya 		fs = strtok(line, " \t");
29591a6e85SSai Praneeth Prakhya 		if (!fs)
30591a6e85SSai Praneeth Prakhya 			continue;
31591a6e85SSai Praneeth Prakhya 		mntpoint = strtok(NULL, " \t");
32591a6e85SSai Praneeth Prakhya 		if (!mntpoint)
33591a6e85SSai Praneeth Prakhya 			continue;
34591a6e85SSai Praneeth Prakhya 		fs = strtok(NULL, " \t");
35591a6e85SSai Praneeth Prakhya 		if (!fs)
36591a6e85SSai Praneeth Prakhya 			continue;
37591a6e85SSai Praneeth Prakhya 		if (strcmp(fs, "resctrl"))
38591a6e85SSai Praneeth Prakhya 			continue;
39591a6e85SSai Praneeth Prakhya 
40591a6e85SSai Praneeth Prakhya 		fclose(mounts);
41591a6e85SSai Praneeth Prakhya 		if (buffer)
42591a6e85SSai Praneeth Prakhya 			strncpy(buffer, mntpoint, 256);
43591a6e85SSai Praneeth Prakhya 
44591a6e85SSai Praneeth Prakhya 		return 0;
45591a6e85SSai Praneeth Prakhya 	}
46591a6e85SSai Praneeth Prakhya 
47591a6e85SSai Praneeth Prakhya 	fclose(mounts);
48591a6e85SSai Praneeth Prakhya 
49591a6e85SSai Praneeth Prakhya 	return -ENOENT;
50591a6e85SSai Praneeth Prakhya }
51591a6e85SSai Praneeth Prakhya 
5278941183SFenghua Yu char cbm_mask[256];
5378941183SFenghua Yu 
54591a6e85SSai Praneeth Prakhya /*
55591a6e85SSai Praneeth Prakhya  * remount_resctrlfs - Remount resctrl FS at /sys/fs/resctrl
56591a6e85SSai Praneeth Prakhya  * @mum_resctrlfs:	Should the resctrl FS be remounted?
57591a6e85SSai Praneeth Prakhya  *
58591a6e85SSai Praneeth Prakhya  * If not mounted, mount it.
59591a6e85SSai Praneeth Prakhya  * If mounted and mum_resctrlfs then remount resctrl FS.
60591a6e85SSai Praneeth Prakhya  * If mounted and !mum_resctrlfs then noop
61591a6e85SSai Praneeth Prakhya  *
62591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
63591a6e85SSai Praneeth Prakhya  */
64591a6e85SSai Praneeth Prakhya int remount_resctrlfs(bool mum_resctrlfs)
65591a6e85SSai Praneeth Prakhya {
66591a6e85SSai Praneeth Prakhya 	char mountpoint[256];
67591a6e85SSai Praneeth Prakhya 	int ret;
68591a6e85SSai Praneeth Prakhya 
69591a6e85SSai Praneeth Prakhya 	ret = find_resctrl_mount(mountpoint);
70591a6e85SSai Praneeth Prakhya 	if (ret)
71591a6e85SSai Praneeth Prakhya 		strcpy(mountpoint, RESCTRL_PATH);
72591a6e85SSai Praneeth Prakhya 
73591a6e85SSai Praneeth Prakhya 	if (!ret && mum_resctrlfs && umount(mountpoint)) {
74591a6e85SSai Praneeth Prakhya 		printf("not ok unmounting \"%s\"\n", mountpoint);
75591a6e85SSai Praneeth Prakhya 		perror("# umount");
76591a6e85SSai Praneeth Prakhya 		tests_run++;
77591a6e85SSai Praneeth Prakhya 	}
78591a6e85SSai Praneeth Prakhya 
79591a6e85SSai Praneeth Prakhya 	if (!ret && !mum_resctrlfs)
80591a6e85SSai Praneeth Prakhya 		return 0;
81591a6e85SSai Praneeth Prakhya 
82591a6e85SSai Praneeth Prakhya 	ret = mount("resctrl", RESCTRL_PATH, "resctrl", 0, NULL);
83591a6e85SSai Praneeth Prakhya 	printf("%sok mounting resctrl to \"%s\"\n", ret ? "not " : "",
84591a6e85SSai Praneeth Prakhya 	       RESCTRL_PATH);
85591a6e85SSai Praneeth Prakhya 	if (ret)
86591a6e85SSai Praneeth Prakhya 		perror("# mount");
87591a6e85SSai Praneeth Prakhya 
88591a6e85SSai Praneeth Prakhya 	tests_run++;
89591a6e85SSai Praneeth Prakhya 
90591a6e85SSai Praneeth Prakhya 	return ret;
91591a6e85SSai Praneeth Prakhya }
92591a6e85SSai Praneeth Prakhya 
93591a6e85SSai Praneeth Prakhya int umount_resctrlfs(void)
94591a6e85SSai Praneeth Prakhya {
95591a6e85SSai Praneeth Prakhya 	if (umount(RESCTRL_PATH)) {
96591a6e85SSai Praneeth Prakhya 		perror("# Unable to umount resctrl");
97591a6e85SSai Praneeth Prakhya 
98591a6e85SSai Praneeth Prakhya 		return errno;
99591a6e85SSai Praneeth Prakhya 	}
100591a6e85SSai Praneeth Prakhya 
101591a6e85SSai Praneeth Prakhya 	return 0;
102591a6e85SSai Praneeth Prakhya }
103591a6e85SSai Praneeth Prakhya 
104591a6e85SSai Praneeth Prakhya /*
105591a6e85SSai Praneeth Prakhya  * get_resource_id - Get socket number/l3 id for a specified CPU
106591a6e85SSai Praneeth Prakhya  * @cpu_no:	CPU number
107591a6e85SSai Praneeth Prakhya  * @resource_id: Socket number or l3_id
108591a6e85SSai Praneeth Prakhya  *
109591a6e85SSai Praneeth Prakhya  * Return: >= 0 on success, < 0 on failure.
110591a6e85SSai Praneeth Prakhya  */
111591a6e85SSai Praneeth Prakhya int get_resource_id(int cpu_no, int *resource_id)
112591a6e85SSai Praneeth Prakhya {
113591a6e85SSai Praneeth Prakhya 	char phys_pkg_path[1024];
114591a6e85SSai Praneeth Prakhya 	FILE *fp;
115591a6e85SSai Praneeth Prakhya 
116*c0327e1dSBabu Moger 	if (is_amd)
117*c0327e1dSBabu Moger 		sprintf(phys_pkg_path, "%s%d/cache/index3/id",
118*c0327e1dSBabu Moger 			PHYS_ID_PATH, cpu_no);
119*c0327e1dSBabu Moger 	else
120591a6e85SSai Praneeth Prakhya 		sprintf(phys_pkg_path, "%s%d/topology/physical_package_id",
121591a6e85SSai Praneeth Prakhya 			PHYS_ID_PATH, cpu_no);
122*c0327e1dSBabu Moger 
123591a6e85SSai Praneeth Prakhya 	fp = fopen(phys_pkg_path, "r");
124591a6e85SSai Praneeth Prakhya 	if (!fp) {
125591a6e85SSai Praneeth Prakhya 		perror("Failed to open physical_package_id");
126591a6e85SSai Praneeth Prakhya 
127591a6e85SSai Praneeth Prakhya 		return -1;
128591a6e85SSai Praneeth Prakhya 	}
129591a6e85SSai Praneeth Prakhya 	if (fscanf(fp, "%d", resource_id) <= 0) {
130591a6e85SSai Praneeth Prakhya 		perror("Could not get socket number or l3 id");
131591a6e85SSai Praneeth Prakhya 		fclose(fp);
132591a6e85SSai Praneeth Prakhya 
133591a6e85SSai Praneeth Prakhya 		return -1;
134591a6e85SSai Praneeth Prakhya 	}
135591a6e85SSai Praneeth Prakhya 	fclose(fp);
136591a6e85SSai Praneeth Prakhya 
137591a6e85SSai Praneeth Prakhya 	return 0;
138591a6e85SSai Praneeth Prakhya }
139591a6e85SSai Praneeth Prakhya 
140591a6e85SSai Praneeth Prakhya /*
14178941183SFenghua Yu  * get_cache_size - Get cache size for a specified CPU
14278941183SFenghua Yu  * @cpu_no:	CPU number
14378941183SFenghua Yu  * @cache_type:	Cache level L2/L3
14478941183SFenghua Yu  * @cache_size:	pointer to cache_size
14578941183SFenghua Yu  *
14678941183SFenghua Yu  * Return: = 0 on success, < 0 on failure.
14778941183SFenghua Yu  */
14878941183SFenghua Yu int get_cache_size(int cpu_no, char *cache_type, unsigned long *cache_size)
14978941183SFenghua Yu {
15078941183SFenghua Yu 	char cache_path[1024], cache_str[64];
15178941183SFenghua Yu 	int length, i, cache_num;
15278941183SFenghua Yu 	FILE *fp;
15378941183SFenghua Yu 
15478941183SFenghua Yu 	if (!strcmp(cache_type, "L3")) {
15578941183SFenghua Yu 		cache_num = 3;
15678941183SFenghua Yu 	} else if (!strcmp(cache_type, "L2")) {
15778941183SFenghua Yu 		cache_num = 2;
15878941183SFenghua Yu 	} else {
15978941183SFenghua Yu 		perror("Invalid cache level");
16078941183SFenghua Yu 		return -1;
16178941183SFenghua Yu 	}
16278941183SFenghua Yu 
16378941183SFenghua Yu 	sprintf(cache_path, "/sys/bus/cpu/devices/cpu%d/cache/index%d/size",
16478941183SFenghua Yu 		cpu_no, cache_num);
16578941183SFenghua Yu 	fp = fopen(cache_path, "r");
16678941183SFenghua Yu 	if (!fp) {
16778941183SFenghua Yu 		perror("Failed to open cache size");
16878941183SFenghua Yu 
16978941183SFenghua Yu 		return -1;
17078941183SFenghua Yu 	}
17178941183SFenghua Yu 	if (fscanf(fp, "%s", cache_str) <= 0) {
17278941183SFenghua Yu 		perror("Could not get cache_size");
17378941183SFenghua Yu 		fclose(fp);
17478941183SFenghua Yu 
17578941183SFenghua Yu 		return -1;
17678941183SFenghua Yu 	}
17778941183SFenghua Yu 	fclose(fp);
17878941183SFenghua Yu 
17978941183SFenghua Yu 	length = (int)strlen(cache_str);
18078941183SFenghua Yu 
18178941183SFenghua Yu 	*cache_size = 0;
18278941183SFenghua Yu 
18378941183SFenghua Yu 	for (i = 0; i < length; i++) {
18478941183SFenghua Yu 		if ((cache_str[i] >= '0') && (cache_str[i] <= '9'))
18578941183SFenghua Yu 
18678941183SFenghua Yu 			*cache_size = *cache_size * 10 + (cache_str[i] - '0');
18778941183SFenghua Yu 
18878941183SFenghua Yu 		else if (cache_str[i] == 'K')
18978941183SFenghua Yu 
19078941183SFenghua Yu 			*cache_size = *cache_size * 1024;
19178941183SFenghua Yu 
19278941183SFenghua Yu 		else if (cache_str[i] == 'M')
19378941183SFenghua Yu 
19478941183SFenghua Yu 			*cache_size = *cache_size * 1024 * 1024;
19578941183SFenghua Yu 
19678941183SFenghua Yu 		else
19778941183SFenghua Yu 			break;
19878941183SFenghua Yu 	}
19978941183SFenghua Yu 
20078941183SFenghua Yu 	return 0;
20178941183SFenghua Yu }
20278941183SFenghua Yu 
20378941183SFenghua Yu #define CORE_SIBLINGS_PATH	"/sys/bus/cpu/devices/cpu"
20478941183SFenghua Yu 
20578941183SFenghua Yu /*
20678941183SFenghua Yu  * get_cbm_mask - Get cbm mask for given cache
20778941183SFenghua Yu  * @cache_type:	Cache level L2/L3
20878941183SFenghua Yu  *
20978941183SFenghua Yu  * Mask is stored in cbm_mask which is global variable.
21078941183SFenghua Yu  *
21178941183SFenghua Yu  * Return: = 0 on success, < 0 on failure.
21278941183SFenghua Yu  */
21378941183SFenghua Yu int get_cbm_mask(char *cache_type)
21478941183SFenghua Yu {
21578941183SFenghua Yu 	char cbm_mask_path[1024];
21678941183SFenghua Yu 	FILE *fp;
21778941183SFenghua Yu 
21878941183SFenghua Yu 	sprintf(cbm_mask_path, "%s/%s/cbm_mask", CBM_MASK_PATH, cache_type);
21978941183SFenghua Yu 
22078941183SFenghua Yu 	fp = fopen(cbm_mask_path, "r");
22178941183SFenghua Yu 	if (!fp) {
22278941183SFenghua Yu 		perror("Failed to open cache level");
22378941183SFenghua Yu 
22478941183SFenghua Yu 		return -1;
22578941183SFenghua Yu 	}
22678941183SFenghua Yu 	if (fscanf(fp, "%s", cbm_mask) <= 0) {
22778941183SFenghua Yu 		perror("Could not get max cbm_mask");
22878941183SFenghua Yu 		fclose(fp);
22978941183SFenghua Yu 
23078941183SFenghua Yu 		return -1;
23178941183SFenghua Yu 	}
23278941183SFenghua Yu 	fclose(fp);
23378941183SFenghua Yu 
23478941183SFenghua Yu 	return 0;
23578941183SFenghua Yu }
23678941183SFenghua Yu 
23778941183SFenghua Yu /*
23878941183SFenghua Yu  * get_core_sibling - Get sibling core id from the same socket for given CPU
23978941183SFenghua Yu  * @cpu_no:	CPU number
24078941183SFenghua Yu  *
24178941183SFenghua Yu  * Return:	> 0 on success, < 0 on failure.
24278941183SFenghua Yu  */
24378941183SFenghua Yu int get_core_sibling(int cpu_no)
24478941183SFenghua Yu {
24578941183SFenghua Yu 	char core_siblings_path[1024], cpu_list_str[64];
24678941183SFenghua Yu 	int sibling_cpu_no = -1;
24778941183SFenghua Yu 	FILE *fp;
24878941183SFenghua Yu 
24978941183SFenghua Yu 	sprintf(core_siblings_path, "%s%d/topology/core_siblings_list",
25078941183SFenghua Yu 		CORE_SIBLINGS_PATH, cpu_no);
25178941183SFenghua Yu 
25278941183SFenghua Yu 	fp = fopen(core_siblings_path, "r");
25378941183SFenghua Yu 	if (!fp) {
25478941183SFenghua Yu 		perror("Failed to open core siblings path");
25578941183SFenghua Yu 
25678941183SFenghua Yu 		return -1;
25778941183SFenghua Yu 	}
25878941183SFenghua Yu 	if (fscanf(fp, "%s", cpu_list_str) <= 0) {
25978941183SFenghua Yu 		perror("Could not get core_siblings list");
26078941183SFenghua Yu 		fclose(fp);
26178941183SFenghua Yu 
26278941183SFenghua Yu 		return -1;
26378941183SFenghua Yu 	}
26478941183SFenghua Yu 	fclose(fp);
26578941183SFenghua Yu 
26678941183SFenghua Yu 	char *token = strtok(cpu_list_str, "-,");
26778941183SFenghua Yu 
26878941183SFenghua Yu 	while (token) {
26978941183SFenghua Yu 		sibling_cpu_no = atoi(token);
27078941183SFenghua Yu 		/* Skipping core 0 as we don't want to run test on core 0 */
27178941183SFenghua Yu 		if (sibling_cpu_no != 0)
27278941183SFenghua Yu 			break;
27378941183SFenghua Yu 		token = strtok(NULL, "-,");
27478941183SFenghua Yu 	}
27578941183SFenghua Yu 
27678941183SFenghua Yu 	return sibling_cpu_no;
27778941183SFenghua Yu }
27878941183SFenghua Yu 
27978941183SFenghua Yu /*
280591a6e85SSai Praneeth Prakhya  * taskset_benchmark - Taskset PID (i.e. benchmark) to a specified cpu
281591a6e85SSai Praneeth Prakhya  * @bm_pid:	PID that should be binded
282591a6e85SSai Praneeth Prakhya  * @cpu_no:	CPU number at which the PID would be binded
283591a6e85SSai Praneeth Prakhya  *
284591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
285591a6e85SSai Praneeth Prakhya  */
286591a6e85SSai Praneeth Prakhya int taskset_benchmark(pid_t bm_pid, int cpu_no)
287591a6e85SSai Praneeth Prakhya {
288591a6e85SSai Praneeth Prakhya 	cpu_set_t my_set;
289591a6e85SSai Praneeth Prakhya 
290591a6e85SSai Praneeth Prakhya 	CPU_ZERO(&my_set);
291591a6e85SSai Praneeth Prakhya 	CPU_SET(cpu_no, &my_set);
292591a6e85SSai Praneeth Prakhya 
293591a6e85SSai Praneeth Prakhya 	if (sched_setaffinity(bm_pid, sizeof(cpu_set_t), &my_set)) {
294591a6e85SSai Praneeth Prakhya 		perror("Unable to taskset benchmark");
295591a6e85SSai Praneeth Prakhya 
296591a6e85SSai Praneeth Prakhya 		return -1;
297591a6e85SSai Praneeth Prakhya 	}
298591a6e85SSai Praneeth Prakhya 
299591a6e85SSai Praneeth Prakhya 	return 0;
300591a6e85SSai Praneeth Prakhya }
301591a6e85SSai Praneeth Prakhya 
302591a6e85SSai Praneeth Prakhya /*
303591a6e85SSai Praneeth Prakhya  * run_benchmark - Run a specified benchmark or fill_buf (default benchmark)
304591a6e85SSai Praneeth Prakhya  *		   in specified signal. Direct benchmark stdio to /dev/null.
305591a6e85SSai Praneeth Prakhya  * @signum:	signal number
306591a6e85SSai Praneeth Prakhya  * @info:	signal info
307591a6e85SSai Praneeth Prakhya  * @ucontext:	user context in signal handling
308591a6e85SSai Praneeth Prakhya  *
309591a6e85SSai Praneeth Prakhya  * Return: void
310591a6e85SSai Praneeth Prakhya  */
311591a6e85SSai Praneeth Prakhya void run_benchmark(int signum, siginfo_t *info, void *ucontext)
312591a6e85SSai Praneeth Prakhya {
31378941183SFenghua Yu 	int operation, ret, malloc_and_init_memory, memflush;
31478941183SFenghua Yu 	unsigned long span, buffer_span;
315591a6e85SSai Praneeth Prakhya 	char **benchmark_cmd;
31678941183SFenghua Yu 	char resctrl_val[64];
317591a6e85SSai Praneeth Prakhya 	FILE *fp;
318591a6e85SSai Praneeth Prakhya 
319591a6e85SSai Praneeth Prakhya 	benchmark_cmd = info->si_ptr;
320591a6e85SSai Praneeth Prakhya 
321591a6e85SSai Praneeth Prakhya 	/*
322591a6e85SSai Praneeth Prakhya 	 * Direct stdio of child to /dev/null, so that only parent writes to
323591a6e85SSai Praneeth Prakhya 	 * stdio (console)
324591a6e85SSai Praneeth Prakhya 	 */
325591a6e85SSai Praneeth Prakhya 	fp = freopen("/dev/null", "w", stdout);
326591a6e85SSai Praneeth Prakhya 	if (!fp)
327591a6e85SSai Praneeth Prakhya 		PARENT_EXIT("Unable to direct benchmark status to /dev/null");
328591a6e85SSai Praneeth Prakhya 
329591a6e85SSai Praneeth Prakhya 	if (strcmp(benchmark_cmd[0], "fill_buf") == 0) {
330591a6e85SSai Praneeth Prakhya 		/* Execute default fill_buf benchmark */
331591a6e85SSai Praneeth Prakhya 		span = strtoul(benchmark_cmd[1], NULL, 10);
33278941183SFenghua Yu 		malloc_and_init_memory = atoi(benchmark_cmd[2]);
33378941183SFenghua Yu 		memflush =  atoi(benchmark_cmd[3]);
334591a6e85SSai Praneeth Prakhya 		operation = atoi(benchmark_cmd[4]);
33578941183SFenghua Yu 		sprintf(resctrl_val, "%s", benchmark_cmd[5]);
33678941183SFenghua Yu 
33778941183SFenghua Yu 		if (strcmp(resctrl_val, "cqm") != 0)
33878941183SFenghua Yu 			buffer_span = span * MB;
33978941183SFenghua Yu 		else
34078941183SFenghua Yu 			buffer_span = span;
34178941183SFenghua Yu 
34278941183SFenghua Yu 		if (run_fill_buf(buffer_span, malloc_and_init_memory, memflush,
34378941183SFenghua Yu 				 operation, resctrl_val))
344591a6e85SSai Praneeth Prakhya 			fprintf(stderr, "Error in running fill buffer\n");
345591a6e85SSai Praneeth Prakhya 	} else {
346591a6e85SSai Praneeth Prakhya 		/* Execute specified benchmark */
347591a6e85SSai Praneeth Prakhya 		ret = execvp(benchmark_cmd[0], benchmark_cmd);
348591a6e85SSai Praneeth Prakhya 		if (ret)
349591a6e85SSai Praneeth Prakhya 			perror("wrong\n");
350591a6e85SSai Praneeth Prakhya 	}
351591a6e85SSai Praneeth Prakhya 
352591a6e85SSai Praneeth Prakhya 	fclose(stdout);
353591a6e85SSai Praneeth Prakhya 	PARENT_EXIT("Unable to run specified benchmark");
354591a6e85SSai Praneeth Prakhya }
355591a6e85SSai Praneeth Prakhya 
356591a6e85SSai Praneeth Prakhya /*
357591a6e85SSai Praneeth Prakhya  * create_grp - Create a group only if one doesn't exist
358591a6e85SSai Praneeth Prakhya  * @grp_name:	Name of the group
359591a6e85SSai Praneeth Prakhya  * @grp:	Full path and name of the group
360591a6e85SSai Praneeth Prakhya  * @parent_grp:	Full path and name of the parent group
361591a6e85SSai Praneeth Prakhya  *
362591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
363591a6e85SSai Praneeth Prakhya  */
364591a6e85SSai Praneeth Prakhya static int create_grp(const char *grp_name, char *grp, const char *parent_grp)
365591a6e85SSai Praneeth Prakhya {
366591a6e85SSai Praneeth Prakhya 	int found_grp = 0;
367591a6e85SSai Praneeth Prakhya 	struct dirent *ep;
368591a6e85SSai Praneeth Prakhya 	DIR *dp;
369591a6e85SSai Praneeth Prakhya 
37078941183SFenghua Yu 	/*
37178941183SFenghua Yu 	 * At this point, we are guaranteed to have resctrl FS mounted and if
37278941183SFenghua Yu 	 * length of grp_name == 0, it means, user wants to use root con_mon
37378941183SFenghua Yu 	 * grp, so do nothing
37478941183SFenghua Yu 	 */
37578941183SFenghua Yu 	if (strlen(grp_name) == 0)
37678941183SFenghua Yu 		return 0;
37778941183SFenghua Yu 
378591a6e85SSai Praneeth Prakhya 	/* Check if requested grp exists or not */
379591a6e85SSai Praneeth Prakhya 	dp = opendir(parent_grp);
380591a6e85SSai Praneeth Prakhya 	if (dp) {
381591a6e85SSai Praneeth Prakhya 		while ((ep = readdir(dp)) != NULL) {
382591a6e85SSai Praneeth Prakhya 			if (strcmp(ep->d_name, grp_name) == 0)
383591a6e85SSai Praneeth Prakhya 				found_grp = 1;
384591a6e85SSai Praneeth Prakhya 		}
385591a6e85SSai Praneeth Prakhya 		closedir(dp);
386591a6e85SSai Praneeth Prakhya 	} else {
387591a6e85SSai Praneeth Prakhya 		perror("Unable to open resctrl for group");
388591a6e85SSai Praneeth Prakhya 
389591a6e85SSai Praneeth Prakhya 		return -1;
390591a6e85SSai Praneeth Prakhya 	}
391591a6e85SSai Praneeth Prakhya 
392591a6e85SSai Praneeth Prakhya 	/* Requested grp doesn't exist, hence create it */
393591a6e85SSai Praneeth Prakhya 	if (found_grp == 0) {
394591a6e85SSai Praneeth Prakhya 		if (mkdir(grp, 0) == -1) {
395591a6e85SSai Praneeth Prakhya 			perror("Unable to create group");
396591a6e85SSai Praneeth Prakhya 
397591a6e85SSai Praneeth Prakhya 			return -1;
398591a6e85SSai Praneeth Prakhya 		}
399591a6e85SSai Praneeth Prakhya 	}
400591a6e85SSai Praneeth Prakhya 
401591a6e85SSai Praneeth Prakhya 	return 0;
402591a6e85SSai Praneeth Prakhya }
403591a6e85SSai Praneeth Prakhya 
404591a6e85SSai Praneeth Prakhya static int write_pid_to_tasks(char *tasks, pid_t pid)
405591a6e85SSai Praneeth Prakhya {
406591a6e85SSai Praneeth Prakhya 	FILE *fp;
407591a6e85SSai Praneeth Prakhya 
408591a6e85SSai Praneeth Prakhya 	fp = fopen(tasks, "w");
409591a6e85SSai Praneeth Prakhya 	if (!fp) {
410591a6e85SSai Praneeth Prakhya 		perror("Failed to open tasks file");
411591a6e85SSai Praneeth Prakhya 
412591a6e85SSai Praneeth Prakhya 		return -1;
413591a6e85SSai Praneeth Prakhya 	}
414591a6e85SSai Praneeth Prakhya 	if (fprintf(fp, "%d\n", pid) < 0) {
415591a6e85SSai Praneeth Prakhya 		perror("Failed to wr pid to tasks file");
416591a6e85SSai Praneeth Prakhya 		fclose(fp);
417591a6e85SSai Praneeth Prakhya 
418591a6e85SSai Praneeth Prakhya 		return -1;
419591a6e85SSai Praneeth Prakhya 	}
420591a6e85SSai Praneeth Prakhya 	fclose(fp);
421591a6e85SSai Praneeth Prakhya 
422591a6e85SSai Praneeth Prakhya 	return 0;
423591a6e85SSai Praneeth Prakhya }
424591a6e85SSai Praneeth Prakhya 
425591a6e85SSai Praneeth Prakhya /*
426591a6e85SSai Praneeth Prakhya  * write_bm_pid_to_resctrl - Write a PID (i.e. benchmark) to resctrl FS
427591a6e85SSai Praneeth Prakhya  * @bm_pid:		PID that should be written
428591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the control monitor group (con_mon grp)
429591a6e85SSai Praneeth Prakhya  * @mongrp:		Name of the monitor group (mon grp)
430591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
431591a6e85SSai Praneeth Prakhya  *
432591a6e85SSai Praneeth Prakhya  * If a con_mon grp is requested, create it and write pid to it, otherwise
433591a6e85SSai Praneeth Prakhya  * write pid to root con_mon grp.
434591a6e85SSai Praneeth Prakhya  * If a mon grp is requested, create it and write pid to it, otherwise
435591a6e85SSai Praneeth Prakhya  * pid is not written, this means that pid is in con_mon grp and hence
436591a6e85SSai Praneeth Prakhya  * should consult con_mon grp's mon_data directory for results.
437591a6e85SSai Praneeth Prakhya  *
438591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
439591a6e85SSai Praneeth Prakhya  */
440591a6e85SSai Praneeth Prakhya int write_bm_pid_to_resctrl(pid_t bm_pid, char *ctrlgrp, char *mongrp,
441591a6e85SSai Praneeth Prakhya 			    char *resctrl_val)
442591a6e85SSai Praneeth Prakhya {
443591a6e85SSai Praneeth Prakhya 	char controlgroup[128], monitorgroup[512], monitorgroup_p[256];
444591a6e85SSai Praneeth Prakhya 	char tasks[1024];
445591a6e85SSai Praneeth Prakhya 	int ret = 0;
446591a6e85SSai Praneeth Prakhya 
447591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp))
448591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s", RESCTRL_PATH, ctrlgrp);
449591a6e85SSai Praneeth Prakhya 	else
450591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s", RESCTRL_PATH);
451591a6e85SSai Praneeth Prakhya 
452591a6e85SSai Praneeth Prakhya 	/* Create control and monitoring group and write pid into it */
453591a6e85SSai Praneeth Prakhya 	ret = create_grp(ctrlgrp, controlgroup, RESCTRL_PATH);
454591a6e85SSai Praneeth Prakhya 	if (ret)
455591a6e85SSai Praneeth Prakhya 		goto out;
456591a6e85SSai Praneeth Prakhya 	sprintf(tasks, "%s/tasks", controlgroup);
457591a6e85SSai Praneeth Prakhya 	ret = write_pid_to_tasks(tasks, bm_pid);
458591a6e85SSai Praneeth Prakhya 	if (ret)
459591a6e85SSai Praneeth Prakhya 		goto out;
460591a6e85SSai Praneeth Prakhya 
46178941183SFenghua Yu 	/* Create mon grp and write pid into it for "mbm" and "cqm" test */
46278941183SFenghua Yu 	if ((strcmp(resctrl_val, "cqm") == 0) ||
46378941183SFenghua Yu 	    (strcmp(resctrl_val, "mbm") == 0)) {
46478941183SFenghua Yu 		if (strlen(mongrp)) {
465591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup_p, "%s/mon_groups", controlgroup);
466591a6e85SSai Praneeth Prakhya 			sprintf(monitorgroup, "%s/%s", monitorgroup_p, mongrp);
467591a6e85SSai Praneeth Prakhya 			ret = create_grp(mongrp, monitorgroup, monitorgroup_p);
468591a6e85SSai Praneeth Prakhya 			if (ret)
469591a6e85SSai Praneeth Prakhya 				goto out;
470591a6e85SSai Praneeth Prakhya 
471591a6e85SSai Praneeth Prakhya 			sprintf(tasks, "%s/mon_groups/%s/tasks",
472591a6e85SSai Praneeth Prakhya 				controlgroup, mongrp);
473591a6e85SSai Praneeth Prakhya 			ret = write_pid_to_tasks(tasks, bm_pid);
474591a6e85SSai Praneeth Prakhya 			if (ret)
475591a6e85SSai Praneeth Prakhya 				goto out;
476591a6e85SSai Praneeth Prakhya 		}
477591a6e85SSai Praneeth Prakhya 	}
478591a6e85SSai Praneeth Prakhya 
479591a6e85SSai Praneeth Prakhya out:
480591a6e85SSai Praneeth Prakhya 	printf("%sok writing benchmark parameters to resctrl FS\n",
481591a6e85SSai Praneeth Prakhya 	       ret ? "not " : "");
482591a6e85SSai Praneeth Prakhya 	if (ret)
483591a6e85SSai Praneeth Prakhya 		perror("# writing to resctrlfs");
484591a6e85SSai Praneeth Prakhya 
485591a6e85SSai Praneeth Prakhya 	tests_run++;
486591a6e85SSai Praneeth Prakhya 
487591a6e85SSai Praneeth Prakhya 	return ret;
488591a6e85SSai Praneeth Prakhya }
489591a6e85SSai Praneeth Prakhya 
490591a6e85SSai Praneeth Prakhya /*
491591a6e85SSai Praneeth Prakhya  * write_schemata - Update schemata of a con_mon grp
492591a6e85SSai Praneeth Prakhya  * @ctrlgrp:		Name of the con_mon grp
493591a6e85SSai Praneeth Prakhya  * @schemata:		Schemata that should be updated to
494591a6e85SSai Praneeth Prakhya  * @cpu_no:		CPU number that the benchmark PID is binded to
495591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Resctrl feature (Eg: mbm, mba.. etc)
496591a6e85SSai Praneeth Prakhya  *
497591a6e85SSai Praneeth Prakhya  * Update schemata of a con_mon grp *only* if requested resctrl feature is
498591a6e85SSai Praneeth Prakhya  * allocation type
499591a6e85SSai Praneeth Prakhya  *
500591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
501591a6e85SSai Praneeth Prakhya  */
502591a6e85SSai Praneeth Prakhya int write_schemata(char *ctrlgrp, char *schemata, int cpu_no, char *resctrl_val)
503591a6e85SSai Praneeth Prakhya {
504591a6e85SSai Praneeth Prakhya 	char controlgroup[1024], schema[1024], reason[64];
505591a6e85SSai Praneeth Prakhya 	int resource_id, ret = 0;
506591a6e85SSai Praneeth Prakhya 	FILE *fp;
507591a6e85SSai Praneeth Prakhya 
50878941183SFenghua Yu 	if ((strcmp(resctrl_val, "mba") != 0) &&
509790bf585SFenghua Yu 	    (strcmp(resctrl_val, "cat") != 0) &&
51078941183SFenghua Yu 	    (strcmp(resctrl_val, "cqm") != 0))
511591a6e85SSai Praneeth Prakhya 		return -ENOENT;
512591a6e85SSai Praneeth Prakhya 
513591a6e85SSai Praneeth Prakhya 	if (!schemata) {
514591a6e85SSai Praneeth Prakhya 		printf("# Skipping empty schemata update\n");
515591a6e85SSai Praneeth Prakhya 
516591a6e85SSai Praneeth Prakhya 		return -1;
517591a6e85SSai Praneeth Prakhya 	}
518591a6e85SSai Praneeth Prakhya 
519591a6e85SSai Praneeth Prakhya 	if (get_resource_id(cpu_no, &resource_id) < 0) {
520591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to get resource id");
521591a6e85SSai Praneeth Prakhya 		ret = -1;
522591a6e85SSai Praneeth Prakhya 
523591a6e85SSai Praneeth Prakhya 		goto out;
524591a6e85SSai Praneeth Prakhya 	}
525591a6e85SSai Praneeth Prakhya 
526591a6e85SSai Praneeth Prakhya 	if (strlen(ctrlgrp) != 0)
527591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/%s/schemata", RESCTRL_PATH, ctrlgrp);
528591a6e85SSai Praneeth Prakhya 	else
529591a6e85SSai Praneeth Prakhya 		sprintf(controlgroup, "%s/schemata", RESCTRL_PATH);
530591a6e85SSai Praneeth Prakhya 
531790bf585SFenghua Yu 	if (!strcmp(resctrl_val, "cat") || !strcmp(resctrl_val, "cqm"))
53278941183SFenghua Yu 		sprintf(schema, "%s%d%c%s", "L3:", resource_id, '=', schemata);
53378941183SFenghua Yu 	if (strcmp(resctrl_val, "mba") == 0)
534591a6e85SSai Praneeth Prakhya 		sprintf(schema, "%s%d%c%s", "MB:", resource_id, '=', schemata);
535591a6e85SSai Praneeth Prakhya 
536591a6e85SSai Praneeth Prakhya 	fp = fopen(controlgroup, "w");
537591a6e85SSai Praneeth Prakhya 	if (!fp) {
538591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to open control group");
539591a6e85SSai Praneeth Prakhya 		ret = -1;
540591a6e85SSai Praneeth Prakhya 
541591a6e85SSai Praneeth Prakhya 		goto out;
542591a6e85SSai Praneeth Prakhya 	}
543591a6e85SSai Praneeth Prakhya 
544591a6e85SSai Praneeth Prakhya 	if (fprintf(fp, "%s\n", schema) < 0) {
545591a6e85SSai Praneeth Prakhya 		sprintf(reason, "Failed to write schemata in control group");
546591a6e85SSai Praneeth Prakhya 		fclose(fp);
547591a6e85SSai Praneeth Prakhya 		ret = -1;
548591a6e85SSai Praneeth Prakhya 
549591a6e85SSai Praneeth Prakhya 		goto out;
550591a6e85SSai Praneeth Prakhya 	}
551591a6e85SSai Praneeth Prakhya 	fclose(fp);
552591a6e85SSai Praneeth Prakhya 
553591a6e85SSai Praneeth Prakhya out:
554591a6e85SSai Praneeth Prakhya 	printf("%sok Write schema \"%s\" to resctrl FS%s%s\n",
555591a6e85SSai Praneeth Prakhya 	       ret ? "not " : "", schema, ret ? " # " : "",
556591a6e85SSai Praneeth Prakhya 	       ret ? reason : "");
557591a6e85SSai Praneeth Prakhya 	tests_run++;
558591a6e85SSai Praneeth Prakhya 
559591a6e85SSai Praneeth Prakhya 	return ret;
560591a6e85SSai Praneeth Prakhya }
561591a6e85SSai Praneeth Prakhya 
562ecdbb911SFenghua Yu bool check_resctrlfs_support(void)
563ecdbb911SFenghua Yu {
564ecdbb911SFenghua Yu 	FILE *inf = fopen("/proc/filesystems", "r");
565ecdbb911SFenghua Yu 	DIR *dp;
566ecdbb911SFenghua Yu 	char *res;
567ecdbb911SFenghua Yu 	bool ret = false;
568ecdbb911SFenghua Yu 
569ecdbb911SFenghua Yu 	if (!inf)
570ecdbb911SFenghua Yu 		return false;
571ecdbb911SFenghua Yu 
572ecdbb911SFenghua Yu 	res = fgrep(inf, "nodev\tresctrl\n");
573ecdbb911SFenghua Yu 
574ecdbb911SFenghua Yu 	if (res) {
575ecdbb911SFenghua Yu 		ret = true;
576ecdbb911SFenghua Yu 		free(res);
577ecdbb911SFenghua Yu 	}
578ecdbb911SFenghua Yu 
579ecdbb911SFenghua Yu 	fclose(inf);
580ecdbb911SFenghua Yu 
581ecdbb911SFenghua Yu 	printf("%sok kernel supports resctrl filesystem\n", ret ? "" : "not ");
582ecdbb911SFenghua Yu 	tests_run++;
583ecdbb911SFenghua Yu 
584ecdbb911SFenghua Yu 	dp = opendir(RESCTRL_PATH);
585ecdbb911SFenghua Yu 	printf("%sok resctrl mountpoint \"%s\" exists\n",
586ecdbb911SFenghua Yu 	       dp ? "" : "not ", RESCTRL_PATH);
587ecdbb911SFenghua Yu 	if (dp)
588ecdbb911SFenghua Yu 		closedir(dp);
589ecdbb911SFenghua Yu 	tests_run++;
590ecdbb911SFenghua Yu 
591ecdbb911SFenghua Yu 	printf("# resctrl filesystem %s mounted\n",
592ecdbb911SFenghua Yu 	       find_resctrl_mount(NULL) ? "not" : "is");
593ecdbb911SFenghua Yu 
594ecdbb911SFenghua Yu 	return ret;
595ecdbb911SFenghua Yu }
596ecdbb911SFenghua Yu 
597591a6e85SSai Praneeth Prakhya char *fgrep(FILE *inf, const char *str)
598591a6e85SSai Praneeth Prakhya {
599591a6e85SSai Praneeth Prakhya 	char line[256];
600591a6e85SSai Praneeth Prakhya 	int slen = strlen(str);
601591a6e85SSai Praneeth Prakhya 
602591a6e85SSai Praneeth Prakhya 	while (!feof(inf)) {
603591a6e85SSai Praneeth Prakhya 		if (!fgets(line, 256, inf))
604591a6e85SSai Praneeth Prakhya 			break;
605591a6e85SSai Praneeth Prakhya 		if (strncmp(line, str, slen))
606591a6e85SSai Praneeth Prakhya 			continue;
607591a6e85SSai Praneeth Prakhya 
608591a6e85SSai Praneeth Prakhya 		return strdup(line);
609591a6e85SSai Praneeth Prakhya 	}
610591a6e85SSai Praneeth Prakhya 
611591a6e85SSai Praneeth Prakhya 	return NULL;
612591a6e85SSai Praneeth Prakhya }
613591a6e85SSai Praneeth Prakhya 
614591a6e85SSai Praneeth Prakhya /*
615591a6e85SSai Praneeth Prakhya  * validate_resctrl_feature_request - Check if requested feature is valid.
616591a6e85SSai Praneeth Prakhya  * @resctrl_val:	Requested feature
617591a6e85SSai Praneeth Prakhya  *
618591a6e85SSai Praneeth Prakhya  * Return: 0 on success, non-zero on failure
619591a6e85SSai Praneeth Prakhya  */
620591a6e85SSai Praneeth Prakhya bool validate_resctrl_feature_request(char *resctrl_val)
621591a6e85SSai Praneeth Prakhya {
622591a6e85SSai Praneeth Prakhya 	FILE *inf = fopen("/proc/cpuinfo", "r");
623591a6e85SSai Praneeth Prakhya 	bool found = false;
624591a6e85SSai Praneeth Prakhya 	char *res;
625591a6e85SSai Praneeth Prakhya 
626591a6e85SSai Praneeth Prakhya 	if (!inf)
627591a6e85SSai Praneeth Prakhya 		return false;
628591a6e85SSai Praneeth Prakhya 
629591a6e85SSai Praneeth Prakhya 	res = fgrep(inf, "flags");
630591a6e85SSai Praneeth Prakhya 
631591a6e85SSai Praneeth Prakhya 	if (res) {
632591a6e85SSai Praneeth Prakhya 		char *s = strchr(res, ':');
633591a6e85SSai Praneeth Prakhya 
634591a6e85SSai Praneeth Prakhya 		found = s && !strstr(s, resctrl_val);
635591a6e85SSai Praneeth Prakhya 		free(res);
636591a6e85SSai Praneeth Prakhya 	}
637591a6e85SSai Praneeth Prakhya 	fclose(inf);
638591a6e85SSai Praneeth Prakhya 
639591a6e85SSai Praneeth Prakhya 	return found;
640591a6e85SSai Praneeth Prakhya }
641591a6e85SSai Praneeth Prakhya 
642ecdbb911SFenghua Yu int filter_dmesg(void)
643ecdbb911SFenghua Yu {
644ecdbb911SFenghua Yu 	char line[1024];
645ecdbb911SFenghua Yu 	FILE *fp;
646ecdbb911SFenghua Yu 	int pipefds[2];
647ecdbb911SFenghua Yu 	pid_t pid;
648ecdbb911SFenghua Yu 	int ret;
649ecdbb911SFenghua Yu 
650ecdbb911SFenghua Yu 	ret = pipe(pipefds);
651ecdbb911SFenghua Yu 	if (ret) {
652ecdbb911SFenghua Yu 		perror("pipe");
653ecdbb911SFenghua Yu 		return ret;
654ecdbb911SFenghua Yu 	}
655ecdbb911SFenghua Yu 	pid = fork();
656ecdbb911SFenghua Yu 	if (pid == 0) {
657ecdbb911SFenghua Yu 		close(pipefds[0]);
658ecdbb911SFenghua Yu 		dup2(pipefds[1], STDOUT_FILENO);
659ecdbb911SFenghua Yu 		execlp("dmesg", "dmesg", NULL);
660ecdbb911SFenghua Yu 		perror("executing dmesg");
661ecdbb911SFenghua Yu 		exit(1);
662ecdbb911SFenghua Yu 	}
663ecdbb911SFenghua Yu 	close(pipefds[1]);
664ecdbb911SFenghua Yu 	fp = fdopen(pipefds[0], "r");
665ecdbb911SFenghua Yu 	if (!fp) {
666ecdbb911SFenghua Yu 		perror("fdopen(pipe)");
667ecdbb911SFenghua Yu 		kill(pid, SIGTERM);
668ecdbb911SFenghua Yu 
669ecdbb911SFenghua Yu 		return -1;
670ecdbb911SFenghua Yu 	}
671ecdbb911SFenghua Yu 
672ecdbb911SFenghua Yu 	while (fgets(line, 1024, fp)) {
673ecdbb911SFenghua Yu 		if (strstr(line, "intel_rdt:"))
674ecdbb911SFenghua Yu 			printf("# dmesg: %s", line);
675ecdbb911SFenghua Yu 		if (strstr(line, "resctrl:"))
676ecdbb911SFenghua Yu 			printf("# dmesg: %s", line);
677ecdbb911SFenghua Yu 	}
678ecdbb911SFenghua Yu 	fclose(fp);
679ecdbb911SFenghua Yu 	waitpid(pid, NULL, 0);
680ecdbb911SFenghua Yu 
681ecdbb911SFenghua Yu 	return 0;
682ecdbb911SFenghua Yu }
683ecdbb911SFenghua Yu 
684591a6e85SSai Praneeth Prakhya int validate_bw_report_request(char *bw_report)
685591a6e85SSai Praneeth Prakhya {
686591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "reads") == 0)
687591a6e85SSai Praneeth Prakhya 		return 0;
688591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "writes") == 0)
689591a6e85SSai Praneeth Prakhya 		return 0;
690591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "nt-writes") == 0) {
691591a6e85SSai Praneeth Prakhya 		strcpy(bw_report, "writes");
692591a6e85SSai Praneeth Prakhya 		return 0;
693591a6e85SSai Praneeth Prakhya 	}
694591a6e85SSai Praneeth Prakhya 	if (strcmp(bw_report, "total") == 0)
695591a6e85SSai Praneeth Prakhya 		return 0;
696591a6e85SSai Praneeth Prakhya 
697591a6e85SSai Praneeth Prakhya 	fprintf(stderr, "Requested iMC B/W report type unavailable\n");
698591a6e85SSai Praneeth Prakhya 
699591a6e85SSai Praneeth Prakhya 	return -1;
700591a6e85SSai Praneeth Prakhya }
701591a6e85SSai Praneeth Prakhya 
702591a6e85SSai Praneeth Prakhya int perf_event_open(struct perf_event_attr *hw_event, pid_t pid, int cpu,
703591a6e85SSai Praneeth Prakhya 		    int group_fd, unsigned long flags)
704591a6e85SSai Praneeth Prakhya {
705591a6e85SSai Praneeth Prakhya 	int ret;
706591a6e85SSai Praneeth Prakhya 
707591a6e85SSai Praneeth Prakhya 	ret = syscall(__NR_perf_event_open, hw_event, pid, cpu,
708591a6e85SSai Praneeth Prakhya 		      group_fd, flags);
709591a6e85SSai Praneeth Prakhya 	return ret;
710591a6e85SSai Praneeth Prakhya }
71178941183SFenghua Yu 
71278941183SFenghua Yu unsigned int count_bits(unsigned long n)
71378941183SFenghua Yu {
71478941183SFenghua Yu 	unsigned int count = 0;
71578941183SFenghua Yu 
71678941183SFenghua Yu 	while (n) {
71778941183SFenghua Yu 		count += n & 1;
71878941183SFenghua Yu 		n >>= 1;
71978941183SFenghua Yu 	}
72078941183SFenghua Yu 
72178941183SFenghua Yu 	return count;
72278941183SFenghua Yu }
723