debugfs.c 4.5 KB

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