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