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 */ 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 */ 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 */ 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 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 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 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 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 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 */ 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