ongoing ABI implementation
[lttng-modules.git] / ltt-ring-buffer-client.h
1 /*
2 * ltt-ring-buffer-client.h
3 *
4 * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * LTTng lib ring buffer client template.
7 *
8 * Dual LGPL v2.1/GPL v2 license.
9 */
10
11 #include <linux/module.h>
12 #include "ltt-tracer.h"
13
14 struct ring_buffer_priv {
15 struct dentry *dentry;
16 }
17
18 struct channel_priv {
19 struct ltt_trace *trace;
20 struct ring_buffer_priv *buf;
21 };
22
23 static const struct lib_ring_buffer_config client_config;
24
25 static u64 client_ring_buffer_clock_read(struct channel *chan)
26 {
27 return lib_ring_buffer_clock_read(chan);
28 }
29
30 static
31 size_t client_record_header_size(const struct lib_ring_buffer_config *config,
32 struct channel *chan, size_t offset,
33 size_t data_size,
34 size_t *pre_header_padding,
35 unsigned int rflags,
36 struct lib_ring_buffer_ctx *ctx)
37 {
38 return record_header_size(config, chan, offset, data_size,
39 pre_header_padding, rflags, ctx);
40 }
41
42 /**
43 * client_subbuffer_header_size - called on buffer-switch to a new sub-buffer
44 *
45 * Return header size without padding after the structure. Don't use packed
46 * structure because gcc generates inefficient code on some architectures
47 * (powerpc, mips..)
48 */
49 static size_t client_subbuffer_header_size(void)
50 {
51 return offsetof(struct subbuffer_header, header_end);
52 }
53
54 static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc,
55 unsigned int subbuf_idx)
56 {
57 struct channel *chan = buf->backend.chan;
58 struct subbuffer_header *header =
59 (struct subbuffer_header *)
60 lib_ring_buffer_offset_address(&buf->backend,
61 subbuf_idx * chan->backend.subbuf_size);
62
63 header->cycle_count_begin = tsc;
64 header->data_size = 0xFFFFFFFF; /* for debugging */
65 write_trace_header(chan->backend.priv, header);
66 }
67
68 /*
69 * offset is assumed to never be 0 here : never deliver a completely empty
70 * subbuffer. data_size is between 1 and subbuf_size.
71 */
72 static void client_buffer_end(struct lib_ring_buffer *buf, u64 tsc,
73 unsigned int subbuf_idx, unsigned long data_size)
74 {
75 struct channel *chan = buf->backend.chan;
76 struct subbuffer_header *header =
77 (struct subbuffer_header *)
78 lib_ring_buffer_offset_address(&buf->backend,
79 subbuf_idx * chan->backend.subbuf_size);
80 unsigned long records_lost = 0;
81
82 header->data_size = data_size;
83 header->subbuf_size = PAGE_ALIGN(data_size);
84 header->cycle_count_end = tsc;
85 records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf);
86 records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf);
87 records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf);
88 header->events_lost = records_lost;
89 header->subbuf_corrupt = 0; /* deprecated */
90 }
91
92 static int client_buffer_create(struct lib_ring_buffer *buf, void *priv,
93 int cpu, const char *name)
94 {
95 struct channel_priv *chan_priv = priv;
96 struct ring_buffer_priv *buf_priv;
97 struct dentry *trace_dentry;
98 char *tmpname;
99 int ret = 0;
100
101 if (client_config.alloc == RING_BUFFER_ALLOC_PER_CPU)
102 buf_priv = per_cpu_ptr(chan_priv->buf, cpu);
103 else
104 buf_priv = chan_priv->buf;
105
106 tmpname = kzalloc(NAME_MAX + 1, GFP_KERNEL);
107 if (!tmpname) {
108 ret = -ENOMEM;
109 goto end;
110 }
111
112 snprintf(tmpname, NAME_MAX, "%s%s_%d",
113 (client_config.mode == RING_BUFFER_OVERWRITE) ? "flight-" : "",
114 name, cpu);
115
116 trace_dentry = chan_priv->trace->dentry.trace_root;
117 buf_priv->dentry = debugfs_create_file(tmpname, S_IRUSR, trace_dentry,
118 buf,
119 &lib_ring_buffer_file_operations);
120 if (!buf_priv->dentry) {
121 ret = -ENOMEM;
122 goto free_name;
123 }
124 free_name:
125 kfree(tmpname);
126 end:
127 return ret;
128 }
129
130 static void client_buffer_finalize(struct lib_ring_buffer *buf, void *priv, int cpu)
131 {
132 struct channel_priv *chan_priv = priv;
133 struct lib_ring_buffer_priv *buf_priv;
134
135 if (client_config.alloc == RING_BUFFER_ALLOC_PER_CPU)
136 buf_priv = per_cpu_ptr(chan_priv->buf, cpu);
137 else
138 buf_priv = chan_priv->buf;
139
140 debugfs_remove(buf_priv->dentry);
141 }
142
143 static const struct lib_ring_buffer_config client_config = {
144 .cb.ring_buffer_clock_read = client_ring_buffer_clock_read,
145 .cb.record_header_size = client_record_header_size,
146 .cb.subbuffer_header_size = client_subbuffer_header_size,
147 .cb.buffer_begin = client_buffer_begin,
148 .cb.buffer_end = client_buffer_end,
149 .cb.buffer_create = client_buffer_create,
150 .cb.buffer_finalize = client_buffer_finalize,
151
152 .tsc_bits = 32,
153 .alloc = RING_BUFFER_ALLOC_PER_CPU,
154 .sync = RING_BUFFER_SYNC_PER_CPU,
155 .mode = RING_BUFFER_MODE_TEMPLATE,
156 #ifdef RING_BUFFER_ALIGN
157 .align = RING_BUFFER_NATURAL,
158 #else
159 .align = RING_BUFFER_PACKED,
160 #endif
161 .backend = RING_BUFFER_PAGE,
162 .output = RING_BUFFER_SPLICE,
163 .oops = RING_BUFFER_OOPS_CONSISTENCY,
164 .ipi = RING_BUFFER_IPI_BARRIER,
165 .wakeup = RING_BUFFER_WAKEUP_BY_TIMER,
166 };
167
168 static
169 struct channel *ltt_channel_create(const char *name, struct ltt_trace *trace,
170 void *buf_addr,
171 size_t subbuf_size, size_t num_subbuf,
172 unsigned int switch_timer_interval,
173 unsigned int read_timer_interval)
174 {
175 struct channel *chan;
176 struct chan_priv *chan_priv;
177
178 chan_priv = kzalloc(sizeof(struct chan_priv), GFP_KERNEL);
179 if (!chan_priv)
180 return NULL;
181 if (client_config.alloc == RING_BUFFER_ALLOC_PER_CPU) {
182 chan_priv->buf = alloc_percpu(struct lib_ring_buffer_priv);
183 memset(chan_priv->buf, 0, sizeof(*chan_priv->buf));
184 } else
185 chan_priv->buf = kzalloc(sizeof(*chan_priv->buf), GFP_KERNEL)
186 if (!channel_priv->buf)
187 goto free_chan_priv;
188 chan_priv->trace = trace;
189 chan = channel_create(&client_config, name, chan_priv, buf_addr,
190 subbuf_size, num_subbuf, switch_timer_interval,
191 read_timer_interval);
192 if (!chan)
193 goto free_buf_priv;
194 return chan;
195
196 free_buf_priv:
197 if (client_config.alloc == RING_BUFFER_ALLOC_PER_CPU)
198 free_percpu(chan_priv->buf);
199 else
200 kfree(chan_priv->buf);
201 free_chan_priv:
202 kfree(chan_priv);
203 return NULL;
204 }
205
206 static
207 void ltt_channel_destroy(struct channel *chan)
208 {
209 struct chan_priv *chan_priv = channel_get_private(chan);
210
211 channel_destroy(chan);
212 if (client_config.alloc == RING_BUFFER_ALLOC_PER_CPU)
213 free_percpu(chan_priv->buf);
214 else
215 kfree(chan_priv->buf);
216 kfree(chan_priv);
217 }
218
219 static
220 struct lib_ring_buffer *ltt_buffer_read_open(struct channel *chan)
221 {
222 struct lib_ring_buffer *buf;
223 int cpu;
224
225 for_each_channel_cpu(cpu, chan->chan) {
226 buf = channel_get_ring_buffer(&config_config, chan, cpu);
227 if (!lib_ring_buffer_open_read(buf))
228 return buf;
229 }
230 return NULL;
231 }
232
233 static
234 struct lib_ring_buffer *ltt_buffer_read_close(struct lib_ring_buffer *buf)
235 {
236 lib_ring_buffer_release_read(buf);
237 }
238
239 static void ltt_relay_remove_dirs(struct ltt_trace *trace)
240 {
241 debugfs_remove(trace->dentry.trace_root);
242 }
243
244 static int ltt_relay_create_dirs(struct ltt_trace *new_trace)
245 {
246 struct dentry *ltt_root_dentry;
247 int ret;
248
249 ltt_root_dentry = get_ltt_root();
250 if (!ltt_root_dentry)
251 return ENOENT;
252
253 new_trace->dentry.trace_root = debugfs_create_dir(new_trace->trace_name,
254 ltt_root_dentry);
255 put_ltt_root();
256 if (new_trace->dentry.trace_root == NULL) {
257 printk(KERN_ERR "LTT : Trace directory name %s already taken\n",
258 new_trace->trace_name);
259 return EEXIST;
260 }
261 return 0;
262 }
263
264 static struct ltt_transport ltt_relay_transport = {
265 .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING,
266 .owner = THIS_MODULE,
267 .ops = {
268 .create_dirs = ltt_relay_create_dirs,
269 .remove_dirs = ltt_relay_remove_dirs,
270 .create_channel = ltt_channel_create,
271 .destroy_channel = ltt_channel_destroy,
272 .buffer_read_open = ltt_buffer_read_open,
273 .buffer_read_close = ltt_buffer_read_close,
274 },
275 };
276
277 static int __init ltt_ring_buffer_client_init(void)
278 {
279 printk(KERN_INFO "LTT : ltt ring buffer client init\n");
280 ltt_transport_register(&ltt_relay_transport);
281 return 0;
282 }
283
284 static void __exit ltt_ring_buffer_client_exit(void)
285 {
286 printk(KERN_INFO "LTT : ltt ring buffer client exit\n");
287 ltt_transport_unregister(&ltt_relay_transport);
288 }
289
290 MODULE_LICENSE("GPL and additional rights");
291 MODULE_AUTHOR("Mathieu Desnoyers");
292 MODULE_DESCRIPTION("LTTng ring buffer " RING_BUFFER_MODE_TEMPLATE_STRING
293 " client");
This page took 0.063639 seconds and 5 git commands to generate.