13 #include <sys/mount.h>
16 #include "debug-internal.h"
19 #define STR(x) _STR(x)
22 #define SYSFS_MAGIC 0x62656572
25 #ifndef PROC_SUPER_MAGIC
26 #define PROC_SUPER_MAGIC 0x9fa0
30 #define DEBUGFS_MAGIC 0x64626720
34 #define TRACEFS_MAGIC 0x74726163
37 #ifndef HUGETLBFS_MAGIC
38 #define HUGETLBFS_MAGIC 0x958458f6
42 #define BPF_FS_MAGIC 0xcafe4a11
45 static const char * const sysfs__fs_known_mountpoints
[] = {
50 static const char * const procfs__known_mountpoints
[] = {
55 #ifndef DEBUGFS_DEFAULT_PATH
56 #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
59 static const char * const debugfs__known_mountpoints
[] = {
66 #ifndef TRACEFS_DEFAULT_PATH
67 #define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
70 static const char * const tracefs__known_mountpoints
[] = {
72 "/sys/kernel/debug/tracing",
78 static const char * const hugetlbfs__known_mountpoints
[] = {
82 static const char * const bpf_fs__known_mountpoints
[] = {
89 const char * const *mounts
;
104 #ifndef TRACEFS_MAGIC
105 #define TRACEFS_MAGIC 0x74726163
108 static struct fs fs__entries
[] = {
111 .mounts
= sysfs__fs_known_mountpoints
,
112 .magic
= SYSFS_MAGIC
,
116 .mounts
= procfs__known_mountpoints
,
117 .magic
= PROC_SUPER_MAGIC
,
121 .mounts
= debugfs__known_mountpoints
,
122 .magic
= DEBUGFS_MAGIC
,
126 .mounts
= tracefs__known_mountpoints
,
127 .magic
= TRACEFS_MAGIC
,
131 .mounts
= hugetlbfs__known_mountpoints
,
132 .magic
= HUGETLBFS_MAGIC
,
136 .mounts
= bpf_fs__known_mountpoints
,
137 .magic
= BPF_FS_MAGIC
,
141 static bool fs__read_mounts(struct fs
*fs
)
147 fp
= fopen("/proc/mounts", "r");
152 fscanf(fp
, "%*s %" STR(PATH_MAX
) "s %99s %*s %*d %*d\n",
153 fs
->path
, type
) == 2) {
155 if (strcmp(type
, fs
->name
) == 0)
160 return fs
->found
= found
;
163 static int fs__valid_mount(const char *fs
, long magic
)
167 if (statfs(fs
, &st_fs
) < 0)
169 else if ((long)st_fs
.f_type
!= magic
)
175 static bool fs__check_mounts(struct fs
*fs
)
177 const char * const *ptr
;
181 if (fs__valid_mount(*ptr
, fs
->magic
) == 0) {
183 strcpy(fs
->path
, *ptr
);
192 static void mem_toupper(char *f
, size_t len
)
202 * Check for "NAME_PATH" environment variable to override fs location (for
203 * testing). This matches the recommendation in Documentation/sysfs-rules.txt
206 static bool fs__env_override(struct fs
*fs
)
209 size_t name_len
= strlen(fs
->name
);
210 /* name + "_PATH" + '\0' */
211 char upper_name
[name_len
+ 5 + 1];
212 memcpy(upper_name
, fs
->name
, name_len
);
213 mem_toupper(upper_name
, name_len
);
214 strcpy(&upper_name
[name_len
], "_PATH");
216 override_path
= getenv(upper_name
);
221 strncpy(fs
->path
, override_path
, sizeof(fs
->path
));
225 static const char *fs__get_mountpoint(struct fs
*fs
)
227 if (fs__env_override(fs
))
230 if (fs__check_mounts(fs
))
233 if (fs__read_mounts(fs
))
239 static const char *fs__mountpoint(int idx
)
241 struct fs
*fs
= &fs__entries
[idx
];
244 return (const char *)fs
->path
;
246 return fs__get_mountpoint(fs
);
249 static const char *mount_overload(struct fs
*fs
)
251 size_t name_len
= strlen(fs
->name
);
252 /* "PERF_" + name + "_ENVIRONMENT" + '\0' */
253 char upper_name
[5 + name_len
+ 12 + 1];
255 snprintf(upper_name
, name_len
, "PERF_%s_ENVIRONMENT", fs
->name
);
256 mem_toupper(upper_name
, name_len
);
258 return getenv(upper_name
) ?: *fs
->mounts
;
261 static const char *fs__mount(int idx
)
263 struct fs
*fs
= &fs__entries
[idx
];
264 const char *mountpoint
;
266 if (fs__mountpoint(idx
))
267 return (const char *)fs
->path
;
269 mountpoint
= mount_overload(fs
);
271 if (mount(NULL
, mountpoint
, fs
->name
, 0, NULL
) < 0)
274 return fs__check_mounts(fs
) ? fs
->path
: NULL
;
277 #define FS(name, idx) \
278 const char *name##__mountpoint(void) \
280 return fs__mountpoint(idx); \
283 const char *name##__mount(void) \
285 return fs__mount(idx); \
288 bool name##__configured(void) \
290 return name##__mountpoint() != NULL; \
293 FS(sysfs
, FS__SYSFS
);
294 FS(procfs
, FS__PROCFS
);
295 FS(debugfs
, FS__DEBUGFS
);
296 FS(tracefs
, FS__TRACEFS
);
297 FS(hugetlbfs
, FS__HUGETLBFS
);
298 FS(bpf_fs
, FS__BPF_FS
);
300 int filename__read_int(const char *filename
, int *value
)
303 int fd
= open(filename
, O_RDONLY
), err
= -1;
308 if (read(fd
, line
, sizeof(line
)) > 0) {
318 * Parses @value out of @filename with strtoull.
319 * By using 0 for base, the strtoull detects the
320 * base automatically (see man strtoull).
322 int filename__read_ull(const char *filename
, unsigned long long *value
)
325 int fd
= open(filename
, O_RDONLY
), err
= -1;
330 if (read(fd
, line
, sizeof(line
)) > 0) {
331 *value
= strtoull(line
, NULL
, 0);
332 if (*value
!= ULLONG_MAX
)
340 #define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
342 int filename__read_str(const char *filename
, char **buf
, size_t *sizep
)
344 size_t size
= 0, alloc_size
= 0;
345 void *bf
= NULL
, *nbf
;
347 char sbuf
[STRERR_BUFSIZE
];
349 fd
= open(filename
, O_RDONLY
);
354 if (size
== alloc_size
) {
355 alloc_size
+= BUFSIZ
;
356 nbf
= realloc(bf
, alloc_size
);
365 n
= read(fd
, bf
+ size
, alloc_size
- size
);
368 pr_warning("read failed %d: %s\n", errno
,
369 strerror_r(errno
, sbuf
, sizeof(sbuf
)));
390 int filename__write_int(const char *filename
, int value
)
392 int fd
= open(filename
, O_WRONLY
), err
= -1;
398 sprintf(buf
, "%d", value
);
399 if (write(fd
, buf
, sizeof(buf
)) == sizeof(buf
))
406 int procfs__read_str(const char *entry
, char **buf
, size_t *sizep
)
409 const char *procfs
= procfs__mountpoint();
414 snprintf(path
, sizeof(path
), "%s/%s", procfs
, entry
);
416 return filename__read_str(path
, buf
, sizep
);
419 int sysfs__read_ull(const char *entry
, unsigned long long *value
)
422 const char *sysfs
= sysfs__mountpoint();
427 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
429 return filename__read_ull(path
, value
);
432 int sysfs__read_int(const char *entry
, int *value
)
435 const char *sysfs
= sysfs__mountpoint();
440 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
442 return filename__read_int(path
, value
);
445 int sysfs__read_str(const char *entry
, char **buf
, size_t *sizep
)
448 const char *sysfs
= sysfs__mountpoint();
453 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
455 return filename__read_str(path
, buf
, sizep
);
458 int sysfs__read_bool(const char *entry
, bool *value
)
464 ret
= sysfs__read_str(entry
, &buf
, &size
);
487 int sysctl__read_int(const char *sysctl
, int *value
)
490 const char *procfs
= procfs__mountpoint();
495 snprintf(path
, sizeof(path
), "%s/sys/%s", procfs
, sysctl
);
497 return filename__read_int(path
, value
);
500 int sysfs__write_int(const char *entry
, int value
)
503 const char *sysfs
= sysfs__mountpoint();
508 if (snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
) >= PATH_MAX
)
511 return filename__write_int(path
, value
);