1 // SPDX-License-Identifier: GPL-2.0
10 #include <sys/types.h>
14 #include <sys/mount.h>
17 #include "debug-internal.h"
20 #define STR(x) _STR(x)
23 #define SYSFS_MAGIC 0x62656572
26 #ifndef PROC_SUPER_MAGIC
27 #define PROC_SUPER_MAGIC 0x9fa0
31 #define DEBUGFS_MAGIC 0x64626720
35 #define TRACEFS_MAGIC 0x74726163
38 #ifndef HUGETLBFS_MAGIC
39 #define HUGETLBFS_MAGIC 0x958458f6
43 #define BPF_FS_MAGIC 0xcafe4a11
46 static const char * const sysfs__fs_known_mountpoints
[] = {
51 static const char * const procfs__known_mountpoints
[] = {
56 #ifndef DEBUGFS_DEFAULT_PATH
57 #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
60 static const char * const debugfs__known_mountpoints
[] = {
67 #ifndef TRACEFS_DEFAULT_PATH
68 #define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
71 static const char * const tracefs__known_mountpoints
[] = {
73 "/sys/kernel/debug/tracing",
79 static const char * const hugetlbfs__known_mountpoints
[] = {
83 static const char * const bpf_fs__known_mountpoints
[] = {
90 const char * const *mounts
;
105 #ifndef TRACEFS_MAGIC
106 #define TRACEFS_MAGIC 0x74726163
109 static struct fs fs__entries
[] = {
112 .mounts
= sysfs__fs_known_mountpoints
,
113 .magic
= SYSFS_MAGIC
,
117 .mounts
= procfs__known_mountpoints
,
118 .magic
= PROC_SUPER_MAGIC
,
122 .mounts
= debugfs__known_mountpoints
,
123 .magic
= DEBUGFS_MAGIC
,
127 .mounts
= tracefs__known_mountpoints
,
128 .magic
= TRACEFS_MAGIC
,
132 .mounts
= hugetlbfs__known_mountpoints
,
133 .magic
= HUGETLBFS_MAGIC
,
137 .mounts
= bpf_fs__known_mountpoints
,
138 .magic
= BPF_FS_MAGIC
,
142 static bool fs__read_mounts(struct fs
*fs
)
148 fp
= fopen("/proc/mounts", "r");
153 fscanf(fp
, "%*s %" STR(PATH_MAX
) "s %99s %*s %*d %*d\n",
154 fs
->path
, type
) == 2) {
156 if (strcmp(type
, fs
->name
) == 0)
161 return fs
->found
= found
;
164 static int fs__valid_mount(const char *fs
, long magic
)
168 if (statfs(fs
, &st_fs
) < 0)
170 else if ((long)st_fs
.f_type
!= magic
)
176 static bool fs__check_mounts(struct fs
*fs
)
178 const char * const *ptr
;
182 if (fs__valid_mount(*ptr
, fs
->magic
) == 0) {
184 strcpy(fs
->path
, *ptr
);
193 static void mem_toupper(char *f
, size_t len
)
203 * Check for "NAME_PATH" environment variable to override fs location (for
204 * testing). This matches the recommendation in Documentation/sysfs-rules.txt
207 static bool fs__env_override(struct fs
*fs
)
210 size_t name_len
= strlen(fs
->name
);
211 /* name + "_PATH" + '\0' */
212 char upper_name
[name_len
+ 5 + 1];
213 memcpy(upper_name
, fs
->name
, name_len
);
214 mem_toupper(upper_name
, name_len
);
215 strcpy(&upper_name
[name_len
], "_PATH");
217 override_path
= getenv(upper_name
);
222 strncpy(fs
->path
, override_path
, sizeof(fs
->path
));
226 static const char *fs__get_mountpoint(struct fs
*fs
)
228 if (fs__env_override(fs
))
231 if (fs__check_mounts(fs
))
234 if (fs__read_mounts(fs
))
240 static const char *fs__mountpoint(int idx
)
242 struct fs
*fs
= &fs__entries
[idx
];
245 return (const char *)fs
->path
;
247 return fs__get_mountpoint(fs
);
250 static const char *mount_overload(struct fs
*fs
)
252 size_t name_len
= strlen(fs
->name
);
253 /* "PERF_" + name + "_ENVIRONMENT" + '\0' */
254 char upper_name
[5 + name_len
+ 12 + 1];
256 snprintf(upper_name
, name_len
, "PERF_%s_ENVIRONMENT", fs
->name
);
257 mem_toupper(upper_name
, name_len
);
259 return getenv(upper_name
) ?: *fs
->mounts
;
262 static const char *fs__mount(int idx
)
264 struct fs
*fs
= &fs__entries
[idx
];
265 const char *mountpoint
;
267 if (fs__mountpoint(idx
))
268 return (const char *)fs
->path
;
270 mountpoint
= mount_overload(fs
);
272 if (mount(NULL
, mountpoint
, fs
->name
, 0, NULL
) < 0)
275 return fs__check_mounts(fs
) ? fs
->path
: NULL
;
278 #define FS(name, idx) \
279 const char *name##__mountpoint(void) \
281 return fs__mountpoint(idx); \
284 const char *name##__mount(void) \
286 return fs__mount(idx); \
289 bool name##__configured(void) \
291 return name##__mountpoint() != NULL; \
294 FS(sysfs
, FS__SYSFS
);
295 FS(procfs
, FS__PROCFS
);
296 FS(debugfs
, FS__DEBUGFS
);
297 FS(tracefs
, FS__TRACEFS
);
298 FS(hugetlbfs
, FS__HUGETLBFS
);
299 FS(bpf_fs
, FS__BPF_FS
);
301 int filename__read_int(const char *filename
, int *value
)
304 int fd
= open(filename
, O_RDONLY
), err
= -1;
309 if (read(fd
, line
, sizeof(line
)) > 0) {
319 * Parses @value out of @filename with strtoull.
320 * By using 0 for base, the strtoull detects the
321 * base automatically (see man strtoull).
323 int filename__read_ull(const char *filename
, unsigned long long *value
)
326 int fd
= open(filename
, O_RDONLY
), err
= -1;
331 if (read(fd
, line
, sizeof(line
)) > 0) {
332 *value
= strtoull(line
, NULL
, 0);
333 if (*value
!= ULLONG_MAX
)
341 #define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
343 int filename__read_str(const char *filename
, char **buf
, size_t *sizep
)
345 size_t size
= 0, alloc_size
= 0;
346 void *bf
= NULL
, *nbf
;
348 char sbuf
[STRERR_BUFSIZE
];
350 fd
= open(filename
, O_RDONLY
);
355 if (size
== alloc_size
) {
356 alloc_size
+= BUFSIZ
;
357 nbf
= realloc(bf
, alloc_size
);
366 n
= read(fd
, bf
+ size
, alloc_size
- size
);
369 pr_warning("read failed %d: %s\n", errno
,
370 strerror_r(errno
, sbuf
, sizeof(sbuf
)));
391 int filename__write_int(const char *filename
, int value
)
393 int fd
= open(filename
, O_WRONLY
), err
= -1;
399 sprintf(buf
, "%d", value
);
400 if (write(fd
, buf
, sizeof(buf
)) == sizeof(buf
))
407 int procfs__read_str(const char *entry
, char **buf
, size_t *sizep
)
410 const char *procfs
= procfs__mountpoint();
415 snprintf(path
, sizeof(path
), "%s/%s", procfs
, entry
);
417 return filename__read_str(path
, buf
, sizep
);
420 int sysfs__read_ull(const char *entry
, unsigned long long *value
)
423 const char *sysfs
= sysfs__mountpoint();
428 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
430 return filename__read_ull(path
, value
);
433 int sysfs__read_int(const char *entry
, int *value
)
436 const char *sysfs
= sysfs__mountpoint();
441 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
443 return filename__read_int(path
, value
);
446 int sysfs__read_str(const char *entry
, char **buf
, size_t *sizep
)
449 const char *sysfs
= sysfs__mountpoint();
454 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
456 return filename__read_str(path
, buf
, sizep
);
459 int sysfs__read_bool(const char *entry
, bool *value
)
465 ret
= sysfs__read_str(entry
, &buf
, &size
);
488 int sysctl__read_int(const char *sysctl
, int *value
)
491 const char *procfs
= procfs__mountpoint();
496 snprintf(path
, sizeof(path
), "%s/sys/%s", procfs
, sysctl
);
498 return filename__read_int(path
, value
);
501 int sysfs__write_int(const char *entry
, int value
)
504 const char *sysfs
= sysfs__mountpoint();
509 if (snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
) >= PATH_MAX
)
512 return filename__write_int(path
, value
);