Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtla: Remove procps-ng dependency

Daniel Wagner reported to me that readproc.h got deprecated. Also,
while the procps-ng library was available on Fedora, it was not available
on RHEL, which is a piece of evidence that it was not that used.

rtla uses procps-ng only to find the PID of the tracers' workload.

I used the procps-ng library to avoid reinventing the wheel. But in this
case, reinventing the wheel took me less time than the time we already
took trying to work around problems.

Implement a function that reads /proc/ entries, checking if:
- the entry is a directory
- the directory name is composed only of digits (PID)
- the directory contains the comm file
- the comm file contains a comm that matches the tracers'
workload prefix.
- then return true; otherwise, return false.

And use it instead of procps-ng.

Link: https://lkml.kernel.org/r/e8276e122ee9eb2c5a0ba8e673fb6488b924b825.1652423574.git.bristot@kernel.org

Cc: John Kacur <jkacur@redhat.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Tao Zhou <tao.zhou@linux.dev>
Fixes: b1696371d865 ("rtla: Helper functions for rtla")
Reported-by: Daniel Wagner <dwagner@suse.de>
Reviewed-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Daniel Bristot de Oliveira <bristot@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

authored by

Daniel Bristot de Oliveira and committed by
Steven Rostedt (Google)
dada03db 941a53c3

+89 -25
+1 -1
tools/tracing/rtla/Makefile
··· 32 32 33 33 CFLAGS := -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) 34 34 LDFLAGS := -ggdb 35 - LIBS := $$($(PKG_CONFIG) --libs libtracefs) -lprocps 35 + LIBS := $$($(PKG_CONFIG) --libs libtracefs) 36 36 37 37 SRC := $(wildcard src/*.c) 38 38 HDR := $(wildcard src/*.h)
-1
tools/tracing/rtla/README.txt
··· 11 11 12 12 - libtracefs 13 13 - libtraceevent 14 - - procps 15 14 16 15 It also depends on python3-docutils to compile man pages. 17 16
+86 -22
tools/tracing/rtla/src/utils.c
··· 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 262 263 263 return 0; 264 264 } 265 + 265 266 /* 266 - * set_comm_sched_attr - set sched params to threads starting with char *comm 267 + * procfs_is_workload_pid - check if a procfs entry contains a comm_prefix* comm 267 268 * 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 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 + 321 + /* 322 + * set_comm_sched_attr - set sched params to threads starting with char *comm_prefix 323 + * 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) 294 - goto out_err; 295 - } 296 352 297 - closeproc(ptp); 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); 357 + goto out_err; 358 + } 359 + 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
+2 -1
tools/tracing/rtla/src/utils.h
··· 6 6 * '18446744073709551615\0' 7 7 */ 8 8 #define BUFF_U64_STR_SIZE 24 9 + #define MAX_PATH 1024 9 10 10 11 #define container_of(ptr, type, member)({ \ 11 12 const typeof(((type *)0)->member) *__mptr = (ptr); \ ··· 54 53 }; 55 54 56 55 int parse_prio(char *arg, struct sched_attr *sched_param); 57 - int set_comm_sched_attr(const char *comm, struct sched_attr *attr); 56 + int set_comm_sched_attr(const char *comm_prefix, struct sched_attr *attr); 58 57 int set_cpu_dma_latency(int32_t latency);