Fix: don't flush-final for offset 0 if reader is on sub-buffer
[lttng-modules.git] / lttng-probes.c
... / ...
CommitLineData
1/*
2 * lttng-probes.c
3 *
4 * Holds LTTng probes registry.
5 *
6 * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; only
11 * version 2.1 of the License.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23#include <linux/module.h>
24#include <linux/list.h>
25#include <linux/mutex.h>
26#include <linux/seq_file.h>
27
28#include "lttng-events.h"
29
30static LIST_HEAD(probe_list);
31static DEFINE_MUTEX(probe_mutex);
32
33static
34const struct lttng_event_desc *find_event(const char *name)
35{
36 struct lttng_probe_desc *probe_desc;
37 int i;
38
39 list_for_each_entry(probe_desc, &probe_list, head) {
40 for (i = 0; i < probe_desc->nr_events; i++) {
41 if (!strcmp(probe_desc->event_desc[i]->name, name))
42 return probe_desc->event_desc[i];
43 }
44 }
45 return NULL;
46}
47
48int lttng_probe_register(struct lttng_probe_desc *desc)
49{
50 int ret = 0;
51 int i;
52
53 mutex_lock(&probe_mutex);
54 /*
55 * TODO: This is O(N^2). Turn into a hash table when probe registration
56 * overhead becomes an issue.
57 */
58 for (i = 0; i < desc->nr_events; i++) {
59 if (find_event(desc->event_desc[i]->name)) {
60 ret = -EEXIST;
61 goto end;
62 }
63 }
64 list_add(&desc->head, &probe_list);
65end:
66 mutex_unlock(&probe_mutex);
67 return ret;
68}
69EXPORT_SYMBOL_GPL(lttng_probe_register);
70
71void lttng_probe_unregister(struct lttng_probe_desc *desc)
72{
73 mutex_lock(&probe_mutex);
74 list_del(&desc->head);
75 mutex_unlock(&probe_mutex);
76}
77EXPORT_SYMBOL_GPL(lttng_probe_unregister);
78
79const struct lttng_event_desc *lttng_event_get(const char *name)
80{
81 const struct lttng_event_desc *event;
82 int ret;
83
84 mutex_lock(&probe_mutex);
85 event = find_event(name);
86 mutex_unlock(&probe_mutex);
87 if (!event)
88 return NULL;
89 ret = try_module_get(event->owner);
90 WARN_ON_ONCE(!ret);
91 return event;
92}
93EXPORT_SYMBOL_GPL(lttng_event_get);
94
95void lttng_event_put(const struct lttng_event_desc *event)
96{
97 module_put(event->owner);
98}
99EXPORT_SYMBOL_GPL(lttng_event_put);
100
101static
102void *tp_list_start(struct seq_file *m, loff_t *pos)
103{
104 struct lttng_probe_desc *probe_desc;
105 int iter = 0, i;
106
107 mutex_lock(&probe_mutex);
108 list_for_each_entry(probe_desc, &probe_list, head) {
109 for (i = 0; i < probe_desc->nr_events; i++) {
110 if (iter++ >= *pos)
111 return (void *) probe_desc->event_desc[i];
112 }
113 }
114 /* End of list */
115 return NULL;
116}
117
118static
119void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos)
120{
121 struct lttng_probe_desc *probe_desc;
122 int iter = 0, i;
123
124 (*ppos)++;
125 list_for_each_entry(probe_desc, &probe_list, head) {
126 for (i = 0; i < probe_desc->nr_events; i++) {
127 if (iter++ >= *ppos)
128 return (void *) probe_desc->event_desc[i];
129 }
130 }
131 /* End of list */
132 return NULL;
133}
134
135static
136void tp_list_stop(struct seq_file *m, void *p)
137{
138 mutex_unlock(&probe_mutex);
139}
140
141static
142int tp_list_show(struct seq_file *m, void *p)
143{
144 const struct lttng_event_desc *probe_desc = p;
145
146 /*
147 * Don't export lttng internal event: lttng_metadata.
148 */
149 if (!strcmp(probe_desc->name, "lttng_metadata"))
150 return 0;
151 seq_printf(m, "event { name = %s; };\n",
152 probe_desc->name);
153 return 0;
154}
155
156static
157const struct seq_operations lttng_tracepoint_list_seq_ops = {
158 .start = tp_list_start,
159 .next = tp_list_next,
160 .stop = tp_list_stop,
161 .show = tp_list_show,
162};
163
164static
165int lttng_tracepoint_list_open(struct inode *inode, struct file *file)
166{
167 return seq_open(file, &lttng_tracepoint_list_seq_ops);
168}
169
170const struct file_operations lttng_tracepoint_list_fops = {
171 .owner = THIS_MODULE,
172 .open = lttng_tracepoint_list_open,
173 .read = seq_read,
174 .llseek = seq_lseek,
175 .release = seq_release,
176};
This page took 0.023713 seconds and 4 git commands to generate.