0001
0002
0003
0004
0005
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
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
0186
0187
0188
0189
0190
0191
0192
0193
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
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
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
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
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
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
0361
0362
0363
0364
0365
0366
0367
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
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
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
0415
0416
0417
0418
0419
0420
0421
0422
0423
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
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
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
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477 int dynevent_create(struct dynevent_cmd *cmd)
0478 {
0479 return cmd->run_command(cmd);
0480 }
0481 EXPORT_SYMBOL_GPL(dynevent_create);