xref: /openbmc/linux/tools/lib/api/fs/tracing_path.c (revision 4605eab3)
1 #ifndef _GNU_SOURCE
2 # define _GNU_SOURCE
3 #endif
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include "fs.h"
11 
12 #include "tracing_path.h"
13 
14 
15 char tracing_path[PATH_MAX + 1]        = "/sys/kernel/debug/tracing";
16 char tracing_events_path[PATH_MAX + 1] = "/sys/kernel/debug/tracing/events";
17 
18 
19 static void __tracing_path_set(const char *tracing, const char *mountpoint)
20 {
21 	snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
22 		 mountpoint, tracing);
23 	snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
24 		 mountpoint, tracing, "events");
25 }
26 
27 static const char *tracing_path_tracefs_mount(void)
28 {
29 	const char *mnt;
30 
31 	mnt = tracefs__mount();
32 	if (!mnt)
33 		return NULL;
34 
35 	__tracing_path_set("", mnt);
36 
37 	return mnt;
38 }
39 
40 static const char *tracing_path_debugfs_mount(void)
41 {
42 	const char *mnt;
43 
44 	mnt = debugfs__mount();
45 	if (!mnt)
46 		return NULL;
47 
48 	__tracing_path_set("tracing/", mnt);
49 
50 	return mnt;
51 }
52 
53 const char *tracing_path_mount(void)
54 {
55 	const char *mnt;
56 
57 	mnt = tracing_path_tracefs_mount();
58 	if (mnt)
59 		return mnt;
60 
61 	mnt = tracing_path_debugfs_mount();
62 
63 	return mnt;
64 }
65 
66 void tracing_path_set(const char *mntpt)
67 {
68 	__tracing_path_set("tracing/", mntpt);
69 }
70 
71 char *get_tracing_file(const char *name)
72 {
73 	char *file;
74 
75 	if (asprintf(&file, "%s/%s", tracing_path, name) < 0)
76 		return NULL;
77 
78 	return file;
79 }
80 
81 void put_tracing_file(char *file)
82 {
83 	free(file);
84 }
85 
86 static int strerror_open(int err, char *buf, size_t size, const char *filename)
87 {
88 	char sbuf[128];
89 
90 	switch (err) {
91 	case ENOENT:
92 		/*
93 		 * We will get here if we can't find the tracepoint, but one of
94 		 * debugfs or tracefs is configured, which means you probably
95 		 * want some tracepoint which wasn't compiled in your kernel.
96 		 * - jirka
97 		 */
98 		if (debugfs__configured() || tracefs__configured()) {
99 			snprintf(buf, size,
100 				 "Error:\tFile %s/%s not found.\n"
101 				 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
102 				 tracing_events_path, filename);
103 			break;
104 		}
105 		snprintf(buf, size, "%s",
106 			 "Error:\tUnable to find debugfs/tracefs\n"
107 			 "Hint:\tWas your kernel compiled with debugfs/tracefs support?\n"
108 			 "Hint:\tIs the debugfs/tracefs filesystem mounted?\n"
109 			 "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
110 		break;
111 	case EACCES: {
112 		const char *mountpoint = debugfs__mountpoint();
113 
114 		if (!access(mountpoint, R_OK) && strncmp(filename, "tracing/", 8) == 0) {
115 			const char *tracefs_mntpoint = tracefs__mountpoint();
116 
117 			if (tracefs_mntpoint)
118 				mountpoint = tracefs__mountpoint();
119 		}
120 
121 		snprintf(buf, size,
122 			 "Error:\tNo permissions to read %s/%s\n"
123 			 "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
124 			 tracing_events_path, filename, mountpoint);
125 	}
126 		break;
127 	default:
128 		snprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf)));
129 		break;
130 	}
131 
132 	return 0;
133 }
134 
135 int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
136 {
137 	char path[PATH_MAX];
138 
139 	snprintf(path, PATH_MAX, "%s/%s", sys, name ?: "*");
140 
141 	return strerror_open(err, buf, size, path);
142 }
143