|
3 | 3 | * Copyright (C) 2021 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org> |
4 | 4 | */ |
5 | 5 |
|
6 | | -#include <proc/readproc.h> |
| 6 | +#include <dirent.h> |
7 | 7 | #include <stdarg.h> |
8 | 8 | #include <stdlib.h> |
9 | 9 | #include <string.h> |
@@ -262,43 +262,107 @@ int __set_sched_attr(int pid, struct sched_attr *attr) |
262 | 262 |
|
263 | 263 | return 0; |
264 | 264 | } |
| 265 | + |
| 266 | +/* |
| 267 | + * procfs_is_workload_pid - check if a procfs entry contains a comm_prefix* comm |
| 268 | + * |
| 269 | + * Check if the procfs entry is a directory of a process, and then check if the |
| 270 | + * process has a comm with the prefix set in char *comm_prefix. As the |
| 271 | + * current users of this function only check for kernel threads, there is no |
| 272 | + * need to check for the threads for the process. |
| 273 | + * |
| 274 | + * Return: True if the proc_entry contains a comm file with comm_prefix*. |
| 275 | + * Otherwise returns false. |
| 276 | + */ |
| 277 | +static int procfs_is_workload_pid(const char *comm_prefix, struct dirent *proc_entry) |
| 278 | +{ |
| 279 | + char buffer[MAX_PATH]; |
| 280 | + int comm_fd, retval; |
| 281 | + char *t_name; |
| 282 | + |
| 283 | + if (proc_entry->d_type != DT_DIR) |
| 284 | + return 0; |
| 285 | + |
| 286 | + if (*proc_entry->d_name == '.') |
| 287 | + return 0; |
| 288 | + |
| 289 | + /* check if the string is a pid */ |
| 290 | + for (t_name = proc_entry->d_name; t_name; t_name++) { |
| 291 | + if (!isdigit(*t_name)) |
| 292 | + break; |
| 293 | + } |
| 294 | + |
| 295 | + if (*t_name != '\0') |
| 296 | + return 0; |
| 297 | + |
| 298 | + snprintf(buffer, MAX_PATH, "/proc/%s/comm", proc_entry->d_name); |
| 299 | + comm_fd = open(buffer, O_RDONLY); |
| 300 | + if (comm_fd < 0) |
| 301 | + return 0; |
| 302 | + |
| 303 | + memset(buffer, 0, MAX_PATH); |
| 304 | + retval = read(comm_fd, buffer, MAX_PATH); |
| 305 | + |
| 306 | + close(comm_fd); |
| 307 | + |
| 308 | + if (retval <= 0) |
| 309 | + return 0; |
| 310 | + |
| 311 | + retval = strncmp(comm_prefix, buffer, strlen(comm_prefix)); |
| 312 | + if (retval) |
| 313 | + return 0; |
| 314 | + |
| 315 | + /* comm already have \n */ |
| 316 | + debug_msg("Found workload pid:%s comm:%s", proc_entry->d_name, buffer); |
| 317 | + |
| 318 | + return 1; |
| 319 | +} |
| 320 | + |
265 | 321 | /* |
266 | | - * set_comm_sched_attr - set sched params to threads starting with char *comm |
| 322 | + * set_comm_sched_attr - set sched params to threads starting with char *comm_prefix |
267 | 323 | * |
268 | | - * This function uses procps to list the currently running threads and then |
269 | | - * set the sched_attr *attr to the threads that start with char *comm. It is |
| 324 | + * This function uses procfs to list the currently running threads and then set the |
| 325 | + * sched_attr *attr to the threads that start with char *comm_prefix. It is |
270 | 326 | * mainly used to set the priority to the kernel threads created by the |
271 | 327 | * tracers. |
272 | 328 | */ |
273 | | -int set_comm_sched_attr(const char *comm, struct sched_attr *attr) |
| 329 | +int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr) |
274 | 330 | { |
275 | | - int flags = PROC_FILLCOM | PROC_FILLSTAT; |
276 | | - PROCTAB *ptp; |
277 | | - proc_t task; |
| 331 | + struct dirent *proc_entry; |
| 332 | + DIR *procfs; |
278 | 333 | int retval; |
279 | 334 |
|
280 | | - ptp = openproc(flags); |
281 | | - if (!ptp) { |
282 | | - err_msg("error openproc()\n"); |
283 | | - return -ENOENT; |
| 335 | + if (strlen(comm_prefix) >= MAX_PATH) { |
| 336 | + err_msg("Command prefix is too long: %d < strlen(%s)\n", |
| 337 | + MAX_PATH, comm_prefix); |
| 338 | + return 1; |
284 | 339 | } |
285 | 340 |
|
286 | | - memset(&task, 0, sizeof(task)); |
| 341 | + procfs = opendir("/proc"); |
| 342 | + if (!procfs) { |
| 343 | + err_msg("Could not open procfs\n"); |
| 344 | + return 1; |
| 345 | + } |
287 | 346 |
|
288 | | - while (readproc(ptp, &task)) { |
289 | | - retval = strncmp(comm, task.cmd, strlen(comm)); |
290 | | - if (retval) |
| 347 | + while ((proc_entry = readdir(procfs))) { |
| 348 | + |
| 349 | + retval = procfs_is_workload_pid(comm_prefix, proc_entry); |
| 350 | + if (!retval) |
291 | 351 | continue; |
292 | | - retval = __set_sched_attr(task.tid, attr); |
293 | | - if (retval) |
| 352 | + |
| 353 | + /* procfs_is_workload_pid confirmed it is a pid */ |
| 354 | + retval = __set_sched_attr(atoi(proc_entry->d_name), attr); |
| 355 | + if (retval) { |
| 356 | + err_msg("Error setting sched attributes for pid:%s\n", proc_entry->d_name); |
294 | 357 | goto out_err; |
295 | | - } |
| 358 | + } |
296 | 359 |
|
297 | | - closeproc(ptp); |
| 360 | + debug_msg("Set sched attributes for pid:%s\n", proc_entry->d_name); |
| 361 | + } |
298 | 362 | return 0; |
299 | 363 |
|
300 | 364 | out_err: |
301 | | - closeproc(ptp); |
| 365 | + closedir(procfs); |
302 | 366 | return 1; |
303 | 367 | } |
304 | 368 |
|
|
0 commit comments