1 /* 2 * Ftrace trace backend 3 * 4 * Copyright (C) 2013 Hitachi, Ltd. 5 * Created by Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com> 6 * 7 * This work is licensed under the terms of the GNU GPL, version 2. See 8 * the COPYING file in the top-level directory. 9 * 10 */ 11 12 #include "qemu/osdep.h" 13 #include "trace/control.h" 14 #include "trace/ftrace.h" 15 16 int trace_marker_fd; 17 18 static int find_mount(char *mount_point, const char *fstype) 19 { 20 char type[100]; 21 FILE *fp; 22 int ret = 0; 23 24 fp = fopen("/proc/mounts", "r"); 25 if (fp == NULL) { 26 return 0; 27 } 28 29 while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n", 30 mount_point, type) == 2) { 31 if (strcmp(type, fstype) == 0) { 32 ret = 1; 33 break; 34 } 35 } 36 fclose(fp); 37 38 return ret; 39 } 40 41 void ftrace_write(const char *fmt, ...) 42 { 43 char ftrace_buf[MAX_TRACE_STRLEN]; 44 int unused __attribute__ ((unused)); 45 int trlen; 46 va_list ap; 47 48 va_start(ap, fmt); 49 trlen = vsnprintf(ftrace_buf, MAX_TRACE_STRLEN, fmt, ap); 50 va_end(ap); 51 52 trlen = MIN(trlen, MAX_TRACE_STRLEN - 1); 53 unused = write(trace_marker_fd, ftrace_buf, trlen); 54 } 55 56 bool ftrace_init(void) 57 { 58 char mount_point[PATH_MAX]; 59 char path[PATH_MAX]; 60 int tracefs_found; 61 int trace_fd = -1; 62 const char *subdir = ""; 63 64 tracefs_found = find_mount(mount_point, "tracefs"); 65 if (!tracefs_found) { 66 tracefs_found = find_mount(mount_point, "debugfs"); 67 subdir = "/tracing"; 68 } 69 70 if (tracefs_found) { 71 if (snprintf(path, PATH_MAX, "%s%s/tracing_on", mount_point, subdir) 72 >= sizeof(path)) { 73 fprintf(stderr, "Using tracefs mountpoint would exceed PATH_MAX\n"); 74 return false; 75 } 76 trace_fd = open(path, O_WRONLY); 77 if (trace_fd < 0) { 78 if (errno == EACCES) { 79 trace_marker_fd = open("/dev/null", O_WRONLY); 80 if (trace_marker_fd != -1) { 81 return true; 82 } 83 } 84 perror("Could not open ftrace 'tracing_on' file"); 85 return false; 86 } else { 87 if (write(trace_fd, "1", 1) < 0) { 88 perror("Could not write to 'tracing_on' file"); 89 close(trace_fd); 90 return false; 91 } 92 close(trace_fd); 93 } 94 if (snprintf(path, PATH_MAX, "%s%s/trace_marker", mount_point, subdir) 95 >= sizeof(path)) { 96 fprintf(stderr, "Using tracefs mountpoint would exceed PATH_MAX\n"); 97 return false; 98 } 99 trace_marker_fd = open(path, O_WRONLY); 100 if (trace_marker_fd < 0) { 101 perror("Could not open ftrace 'trace_marker' file"); 102 return false; 103 } 104 } else { 105 fprintf(stderr, "tracefs is not mounted\n"); 106 return false; 107 } 108 109 return true; 110 } 111