| /* | 
 |  * Ftrace trace backend | 
 |  * | 
 |  * Copyright (C) 2013 Hitachi, Ltd. | 
 |  * Created by Eiichi Tsukata <eiichi.tsukata.xh@hitachi.com> | 
 |  * | 
 |  * This work is licensed under the terms of the GNU GPL, version 2.  See | 
 |  * the COPYING file in the top-level directory. | 
 |  * | 
 |  */ | 
 |  | 
 | #include "qemu/osdep.h" | 
 | #include "trace/control.h" | 
 | #include "trace/ftrace.h" | 
 |  | 
 | int trace_marker_fd; | 
 |  | 
 | static int find_mount(char *mount_point, const char *fstype) | 
 | { | 
 |     char type[100]; | 
 |     FILE *fp; | 
 |     int ret = 0; | 
 |  | 
 |     fp = fopen("/proc/mounts", "r"); | 
 |     if (fp == NULL) { | 
 |         return 0; | 
 |     } | 
 |  | 
 |     while (fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n", | 
 |                   mount_point, type) == 2) { | 
 |         if (strcmp(type, fstype) == 0) { | 
 |             ret = 1; | 
 |             break; | 
 |         } | 
 |     } | 
 |     fclose(fp); | 
 |  | 
 |     return ret; | 
 | } | 
 |  | 
 | bool ftrace_init(void) | 
 | { | 
 |     char mount_point[PATH_MAX]; | 
 |     char path[PATH_MAX]; | 
 |     int tracefs_found; | 
 |     int trace_fd = -1; | 
 |     const char *subdir = ""; | 
 |  | 
 |     tracefs_found = find_mount(mount_point, "tracefs"); | 
 |     if (!tracefs_found) { | 
 |         tracefs_found = find_mount(mount_point, "debugfs"); | 
 |         subdir = "/tracing"; | 
 |     } | 
 |  | 
 |     if (tracefs_found) { | 
 |         if (snprintf(path, PATH_MAX, "%s%s/tracing_on", mount_point, subdir) | 
 |                 >= sizeof(path)) { | 
 |             fprintf(stderr, "Using tracefs mountpoint would exceed PATH_MAX\n"); | 
 |             return false; | 
 |         } | 
 |         trace_fd = open(path, O_WRONLY); | 
 |         if (trace_fd < 0) { | 
 |             if (errno == EACCES) { | 
 |                 trace_marker_fd = open("/dev/null", O_WRONLY); | 
 |                 if (trace_marker_fd != -1) { | 
 |                     return true; | 
 |                 } | 
 |             } | 
 |             perror("Could not open ftrace 'tracing_on' file"); | 
 |             return false; | 
 |         } else { | 
 |             if (write(trace_fd, "1", 1) < 0) { | 
 |                 perror("Could not write to 'tracing_on' file"); | 
 |                 close(trace_fd); | 
 |                 return false; | 
 |             } | 
 |             close(trace_fd); | 
 |         } | 
 |         if (snprintf(path, PATH_MAX, "%s%s/trace_marker", mount_point, subdir) | 
 |                 >= sizeof(path)) { | 
 |             fprintf(stderr, "Using tracefs mountpoint would exceed PATH_MAX\n"); | 
 |             return false; | 
 |         } | 
 |         trace_marker_fd = open(path, O_WRONLY); | 
 |         if (trace_marker_fd < 0) { | 
 |             perror("Could not open ftrace 'trace_marker' file"); | 
 |             return false; | 
 |         } | 
 |     } else { | 
 |         fprintf(stderr, "tracefs is not mounted\n"); | 
 |         return false; | 
 |     } | 
 |  | 
 |     return true; | 
 | } |