1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #ifndef _GNU_SOURCE |
3 | # define _GNU_SOURCE |
4 | #endif |
5 | |
6 | #include <stdio.h> |
7 | #include <stdlib.h> |
8 | #include <string.h> |
9 | #include <linux/string.h> |
10 | #include <errno.h> |
11 | #include <unistd.h> |
12 | #include "fs.h" |
13 | |
14 | #include "tracing_path.h" |
15 | |
16 | static char tracing_path[PATH_MAX] = "/sys/kernel/tracing" ; |
17 | |
18 | static void __tracing_path_set(const char *tracing, const char *mountpoint) |
19 | { |
20 | snprintf(tracing_path, sizeof(tracing_path), "%s/%s" , |
21 | mountpoint, tracing); |
22 | } |
23 | |
24 | static const char *tracing_path_tracefs_mount(void) |
25 | { |
26 | const char *mnt; |
27 | |
28 | mnt = tracefs__mount(); |
29 | if (!mnt) |
30 | return NULL; |
31 | |
32 | __tracing_path_set(tracing: "" , mountpoint: mnt); |
33 | |
34 | return tracing_path; |
35 | } |
36 | |
37 | static const char *tracing_path_debugfs_mount(void) |
38 | { |
39 | const char *mnt; |
40 | |
41 | mnt = debugfs__mount(); |
42 | if (!mnt) |
43 | return NULL; |
44 | |
45 | __tracing_path_set(tracing: "tracing/" , mountpoint: mnt); |
46 | |
47 | return tracing_path; |
48 | } |
49 | |
50 | const char *tracing_path_mount(void) |
51 | { |
52 | const char *mnt; |
53 | |
54 | mnt = tracing_path_tracefs_mount(); |
55 | if (mnt) |
56 | return mnt; |
57 | |
58 | mnt = tracing_path_debugfs_mount(); |
59 | |
60 | return mnt; |
61 | } |
62 | |
63 | void tracing_path_set(const char *mntpt) |
64 | { |
65 | __tracing_path_set(tracing: "tracing/" , mountpoint: mntpt); |
66 | } |
67 | |
68 | char *get_tracing_file(const char *name) |
69 | { |
70 | char *file; |
71 | |
72 | if (asprintf(&file, "%s/%s" , tracing_path_mount(), name) < 0) |
73 | return NULL; |
74 | |
75 | return file; |
76 | } |
77 | |
78 | void put_tracing_file(char *file) |
79 | { |
80 | free(file); |
81 | } |
82 | |
83 | char *get_events_file(const char *name) |
84 | { |
85 | char *file; |
86 | |
87 | if (asprintf(&file, "%s/events/%s" , tracing_path_mount(), name) < 0) |
88 | return NULL; |
89 | |
90 | return file; |
91 | } |
92 | |
93 | void put_events_file(char *file) |
94 | { |
95 | free(file); |
96 | } |
97 | |
98 | DIR *tracing_events__opendir(void) |
99 | { |
100 | DIR *dir = NULL; |
101 | char *path = get_tracing_file(name: "events" ); |
102 | |
103 | if (path) { |
104 | dir = opendir(path); |
105 | put_events_file(file: path); |
106 | } |
107 | |
108 | return dir; |
109 | } |
110 | |
111 | int tracing_events__scandir_alphasort(struct dirent ***namelist) |
112 | { |
113 | char *path = get_tracing_file(name: "events" ); |
114 | int ret; |
115 | |
116 | if (!path) { |
117 | *namelist = NULL; |
118 | return 0; |
119 | } |
120 | |
121 | ret = scandir(path, namelist, NULL, alphasort); |
122 | put_events_file(file: path); |
123 | |
124 | return ret; |
125 | } |
126 | |
127 | int tracing_path__strerror_open_tp(int err, char *buf, size_t size, |
128 | const char *sys, const char *name) |
129 | { |
130 | char sbuf[128]; |
131 | char filename[PATH_MAX]; |
132 | |
133 | snprintf(filename, PATH_MAX, "%s/%s" , sys, name ?: "*" ); |
134 | |
135 | switch (err) { |
136 | case ENOENT: |
137 | /* |
138 | * We will get here if we can't find the tracepoint, but one of |
139 | * debugfs or tracefs is configured, which means you probably |
140 | * want some tracepoint which wasn't compiled in your kernel. |
141 | * - jirka |
142 | */ |
143 | if (debugfs__configured() || tracefs__configured()) { |
144 | /* sdt markers */ |
145 | if (!strncmp(filename, "sdt_" , 4)) { |
146 | snprintf(buf, size, |
147 | "Error:\tFile %s/events/%s not found.\n" |
148 | "Hint:\tSDT event cannot be directly recorded on.\n" |
149 | "\tPlease first use 'perf probe %s:%s' before recording it.\n" , |
150 | tracing_path, filename, sys, name); |
151 | } else { |
152 | snprintf(buf, size, |
153 | "Error:\tFile %s/events/%s not found.\n" |
154 | "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n" , |
155 | tracing_path, filename); |
156 | } |
157 | break; |
158 | } |
159 | snprintf(buf, size, "%s" , |
160 | "Error:\tUnable to find debugfs/tracefs\n" |
161 | "Hint:\tWas your kernel compiled with debugfs/tracefs support?\n" |
162 | "Hint:\tIs the debugfs/tracefs filesystem mounted?\n" |
163 | "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'" ); |
164 | break; |
165 | case EACCES: { |
166 | snprintf(buf, size, |
167 | "Error:\tNo permissions to read %s/events/%s\n" |
168 | "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n" , |
169 | tracing_path, filename, tracing_path_mount()); |
170 | } |
171 | break; |
172 | default: |
173 | snprintf(buf, size, "%s" , str_error_r(err, sbuf, sizeof(sbuf))); |
174 | break; |
175 | } |
176 | |
177 | return 0; |
178 | } |
179 | |