Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Generic dynamic event control interface
0004  *
0005  * Copyright (C) 2018 Masami Hiramatsu <mhiramat@kernel.org>
0006  */
0007 
0008 #include <linux/debugfs.h>
0009 #include <linux/kernel.h>
0010 #include <linux/list.h>
0011 #include <linux/mm.h>
0012 #include <linux/mutex.h>
0013 #include <linux/tracefs.h>
0014 
0015 #include "trace.h"
0016 #include "trace_output.h"   /* for trace_event_sem */
0017 #include "trace_dynevent.h"
0018 
0019 static DEFINE_MUTEX(dyn_event_ops_mutex);
0020 static LIST_HEAD(dyn_event_ops_list);
0021 
0022 bool trace_event_dyn_try_get_ref(struct trace_event_call *dyn_call)
0023 {
0024     struct trace_event_call *call;
0025     bool ret = false;
0026 
0027     if (WARN_ON_ONCE(!(dyn_call->flags & TRACE_EVENT_FL_DYNAMIC)))
0028         return false;
0029 
0030     down_read(&trace_event_sem);
0031     list_for_each_entry(call, &ftrace_events, list) {
0032         if (call == dyn_call) {
0033             atomic_inc(&dyn_call->refcnt);
0034             ret = true;
0035         }
0036     }
0037     up_read(&trace_event_sem);
0038     return ret;
0039 }
0040 
0041 void trace_event_dyn_put_ref(struct trace_event_call *call)
0042 {
0043     if (WARN_ON_ONCE(!(call->flags & TRACE_EVENT_FL_DYNAMIC)))
0044         return;
0045 
0046     if (WARN_ON_ONCE(atomic_read(&call->refcnt) <= 0)) {
0047         atomic_set(&call->refcnt, 0);
0048         return;
0049     }
0050 
0051     atomic_dec(&call->refcnt);
0052 }
0053 
0054 bool trace_event_dyn_busy(struct trace_event_call *call)
0055 {
0056     return atomic_read(&call->refcnt) != 0;
0057 }
0058 
0059 int dyn_event_register(struct dyn_event_operations *ops)
0060 {
0061     if (!ops || !ops->create || !ops->show || !ops->is_busy ||
0062         !ops->free || !ops->match)
0063         return -EINVAL;
0064 
0065     INIT_LIST_HEAD(&ops->list);
0066     mutex_lock(&dyn_event_ops_mutex);
0067     list_add_tail(&ops->list, &dyn_event_ops_list);
0068     mutex_unlock(&dyn_event_ops_mutex);
0069     return 0;
0070 }
0071 
0072 int dyn_event_release(const char *raw_command, struct dyn_event_operations *type)
0073 {
0074     struct dyn_event *pos, *n;
0075     char *system = NULL, *event, *p;
0076     int argc, ret = -ENOENT;
0077     char **argv;
0078 
0079     argv = argv_split(GFP_KERNEL, raw_command, &argc);
0080     if (!argv)
0081         return -ENOMEM;
0082 
0083     if (argv[0][0] == '-') {
0084         if (argv[0][1] != ':') {
0085             ret = -EINVAL;
0086             goto out;
0087         }
0088         event = &argv[0][2];
0089     } else {
0090         event = strchr(argv[0], ':');
0091         if (!event) {
0092             ret = -EINVAL;
0093             goto out;
0094         }
0095         event++;
0096     }
0097 
0098     p = strchr(event, '/');
0099     if (p) {
0100         system = event;
0101         event = p + 1;
0102         *p = '\0';
0103     }
0104     if (!system && event[0] == '\0') {
0105         ret = -EINVAL;
0106         goto out;
0107     }
0108 
0109     mutex_lock(&event_mutex);
0110     for_each_dyn_event_safe(pos, n) {
0111         if (type && type != pos->ops)
0112             continue;
0113         if (!pos->ops->match(system, event,
0114                 argc - 1, (const char **)argv + 1, pos))
0115             continue;
0116 
0117         ret = pos->ops->free(pos);
0118         if (ret)
0119             break;
0120     }
0121     mutex_unlock(&event_mutex);
0122 out:
0123     argv_free(argv);
0124     return ret;
0125 }
0126 
0127 static int create_dyn_event(const char *raw_command)
0128 {
0129     struct dyn_event_operations *ops;
0130     int ret = -ENODEV;
0131 
0132     if (raw_command[0] == '-' || raw_command[0] == '!')
0133         return dyn_event_release(raw_command, NULL);
0134 
0135     mutex_lock(&dyn_event_ops_mutex);
0136     list_for_each_entry(ops, &dyn_event_ops_list, list) {
0137         ret = ops->create(raw_command);
0138         if (!ret || ret != -ECANCELED)
0139             break;
0140     }
0141     mutex_unlock(&dyn_event_ops_mutex);
0142     if (ret == -ECANCELED)
0143         ret = -EINVAL;
0144 
0145     return ret;
0146 }
0147 
0148 /* Protected by event_mutex */
0149 LIST_HEAD(dyn_event_list);
0150 
0151 void *dyn_event_seq_start(struct seq_file *m, loff_t *pos)
0152 {
0153     mutex_lock(&event_mutex);
0154     return seq_list_start(&dyn_event_list, *pos);
0155 }
0156 
0157 void *dyn_event_seq_next(struct seq_file *m, void *v, loff_t *pos)
0158 {
0159     return seq_list_next(v, &dyn_event_list, pos);
0160 }
0161 
0162 void dyn_event_seq_stop(struct seq_file *m, void *v)
0163 {
0164     mutex_unlock(&event_mutex);
0165 }
0166 
0167 static int dyn_event_seq_show(struct seq_file *m, void *v)
0168 {
0169     struct dyn_event *ev = v;
0170 
0171     if (ev && ev->ops)
0172         return ev->ops->show(m, ev);
0173 
0174     return 0;
0175 }
0176 
0177 static const struct seq_operations dyn_event_seq_op = {
0178     .start  = dyn_event_seq_start,
0179     .next   = dyn_event_seq_next,
0180     .stop   = dyn_event_seq_stop,
0181     .show   = dyn_event_seq_show
0182 };
0183 
0184 /*
0185  * dyn_events_release_all - Release all specific events
0186  * @type:   the dyn_event_operations * which filters releasing events
0187  *
0188  * This releases all events which ->ops matches @type. If @type is NULL,
0189  * all events are released.
0190  * Return -EBUSY if any of them are in use, and return other errors when
0191  * it failed to free the given event. Except for -EBUSY, event releasing
0192  * process will be aborted at that point and there may be some other
0193  * releasable events on the list.
0194  */
0195 int dyn_events_release_all(struct dyn_event_operations *type)
0196 {
0197     struct dyn_event *ev, *tmp;
0198     int ret = 0;
0199 
0200     mutex_lock(&event_mutex);
0201     for_each_dyn_event(ev) {
0202         if (type && ev->ops != type)
0203             continue;
0204         if (ev->ops->is_busy(ev)) {
0205             ret = -EBUSY;
0206             goto out;
0207         }
0208     }
0209     for_each_dyn_event_safe(ev, tmp) {
0210         if (type && ev->ops != type)
0211             continue;
0212         ret = ev->ops->free(ev);
0213         if (ret)
0214             break;
0215     }
0216 out:
0217     mutex_unlock(&event_mutex);
0218 
0219     return ret;
0220 }
0221 
0222 static int dyn_event_open(struct inode *inode, struct file *file)
0223 {
0224     int ret;
0225 
0226     ret = tracing_check_open_get_tr(NULL);
0227     if (ret)
0228         return ret;
0229 
0230     if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
0231         ret = dyn_events_release_all(NULL);
0232         if (ret < 0)
0233             return ret;
0234     }
0235 
0236     return seq_open(file, &dyn_event_seq_op);
0237 }
0238 
0239 static ssize_t dyn_event_write(struct file *file, const char __user *buffer,
0240                 size_t count, loff_t *ppos)
0241 {
0242     return trace_parse_run_command(file, buffer, count, ppos,
0243                        create_dyn_event);
0244 }
0245 
0246 static const struct file_operations dynamic_events_ops = {
0247     .owner          = THIS_MODULE,
0248     .open           = dyn_event_open,
0249     .read           = seq_read,
0250     .llseek         = seq_lseek,
0251     .release        = seq_release,
0252     .write      = dyn_event_write,
0253 };
0254 
0255 /* Make a tracefs interface for controlling dynamic events */
0256 static __init int init_dynamic_event(void)
0257 {
0258     int ret;
0259 
0260     ret = tracing_init_dentry();
0261     if (ret)
0262         return 0;
0263 
0264     trace_create_file("dynamic_events", TRACE_MODE_WRITE, NULL,
0265               NULL, &dynamic_events_ops);
0266 
0267     return 0;
0268 }
0269 fs_initcall(init_dynamic_event);
0270 
0271 /**
0272  * dynevent_arg_add - Add an arg to a dynevent_cmd
0273  * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
0274  * @arg: The argument to append to the current cmd
0275  * @check_arg: An (optional) pointer to a function checking arg sanity
0276  *
0277  * Append an argument to a dynevent_cmd.  The argument string will be
0278  * appended to the current cmd string, followed by a separator, if
0279  * applicable.  Before the argument is added, the @check_arg function,
0280  * if present, will be used to check the sanity of the current arg
0281  * string.
0282  *
0283  * The cmd string and separator should be set using the
0284  * dynevent_arg_init() before any arguments are added using this
0285  * function.
0286  *
0287  * Return: 0 if successful, error otherwise.
0288  */
0289 int dynevent_arg_add(struct dynevent_cmd *cmd,
0290              struct dynevent_arg *arg,
0291              dynevent_check_arg_fn_t check_arg)
0292 {
0293     int ret = 0;
0294 
0295     if (check_arg) {
0296         ret = check_arg(arg);
0297         if (ret)
0298             return ret;
0299     }
0300 
0301     ret = seq_buf_printf(&cmd->seq, " %s%c", arg->str, arg->separator);
0302     if (ret) {
0303         pr_err("String is too long: %s%c\n", arg->str, arg->separator);
0304         return -E2BIG;
0305     }
0306 
0307     return ret;
0308 }
0309 
0310 /**
0311  * dynevent_arg_pair_add - Add an arg pair to a dynevent_cmd
0312  * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
0313  * @arg_pair: The argument pair to append to the current cmd
0314  * @check_arg: An (optional) pointer to a function checking arg sanity
0315  *
0316  * Append an argument pair to a dynevent_cmd.  An argument pair
0317  * consists of a left-hand-side argument and a right-hand-side
0318  * argument separated by an operator, which can be whitespace, all
0319  * followed by a separator, if applicable.  This can be used to add
0320  * arguments of the form 'type variable_name;' or 'x+y'.
0321  *
0322  * The lhs argument string will be appended to the current cmd string,
0323  * followed by an operator, if applicable, followed by the rhs string,
0324  * followed finally by a separator, if applicable.  Before the
0325  * argument is added, the @check_arg function, if present, will be
0326  * used to check the sanity of the current arg strings.
0327  *
0328  * The cmd strings, operator, and separator should be set using the
0329  * dynevent_arg_pair_init() before any arguments are added using this
0330  * function.
0331  *
0332  * Return: 0 if successful, error otherwise.
0333  */
0334 int dynevent_arg_pair_add(struct dynevent_cmd *cmd,
0335               struct dynevent_arg_pair *arg_pair,
0336               dynevent_check_arg_fn_t check_arg)
0337 {
0338     int ret = 0;
0339 
0340     if (check_arg) {
0341         ret = check_arg(arg_pair);
0342         if (ret)
0343             return ret;
0344     }
0345 
0346     ret = seq_buf_printf(&cmd->seq, " %s%c%s%c", arg_pair->lhs,
0347                  arg_pair->operator, arg_pair->rhs,
0348                  arg_pair->separator);
0349     if (ret) {
0350         pr_err("field string is too long: %s%c%s%c\n", arg_pair->lhs,
0351                arg_pair->operator, arg_pair->rhs,
0352                arg_pair->separator);
0353         return -E2BIG;
0354     }
0355 
0356     return ret;
0357 }
0358 
0359 /**
0360  * dynevent_str_add - Add a string to a dynevent_cmd
0361  * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
0362  * @str: The string to append to the current cmd
0363  *
0364  * Append a string to a dynevent_cmd.  The string will be appended to
0365  * the current cmd string as-is, with nothing prepended or appended.
0366  *
0367  * Return: 0 if successful, error otherwise.
0368  */
0369 int dynevent_str_add(struct dynevent_cmd *cmd, const char *str)
0370 {
0371     int ret = 0;
0372 
0373     ret = seq_buf_puts(&cmd->seq, str);
0374     if (ret) {
0375         pr_err("String is too long: %s\n", str);
0376         return -E2BIG;
0377     }
0378 
0379     return ret;
0380 }
0381 
0382 /**
0383  * dynevent_cmd_init - Initialize a dynevent_cmd object
0384  * @cmd: A pointer to the dynevent_cmd struct representing the cmd
0385  * @buf: A pointer to the buffer to generate the command into
0386  * @maxlen: The length of the buffer the command will be generated into
0387  * @type: The type of the cmd, checked against further operations
0388  * @run_command: The type-specific function that will actually run the command
0389  *
0390  * Initialize a dynevent_cmd.  A dynevent_cmd is used to build up and
0391  * run dynamic event creation commands, such as commands for creating
0392  * synthetic and kprobe events.  Before calling any of the functions
0393  * used to build the command, a dynevent_cmd object should be
0394  * instantiated and initialized using this function.
0395  *
0396  * The initialization sets things up by saving a pointer to the
0397  * user-supplied buffer and its length via the @buf and @maxlen
0398  * params, and by saving the cmd-specific @type and @run_command
0399  * params which are used to check subsequent dynevent_cmd operations
0400  * and actually run the command when complete.
0401  */
0402 void dynevent_cmd_init(struct dynevent_cmd *cmd, char *buf, int maxlen,
0403                enum dynevent_type type,
0404                dynevent_create_fn_t run_command)
0405 {
0406     memset(cmd, '\0', sizeof(*cmd));
0407 
0408     seq_buf_init(&cmd->seq, buf, maxlen);
0409     cmd->type = type;
0410     cmd->run_command = run_command;
0411 }
0412 
0413 /**
0414  * dynevent_arg_init - Initialize a dynevent_arg object
0415  * @arg: A pointer to the dynevent_arg struct representing the arg
0416  * @separator: An (optional) separator, appended after adding the arg
0417  *
0418  * Initialize a dynevent_arg object.  A dynevent_arg represents an
0419  * object used to append single arguments to the current command
0420  * string.  After the arg string is successfully appended to the
0421  * command string, the optional @separator is appended.  If no
0422  * separator was specified when initializing the arg, a space will be
0423  * appended.
0424  */
0425 void dynevent_arg_init(struct dynevent_arg *arg,
0426                char separator)
0427 {
0428     memset(arg, '\0', sizeof(*arg));
0429 
0430     if (!separator)
0431         separator = ' ';
0432     arg->separator = separator;
0433 }
0434 
0435 /**
0436  * dynevent_arg_pair_init - Initialize a dynevent_arg_pair object
0437  * @arg_pair: A pointer to the dynevent_arg_pair struct representing the arg
0438  * @operator: An (optional) operator, appended after adding the first arg
0439  * @separator: An (optional) separator, appended after adding the second arg
0440  *
0441  * Initialize a dynevent_arg_pair object.  A dynevent_arg_pair
0442  * represents an object used to append argument pairs such as 'type
0443  * variable_name;' or 'x+y' to the current command string.  An
0444  * argument pair consists of a left-hand-side argument and a
0445  * right-hand-side argument separated by an operator, which can be
0446  * whitespace, all followed by a separator, if applicable.  After the
0447  * first arg string is successfully appended to the command string,
0448  * the optional @operator is appended, followed by the second arg and
0449  * optional @separator.  If no separator was specified when
0450  * initializing the arg, a space will be appended.
0451  */
0452 void dynevent_arg_pair_init(struct dynevent_arg_pair *arg_pair,
0453                 char operator, char separator)
0454 {
0455     memset(arg_pair, '\0', sizeof(*arg_pair));
0456 
0457     if (!operator)
0458         operator = ' ';
0459     arg_pair->operator = operator;
0460 
0461     if (!separator)
0462         separator = ' ';
0463     arg_pair->separator = separator;
0464 }
0465 
0466 /**
0467  * dynevent_create - Create the dynamic event contained in dynevent_cmd
0468  * @cmd: The dynevent_cmd object containing the dynamic event creation command
0469  *
0470  * Once a dynevent_cmd object has been successfully built up via the
0471  * dynevent_cmd_init(), dynevent_arg_add() and dynevent_arg_pair_add()
0472  * functions, this function runs the final command to actually create
0473  * the event.
0474  *
0475  * Return: 0 if the event was successfully created, error otherwise.
0476  */
0477 int dynevent_create(struct dynevent_cmd *cmd)
0478 {
0479     return cmd->run_command(cmd);
0480 }
0481 EXPORT_SYMBOL_GPL(dynevent_create);