linux/tools/lib/api/fs/tracing_path.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#ifndef _GNU_SOURCE
   3# define _GNU_SOURCE
   4#endif
   5
   6#include <stdio.h>
   7#include <stdlib.h>
   8#include <string.h>
   9#include <linux/string.h>
  10#include <errno.h>
  11#include <unistd.h>
  12#include "fs.h"
  13
  14#include "tracing_path.h"
  15
  16static char tracing_mnt[PATH_MAX]  = "/sys/kernel/debug";
  17static char tracing_path[PATH_MAX]        = "/sys/kernel/debug/tracing";
  18static char tracing_events_path[PATH_MAX] = "/sys/kernel/debug/tracing/events";
  19
  20static void __tracing_path_set(const char *tracing, const char *mountpoint)
  21{
  22        snprintf(tracing_mnt, sizeof(tracing_mnt), "%s", mountpoint);
  23        snprintf(tracing_path, sizeof(tracing_path), "%s/%s",
  24                 mountpoint, tracing);
  25        snprintf(tracing_events_path, sizeof(tracing_events_path), "%s/%s%s",
  26                 mountpoint, tracing, "events");
  27}
  28
  29static const char *tracing_path_tracefs_mount(void)
  30{
  31        const char *mnt;
  32
  33        mnt = tracefs__mount();
  34        if (!mnt)
  35                return NULL;
  36
  37        __tracing_path_set("", mnt);
  38
  39        return tracing_path;
  40}
  41
  42static const char *tracing_path_debugfs_mount(void)
  43{
  44        const char *mnt;
  45
  46        mnt = debugfs__mount();
  47        if (!mnt)
  48                return NULL;
  49
  50        __tracing_path_set("tracing/", mnt);
  51
  52        return tracing_path;
  53}
  54
  55const char *tracing_path_mount(void)
  56{
  57        const char *mnt;
  58
  59        mnt = tracing_path_tracefs_mount();
  60        if (mnt)
  61                return mnt;
  62
  63        mnt = tracing_path_debugfs_mount();
  64
  65        return mnt;
  66}
  67
  68void tracing_path_set(const char *mntpt)
  69{
  70        __tracing_path_set("tracing/", mntpt);
  71}
  72
  73char *get_tracing_file(const char *name)
  74{
  75        char *file;
  76
  77        if (asprintf(&file, "%s/%s", tracing_path_mount(), name) < 0)
  78                return NULL;
  79
  80        return file;
  81}
  82
  83void put_tracing_file(char *file)
  84{
  85        free(file);
  86}
  87
  88char *get_events_file(const char *name)
  89{
  90        char *file;
  91
  92        if (asprintf(&file, "%s/events/%s", tracing_path_mount(), name) < 0)
  93                return NULL;
  94
  95        return file;
  96}
  97
  98void put_events_file(char *file)
  99{
 100        free(file);
 101}
 102
 103DIR *tracing_events__opendir(void)
 104{
 105        DIR *dir = NULL;
 106        char *path = get_tracing_file("events");
 107
 108        if (path) {
 109                dir = opendir(path);
 110                put_events_file(path);
 111        }
 112
 113        return dir;
 114}
 115
 116int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
 117                                   const char *sys, const char *name)
 118{
 119        char sbuf[128];
 120        char filename[PATH_MAX];
 121
 122        snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*");
 123
 124        switch (err) {
 125        case ENOENT:
 126                /*
 127                 * We will get here if we can't find the tracepoint, but one of
 128                 * debugfs or tracefs is configured, which means you probably
 129                 * want some tracepoint which wasn't compiled in your kernel.
 130                 * - jirka
 131                 */
 132                if (debugfs__configured() || tracefs__configured()) {
 133                        /* sdt markers */
 134                        if (!strncmp(filename, "sdt_", 4)) {
 135                                snprintf(buf, size,
 136                                        "Error:\tFile %s/%s not found.\n"
 137                                        "Hint:\tSDT event cannot be directly recorded on.\n"
 138                                        "\tPlease first use 'perf probe %s:%s' before recording it.\n",
 139                                        tracing_events_path, filename, sys, name);
 140                        } else {
 141                                snprintf(buf, size,
 142                                         "Error:\tFile %s/%s not found.\n"
 143                                         "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
 144                                         tracing_events_path, filename);
 145                        }
 146                        break;
 147                }
 148                snprintf(buf, size, "%s",
 149                         "Error:\tUnable to find debugfs/tracefs\n"
 150                         "Hint:\tWas your kernel compiled with debugfs/tracefs support?\n"
 151                         "Hint:\tIs the debugfs/tracefs filesystem mounted?\n"
 152                         "Hint:\tTry 'sudo mount -t debugfs nodev /sys/kernel/debug'");
 153                break;
 154        case EACCES: {
 155                snprintf(buf, size,
 156                         "Error:\tNo permissions to read %s/%s\n"
 157                         "Hint:\tTry 'sudo mount -o remount,mode=755 %s'\n",
 158                         tracing_events_path, filename, tracing_path_mount());
 159        }
 160                break;
 161        default:
 162                snprintf(buf, size, "%s", str_error_r(err, sbuf, sizeof(sbuf)));
 163                break;
 164        }
 165
 166        return 0;
 167}
 168