2 * ltt-ring-buffer-client.c
4 * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
6 * LTTng lib ring buffer client.
8 * Dual LGPL v2.1/GPL v2 license.
11 #include <linux/module.h>
12 #include "ltt-tracer.h"
14 struct ring_buffer_priv
{
15 struct dentry
*dentry
;
19 struct ltt_trace
*trace
;
20 struct ring_buffer_priv
*buf
;
23 static const struct lib_ring_buffer_config client_config
;
25 static u64
client_ring_buffer_clock_read(struct channel
*chan
)
27 return lib_ring_buffer_clock_read(chan
);
30 size_t client_record_header_size(const struct lib_ring_buffer_config
*config
,
31 struct channel
*chan
, size_t offset
,
33 size_t *pre_header_padding
,
35 struct lib_ring_buffer_ctx
*ctx
)
37 return record_header_size(config
, chan
, offset
, data_size
,
38 pre_header_padding
, rflags
, ctx
);
42 * client_subbuffer_header_size - called on buffer-switch to a new sub-buffer
44 * Return header size without padding after the structure. Don't use packed
45 * structure because gcc generates inefficient code on some architectures
48 static size_t client_subbuffer_header_size(void)
50 return offsetof(struct subbuffer_header
, header_end
);
53 static void client_buffer_begin(struct lib_ring_buffer
*buf
, u64 tsc
,
54 unsigned int subbuf_idx
)
56 struct channel
*chan
= buf
->backend
.chan
;
57 struct subbuffer_header
*header
=
58 (struct subbuffer_header
*)
59 lib_ring_buffer_offset_address(&buf
->backend
,
60 subbuf_idx
* chan
->backend
.subbuf_size
);
62 header
->cycle_count_begin
= tsc
;
63 header
->data_size
= 0xFFFFFFFF; /* for debugging */
64 write_trace_header(chan
->backend
.priv
, header
);
68 * offset is assumed to never be 0 here : never deliver a completely empty
69 * subbuffer. data_size is between 1 and subbuf_size.
71 static void client_buffer_end(struct lib_ring_buffer
*buf
, u64 tsc
,
72 unsigned int subbuf_idx
, unsigned long data_size
)
74 struct channel
*chan
= buf
->backend
.chan
;
75 struct subbuffer_header
*header
=
76 (struct subbuffer_header
*)
77 lib_ring_buffer_offset_address(&buf
->backend
,
78 subbuf_idx
* chan
->backend
.subbuf_size
);
79 unsigned long records_lost
= 0;
81 header
->data_size
= data_size
;
82 header
->subbuf_size
= PAGE_ALIGN(data_size
);
83 header
->cycle_count_end
= tsc
;
84 records_lost
+= lib_ring_buffer_get_records_lost_full(&client_config
, buf
);
85 records_lost
+= lib_ring_buffer_get_records_lost_wrap(&client_config
, buf
);
86 records_lost
+= lib_ring_buffer_get_records_lost_big(&client_config
, buf
);
87 header
->events_lost
= records_lost
;
88 header
->subbuf_corrupt
= 0; /* deprecated */
91 static int client_buffer_create(struct lib_ring_buffer
*buf
, void *priv
,
92 int cpu
, const char *name
)
94 struct channel_priv
*chan_priv
= priv
;
95 struct ring_buffer_priv
*buf_priv
;
96 struct dentry
*trace_dentry
;
100 if (client_config
.alloc
== RING_BUFFER_ALLOC_PER_CPU
)
101 buf_priv
= per_cpu_ptr(chan_priv
->buf
, cpu
);
103 buf_priv
= chan_priv
->buf
;
105 tmpname
= kzalloc(NAME_MAX
+ 1, GFP_KERNEL
);
111 snprintf(tmpname
, NAME_MAX
, "%s%s_%d",
112 (client_config
.mode
== RING_BUFFER_OVERWRITE
) ? : "",
115 trace_dentry
= chan_priv
->trace
->dentry
.trace_root
;
116 buf_priv
->dentry
= debugfs_create_file(tmpname
, S_IRUSR
, trace_dentry
,
118 &lib_ring_buffer_file_operations
);
119 if (!buf_priv
->dentry
) {
129 static void client_buffer_finalize(struct lib_ring_buffer
*buf
, void *priv
, int cpu
)
131 struct channel_priv
*chan_priv
= priv
;
132 struct lib_ring_buffer_priv
*buf_priv
;
134 if (client_config
.alloc
== RING_BUFFER_ALLOC_PER_CPU
)
135 buf_priv
= per_cpu_ptr(chan_priv
->buf
, cpu
);
137 buf_priv
= chan_priv
->buf
;
139 debugfs_remove(buf_priv
->dentry
);
142 static const struct lib_ring_buffer_config client_config
= {
143 .cb
.ring_buffer_clock_read
= client_ring_buffer_clock_read
,
144 .cb
.record_header_size
= client_record_header_size
,
145 .cb
.subbuffer_header_size
= client_subbuffer_header_size
,
146 .cb
.buffer_begin
= client_buffer_begin
,
147 .cb
.buffer_end
= client_buffer_end
,
148 .cb
.buffer_create
= client_buffer_create
,
149 .cb
.buffer_finalize
= client_buffer_finalize
,
152 .alloc
= RING_BUFFER_ALLOC_PER_CPU
,
153 .sync
= RING_BUFFER_SYNC_PER_CPU
,
154 .mode
= RING_BUFFER_OVERWRITE
,
155 #ifdef RING_BUFFER_ALIGN
156 .align
= RING_BUFFER_NATURAL
,
158 .align
= RING_BUFFER_PACKED
,
160 .backend
= RING_BUFFER_PAGE
,
161 .output
= RING_BUFFER_SPLICE
,
162 .oops
= RING_BUFFER_OOPS_CONSISTENCY
,
163 .ipi
= RING_BUFFER_IPI_BARRIER
,
164 .wakeup
= RING_BUFFER_WAKEUP_BY_TIMER
,
167 struct channel
*ltt_channel_create(const char *name
, struct ltt_trace
*trace
,
169 size_t subbuf_size
, size_t num_subbuf
,
170 unsigned int switch_timer_interval
,
171 unsigned int read_timer_interval
)
173 struct channel
*chan
;
174 struct chan_priv
*chan_priv
;
176 chan_priv
= kzalloc(sizeof(struct chan_priv
), GFP_KERNEL
);
179 if (client_config
.alloc
== RING_BUFFER_ALLOC_PER_CPU
) {
180 chan_priv
->buf
= alloc_percpu(struct lib_ring_buffer_priv
);
181 memset(chan_priv
->buf
, 0, sizeof(*chan_priv
->buf
));
183 chan_priv
->buf
= kzalloc(sizeof(*chan_priv
->buf
), GFP_KERNEL
)
184 if (!channel_priv
->buf
)
186 chan_priv
->trace
= trace
;
187 chan
= channel_create(&client_config
, name
, chan_priv
, buf_addr
,
188 subbuf_size
, num_subbuf
, switch_timer_interval
,
189 read_timer_interval
);
195 if (client_config
.alloc
== RING_BUFFER_ALLOC_PER_CPU
)
196 free_percpu(chan_priv
->buf
);
198 kfree(chan_priv
->buf
);
204 void ltt_channel_destroy(struct channel
*chan
)
206 struct chan_priv
*chan_priv
= channel_get_private(chan
);
208 channel_destroy(chan
);
209 if (client_config
.alloc
== RING_BUFFER_ALLOC_PER_CPU
)
210 free_percpu(chan_priv
->buf
);
212 kfree(chan_priv
->buf
);
216 static void ltt_relay_remove_dirs(struct ltt_trace
*trace
)
219 ltt_ascii_remove_dir(trace
);
221 debugfs_remove(trace
->dentry
.trace_root
);
224 static int ltt_relay_create_dirs(struct ltt_trace
*new_trace
)
226 struct dentry
*ltt_root_dentry
;
229 ltt_root_dentry
= get_ltt_root();
230 if (!ltt_root_dentry
)
233 new_trace
->dentry
.trace_root
= debugfs_create_dir(new_trace
->trace_name
,
236 if (new_trace
->dentry
.trace_root
== NULL
) {
237 printk(KERN_ERR
"LTT : Trace directory name %s already taken\n",
238 new_trace
->trace_name
);
242 ret
= ltt_ascii_create_dir(new_trace
);
244 printk(KERN_WARNING
"LTT : Unable to create ascii output file "
245 "for trace %s\n", new_trace
->trace_name
);
249 static struct ltt_transport ltt_relay_transport
= {
251 .owner
= THIS_MODULE
,
253 .create_dirs
= ltt_relay_create_dirs
,
254 .remove_dirs
= ltt_relay_remove_dirs
,
258 int __init
ltt_ring_buffer_client_init(void)
260 printk(KERN_INFO
"LTT : ltt ring buffer client init\n");
261 ltt_transport_register(<t_relay_transport
);
265 void __exit
ltt_ring_buffer_client_exit(void)
267 printk(KERN_INFO
"LTT : ltt ring buffer client exit\n");
268 ltt_transport_unregister(<t_relay_transport
);
271 MODULE_LICENSE("GPL and additional rights");
272 MODULE_AUTHOR("Mathieu Desnoyers");
273 MODULE_DESCRIPTION("LTTng Ring Buffer Client");