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
41 static const char * const sysfs__fs_known_mountpoints
[] = {
46 static const char * const procfs__known_mountpoints
[] = {
51 #ifndef DEBUGFS_DEFAULT_PATH
52 #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
55 static const char * const debugfs__known_mountpoints
[] = {
62 #ifndef TRACEFS_DEFAULT_PATH
63 #define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
66 static const char * const tracefs__known_mountpoints
[] = {
68 "/sys/kernel/debug/tracing",
74 static const char * const hugetlbfs__known_mountpoints
[] = {
80 const char * const *mounts
;
95 #define TRACEFS_MAGIC 0x74726163
98 static struct fs fs__entries
[] = {
101 .mounts
= sysfs__fs_known_mountpoints
,
102 .magic
= SYSFS_MAGIC
,
106 .mounts
= procfs__known_mountpoints
,
107 .magic
= PROC_SUPER_MAGIC
,
111 .mounts
= debugfs__known_mountpoints
,
112 .magic
= DEBUGFS_MAGIC
,
116 .mounts
= tracefs__known_mountpoints
,
117 .magic
= TRACEFS_MAGIC
,
121 .mounts
= hugetlbfs__known_mountpoints
,
122 .magic
= HUGETLBFS_MAGIC
,
126 static bool fs__read_mounts(struct fs
*fs
)
132 fp
= fopen("/proc/mounts", "r");
137 fscanf(fp
, "%*s %" STR(PATH_MAX
) "s %99s %*s %*d %*d\n",
138 fs
->path
, type
) == 2) {
140 if (strcmp(type
, fs
->name
) == 0)
145 return fs
->found
= found
;
148 static int fs__valid_mount(const char *fs
, long magic
)
152 if (statfs(fs
, &st_fs
) < 0)
154 else if ((long)st_fs
.f_type
!= magic
)
160 static bool fs__check_mounts(struct fs
*fs
)
162 const char * const *ptr
;
166 if (fs__valid_mount(*ptr
, fs
->magic
) == 0) {
168 strcpy(fs
->path
, *ptr
);
177 static void mem_toupper(char *f
, size_t len
)
187 * Check for "NAME_PATH" environment variable to override fs location (for
188 * testing). This matches the recommendation in Documentation/sysfs-rules.txt
191 static bool fs__env_override(struct fs
*fs
)
194 size_t name_len
= strlen(fs
->name
);
195 /* name + "_PATH" + '\0' */
196 char upper_name
[name_len
+ 5 + 1];
197 memcpy(upper_name
, fs
->name
, name_len
);
198 mem_toupper(upper_name
, name_len
);
199 strcpy(&upper_name
[name_len
], "_PATH");
201 override_path
= getenv(upper_name
);
206 strncpy(fs
->path
, override_path
, sizeof(fs
->path
));
210 static const char *fs__get_mountpoint(struct fs
*fs
)
212 if (fs__env_override(fs
))
215 if (fs__check_mounts(fs
))
218 if (fs__read_mounts(fs
))
224 static const char *fs__mountpoint(int idx
)
226 struct fs
*fs
= &fs__entries
[idx
];
229 return (const char *)fs
->path
;
231 return fs__get_mountpoint(fs
);
234 static const char *mount_overload(struct fs
*fs
)
236 size_t name_len
= strlen(fs
->name
);
237 /* "PERF_" + name + "_ENVIRONMENT" + '\0' */
238 char upper_name
[5 + name_len
+ 12 + 1];
240 snprintf(upper_name
, name_len
, "PERF_%s_ENVIRONMENT", fs
->name
);
241 mem_toupper(upper_name
, name_len
);
243 return getenv(upper_name
) ?: *fs
->mounts
;
246 static const char *fs__mount(int idx
)
248 struct fs
*fs
= &fs__entries
[idx
];
249 const char *mountpoint
;
251 if (fs__mountpoint(idx
))
252 return (const char *)fs
->path
;
254 mountpoint
= mount_overload(fs
);
256 if (mount(NULL
, mountpoint
, fs
->name
, 0, NULL
) < 0)
259 return fs__check_mounts(fs
) ? fs
->path
: NULL
;
262 #define FS(name, idx) \
263 const char *name##__mountpoint(void) \
265 return fs__mountpoint(idx); \
268 const char *name##__mount(void) \
270 return fs__mount(idx); \
273 bool name##__configured(void) \
275 return name##__mountpoint() != NULL; \
278 FS(sysfs
, FS__SYSFS
);
279 FS(procfs
, FS__PROCFS
);
280 FS(debugfs
, FS__DEBUGFS
);
281 FS(tracefs
, FS__TRACEFS
);
282 FS(hugetlbfs
, FS__HUGETLBFS
);
284 int filename__read_int(const char *filename
, int *value
)
287 int fd
= open(filename
, O_RDONLY
), err
= -1;
292 if (read(fd
, line
, sizeof(line
)) > 0) {
302 * Parses @value out of @filename with strtoull.
303 * By using 0 for base, the strtoull detects the
304 * base automatically (see man strtoull).
306 int filename__read_ull(const char *filename
, unsigned long long *value
)
309 int fd
= open(filename
, O_RDONLY
), err
= -1;
314 if (read(fd
, line
, sizeof(line
)) > 0) {
315 *value
= strtoull(line
, NULL
, 0);
316 if (*value
!= ULLONG_MAX
)
324 #define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
326 int filename__read_str(const char *filename
, char **buf
, size_t *sizep
)
328 size_t size
= 0, alloc_size
= 0;
329 void *bf
= NULL
, *nbf
;
331 char sbuf
[STRERR_BUFSIZE
];
333 fd
= open(filename
, O_RDONLY
);
338 if (size
== alloc_size
) {
339 alloc_size
+= BUFSIZ
;
340 nbf
= realloc(bf
, alloc_size
);
349 n
= read(fd
, bf
+ size
, alloc_size
- size
);
352 pr_warning("read failed %d: %s\n", errno
,
353 strerror_r(errno
, sbuf
, sizeof(sbuf
)));
374 int procfs__read_str(const char *entry
, char **buf
, size_t *sizep
)
377 const char *procfs
= procfs__mountpoint();
382 snprintf(path
, sizeof(path
), "%s/%s", procfs
, entry
);
384 return filename__read_str(path
, buf
, sizep
);
387 int sysfs__read_ull(const char *entry
, unsigned long long *value
)
390 const char *sysfs
= sysfs__mountpoint();
395 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
397 return filename__read_ull(path
, value
);
400 int sysfs__read_int(const char *entry
, int *value
)
403 const char *sysfs
= sysfs__mountpoint();
408 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
410 return filename__read_int(path
, value
);
413 int sysfs__read_str(const char *entry
, char **buf
, size_t *sizep
)
416 const char *sysfs
= sysfs__mountpoint();
421 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
423 return filename__read_str(path
, buf
, sizep
);
426 int sysctl__read_int(const char *sysctl
, int *value
)
429 const char *procfs
= procfs__mountpoint();
434 snprintf(path
, sizeof(path
), "%s/sys/%s", procfs
, sysctl
);
436 return filename__read_int(path
, value
);