13 #include <sys/mount.h>
18 #define STR(x) _STR(x)
21 #define SYSFS_MAGIC 0x62656572
24 #ifndef PROC_SUPER_MAGIC
25 #define PROC_SUPER_MAGIC 0x9fa0
29 #define DEBUGFS_MAGIC 0x64626720
33 #define TRACEFS_MAGIC 0x74726163
36 static const char * const sysfs__fs_known_mountpoints
[] = {
41 static const char * const procfs__known_mountpoints
[] = {
46 #ifndef DEBUGFS_DEFAULT_PATH
47 #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
50 static const char * const debugfs__known_mountpoints
[] = {
57 #ifndef TRACEFS_DEFAULT_PATH
58 #define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
61 static const char * const tracefs__known_mountpoints
[] = {
63 "/sys/kernel/debug/tracing",
71 const char * const *mounts
;
85 #define TRACEFS_MAGIC 0x74726163
88 static struct fs fs__entries
[] = {
91 .mounts
= sysfs__fs_known_mountpoints
,
96 .mounts
= procfs__known_mountpoints
,
97 .magic
= PROC_SUPER_MAGIC
,
101 .mounts
= debugfs__known_mountpoints
,
102 .magic
= DEBUGFS_MAGIC
,
106 .mounts
= tracefs__known_mountpoints
,
107 .magic
= TRACEFS_MAGIC
,
111 static bool fs__read_mounts(struct fs
*fs
)
117 fp
= fopen("/proc/mounts", "r");
122 fscanf(fp
, "%*s %" STR(PATH_MAX
) "s %99s %*s %*d %*d\n",
123 fs
->path
, type
) == 2) {
125 if (strcmp(type
, fs
->name
) == 0)
130 return fs
->found
= found
;
133 static int fs__valid_mount(const char *fs
, long magic
)
137 if (statfs(fs
, &st_fs
) < 0)
139 else if ((long)st_fs
.f_type
!= magic
)
145 static bool fs__check_mounts(struct fs
*fs
)
147 const char * const *ptr
;
151 if (fs__valid_mount(*ptr
, fs
->magic
) == 0) {
153 strcpy(fs
->path
, *ptr
);
162 static void mem_toupper(char *f
, size_t len
)
172 * Check for "NAME_PATH" environment variable to override fs location (for
173 * testing). This matches the recommendation in Documentation/sysfs-rules.txt
176 static bool fs__env_override(struct fs
*fs
)
179 size_t name_len
= strlen(fs
->name
);
180 /* name + "_PATH" + '\0' */
181 char upper_name
[name_len
+ 5 + 1];
182 memcpy(upper_name
, fs
->name
, name_len
);
183 mem_toupper(upper_name
, name_len
);
184 strcpy(&upper_name
[name_len
], "_PATH");
186 override_path
= getenv(upper_name
);
191 strncpy(fs
->path
, override_path
, sizeof(fs
->path
));
195 static const char *fs__get_mountpoint(struct fs
*fs
)
197 if (fs__env_override(fs
))
200 if (fs__check_mounts(fs
))
203 if (fs__read_mounts(fs
))
209 static const char *fs__mountpoint(int idx
)
211 struct fs
*fs
= &fs__entries
[idx
];
214 return (const char *)fs
->path
;
216 return fs__get_mountpoint(fs
);
219 static const char *mount_overload(struct fs
*fs
)
221 size_t name_len
= strlen(fs
->name
);
222 /* "PERF_" + name + "_ENVIRONMENT" + '\0' */
223 char upper_name
[5 + name_len
+ 12 + 1];
225 snprintf(upper_name
, name_len
, "PERF_%s_ENVIRONMENT", fs
->name
);
226 mem_toupper(upper_name
, name_len
);
228 return getenv(upper_name
) ?: *fs
->mounts
;
231 static const char *fs__mount(int idx
)
233 struct fs
*fs
= &fs__entries
[idx
];
234 const char *mountpoint
;
236 if (fs__mountpoint(idx
))
237 return (const char *)fs
->path
;
239 mountpoint
= mount_overload(fs
);
241 if (mount(NULL
, mountpoint
, fs
->name
, 0, NULL
) < 0)
244 return fs__check_mounts(fs
) ? fs
->path
: NULL
;
247 #define FS(name, idx) \
248 const char *name##__mountpoint(void) \
250 return fs__mountpoint(idx); \
253 const char *name##__mount(void) \
255 return fs__mount(idx); \
258 bool name##__configured(void) \
260 return name##__mountpoint() != NULL; \
263 FS(sysfs
, FS__SYSFS
);
264 FS(procfs
, FS__PROCFS
);
265 FS(debugfs
, FS__DEBUGFS
);
266 FS(tracefs
, FS__TRACEFS
);
268 int filename__read_int(const char *filename
, int *value
)
271 int fd
= open(filename
, O_RDONLY
), err
= -1;
276 if (read(fd
, line
, sizeof(line
)) > 0) {
285 int filename__read_ull(const char *filename
, unsigned long long *value
)
288 int fd
= open(filename
, O_RDONLY
), err
= -1;
293 if (read(fd
, line
, sizeof(line
)) > 0) {
294 *value
= strtoull(line
, NULL
, 10);
295 if (*value
!= ULLONG_MAX
)
303 int sysfs__read_ull(const char *entry
, unsigned long long *value
)
306 const char *sysfs
= sysfs__mountpoint();
311 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
313 return filename__read_ull(path
, value
);
316 int sysfs__read_int(const char *entry
, int *value
)
319 const char *sysfs
= sysfs__mountpoint();
324 snprintf(path
, sizeof(path
), "%s/%s", sysfs
, entry
);
326 return filename__read_int(path
, value
);
329 int sysctl__read_int(const char *sysctl
, int *value
)
332 const char *procfs
= procfs__mountpoint();
337 snprintf(path
, sizeof(path
), "%s/sys/%s", procfs
, sysctl
);
339 return filename__read_int(path
, value
);