| 1 | |
| 2 | |
| 3 | * Generic dynamic event control interface
|
| 4 | *
|
| 5 | * Copyright (C) 2018 Masami Hiramatsu <[email protected]>
|
| 6 |
|
| 7 |
|
| 8 | #include <linux/debugfs.h>
|
| 9 | #include <linux/kernel.h>
|
| 10 | #include <linux/list.h>
|
| 11 | #include <linux/mm.h>
|
| 12 | #include <linux/mutex.h>
|
| 13 | #include <linux/tracefs.h>
|
| 14 |
|
| 15 | #include "trace.h"
|
| 16 | #include "trace_output.h"
|
| 17 | #include "trace_dynevent.h"
|
| 18 |
|
| 19 | DEFINE_MUTEX(dyn_event_ops_mutex);
|
| 20 | static LIST_HEAD(dyn_event_ops_list);
|
| 21 |
|
| 22 | bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call)
|
| 23 | {
|
| 24 | struct trace_event_call *call;
|
| 25 | bool ret = false;
|
| 26 |
|
| 27 | if (WARN_ON_ONCE(!(dyn_call->flags & TRACE_EVENT_FL_DYNAMIC)))
|
| 28 | return false;
|
| 29 |
|
| 30 | down_read(&trace_event_sem);
|
| 31 | list_for_each_entry(call, &ftrace_events, list) {
|
| 32 | if (call == dyn_call) {
|
| 33 | atomic_inc(&dyn_call->refcnt);
|
| 34 | ret = true;
|
| 35 | }
|
| 36 | }
|
| 37 | up_read(&trace_event_sem);
|
| 38 | return ret;
|
| 39 | }
|
| 40 |
|
| 41 | void trace_event_dyn_put_ref(struct trace_event_call *call)
|
| 42 | {
|
| 43 | if (WARN_ON_ONCE(!(call->flags & TRACE_EVENT_FL_DYNAMIC)))
|
| 44 | return;
|
| 45 |
|
| 46 | if (WARN_ON_ONCE(atomic_read(&call->refcnt) <= 0)) {
|
| 47 | atomic_set(&call->refcnt, 0);
|
| 48 | return;
|
| 49 | }
|
| 50 |
|
| 51 | atomic_dec(&call->refcnt);
|
| 52 | }
|
| 53 |
|
| 54 | bool trace_event_dyn_busy(struct trace_event_call *call)
|
| 55 | {
|
| 56 | return atomic_read(&call->refcnt) != 0;
|
| 57 | }
|
| 58 |
|
| 59 | int dyn_event_register(struct dyn_event_operations *ops)
|
| 60 | {
|
| 61 | if (!ops || !ops->create || !ops->show || !ops->is_busy ||
|
| 62 | !ops->free || !ops->match)
|
| 63 | return -EINVAL;
|
| 64 |
|
| 65 | INIT_LIST_HEAD(&ops->list);
|
| 66 | mutex_lock(&dyn_event_ops_mutex);
|
| 67 | list_add_tail(&ops->list, &dyn_event_ops_list);
|
| 68 | mutex_unlock(&dyn_event_ops_mutex);
|
| 69 | return 0;
|
| 70 | }
|
| 71 |
|
| 72 | int dyn_event_release(const char *raw_command, struct dyn_event_operations *type)
|
| 73 | {
|
| 74 | struct dyn_event *pos, *n;
|
| 75 | char *system = NULL, *event, *p;
|
| 76 | int argc, ret = -ENOENT;
|
| 77 | char **argv __free(argv_free) = argv_split(GFP_KERNEL, raw_command, &argc);
|
| 78 |
|
| 79 | if (!argv)
|
| 80 | return -ENOMEM;
|
| 81 |
|
| 82 | if (argv[0][0] == '-') {
|
| 83 | if (argv[0][1] != ':')
|
| 84 | return -EINVAL;
|
| 85 | event = &argv[0][2];
|
| 86 | } else {
|
| 87 | event = strchr(argv[0], ':');
|
| 88 | if (!event)
|
| 89 | return -EINVAL;
|
| 90 | event++;
|
| 91 | }
|
| 92 |
|
| 93 | p = strchr(event, '/');
|
| 94 | if (p) {
|
| 95 | system = event;
|
| 96 | event = p + 1;
|
| 97 | *p = '\0';
|
| 98 | }
|
| 99 | if (!system && event[0] == '\0')
|
| 100 | return -EINVAL;
|
| 101 |
|
| 102 | mutex_lock(&event_mutex);
|
| 103 | for_each_dyn_event_safe(pos, n) {
|
| 104 | if (type && type != pos->ops)
|
| 105 | continue;
|
| 106 | if (!pos->ops->match(system, event,
|
| 107 | argc - 1, (const char **)argv + 1, pos))
|
| 108 | continue;
|
| 109 |
|
| 110 | ret = pos->ops->free(pos);
|
| 111 | if (ret)
|
| 112 | break;
|
| 113 | }
|
| 114 | tracing_reset_all_online_cpus();
|
| 115 | mutex_unlock(&event_mutex);
|
| 116 | return ret;
|
| 117 | }
|
| 118 |
|
| 119 | static int create_dyn_event(const char *raw_command);
|
| 120 |
|
| 121 | |
| 122 | * Locked version of event creation. The event creation must be protected by
|
| 123 | * dyn_event_ops_mutex because of protecting trace_probe_log.
|
| 124 |
|
| 125 | int dyn_event_create(const char *raw_command, struct dyn_event_operations *type)
|
| 126 | {
|
| 127 | int ret;
|
| 128 |
|
| 129 | if (!type)
|
| 130 | return create_dyn_event(raw_command);
|
| 131 |
|
| 132 | mutex_lock(&dyn_event_ops_mutex);
|
| 133 | ret = type->create(raw_command);
|
| 134 | mutex_unlock(&dyn_event_ops_mutex);
|
| 135 | return ret;
|
| 136 | }
|
| 137 |
|
| 138 | static int create_dyn_event(const char *raw_command)
|
| 139 | {
|
| 140 | struct dyn_event_operations *ops;
|
| 141 | int ret = -ENODEV;
|
| 142 |
|
| 143 | if (raw_command[0] == '-' || raw_command[0] == '!')
|
| 144 | return dyn_event_release(raw_command, NULL);
|
| 145 |
|
| 146 | mutex_lock(&dyn_event_ops_mutex);
|
| 147 | list_for_each_entry(ops, &dyn_event_ops_list, list) {
|
| 148 | ret = ops->create(raw_command);
|
| 149 | if (!ret || ret != -ECANCELED)
|
| 150 | break;
|
| 151 | }
|
| 152 | if (ret == -ECANCELED) {
|
| 153 | static const char *err_msg[] = {"No matching dynamic event type"};
|
| 154 |
|
| 155 |
|
| 156 | tracing_log_err(NULL, "dynevent", raw_command, err_msg,
|
| 157 | 0, 0);
|
| 158 | ret = -EINVAL;
|
| 159 | }
|
| 160 |
|
| 161 | mutex_unlock(&dyn_event_ops_mutex);
|
| 162 |
|
| 163 | return ret;
|
| 164 | }
|
| 165 |
|
| 166 |
|
| 167 | LIST_HEAD(dyn_event_list);
|
| 168 |
|
| 169 | void *dyn_event_seq_start(struct seq_file *m, loff_t *pos)
|
| 170 | {
|
| 171 | mutex_lock(&event_mutex);
|
| 172 | return seq_list_start(&dyn_event_list, *pos);
|
| 173 | }
|
| 174 |
|
| 175 | void *dyn_event_seq_next(struct seq_file *m, void *v, loff_t *pos)
|
| 176 | {
|
| 177 | return seq_list_next(v, &dyn_event_list, pos);
|
| 178 | }
|
| 179 |
|
| 180 | void dyn_event_seq_stop(struct seq_file *m, void *v)
|
| 181 | {
|
| 182 | mutex_unlock(&event_mutex);
|
| 183 | }
|
| 184 |
|
| 185 | static int dyn_event_seq_show(struct seq_file *m, void *v)
|
| 186 | {
|
| 187 | struct dyn_event *ev = v;
|
| 188 |
|
| 189 | if (ev && ev->ops)
|
| 190 | return ev->ops->show(m, ev);
|
| 191 |
|
| 192 | return 0;
|
| 193 | }
|
| 194 |
|
| 195 | static const struct seq_operations dyn_event_seq_op = {
|
| 196 | .start = dyn_event_seq_start,
|
| 197 | .next = dyn_event_seq_next,
|
| 198 | .stop = dyn_event_seq_stop,
|
| 199 | .show = dyn_event_seq_show
|
| 200 | };
|
| 201 |
|
| 202 | |
| 203 | * dyn_events_release_all - Release all specific events
|
| 204 | * @type: the dyn_event_operations * which filters releasing events
|
| 205 | *
|
| 206 | * This releases all events which ->ops matches @type. If @type is NULL,
|
| 207 | * all events are released.
|
| 208 | * Return -EBUSY if any of them are in use, and return other errors when
|
| 209 | * it failed to free the given event. Except for -EBUSY, event releasing
|
| 210 | * process will be aborted at that point and there may be some other
|
| 211 | * releasable events on the list.
|
| 212 |
|
| 213 | int dyn_events_release_all(struct dyn_event_operations *type)
|
| 214 | {
|
| 215 | struct dyn_event *ev, *tmp;
|
| 216 | int ret = 0;
|
| 217 |
|
| 218 | mutex_lock(&event_mutex);
|
| 219 | for_each_dyn_event(ev) {
|
| 220 | if (type && ev->ops != type)
|
| 221 | continue;
|
| 222 | if (ev->ops->is_busy(ev)) {
|
| 223 | ret = -EBUSY;
|
| 224 | goto out;
|
| 225 | }
|
| 226 | }
|
| 227 | for_each_dyn_event_safe(ev, tmp) {
|
| 228 | if (type && ev->ops != type)
|
| 229 | continue;
|
| 230 | ret = ev->ops->free(ev);
|
| 231 | if (ret)
|
| 232 | break;
|
| 233 | }
|
| 234 | out:
|
| 235 | tracing_reset_all_online_cpus();
|
| 236 | mutex_unlock(&event_mutex);
|
| 237 |
|
| 238 | return ret;
|
| 239 | }
|
| 240 |
|
| 241 | static int dyn_event_open(struct inode *inode, struct file *file)
|
| 242 | {
|
| 243 | int ret;
|
| 244 |
|
| 245 | ret = security_locked_down(LOCKDOWN_TRACEFS);
|
| 246 | if (ret)
|
| 247 | return ret;
|
| 248 |
|
| 249 | ret = tracing_check_open_get_tr(NULL);
|
| 250 | if (ret)
|
| 251 | return ret;
|
| 252 |
|
| 253 | if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
|
| 254 | ret = dyn_events_release_all(NULL);
|
| 255 | if (ret < 0)
|
| 256 | return ret;
|
| 257 | }
|
| 258 |
|
| 259 | return seq_open(file, &dyn_event_seq_op);
|
| 260 | }
|
| 261 |
|
| 262 | static ssize_t dyn_event_write(struct file *file, const char __user *buffer,
|
| 263 | size_t count, loff_t *ppos)
|
| 264 | {
|
| 265 | return trace_parse_run_command(file, buffer, count, ppos,
|
| 266 | create_dyn_event);
|
| 267 | }
|
| 268 |
|
| 269 | static const struct file_operations dynamic_events_ops = {
|
| 270 | .owner = THIS_MODULE,
|
| 271 | .open = dyn_event_open,
|
| 272 | .read = seq_read,
|
| 273 | .llseek = seq_lseek,
|
| 274 | .release = seq_release,
|
| 275 | .write = dyn_event_write,
|
| 276 | };
|
| 277 |
|
| 278 |
|
| 279 | static __init int init_dynamic_event(void)
|
| 280 | {
|
| 281 | int ret;
|
| 282 |
|
| 283 | ret = tracing_init_dentry();
|
| 284 | if (ret)
|
| 285 | return 0;
|
| 286 |
|
| 287 | trace_create_file("dynamic_events", TRACE_MODE_WRITE, NULL,
|
| 288 | NULL, &dynamic_events_ops);
|
| 289 |
|
| 290 | return 0;
|
| 291 | }
|
| 292 | fs_initcall(init_dynamic_event);
|
| 293 |
|
| 294 | |
| 295 | * dynevent_arg_add - Add an arg to a dynevent_cmd
|
| 296 | * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
|
| 297 | * @arg: The argument to append to the current cmd
|
| 298 | * @check_arg: An (optional) pointer to a function checking arg sanity
|
| 299 | *
|
| 300 | * Append an argument to a dynevent_cmd. The argument string will be
|
| 301 | * appended to the current cmd string, followed by a separator, if
|
| 302 | * applicable. Before the argument is added, the @check_arg function,
|
| 303 | * if present, will be used to check the sanity of the current arg
|
| 304 | * string.
|
| 305 | *
|
| 306 | * The cmd string and separator should be set using the
|
| 307 | * dynevent_arg_init() before any arguments are added using this
|
| 308 | * function.
|
| 309 | *
|
| 310 | * Return: 0 if successful, error otherwise.
|
| 311 |
|
| 312 | int dynevent_arg_add(struct dynevent_cmd *cmd,
|
| 313 | struct dynevent_arg *arg,
|
| 314 | dynevent_check_arg_fn_t check_arg)
|
| 315 | {
|
| 316 | int ret = 0;
|
| 317 |
|
| 318 | if (check_arg) {
|
| 319 | ret = check_arg(arg);
|
| 320 | if (ret)
|
| 321 | return ret;
|
| 322 | }
|
| 323 |
|
| 324 | ret = seq_buf_printf(&cmd->seq, " %s%c", arg->str, arg->separator);
|
| 325 | if (ret) {
|
| 326 | pr_err("String is too long: %s%c\n", arg->str, arg->separator);
|
| 327 | return -E2BIG;
|
| 328 | }
|
| 329 |
|
| 330 | return ret;
|
| 331 | }
|
| 332 |
|
| 333 | |
| 334 | * dynevent_arg_pair_add - Add an arg pair to a dynevent_cmd
|
| 335 | * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
|
| 336 | * @arg_pair: The argument pair to append to the current cmd
|
| 337 | * @check_arg: An (optional) pointer to a function checking arg sanity
|
| 338 | *
|
| 339 | * Append an argument pair to a dynevent_cmd. An argument pair
|
| 340 | * consists of a left-hand-side argument and a right-hand-side
|
| 341 | * argument separated by an operator, which can be whitespace, all
|
| 342 | * followed by a separator, if applicable. This can be used to add
|
| 343 | * arguments of the form 'type variable_name;' or 'x+y'.
|
| 344 | *
|
| 345 | * The lhs argument string will be appended to the current cmd string,
|
| 346 | * followed by an operator, if applicable, followed by the rhs string,
|
| 347 | * followed finally by a separator, if applicable. Before the
|
| 348 | * argument is added, the @check_arg function, if present, will be
|
| 349 | * used to check the sanity of the current arg strings.
|
| 350 | *
|
| 351 | * The cmd strings, operator, and separator should be set using the
|
| 352 | * dynevent_arg_pair_init() before any arguments are added using this
|
| 353 | * function.
|
| 354 | *
|
| 355 | * Return: 0 if successful, error otherwise.
|
| 356 |
|
| 357 | int dynevent_arg_pair_add(struct dynevent_cmd *cmd,
|
| 358 | struct dynevent_arg_pair *arg_pair,
|
| 359 | dynevent_check_arg_fn_t check_arg)
|
| 360 | {
|
| 361 | int ret = 0;
|
| 362 |
|
| 363 | if (check_arg) {
|
| 364 | ret = check_arg(arg_pair);
|
| 365 | if (ret)
|
| 366 | return ret;
|
| 367 | }
|
| 368 |
|
| 369 | ret = seq_buf_printf(&cmd->seq, " %s%c%s%c", arg_pair->lhs,
|
| 370 | arg_pair->operator, arg_pair->rhs,
|
| 371 | arg_pair->separator);
|
| 372 | if (ret) {
|
| 373 | pr_err("field string is too long: %s%c%s%c\n", arg_pair->lhs,
|
| 374 | arg_pair->operator, arg_pair->rhs,
|
| 375 | arg_pair->separator);
|
| 376 | return -E2BIG;
|
| 377 | }
|
| 378 |
|
| 379 | return ret;
|
| 380 | }
|
| 381 |
|
| 382 | |
| 383 | * dynevent_str_add - Add a string to a dynevent_cmd
|
| 384 | * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
|
| 385 | * @str: The string to append to the current cmd
|
| 386 | *
|
| 387 | * Append a string to a dynevent_cmd. The string will be appended to
|
| 388 | * the current cmd string as-is, with nothing prepended or appended.
|
| 389 | *
|
| 390 | * Return: 0 if successful, error otherwise.
|
| 391 |
|
| 392 | int dynevent_str_add(struct dynevent_cmd *cmd, const char *str)
|
| 393 | {
|
| 394 | int ret = 0;
|
| 395 |
|
| 396 | ret = seq_buf_puts(&cmd->seq, str);
|
| 397 | if (ret) {
|
| 398 | pr_err("String is too long: %s\n", str);
|
| 399 | return -E2BIG;
|
| 400 | }
|
| 401 |
|
| 402 | return ret;
|
| 403 | }
|
| 404 |
|
| 405 | |
| 406 | * dynevent_cmd_init - Initialize a dynevent_cmd object
|
| 407 | * @cmd: A pointer to the dynevent_cmd struct representing the cmd
|
| 408 | * @buf: A pointer to the buffer to generate the command into
|
| 409 | * @maxlen: The length of the buffer the command will be generated into
|
| 410 | * @type: The type of the cmd, checked against further operations
|
| 411 | * @run_command: The type-specific function that will actually run the command
|
| 412 | *
|
| 413 | * Initialize a dynevent_cmd. A dynevent_cmd is used to build up and
|
| 414 | * run dynamic event creation commands, such as commands for creating
|
| 415 | * synthetic and kprobe events. Before calling any of the functions
|
| 416 | * used to build the command, a dynevent_cmd object should be
|
| 417 | * instantiated and initialized using this function.
|
| 418 | *
|
| 419 | * The initialization sets things up by saving a pointer to the
|
| 420 | * user-supplied buffer and its length via the @buf and @maxlen
|
| 421 | * params, and by saving the cmd-specific @type and @run_command
|
| 422 | * params which are used to check subsequent dynevent_cmd operations
|
| 423 | * and actually run the command when complete.
|
| 424 |
|
| 425 | void dynevent_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen,
|
| 426 | enum dynevent_type type,
|
| 427 | dynevent_create_fn_t run_command)
|
| 428 | {
|
| 429 | memset(cmd, '\0', sizeof(*cmd));
|
| 430 |
|
| 431 | seq_buf_init(&cmd->seq, buf, maxlen);
|
| 432 | cmd->type = type;
|
| 433 | cmd->run_command = run_command;
|
| 434 | }
|
| 435 |
|
| 436 | |
| 437 | * dynevent_arg_init - Initialize a dynevent_arg object
|
| 438 | * @arg: A pointer to the dynevent_arg struct representing the arg
|
| 439 | * @separator: An (optional) separator, appended after adding the arg
|
| 440 | *
|
| 441 | * Initialize a dynevent_arg object. A dynevent_arg represents an
|
| 442 | * object used to append single arguments to the current command
|
| 443 | * string. After the arg string is successfully appended to the
|
| 444 | * command string, the optional @separator is appended. If no
|
| 445 | * separator was specified when initializing the arg, a space will be
|
| 446 | * appended.
|
| 447 |
|
| 448 | void dynevent_arg_init(struct dynevent_arg *arg,
|
| 449 | char separator)
|
| 450 | {
|
| 451 | memset(arg, '\0', sizeof(*arg));
|
| 452 |
|
| 453 | if (!separator)
|
| 454 | separator = ' ';
|
| 455 | arg->separator = separator;
|
| 456 | }
|
| 457 |
|
| 458 | |
| 459 | * dynevent_arg_pair_init - Initialize a dynevent_arg_pair object
|
| 460 | * @arg_pair: A pointer to the dynevent_arg_pair struct representing the arg
|
| 461 | * @operator: An (optional) operator, appended after adding the first arg
|
| 462 | * @separator: An (optional) separator, appended after adding the second arg
|
| 463 | *
|
| 464 | * Initialize a dynevent_arg_pair object. A dynevent_arg_pair
|
| 465 | * represents an object used to append argument pairs such as 'type
|
| 466 | * variable_name;' or 'x+y' to the current command string. An
|
| 467 | * argument pair consists of a left-hand-side argument and a
|
| 468 | * right-hand-side argument separated by an operator, which can be
|
| 469 | * whitespace, all followed by a separator, if applicable. After the
|
| 470 | * first arg string is successfully appended to the command string,
|
| 471 | * the optional @operator is appended, followed by the second arg and
|
| 472 | * optional @separator. If no separator was specified when
|
| 473 | * initializing the arg, a space will be appended.
|
| 474 |
|
| 475 | void dynevent_arg_pair_init(struct dynevent_arg_pair *arg_pair,
|
| 476 | char operator, char separator)
|
| 477 | {
|
| 478 | memset(arg_pair, '\0', sizeof(*arg_pair));
|
| 479 |
|
| 480 | if (!operator)
|
| 481 | operator = ' ';
|
| 482 | arg_pair->operator = operator;
|
| 483 |
|
| 484 | if (!separator)
|
| 485 | separator = ' ';
|
| 486 | arg_pair->separator = separator;
|
| 487 | }
|
| 488 |
|
| 489 | |
| 490 | * dynevent_create - Create the dynamic event contained in dynevent_cmd
|
| 491 | * @cmd: The dynevent_cmd object containing the dynamic event creation command
|
| 492 | *
|
| 493 | * Once a dynevent_cmd object has been successfully built up via the
|
| 494 | * dynevent_cmd_init(), dynevent_arg_add() and dynevent_arg_pair_add()
|
| 495 | * functions, this function runs the final command to actually create
|
| 496 | * the event.
|
| 497 | *
|
| 498 | * Return: 0 if the event was successfully created, error otherwise.
|
| 499 |
|
| 500 | int dynevent_create(struct dynevent_cmd *cmd)
|
| 501 | {
|
| 502 | return cmd->run_command(cmd);
|
| 503 | }
|
| 504 | EXPORT_SYMBOL_GPL(dynevent_create);
|