Handle release of parent files (header)
[lttng-modules.git] / ltt-ring-buffer-client.h
CommitLineData
7514523f 1/*
3d084699 2 * ltt-ring-buffer-client.h
7514523f
MD
3 *
4 * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
3d084699 6 * LTTng lib ring buffer client template.
7514523f
MD
7 *
8 * Dual LGPL v2.1/GPL v2 license.
9 */
10
11#include <linux/module.h>
12#include "ltt-tracer.h"
13
14struct ring_buffer_priv {
15 struct dentry *dentry;
16}
17
18struct channel_priv {
19 struct ltt_trace *trace;
20 struct ring_buffer_priv *buf;
21};
22
23static const struct lib_ring_buffer_config client_config;
24
25static u64 client_ring_buffer_clock_read(struct channel *chan)
26{
27 return lib_ring_buffer_clock_read(chan);
28}
29
1e2015dc 30static
7514523f
MD
31size_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 */
49static size_t client_subbuffer_header_size(void)
50{
51 return offsetof(struct subbuffer_header, header_end);
52}
53
54static 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 */
72static 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
92static 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",
3d084699 113 (client_config.mode == RING_BUFFER_OVERWRITE) ? "flight-" : "",
7514523f
MD
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 }
124free_name:
125 kfree(tmpname);
126end:
127 return ret;
128}
129
130static 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
143static 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,
3d084699 155 .mode = RING_BUFFER_MODE_TEMPLATE,
7514523f
MD
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
1e2015dc 168static
7514523f
MD
169struct 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
196free_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);
201free_chan_priv:
202 kfree(chan_priv);
203 return NULL;
204}
205
1e2015dc 206static
7514523f
MD
207void 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
ad1c05e1
MD
219static
220struct 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
233static
234struct lib_ring_buffer *ltt_buffer_read_close(struct lib_ring_buffer *buf)
235{
236 lib_ring_buffer_release_read(buf);
237}
238
7514523f
MD
239static void ltt_relay_remove_dirs(struct ltt_trace *trace)
240{
7514523f
MD
241 debugfs_remove(trace->dentry.trace_root);
242}
243
244static 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 }
7514523f
MD
261 return 0;
262}
1e2015dc 263
7514523f 264static struct ltt_transport ltt_relay_transport = {
3d084699 265 .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING,
7514523f
MD
266 .owner = THIS_MODULE,
267 .ops = {
268 .create_dirs = ltt_relay_create_dirs,
269 .remove_dirs = ltt_relay_remove_dirs,
1e2015dc
MD
270 .create_channel = ltt_channel_create,
271 .destroy_channel = ltt_channel_destroy,
ad1c05e1
MD
272 .buffer_read_open = ltt_buffer_read_open,
273 .buffer_read_close = ltt_buffer_read_close,
7514523f
MD
274 },
275};
276
3d084699 277static int __init ltt_ring_buffer_client_init(void)
7514523f
MD
278{
279 printk(KERN_INFO "LTT : ltt ring buffer client init\n");
280 ltt_transport_register(&ltt_relay_transport);
281 return 0;
282}
283
3d084699 284static void __exit ltt_ring_buffer_client_exit(void)
7514523f
MD
285{
286 printk(KERN_INFO "LTT : ltt ring buffer client exit\n");
287 ltt_transport_unregister(&ltt_relay_transport);
288}
289
290MODULE_LICENSE("GPL and additional rights");
291MODULE_AUTHOR("Mathieu Desnoyers");
3d084699
MD
292MODULE_DESCRIPTION("LTTng ring buffer " RING_BUFFER_MODE_TEMPLATE_STRING
293 " client");
This page took 0.034466 seconds and 4 git commands to generate.