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 */
  85. int debugfs_mount(const char *mountpoint)
  86. {
  87. char mountcmd[128];
  88. /* see if it's already mounted */
  89. if (debugfs_find_mountpoint()) {
  90. debugfs_premounted = 1;
  91. return 0;
  92. }
  93. /* if not mounted and no argument */
  94. if (mountpoint == NULL) {
  95. /* see if environment variable set */
  96. mountpoint = getenv(PERF_DEBUGFS_ENVIRONMENT);
  97. /* if no environment variable, use default */
  98. if (mountpoint == NULL)
  99. mountpoint = "/sys/kernel/debug";
  100. }
  101. /* save the mountpoint */
  102. strncpy(debugfs_mountpoint, mountpoint, sizeof(debugfs_mountpoint));
  103. /* mount it */
  104. snprintf(mountcmd, sizeof(mountcmd),
  105. "/bin/mount -t debugfs debugfs %s", mountpoint);
  106. return system(mountcmd);
  107. }
  108. /* umount the debugfs */
  109. int debugfs_umount(void)
  110. {
  111. char umountcmd[128];
  112. int ret;
  113. /* if it was already mounted, leave it */
  114. if (debugfs_premounted)
  115. return 0;
  116. /* make sure it's a valid mount point */
  117. ret = debugfs_valid_mountpoint(debugfs_mountpoint);
  118. if (ret)
  119. return ret;
  120. snprintf(umountcmd, sizeof(umountcmd),
  121. "/bin/umount %s", debugfs_mountpoint);
  122. return system(umountcmd);
  123. }
  124. int debugfs_write(const char *entry, const char *value)
  125. {
  126. char path[MAX_PATH+1];
  127. int ret, count;
  128. int fd;
  129. /* construct the path */
  130. snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
  131. /* verify that it exists */
  132. ret = debugfs_valid_entry(path);
  133. if (ret)
  134. return ret;
  135. /* get how many chars we're going to write */
  136. count = strlen(value);
  137. /* open the debugfs entry */
  138. fd = open(path, O_RDWR);
  139. if (fd < 0)
  140. return -errno;
  141. while (count > 0) {
  142. /* write it */
  143. ret = write(fd, value, count);
  144. if (ret <= 0) {
  145. if (ret == EAGAIN)
  146. continue;
  147. close(fd);
  148. return -errno;
  149. }
  150. count -= ret;
  151. }
  152. /* close it */
  153. close(fd);
  154. /* return success */
  155. return 0;
  156. }
  157. /*
  158. * read a debugfs entry
  159. * returns the number of chars read or a negative errno
  160. */
  161. int debugfs_read(const char *entry, char *buffer, size_t size)
  162. {
  163. char path[MAX_PATH+1];
  164. int ret;
  165. int fd;
  166. /* construct the path */
  167. snprintf(path, sizeof(path), "%s/%s", debugfs_mountpoint, entry);
  168. /* verify that it exists */
  169. ret = debugfs_valid_entry(path);
  170. if (ret)
  171. return ret;
  172. /* open the debugfs entry */
  173. fd = open(path, O_RDONLY);
  174. if (fd < 0)
  175. return -errno;
  176. do {
  177. /* read it */
  178. ret = read(fd, buffer, size);
  179. if (ret == 0) {
  180. close(fd);
  181. return EOF;
  182. }
  183. } while (ret < 0 && errno == EAGAIN);
  184. /* close it */
  185. close(fd);
  186. /* make *sure* there's a null character at the end */
  187. buffer[ret] = '\0';
  188. /* return the number of chars read */
  189. return ret;
  190. }