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 static const char * const sysfs__fs_known_mountpoints
[] = {
42 static const char * const procfs__known_mountpoints
[] = {
47 #ifndef DEBUGFS_DEFAULT_PATH
48 #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
51 static const char * const debugfs__known_mountpoints
[] = {
58 #ifndef TRACEFS_DEFAULT_PATH
59 #define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
62 static const char * const tracefs__known_mountpoints
[] = {
64 "/sys/kernel/debug/tracing",
72 const char * const *mounts
;
86 #define TRACEFS_MAGIC 0x74726163
89 static struct fs fs__entries
[] = {
92 .mounts
= sysfs__fs_known_mountpoints
,
97 .mounts
= procfs__known_mountpoints
,
98 .magic
= PROC_SUPER_MAGIC
,
102 .mounts
= debugfs__known_mountpoints
,
103 .magic
= DEBUGFS_MAGIC
,
107 .mounts
= tracefs__known_mountpoints
,
108 .magic
= TRACEFS_MAGIC
,
112 static bool fs__read_mounts(struct fs
*fs
)
118 fp
= fopen("/proc/mounts", "r");
123 fscanf(fp
, "%*s %" STR(PATH_MAX
) "s %99s %*s %*d %*d\n",
124 fs
->path
, type
) == 2) {
126 if (strcmp(type
, fs
->name
) == 0)
131 return fs
->found
= found
;
134 static int fs__valid_mount(const char *fs
, long magic
)
138 if (statfs(fs
, &st_fs
) < 0)
140 else if ((long)st_fs
.f_type
!= magic
)
146 static bool fs__check_mounts(struct fs
*fs
)
148 const char * const *ptr
;
152 if (fs__valid_mount(*ptr
, fs
->magic
) == 0) {
154 strcpy(fs
->path
, *ptr
);
163 static void mem_toupper(char *f
, size_t len
)
173 * Check for "NAME_PATH" environment variable to override fs location (for
174 * testing). This matches the recommendation in Documentation/sysfs-rules.txt
177 static bool fs__env_override(struct fs
*fs
)
180 size_t name_len
= strlen(fs
->name
);
181 /* name + "_PATH" + '\0' */
182 char upper_name
[name_len
+ 5 + 1];
183 memcpy(upper_name
, fs
->name
, name_len
);
184 mem_toupper(upper_name
, name_len
);
185 strcpy(&upper_name
[name_len
], "_PATH");
187 override_path
= getenv(upper_name
);
192 strncpy(fs
->path
, override_path
, sizeof(fs
->path
));
196 static const char *fs__get_mountpoint(struct fs
*fs
)
198 if (fs__env_override(fs
))
201 if (fs__check_mounts(fs
))
204 if (fs__read_mounts(fs
))
210 static const char *fs__mountpoint(int idx
)
212 struct fs
*fs
= &fs__entries
[idx
];
215 return (const char *)fs
->path
;
217 return fs__get_mountpoint(fs
);
220 static const char *mount_overload(struct fs
*fs
)
222 size_t name_len
= strlen(fs
->name
);
223 /* "PERF_" + name + "_ENVIRONMENT" + '\0' */
224 char upper_name
[5 + name_len
+ 12 + 1];
226 snprintf(upper_name
, name_len
, "PERF_%s_ENVIRONMENT", fs
->name
);
227 mem_toupper(upper_name
, name_len
);
229 return getenv(upper_name
) ?: *fs
->mounts
;
232 static const char *fs__mount(int idx
)
234 struct fs
*fs
= &fs__entries
[idx
];
235 const char *mountpoint
;
237 if (fs__mountpoint(idx
))
238 return (const char *)fs
->path
;
240 mountpoint
= mount_overload(fs
);
242 if (mount(NULL
, mountpoint
, fs
->name
, 0, NULL
) < 0)
245 return fs__check_mounts(fs
) ? fs
->path
: NULL
;
248 #define FS(name, idx) \
249 const char *name##__mountpoint(void) \
251 return fs__mountpoint(idx); \
254 const char *name##__mount(void) \
256 return fs__mount(idx); \
259 bool name##__configured(void) \
261 return name##__mountpoint() != NULL; \
264 FS(sysfs
, FS__SYSFS
);
265 FS(procfs
, FS__PROCFS
);
266 FS(debugfs
, FS__DEBUGFS
);
267 FS(tracefs
, FS__TRACEFS
);
269 int filename__read_int(const char *filename
, int *value
)
272 int fd
= open(filename
, O_RDONLY
), err
= -1;
277 if (read(fd
, line
, sizeof(line
)) > 0) {
286 int filename__read_ull(const char *filename
, unsigned long long *value
)
289 int fd
= open(filename
, O_RDONLY
), err
= -1;
294 if (read(fd
, line
, sizeof(line
)) > 0) {
295 *value
= strtoull(line
, NULL
, 10);
296 if (*value
!= ULLONG_MAX
)
304 #define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
306 int filename__read_str(const char *filename
, char **buf
, size_t *sizep
)
308 size_t size
= 0, alloc_size
= 0;
309 void *bf
= NULL
, *nbf
;
311 char sbuf
[STRERR_BUFSIZE
];
313 fd
= open(filename
, O_RDONLY
);
318 if (size
== alloc_size
) {
319 alloc_size
+= BUFSIZ
;
320 nbf
= realloc(bf
, alloc_size
);
329 n
= read(fd
, bf
+ size
, alloc_size
- size
);
332 pr_warning("read failed %d: %s\n", errno
,
333 strerror_r(errno
, sbuf
, sizeof(sbuf
)));
354 int sysfs__read_ull(const char *entry
, unsigned long long *value
)
357 const char *sysfs
= sysfs__mountpoint();
362 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
364 return filename__read_ull(path
, value
);
367 int sysfs__read_int(const char *entry
, int *value
)
370 const char *sysfs
= sysfs__mountpoint();
375 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
377 return filename__read_int(path
, value
);
380 int sysfs__read_str(const char *entry
, char **buf
, size_t *sizep
)
383 const char *sysfs
= sysfs__mountpoint();
388 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
390 return filename__read_str(path
, buf
, sizep
);
393 int sysctl__read_int(const char *sysctl
, int *value
)
396 const char *procfs
= procfs__mountpoint();
401 snprintf(path
, sizeof(path
), "%s/sys/%s", procfs
, sysctl
);
403 return filename__read_int(path
, value
);