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

Merge tag 'trace-tools-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing tool updates from Steven Rostedt:

- Various clean ups and fixes to rtla (Real Time Linux Analysis)

* tag 'trace-tools-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
rtla: Remove procps-ng dependency
rtla: Fix __set_sched_attr error message
rtla: Minor grammar fix for rtla README
rtla: Don't overwrite existing directory mode
rtla: Avoid record NULL pointer dereference
rtla/Makefile: Properly handle dependencies

+165 -51
+13 -1
Documentation/tools/rtla/Makefile
··· 17 17 RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null) 18 18 RST2MAN_OPTS += --verbose 19 19 20 + TEST_RST2MAN = $(shell sh -c "rst2man --version > /dev/null 2>&1 || echo n") 21 + 20 22 $(OUTPUT)%.1: %.rst 21 23 ifndef RST2MAN_DEP 22 - $(error "rst2man not found, but required to generate man pages") 24 + $(info ********************************************) 25 + $(info ** NOTICE: rst2man not found) 26 + $(info **) 27 + $(info ** Consider installing the latest rst2man from your) 28 + $(info ** distribution, e.g., 'dnf install python3-docutils' on Fedora,) 29 + $(info ** or from source:) 30 + $(info **) 31 + $(info ** https://docutils.sourceforge.io/docs/dev/repository.html ) 32 + $(info **) 33 + $(info ********************************************) 34 + $(error NOTICE: rst2man required to generate man pages) 23 35 endif 24 36 rst2man $(RST2MAN_OPTS) $< > $@ 25 37
+38 -2
tools/tracing/rtla/Makefile
··· 23 23 $(call allow-override,LDCONFIG,ldconfig) 24 24 25 25 INSTALL = install 26 + MKDIR = mkdir 26 27 FOPTS := -flto=auto -ffat-lto-objects -fexceptions -fstack-protector-strong \ 27 28 -fasynchronous-unwind-tables -fstack-clash-protection 28 29 WOPTS := -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -Wno-maybe-uninitialized ··· 32 31 33 32 CFLAGS := -O -g -DVERSION=\"$(VERSION)\" $(FOPTS) $(MOPTS) $(WOPTS) $(TRACEFS_HEADERS) 34 33 LDFLAGS := -ggdb 35 - LIBS := $$($(PKG_CONFIG) --libs libtracefs) -lprocps 34 + LIBS := $$($(PKG_CONFIG) --libs libtracefs) 36 35 37 36 SRC := $(wildcard src/*.c) 38 37 HDR := $(wildcard src/*.h) ··· 58 57 DOCSRC = $(SRCTREE)/../../../Documentation/tools/rtla/ 59 58 endif 60 59 60 + LIBTRACEEVENT_MIN_VERSION = 1.5 61 + LIBTRACEFS_MIN_VERSION = 1.3 62 + 63 + TEST_LIBTRACEEVENT = $(shell sh -c "$(PKG_CONFIG) --atleast-version $(LIBTRACEEVENT_MIN_VERSION) libtraceevent > /dev/null 2>&1 || echo n") 64 + ifeq ("$(TEST_LIBTRACEEVENT)", "n") 65 + .PHONY: warning_traceevent 66 + warning_traceevent: 67 + @echo "********************************************" 68 + @echo "** NOTICE: libtraceevent version $(LIBTRACEEVENT_MIN_VERSION) or higher not found" 69 + @echo "**" 70 + @echo "** Consider installing the latest libtraceevent from your" 71 + @echo "** distribution, e.g., 'dnf install libtraceevent' on Fedora," 72 + @echo "** or from source:" 73 + @echo "**" 74 + @echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtraceevent.git/ " 75 + @echo "**" 76 + @echo "********************************************" 77 + endif 78 + 79 + TEST_LIBTRACEFS = $(shell sh -c "$(PKG_CONFIG) --atleast-version $(LIBTRACEFS_MIN_VERSION) libtracefs > /dev/null 2>&1 || echo n") 80 + ifeq ("$(TEST_LIBTRACEFS)", "n") 81 + .PHONY: warning_tracefs 82 + warning_tracefs: 83 + @echo "********************************************" 84 + @echo "** NOTICE: libtracefs version $(LIBTRACEFS_MIN_VERSION) or higher not found" 85 + @echo "**" 86 + @echo "** Consider installing the latest libtracefs from your" 87 + @echo "** distribution, e.g., 'dnf install libtracefs' on Fedora," 88 + @echo "** or from source:" 89 + @echo "**" 90 + @echo "** https://git.kernel.org/pub/scm/libs/libtrace/libtracefs.git/ " 91 + @echo "**" 92 + @echo "********************************************" 93 + endif 94 + 61 95 .PHONY: all 62 96 all: rtla 63 97 ··· 104 68 105 69 .PHONY: install 106 70 install: doc_install 107 - $(INSTALL) -d -m 755 $(DESTDIR)$(BINDIR) 71 + $(MKDIR) -p $(DESTDIR)$(BINDIR) 108 72 $(INSTALL) rtla -m 755 $(DESTDIR)$(BINDIR) 109 73 $(STRIP) $(DESTDIR)$(BINDIR)/rtla 110 74 @test ! -f $(DESTDIR)$(BINDIR)/osnoise || rm $(DESTDIR)$(BINDIR)/osnoise
+5 -8
tools/tracing/rtla/README.txt
··· 1 1 RTLA: Real-Time Linux Analysis tools 2 2 3 - The rtla is a meta-tool that includes a set of commands that 4 - aims to analyze the real-time properties of Linux. But, instead of 5 - testing Linux as a black box, rtla leverages kernel tracing 6 - capabilities to provide precise information about the properties 7 - and root causes of unexpected results. 3 + The rtla meta-tool includes a set of commands that aims to analyze 4 + the real-time properties of Linux. Instead of testing Linux as a black box, 5 + rtla leverages kernel tracing capabilities to provide precise information 6 + about the properties and root causes of unexpected results. 8 7 9 8 Installing RTLA 10 9 11 - RTLA depends on some libraries and tools. More precisely, it depends on the 12 - following libraries: 10 + RTLA depends on the following libraries and tools: 13 11 14 12 - libtracefs 15 13 - libtraceevent 16 - - procps 17 14 18 15 It also depends on python3-docutils to compile man pages. 19 16
+3 -2
tools/tracing/rtla/src/osnoise_hist.c
··· 809 809 retval = set_comm_sched_attr("osnoise/", &params->sched_param); 810 810 if (retval) { 811 811 err_msg("Failed to set sched parameters\n"); 812 - goto out_hist; 812 + goto out_free; 813 813 } 814 814 } 815 815 ··· 819 819 record = osnoise_init_trace_tool("osnoise"); 820 820 if (!record) { 821 821 err_msg("Failed to enable the trace instance\n"); 822 - goto out_hist; 822 + goto out_free; 823 823 } 824 824 825 825 if (params->events) { ··· 869 869 out_hist: 870 870 trace_events_destroy(&record->trace, params->events); 871 871 params->events = NULL; 872 + out_free: 872 873 osnoise_free_histogram(tool->data); 873 874 out_destroy: 874 875 osnoise_destroy_tool(record);
+5 -4
tools/tracing/rtla/src/osnoise_top.c
··· 572 572 retval = osnoise_top_apply_config(tool, params); 573 573 if (retval) { 574 574 err_msg("Could not apply config\n"); 575 - goto out_top; 575 + goto out_free; 576 576 } 577 577 578 578 trace = &tool->trace; ··· 580 580 retval = enable_osnoise(trace); 581 581 if (retval) { 582 582 err_msg("Failed to enable osnoise tracer\n"); 583 - goto out_top; 583 + goto out_free; 584 584 } 585 585 586 586 if (params->set_sched) { 587 587 retval = set_comm_sched_attr("osnoise/", &params->sched_param); 588 588 if (retval) { 589 589 err_msg("Failed to set sched parameters\n"); 590 - goto out_top; 590 + goto out_free; 591 591 } 592 592 } 593 593 ··· 597 597 record = osnoise_init_trace_tool("osnoise"); 598 598 if (!record) { 599 599 err_msg("Failed to enable the trace instance\n"); 600 - goto out_top; 600 + goto out_free; 601 601 } 602 602 603 603 if (params->events) { ··· 649 649 out_top: 650 650 trace_events_destroy(&record->trace, params->events); 651 651 params->events = NULL; 652 + out_free: 652 653 osnoise_free_top(tool->data); 653 654 osnoise_destroy_tool(record); 654 655 osnoise_destroy_tool(tool);
+6 -5
tools/tracing/rtla/src/timerlat_hist.c
··· 821 821 retval = timerlat_hist_apply_config(tool, params); 822 822 if (retval) { 823 823 err_msg("Could not apply config\n"); 824 - goto out_hist; 824 + goto out_free; 825 825 } 826 826 827 827 trace = &tool->trace; ··· 829 829 retval = enable_timerlat(trace); 830 830 if (retval) { 831 831 err_msg("Failed to enable timerlat tracer\n"); 832 - goto out_hist; 832 + goto out_free; 833 833 } 834 834 835 835 if (params->set_sched) { 836 836 retval = set_comm_sched_attr("timerlat/", &params->sched_param); 837 837 if (retval) { 838 838 err_msg("Failed to set sched parameters\n"); 839 - goto out_hist; 839 + goto out_free; 840 840 } 841 841 } 842 842 ··· 844 844 dma_latency_fd = set_cpu_dma_latency(params->dma_latency); 845 845 if (dma_latency_fd < 0) { 846 846 err_msg("Could not set /dev/cpu_dma_latency.\n"); 847 - goto out_hist; 847 + goto out_free; 848 848 } 849 849 } 850 850 ··· 854 854 record = osnoise_init_trace_tool("timerlat"); 855 855 if (!record) { 856 856 err_msg("Failed to enable the trace instance\n"); 857 - goto out_hist; 857 + goto out_free; 858 858 } 859 859 860 860 if (params->events) { ··· 904 904 close(dma_latency_fd); 905 905 trace_events_destroy(&record->trace, params->events); 906 906 params->events = NULL; 907 + out_free: 907 908 timerlat_free_histogram(tool->data); 908 909 osnoise_destroy_tool(record); 909 910 osnoise_destroy_tool(tool);
+6 -5
tools/tracing/rtla/src/timerlat_top.c
··· 612 612 retval = timerlat_top_apply_config(top, params); 613 613 if (retval) { 614 614 err_msg("Could not apply config\n"); 615 - goto out_top; 615 + goto out_free; 616 616 } 617 617 618 618 trace = &top->trace; ··· 620 620 retval = enable_timerlat(trace); 621 621 if (retval) { 622 622 err_msg("Failed to enable timerlat tracer\n"); 623 - goto out_top; 623 + goto out_free; 624 624 } 625 625 626 626 if (params->set_sched) { 627 627 retval = set_comm_sched_attr("timerlat/", &params->sched_param); 628 628 if (retval) { 629 629 err_msg("Failed to set sched parameters\n"); 630 - goto out_top; 630 + goto out_free; 631 631 } 632 632 } 633 633 ··· 635 635 dma_latency_fd = set_cpu_dma_latency(params->dma_latency); 636 636 if (dma_latency_fd < 0) { 637 637 err_msg("Could not set /dev/cpu_dma_latency.\n"); 638 - goto out_top; 638 + goto out_free; 639 639 } 640 640 } 641 641 ··· 645 645 record = osnoise_init_trace_tool("timerlat"); 646 646 if (!record) { 647 647 err_msg("Failed to enable the trace instance\n"); 648 - goto out_top; 648 + goto out_free; 649 649 } 650 650 651 651 if (params->events) { ··· 699 699 close(dma_latency_fd); 700 700 trace_events_destroy(&record->trace, params->events); 701 701 params->events = NULL; 702 + out_free: 702 703 timerlat_free_top(top->data); 703 704 osnoise_destroy_tool(record); 704 705 osnoise_destroy_tool(top);
+87 -23
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> ··· 255 255 256 256 retval = sched_setattr(pid, attr, flags); 257 257 if (retval < 0) { 258 - err_msg("boost_with_deadline failed to boost pid %d: %s\n", 258 + err_msg("Failed to set sched attributes to the pid %d: %s\n", 259 259 pid, strerror(errno)); 260 260 return 1; 261 261 } 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);