• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "util.h"
2 #include "debugfs.h"
3 #include "cache.h"
4 
5 static int debugfs_premounted;
6 static char debugfs_mountpoint[MAX_PATH+1];
7 
8 static const char *debugfs_known_mountpoints[] = {
9 	"/sys/kernel/debug/",
10 	"/debug/",
11 	0,
12 };
13 
14 /* use this to force a umount */
debugfs_force_cleanup(void)15 void debugfs_force_cleanup(void)
16 {
17 	debugfs_find_mountpoint();
18 	debugfs_premounted = 0;
19 	debugfs_umount();
20 }
21 
22 /* construct a full path to a debugfs element */
debugfs_make_path(const char * element,char * buffer,int size)23 int debugfs_make_path(const char *element, char *buffer, int size)
24 {
25 	int len;
26 
27 	if (strlen(debugfs_mountpoint) == 0) {
28 		buffer[0] = '\0';
29 		return -1;
30 	}
31 
32 	len = strlen(debugfs_mountpoint) + strlen(element) + 1;
33 	if (len >= size)
34 		return len+1;
35 
36 	snprintf(buffer, size-1, "%s/%s", debugfs_mountpoint, element);
37 	return 0;
38 }
39 
40 static int debugfs_found;
41 
42 /* find the path to the mounted debugfs */
debugfs_find_mountpoint(void)43 const char *debugfs_find_mountpoint(void)
44 {
45 	const char **ptr;
46 	char type[100];
47 	FILE *fp;
48 
49 	if (debugfs_found)
50 		return (const char *) debugfs_mountpoint;
51 
52 	ptr = debugfs_known_mountpoints;
53 	while (*ptr) {
54 		if (debugfs_valid_mountpoint(*ptr) == 0) {
55 			debugfs_found = 1;
56 			strcpy(debugfs_mountpoint, *ptr);
57 			return debugfs_mountpoint;
58 		}
59 		ptr++;
60 	}
61 
62 	/* give up and parse /proc/mounts */
63 	fp = fopen("/proc/mounts", "r");
64 	if (fp == NULL)
65 		die("Can't open /proc/mounts for read");
66 
67 	while (fscanf(fp, "%*s %"
68 		      STR(MAX_PATH)
69 		      "s %99s %*s %*d %*d\n",
70 		      debugfs_mountpoint, type) == 2) {
71 		if (strcmp(type, "debugfs") == 0)
72 			break;
73 	}
74 	fclose(fp);
75 
76 	if (strcmp(type, "debugfs") != 0)
77 		return NULL;
78 
79 	debugfs_found = 1;
80 
81 	return debugfs_mountpoint;
82 }
83 
84 /* verify that a mountpoint is actually a debugfs instance */
85 
debugfs_valid_mountpoint(const char * debugfs)86 int debugfs_valid_mountpoint(const char *debugfs)
87 {
88 	/* ANDROID_CHANGE_BEGIN */
89 #ifndef __APPLE__
90 	struct statfs st_fs;
91 
92 	if (statfs(debugfs, &st_fs) < 0)
93 		return -ENOENT;
94 	else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
95 		return -ENOENT;
96 
97 #endif
98 	/* ANDROID_CHANGE_END */
99 	return 0;
100 }
101 
102 
debugfs_valid_entry(const char * path)103 int debugfs_valid_entry(const char *path)
104 {
105 	struct stat st;
106 
107 	if (stat(path, &st))
108 		return -errno;
109 
110 	return 0;
111 }
112 
113 /* mount the debugfs somewhere if it's not mounted */
114 
debugfs_mount(const char * mountpoint)115 char *debugfs_mount(const char *mountpoint)
116 {
117 	/* ANDROID_CHANGE_BEGIN */
118 #ifndef __APPLE__
119 	/* see if it's already mounted */
120 	if (debugfs_find_mountpoint()) {
121 		debugfs_premounted = 1;
122 		return debugfs_mountpoint;
123 	}
124 
125 	/* if not mounted and no argument */
126 	if (mountpoint == NULL) {
127 		/* see if environment variable set */
128 		mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
129 		/* if no environment variable, use default */
130 		if (mountpoint == NULL)
131 			mountpoint = "/sys/kernel/debug";
132 	}
133 
134 	if (mount(NULL, mountpoint, "debugfs", 0, NULL) < 0)
135 		return NULL;
136 
137 	/* save the mountpoint */
138 	strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
139 	debugfs_found = 1;
140 
141 	return debugfs_mountpoint;
142 #else
143 	return "perfhost";
144 #endif
145 	/* ANDROID_CHANGE_END */
146 }
147 
148 /* umount the debugfs */
149 
debugfs_umount(void)150 int debugfs_umount(void)
151 {
152 	char umountcmd[128];
153 	int ret;
154 
155 	/* if it was already mounted, leave it */
156 	if (debugfs_premounted)
157 		return 0;
158 
159 	/* make sure it's a valid mount point */
160 	ret = debugfs_valid_mountpoint(debugfs_mountpoint);
161 	if (ret)
162 		return ret;
163 
164 	snprintf(umountcmd, sizeof(umountcmd),
165 		 "/bin/umount %s", debugfs_mountpoint);
166 	return system(umountcmd);
167 }
168 
debugfs_write(const char * entry,const char * value)169 int debugfs_write(const char *entry, const char *value)
170 {
171 	char path[MAX_PATH+1];
172 	int ret, count;
173 	int fd;
174 
175 	/* construct the path */
176 	snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
177 
178 	/* verify that it exists */
179 	ret = debugfs_valid_entry(path);
180 	if (ret)
181 		return ret;
182 
183 	/* get how many chars we're going to write */
184 	count = strlen(value);
185 
186 	/* open the debugfs entry */
187 	fd = open(path, O_RDWR);
188 	if (fd < 0)
189 		return -errno;
190 
191 	while (count > 0) {
192 		/* write it */
193 		ret = write(fd, value, count);
194 		if (ret <= 0) {
195 			if (ret == EAGAIN)
196 				continue;
197 			close(fd);
198 			return -errno;
199 		}
200 		count -= ret;
201 	}
202 
203 	/* close it */
204 	close(fd);
205 
206 	/* return success */
207 	return 0;
208 }
209 
210 /*
211  * read a debugfs entry
212  * returns the number of chars read or a negative errno
213  */
debugfs_read(const char * entry,char * buffer,size_t size)214 int debugfs_read(const char *entry, char *buffer, size_t size)
215 {
216 	char path[MAX_PATH+1];
217 	int ret;
218 	int fd;
219 
220 	/* construct the path */
221 	snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
222 
223 	/* verify that it exists */
224 	ret = debugfs_valid_entry(path);
225 	if (ret)
226 		return ret;
227 
228 	/* open the debugfs entry */
229 	fd = open(path, O_RDONLY);
230 	if (fd < 0)
231 		return -errno;
232 
233 	do {
234 		/* read it */
235 		ret = read(fd, buffer, size);
236 		if (ret == 0) {
237 			close(fd);
238 			return EOF;
239 		}
240 	} while (ret < 0 && errno == EAGAIN);
241 
242 	/* close it */
243 	close(fd);
244 
245 	/* make *sure* there's a null character at the end */
246 	buffer[ret] = '\0';
247 
248 	/* return the number of chars read */
249 	return ret;
250 }
251