Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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