fs.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #include <ctype.h>
  2. #include <errno.h>
  3. #include <limits.h>
  4. #include <stdbool.h>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <sys/vfs.h>
  9. #include <sys/types.h>
  10. #include <sys/stat.h>
  11. #include <fcntl.h>
  12. #include <unistd.h>
  13. #include <sys/mount.h>
  14. #include "fs.h"
  15. #include "debug-internal.h"
  16. #define _STR(x) #x
  17. #define STR(x) _STR(x)
  18. #ifndef SYSFS_MAGIC
  19. #define SYSFS_MAGIC 0x62656572
  20. #endif
  21. #ifndef PROC_SUPER_MAGIC
  22. #define PROC_SUPER_MAGIC 0x9fa0
  23. #endif
  24. #ifndef DEBUGFS_MAGIC
  25. #define DEBUGFS_MAGIC 0x64626720
  26. #endif
  27. #ifndef TRACEFS_MAGIC
  28. #define TRACEFS_MAGIC 0x74726163
  29. #endif
  30. #ifndef HUGETLBFS_MAGIC
  31. #define HUGETLBFS_MAGIC 0x958458f6
  32. #endif
  33. static const char * const sysfs__fs_known_mountpoints[] = {
  34. "/sys",
  35. 0,
  36. };
  37. static const char * const procfs__known_mountpoints[] = {
  38. "/proc",
  39. 0,
  40. };
  41. #ifndef DEBUGFS_DEFAULT_PATH
  42. #define DEBUGFS_DEFAULT_PATH "/sys/kernel/debug"
  43. #endif
  44. static const char * const debugfs__known_mountpoints[] = {
  45. DEBUGFS_DEFAULT_PATH,
  46. "/debug",
  47. 0,
  48. };
  49. #ifndef TRACEFS_DEFAULT_PATH
  50. #define TRACEFS_DEFAULT_PATH "/sys/kernel/tracing"
  51. #endif
  52. static const char * const tracefs__known_mountpoints[] = {
  53. TRACEFS_DEFAULT_PATH,
  54. "/sys/kernel/debug/tracing",
  55. "/tracing",
  56. "/trace",
  57. 0,
  58. };
  59. static const char * const hugetlbfs__known_mountpoints[] = {
  60. 0,
  61. };
  62. struct fs {
  63. const char *name;
  64. const char * const *mounts;
  65. char path[PATH_MAX];
  66. bool found;
  67. long magic;
  68. };
  69. enum {
  70. FS__SYSFS = 0,
  71. FS__PROCFS = 1,
  72. FS__DEBUGFS = 2,
  73. FS__TRACEFS = 3,
  74. FS__HUGETLBFS = 4,
  75. };
  76. #ifndef TRACEFS_MAGIC
  77. #define TRACEFS_MAGIC 0x74726163
  78. #endif
  79. static struct fs fs__entries[] = {
  80. [FS__SYSFS] = {
  81. .name = "sysfs",
  82. .mounts = sysfs__fs_known_mountpoints,
  83. .magic = SYSFS_MAGIC,
  84. },
  85. [FS__PROCFS] = {
  86. .name = "proc",
  87. .mounts = procfs__known_mountpoints,
  88. .magic = PROC_SUPER_MAGIC,
  89. },
  90. [FS__DEBUGFS] = {
  91. .name = "debugfs",
  92. .mounts = debugfs__known_mountpoints,
  93. .magic = DEBUGFS_MAGIC,
  94. },
  95. [FS__TRACEFS] = {
  96. .name = "tracefs",
  97. .mounts = tracefs__known_mountpoints,
  98. .magic = TRACEFS_MAGIC,
  99. },
  100. [FS__HUGETLBFS] = {
  101. .name = "hugetlbfs",
  102. .mounts = hugetlbfs__known_mountpoints,
  103. .magic = HUGETLBFS_MAGIC,
  104. },
  105. };
  106. static bool fs__read_mounts(struct fs *fs)
  107. {
  108. bool found = false;
  109. char type[100];
  110. FILE *fp;
  111. fp = fopen("/proc/mounts", "r");
  112. if (fp == NULL)
  113. return NULL;
  114. while (!found &&
  115. fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
  116. fs->path, type) == 2) {
  117. if (strcmp(type, fs->name) == 0)
  118. found = true;
  119. }
  120. fclose(fp);
  121. return fs->found = found;
  122. }
  123. static int fs__valid_mount(const char *fs, long magic)
  124. {
  125. struct statfs st_fs;
  126. if (statfs(fs, &st_fs) < 0)
  127. return -ENOENT;
  128. else if ((long)st_fs.f_type != magic)
  129. return -ENOENT;
  130. return 0;
  131. }
  132. static bool fs__check_mounts(struct fs *fs)
  133. {
  134. const char * const *ptr;
  135. ptr = fs->mounts;
  136. while (*ptr) {
  137. if (fs__valid_mount(*ptr, fs->magic) == 0) {
  138. fs->found = true;
  139. strcpy(fs->path, *ptr);
  140. return true;
  141. }
  142. ptr++;
  143. }
  144. return false;
  145. }
  146. static void mem_toupper(char *f, size_t len)
  147. {
  148. while (len) {
  149. *f = toupper(*f);
  150. f++;
  151. len--;
  152. }
  153. }
  154. /*
  155. * Check for "NAME_PATH" environment variable to override fs location (for
  156. * testing). This matches the recommendation in Documentation/sysfs-rules.txt
  157. * for SYSFS_PATH.
  158. */
  159. static bool fs__env_override(struct fs *fs)
  160. {
  161. char *override_path;
  162. size_t name_len = strlen(fs->name);
  163. /* name + "_PATH" + '\0' */
  164. char upper_name[name_len + 5 + 1];
  165. memcpy(upper_name, fs->name, name_len);
  166. mem_toupper(upper_name, name_len);
  167. strcpy(&upper_name[name_len], "_PATH");
  168. override_path = getenv(upper_name);
  169. if (!override_path)
  170. return false;
  171. fs->found = true;
  172. strncpy(fs->path, override_path, sizeof(fs->path));
  173. return true;
  174. }
  175. static const char *fs__get_mountpoint(struct fs *fs)
  176. {
  177. if (fs__env_override(fs))
  178. return fs->path;
  179. if (fs__check_mounts(fs))
  180. return fs->path;
  181. if (fs__read_mounts(fs))
  182. return fs->path;
  183. return NULL;
  184. }
  185. static const char *fs__mountpoint(int idx)
  186. {
  187. struct fs *fs = &fs__entries[idx];
  188. if (fs->found)
  189. return (const char *)fs->path;
  190. return fs__get_mountpoint(fs);
  191. }
  192. static const char *mount_overload(struct fs *fs)
  193. {
  194. size_t name_len = strlen(fs->name);
  195. /* "PERF_" + name + "_ENVIRONMENT" + '\0' */
  196. char upper_name[5 + name_len + 12 + 1];
  197. snprintf(upper_name, name_len, "PERF_%s_ENVIRONMENT", fs->name);
  198. mem_toupper(upper_name, name_len);
  199. return getenv(upper_name) ?: *fs->mounts;
  200. }
  201. static const char *fs__mount(int idx)
  202. {
  203. struct fs *fs = &fs__entries[idx];
  204. const char *mountpoint;
  205. if (fs__mountpoint(idx))
  206. return (const char *)fs->path;
  207. mountpoint = mount_overload(fs);
  208. if (mount(NULL, mountpoint, fs->name, 0, NULL) < 0)
  209. return NULL;
  210. return fs__check_mounts(fs) ? fs->path : NULL;
  211. }
  212. #define FS(name, idx) \
  213. const char *name##__mountpoint(void) \
  214. { \
  215. return fs__mountpoint(idx); \
  216. } \
  217. \
  218. const char *name##__mount(void) \
  219. { \
  220. return fs__mount(idx); \
  221. } \
  222. \
  223. bool name##__configured(void) \
  224. { \
  225. return name##__mountpoint() != NULL; \
  226. }
  227. FS(sysfs, FS__SYSFS);
  228. FS(procfs, FS__PROCFS);
  229. FS(debugfs, FS__DEBUGFS);
  230. FS(tracefs, FS__TRACEFS);
  231. FS(hugetlbfs, FS__HUGETLBFS);
  232. int filename__read_int(const char *filename, int *value)
  233. {
  234. char line[64];
  235. int fd = open(filename, O_RDONLY), err = -1;
  236. if (fd < 0)
  237. return -1;
  238. if (read(fd, line, sizeof(line)) > 0) {
  239. *value = atoi(line);
  240. err = 0;
  241. }
  242. close(fd);
  243. return err;
  244. }
  245. /*
  246. * Parses @value out of @filename with strtoull.
  247. * By using 0 for base, the strtoull detects the
  248. * base automatically (see man strtoull).
  249. */
  250. int filename__read_ull(const char *filename, unsigned long long *value)
  251. {
  252. char line[64];
  253. int fd = open(filename, O_RDONLY), err = -1;
  254. if (fd < 0)
  255. return -1;
  256. if (read(fd, line, sizeof(line)) > 0) {
  257. *value = strtoull(line, NULL, 0);
  258. if (*value != ULLONG_MAX)
  259. err = 0;
  260. }
  261. close(fd);
  262. return err;
  263. }
  264. #define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */
  265. int filename__read_str(const char *filename, char **buf, size_t *sizep)
  266. {
  267. size_t size = 0, alloc_size = 0;
  268. void *bf = NULL, *nbf;
  269. int fd, n, err = 0;
  270. char sbuf[STRERR_BUFSIZE];
  271. fd = open(filename, O_RDONLY);
  272. if (fd < 0)
  273. return -errno;
  274. do {
  275. if (size == alloc_size) {
  276. alloc_size += BUFSIZ;
  277. nbf = realloc(bf, alloc_size);
  278. if (!nbf) {
  279. err = -ENOMEM;
  280. break;
  281. }
  282. bf = nbf;
  283. }
  284. n = read(fd, bf + size, alloc_size - size);
  285. if (n < 0) {
  286. if (size) {
  287. pr_warning("read failed %d: %s\n", errno,
  288. strerror_r(errno, sbuf, sizeof(sbuf)));
  289. err = 0;
  290. } else
  291. err = -errno;
  292. break;
  293. }
  294. size += n;
  295. } while (n > 0);
  296. if (!err) {
  297. *sizep = size;
  298. *buf = bf;
  299. } else
  300. free(bf);
  301. close(fd);
  302. return err;
  303. }
  304. int procfs__read_str(const char *entry, char **buf, size_t *sizep)
  305. {
  306. char path[PATH_MAX];
  307. const char *procfs = procfs__mountpoint();
  308. if (!procfs)
  309. return -1;
  310. snprintf(path, sizeof(path), "%s/%s", procfs, entry);
  311. return filename__read_str(path, buf, sizep);
  312. }
  313. int sysfs__read_ull(const char *entry, unsigned long long *value)
  314. {
  315. char path[PATH_MAX];
  316. const char *sysfs = sysfs__mountpoint();
  317. if (!sysfs)
  318. return -1;
  319. snprintf(path, sizeof(path), "%s/%s", sysfs, entry);
  320. return filename__read_ull(path, value);
  321. }
  322. int sysfs__read_int(const char *entry, int *value)
  323. {
  324. char path[PATH_MAX];
  325. const char *sysfs = sysfs__mountpoint();
  326. if (!sysfs)
  327. return -1;
  328. snprintf(path, sizeof(path), "%s/%s", sysfs, entry);
  329. return filename__read_int(path, value);
  330. }
  331. int sysfs__read_str(const char *entry, char **buf, size_t *sizep)
  332. {
  333. char path[PATH_MAX];
  334. const char *sysfs = sysfs__mountpoint();
  335. if (!sysfs)
  336. return -1;
  337. snprintf(path, sizeof(path), "%s/%s", sysfs, entry);
  338. return filename__read_str(path, buf, sizep);
  339. }
  340. int sysctl__read_int(const char *sysctl, int *value)
  341. {
  342. char path[PATH_MAX];
  343. const char *procfs = procfs__mountpoint();
  344. if (!procfs)
  345. return -1;
  346. snprintf(path, sizeof(path), "%s/sys/%s", procfs, sysctl);
  347. return filename__read_int(path, value);
  348. }