libust: New transport mutex v2
[ust.git] / libust / tracer.c
CommitLineData
9dad1eb8 1/*
c1f20530 2 * tracer.c
9dad1eb8
PMF
3 *
4 * (C) Copyright 2005-2008 -
5 * Mathieu Desnoyers (mathieu.desnoyers@polymtl.ca)
6 *
34e4b7db
PMF
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 *
9dad1eb8
PMF
21 * Inspired from LTT :
22 * Karim Yaghmour (karim@opersys.com)
23 * Tom Zanussi (zanussi@us.ibm.com)
24 * Bob Wisniewski (bob@watson.ibm.com)
25 * And from K42 :
26 * Bob Wisniewski (bob@watson.ibm.com)
27 *
28 * Changelog:
29 * 22/09/06, Move to the marker/probes mechanism.
30 * 19/10/05, Complete lockless mechanism.
31 * 27/05/05, Modular redesign and rewrite.
32 */
33
b5b073e2 34#include <urcu-bp.h>
b7ea1a1c 35#include <urcu/rculist.h>
4268fdcd 36
518d7abb
PMF
37#include <ust/clock.h>
38
b6bf28ec 39#include "tracercore.h"
c93858f1 40#include "tracer.h"
b6bf28ec
PMF
41#include "usterr.h"
42
43//ust// static void async_wakeup(unsigned long data);
44//ust//
45//ust// static DEFINE_TIMER(ltt_async_wakeup_timer, async_wakeup, 0, 0);
9dad1eb8
PMF
46
47/* Default callbacks for modules */
48notrace int ltt_filter_control_default(enum ltt_filter_control_msg msg,
b73a4c47 49 struct ust_trace *trace)
9dad1eb8
PMF
50{
51 return 0;
52}
53
b73a4c47 54int ltt_statedump_default(struct ust_trace *trace)
9dad1eb8
PMF
55{
56 return 0;
57}
58
59/* Callbacks for registered modules */
60
61int (*ltt_filter_control_functor)
b73a4c47 62 (enum ltt_filter_control_msg msg, struct ust_trace *trace) =
9dad1eb8
PMF
63 ltt_filter_control_default;
64struct module *ltt_filter_control_owner;
65
66/* These function pointers are protected by a trace activation check */
67struct module *ltt_run_filter_owner;
b73a4c47 68int (*ltt_statedump_functor)(struct ust_trace *trace) =
9dad1eb8
PMF
69 ltt_statedump_default;
70struct module *ltt_statedump_owner;
71
223f2e7c 72struct chan_info_struct chan_infos[] = {
9dad1eb8
PMF
73 [LTT_CHANNEL_METADATA] = {
74 LTT_METADATA_CHANNEL,
75 LTT_DEFAULT_SUBBUF_SIZE_LOW,
76 LTT_DEFAULT_N_SUBBUFS_LOW,
77 },
b6bf28ec
PMF
78 [LTT_CHANNEL_UST] = {
79 LTT_UST_CHANNEL,
9dad1eb8
PMF
80 LTT_DEFAULT_SUBBUF_SIZE_HIGH,
81 LTT_DEFAULT_N_SUBBUFS_HIGH,
82 },
9dad1eb8
PMF
83};
84
85static enum ltt_channels get_channel_type_from_name(const char *name)
86{
87 int i;
88
89 if (!name)
b6bf28ec 90 return LTT_CHANNEL_UST;
9dad1eb8
PMF
91
92 for (i = 0; i < ARRAY_SIZE(chan_infos); i++)
93 if (chan_infos[i].name && !strcmp(name, chan_infos[i].name))
94 return (enum ltt_channels)i;
95
b6bf28ec 96 return LTT_CHANNEL_UST;
9dad1eb8
PMF
97}
98
99/**
100 * ltt_module_register - LTT module registration
101 * @name: module type
102 * @function: callback to register
103 * @owner: module which owns the callback
104 *
105 * The module calling this registration function must ensure that no
106 * trap-inducing code will be executed by "function". E.g. vmalloc_sync_all()
107 * must be called between a vmalloc and the moment the memory is made visible to
108 * "function". This registration acts as a vmalloc_sync_all. Therefore, only if
109 * the module allocates virtual memory after its registration must it
110 * synchronize the TLBs.
111 */
b6bf28ec
PMF
112//ust// int ltt_module_register(enum ltt_module_function name, void *function,
113//ust// struct module *owner)
114//ust// {
115//ust// int ret = 0;
116//ust//
117//ust// /*
118//ust// * Make sure no page fault can be triggered by the module about to be
119//ust// * registered. We deal with this here so we don't have to call
120//ust// * vmalloc_sync_all() in each module's init.
121//ust// */
122//ust// vmalloc_sync_all();
123//ust//
124//ust// switch (name) {
125//ust// case LTT_FUNCTION_RUN_FILTER:
126//ust// if (ltt_run_filter_owner != NULL) {
127//ust// ret = -EEXIST;
128//ust// goto end;
129//ust// }
130//ust// ltt_filter_register((ltt_run_filter_functor)function);
131//ust// ltt_run_filter_owner = owner;
132//ust// break;
133//ust// case LTT_FUNCTION_FILTER_CONTROL:
134//ust// if (ltt_filter_control_owner != NULL) {
135//ust// ret = -EEXIST;
136//ust// goto end;
137//ust// }
138//ust// ltt_filter_control_functor =
139//ust// (int (*)(enum ltt_filter_control_msg,
b73a4c47 140//ust// struct ust_trace *))function;
b6bf28ec
PMF
141//ust// ltt_filter_control_owner = owner;
142//ust// break;
143//ust// case LTT_FUNCTION_STATEDUMP:
144//ust// if (ltt_statedump_owner != NULL) {
145//ust// ret = -EEXIST;
146//ust// goto end;
147//ust// }
148//ust// ltt_statedump_functor =
b73a4c47 149//ust// (int (*)(struct ust_trace *))function;
b6bf28ec
PMF
150//ust// ltt_statedump_owner = owner;
151//ust// break;
152//ust// }
153//ust//
154//ust// end:
155//ust//
156//ust// return ret;
157//ust// }
9dad1eb8
PMF
158
159/**
160 * ltt_module_unregister - LTT module unregistration
161 * @name: module type
162 */
b6bf28ec
PMF
163//ust// void ltt_module_unregister(enum ltt_module_function name)
164//ust// {
165//ust// switch (name) {
166//ust// case LTT_FUNCTION_RUN_FILTER:
167//ust// ltt_filter_unregister();
168//ust// ltt_run_filter_owner = NULL;
169//ust// /* Wait for preempt sections to finish */
170//ust// synchronize_sched();
171//ust// break;
172//ust// case LTT_FUNCTION_FILTER_CONTROL:
173//ust// ltt_filter_control_functor = ltt_filter_control_default;
174//ust// ltt_filter_control_owner = NULL;
175//ust// break;
176//ust// case LTT_FUNCTION_STATEDUMP:
177//ust// ltt_statedump_functor = ltt_statedump_default;
178//ust// ltt_statedump_owner = NULL;
179//ust// break;
180//ust// }
181//ust//
182//ust// }
9dad1eb8 183
0222e121 184static CDS_LIST_HEAD(ltt_transport_list);
8d6300d3
NC
185/* transport mutex, nests inside traces mutex (ltt_lock_traces) */
186static DEFINE_MUTEX(ltt_transport_mutex);
9dad1eb8
PMF
187/**
188 * ltt_transport_register - LTT transport registration
189 * @transport: transport structure
190 *
191 * Registers a transport which can be used as output to extract the data out of
192 * LTTng. The module calling this registration function must ensure that no
193 * trap-inducing code will be executed by the transport functions. E.g.
194 * vmalloc_sync_all() must be called between a vmalloc and the moment the memory
195 * is made visible to the transport function. This registration acts as a
196 * vmalloc_sync_all. Therefore, only if the module allocates virtual memory
197 * after its registration must it synchronize the TLBs.
198 */
5f54827b
PMF
199void ltt_transport_register(struct ltt_transport *transport)
200{
201 /*
202 * Make sure no page fault can be triggered by the module about to be
203 * registered. We deal with this here so we don't have to call
204 * vmalloc_sync_all() in each module's init.
205 */
bb07823d 206//ust// vmalloc_sync_all();
5f54827b 207
8d6300d3 208 pthread_mutex_lock(&ltt_transport_mutex);
0222e121 209 cds_list_add_tail(&transport->node, &ltt_transport_list);
8d6300d3 210 pthread_mutex_unlock(&ltt_transport_mutex);
5f54827b 211}
9dad1eb8
PMF
212
213/**
214 * ltt_transport_unregister - LTT transport unregistration
215 * @transport: transport structure
216 */
bb07823d
PMF
217void ltt_transport_unregister(struct ltt_transport *transport)
218{
8d6300d3 219 pthread_mutex_lock(&ltt_transport_mutex);
0222e121 220 cds_list_del(&transport->node);
8d6300d3 221 pthread_mutex_unlock(&ltt_transport_mutex);
bb07823d 222}
9dad1eb8
PMF
223
224static inline int is_channel_overwrite(enum ltt_channels chan,
225 enum trace_mode mode)
226{
227 switch (mode) {
228 case LTT_TRACE_NORMAL:
229 return 0;
230 case LTT_TRACE_FLIGHT:
231 switch (chan) {
232 case LTT_CHANNEL_METADATA:
233 return 0;
234 default:
235 return 1;
236 }
237 case LTT_TRACE_HYBRID:
238 switch (chan) {
b6bf28ec 239 case LTT_CHANNEL_METADATA:
9dad1eb8 240 return 0;
b6bf28ec
PMF
241 default:
242 return 1;
9dad1eb8
PMF
243 }
244 default:
245 return 0;
246 }
247}
248
b73a4c47 249static void trace_async_wakeup(struct ust_trace *trace)
9dad1eb8
PMF
250{
251 int i;
b5b073e2 252 struct ust_channel *chan;
9dad1eb8
PMF
253
254 /* Must check each channel for pending read wakeup */
255 for (i = 0; i < trace->nr_channels; i++) {
256 chan = &trace->channels[i];
257 if (chan->active)
258 trace->ops->wakeup_channel(chan);
259 }
260}
261
b6bf28ec
PMF
262//ust// /* Timer to send async wakeups to the readers */
263//ust// static void async_wakeup(unsigned long data)
264//ust// {
b73a4c47 265//ust// struct ust_trace *trace;
b6bf28ec
PMF
266//ust//
267//ust// /*
268//ust// * PREEMPT_RT does not allow spinlocks to be taken within preempt
269//ust// * disable sections (spinlock taken in wake_up). However, mainline won't
270//ust// * allow mutex to be taken in interrupt context. Ugly.
271//ust// * A proper way to do this would be to turn the timer into a
272//ust// * periodically woken up thread, but it adds to the footprint.
273//ust// */
274//ust// #ifndef CONFIG_PREEMPT_RT
275//ust// rcu_read_lock_sched();
276//ust// #else
277//ust// ltt_lock_traces();
278//ust// #endif
0222e121 279//ust// cds_list_for_each_entry_rcu(trace, &ltt_traces.head, list) {
b6bf28ec
PMF
280//ust// trace_async_wakeup(trace);
281//ust// }
282//ust// #ifndef CONFIG_PREEMPT_RT
283//ust// rcu_read_unlock_sched();
284//ust// #else
285//ust// ltt_unlock_traces();
286//ust// #endif
287//ust//
288//ust// mod_timer(&ltt_async_wakeup_timer, jiffies + LTT_PERCPU_TIMER_INTERVAL);
289//ust// }
9dad1eb8
PMF
290
291/**
292 * _ltt_trace_find - find a trace by given name.
293 * trace_name: trace name
294 *
295 * Returns a pointer to the trace structure, NULL if not found.
296 */
b73a4c47 297struct ust_trace *_ltt_trace_find(const char *trace_name)
9dad1eb8 298{
b73a4c47 299 struct ust_trace *trace;
9dad1eb8 300
0222e121 301 cds_list_for_each_entry(trace, &ltt_traces.head, list)
9dad1eb8
PMF
302 if (!strncmp(trace->trace_name, trace_name, NAME_MAX))
303 return trace;
304
305 return NULL;
306}
307
308/* _ltt_trace_find_setup :
309 * find a trace in setup list by given name.
310 *
311 * Returns a pointer to the trace structure, NULL if not found.
312 */
b73a4c47 313struct ust_trace *_ltt_trace_find_setup(const char *trace_name)
9dad1eb8 314{
b73a4c47 315 struct ust_trace *trace;
9dad1eb8 316
0222e121 317 cds_list_for_each_entry(trace, &ltt_traces.setup_head, list)
9dad1eb8
PMF
318 if (!strncmp(trace->trace_name, trace_name, NAME_MAX))
319 return trace;
320
321 return NULL;
322}
9dad1eb8
PMF
323
324/**
325 * ltt_release_transport - Release an LTT transport
326 * @kref : reference count on the transport
327 */
205f7ca7 328void ltt_release_transport(struct urcu_ref *urcu_ref)
9dad1eb8 329{
b73a4c47
PMF
330//ust// struct ust_trace *trace = container_of(kref,
331//ust// struct ust_trace, ltt_transport_kref);
772030fe 332//ust// trace->ops->remove_dirs(trace);
9dad1eb8 333}
9dad1eb8
PMF
334
335/**
336 * ltt_release_trace - Release a LTT trace
337 * @kref : reference count on the trace
338 */
205f7ca7 339void ltt_release_trace(struct urcu_ref *urcu_ref)
9dad1eb8 340{
205f7ca7
DG
341 struct ust_trace *trace = _ust_container_of(urcu_ref,
342 struct ust_trace, urcu_ref);
9dad1eb8 343 ltt_channels_trace_free(trace->channels);
909bc43f 344 free(trace);
9dad1eb8 345}
9dad1eb8
PMF
346
347static inline void prepare_chan_size_num(unsigned int *subbuf_size,
348 unsigned int *n_subbufs)
349{
b73a4c47
PMF
350 /* Make sure the subbuffer size is larger than a page */
351 *subbuf_size = max_t(unsigned int, *subbuf_size, PAGE_SIZE);
352
353 /* round to next power of 2 */
9dad1eb8
PMF
354 *subbuf_size = 1 << get_count_order(*subbuf_size);
355 *n_subbufs = 1 << get_count_order(*n_subbufs);
356
357 /* Subbuf size and number must both be power of two */
358 WARN_ON(hweight32(*subbuf_size) != 1);
359 WARN_ON(hweight32(*n_subbufs) != 1);
360}
361
362int _ltt_trace_setup(const char *trace_name)
363{
364 int err = 0;
b73a4c47 365 struct ust_trace *new_trace = NULL;
9dad1eb8
PMF
366 int metadata_index;
367 unsigned int chan;
368 enum ltt_channels chantype;
369
370 if (_ltt_trace_find_setup(trace_name)) {
c1f20530 371 ERR("Trace name %s already used", trace_name);
9dad1eb8
PMF
372 err = -EEXIST;
373 goto traces_error;
374 }
375
376 if (_ltt_trace_find(trace_name)) {
c1f20530 377 ERR("Trace name %s already used", trace_name);
9dad1eb8
PMF
378 err = -EEXIST;
379 goto traces_error;
380 }
381
909bc43f 382 new_trace = zmalloc(sizeof(struct ust_trace));
9dad1eb8 383 if (!new_trace) {
c1f20530 384 ERR("Unable to allocate memory for trace %s", trace_name);
9dad1eb8
PMF
385 err = -ENOMEM;
386 goto traces_error;
387 }
388 strncpy(new_trace->trace_name, trace_name, NAME_MAX);
389 new_trace->channels = ltt_channels_trace_alloc(&new_trace->nr_channels,
8649cd59
PMF
390 ust_channels_overwrite_by_default,
391 ust_channels_request_collection_by_default, 1);
9dad1eb8 392 if (!new_trace->channels) {
c1f20530 393 ERR("Unable to allocate memory for chaninfo %s\n", trace_name);
9dad1eb8
PMF
394 err = -ENOMEM;
395 goto trace_free;
396 }
397
398 /*
399 * Force metadata channel to active, no overwrite.
400 */
401 metadata_index = ltt_channels_get_index_from_name("metadata");
402 WARN_ON(metadata_index < 0);
403 new_trace->channels[metadata_index].overwrite = 0;
404 new_trace->channels[metadata_index].active = 1;
405
406 /*
407 * Set hardcoded tracer defaults for some channels
408 */
409 for (chan = 0; chan < new_trace->nr_channels; chan++) {
410 if (!(new_trace->channels[chan].active))
411 continue;
412
413 chantype = get_channel_type_from_name(
414 ltt_channels_get_name_from_index(chan));
415 new_trace->channels[chan].subbuf_size =
416 chan_infos[chantype].def_subbufsize;
417 new_trace->channels[chan].subbuf_cnt =
418 chan_infos[chantype].def_subbufcount;
419 }
420
0222e121 421 cds_list_add(&new_trace->list, &ltt_traces.setup_head);
9dad1eb8
PMF
422 return 0;
423
424trace_free:
909bc43f 425 free(new_trace);
9dad1eb8
PMF
426traces_error:
427 return err;
428}
9dad1eb8
PMF
429
430
431int ltt_trace_setup(const char *trace_name)
432{
433 int ret;
434 ltt_lock_traces();
435 ret = _ltt_trace_setup(trace_name);
436 ltt_unlock_traces();
437 return ret;
438}
9dad1eb8
PMF
439
440/* must be called from within a traces lock. */
b73a4c47 441static void _ltt_trace_free(struct ust_trace *trace)
9dad1eb8 442{
0222e121 443 cds_list_del(&trace->list);
909bc43f 444 free(trace);
9dad1eb8
PMF
445}
446
447int ltt_trace_set_type(const char *trace_name, const char *trace_type)
448{
449 int err = 0;
b73a4c47 450 struct ust_trace *trace;
9dad1eb8
PMF
451 struct ltt_transport *tran_iter, *transport = NULL;
452
453 ltt_lock_traces();
454
455 trace = _ltt_trace_find_setup(trace_name);
456 if (!trace) {
c1f20530 457 ERR("Trace not found %s", trace_name);
9dad1eb8
PMF
458 err = -ENOENT;
459 goto traces_error;
460 }
461
8d6300d3 462 pthread_mutex_lock(&ltt_transport_mutex);
0222e121 463 cds_list_for_each_entry(tran_iter, &ltt_transport_list, node) {
9dad1eb8
PMF
464 if (!strcmp(tran_iter->name, trace_type)) {
465 transport = tran_iter;
466 break;
467 }
468 }
8d6300d3
NC
469 pthread_mutex_unlock(&ltt_transport_mutex);
470
9dad1eb8 471 if (!transport) {
c1f20530 472 ERR("Transport %s is not present", trace_type);
9dad1eb8
PMF
473 err = -EINVAL;
474 goto traces_error;
475 }
476
477 trace->transport = transport;
478
479traces_error:
480 ltt_unlock_traces();
481 return err;
482}
9dad1eb8
PMF
483
484int ltt_trace_set_channel_subbufsize(const char *trace_name,
485 const char *channel_name, unsigned int size)
486{
487 int err = 0;
b73a4c47 488 struct ust_trace *trace;
9dad1eb8
PMF
489 int index;
490
491 ltt_lock_traces();
492
493 trace = _ltt_trace_find_setup(trace_name);
494 if (!trace) {
c1f20530 495 ERR("Trace not found %s", trace_name);
9dad1eb8
PMF
496 err = -ENOENT;
497 goto traces_error;
498 }
499
500 index = ltt_channels_get_index_from_name(channel_name);
501 if (index < 0) {
c1f20530 502 ERR("Channel %s not found", channel_name);
9dad1eb8
PMF
503 err = -ENOENT;
504 goto traces_error;
505 }
506 trace->channels[index].subbuf_size = size;
507
508traces_error:
509 ltt_unlock_traces();
510 return err;
511}
9dad1eb8
PMF
512
513int ltt_trace_set_channel_subbufcount(const char *trace_name,
514 const char *channel_name, unsigned int cnt)
515{
516 int err = 0;
b73a4c47 517 struct ust_trace *trace;
9dad1eb8
PMF
518 int index;
519
520 ltt_lock_traces();
521
522 trace = _ltt_trace_find_setup(trace_name);
523 if (!trace) {
c1f20530 524 ERR("Trace not found %s", trace_name);
9dad1eb8
PMF
525 err = -ENOENT;
526 goto traces_error;
527 }
528
529 index = ltt_channels_get_index_from_name(channel_name);
530 if (index < 0) {
c1f20530 531 ERR("Channel %s not found", channel_name);
9dad1eb8
PMF
532 err = -ENOENT;
533 goto traces_error;
534 }
535 trace->channels[index].subbuf_cnt = cnt;
536
537traces_error:
538 ltt_unlock_traces();
539 return err;
540}
9dad1eb8
PMF
541
542int ltt_trace_set_channel_enable(const char *trace_name,
543 const char *channel_name, unsigned int enable)
544{
545 int err = 0;
b73a4c47 546 struct ust_trace *trace;
9dad1eb8
PMF
547 int index;
548
549 ltt_lock_traces();
550
551 trace = _ltt_trace_find_setup(trace_name);
552 if (!trace) {
c1f20530 553 ERR("Trace not found %s", trace_name);
9dad1eb8
PMF
554 err = -ENOENT;
555 goto traces_error;
556 }
557
558 /*
559 * Datas in metadata channel(marker info) is necessary to be able to
560 * read the trace, we always enable this channel.
561 */
562 if (!enable && !strcmp(channel_name, "metadata")) {
c1f20530 563 ERR("Trying to disable metadata channel");
9dad1eb8
PMF
564 err = -EINVAL;
565 goto traces_error;
566 }
567
568 index = ltt_channels_get_index_from_name(channel_name);
569 if (index < 0) {
c1f20530 570 ERR("Channel %s not found", channel_name);
9dad1eb8
PMF
571 err = -ENOENT;
572 goto traces_error;
573 }
574
575 trace->channels[index].active = enable;
576
577traces_error:
578 ltt_unlock_traces();
579 return err;
580}
9dad1eb8
PMF
581
582int ltt_trace_set_channel_overwrite(const char *trace_name,
583 const char *channel_name, unsigned int overwrite)
584{
585 int err = 0;
b73a4c47 586 struct ust_trace *trace;
9dad1eb8
PMF
587 int index;
588
589 ltt_lock_traces();
590
591 trace = _ltt_trace_find_setup(trace_name);
592 if (!trace) {
c1f20530 593 ERR("Trace not found %s", trace_name);
9dad1eb8
PMF
594 err = -ENOENT;
595 goto traces_error;
596 }
597
598 /*
599 * Always put the metadata channel in non-overwrite mode :
600 * This is a very low traffic channel and it can't afford to have its
601 * data overwritten : this data (marker info) is necessary to be
602 * able to read the trace.
603 */
604 if (overwrite && !strcmp(channel_name, "metadata")) {
c1f20530 605 ERR("Trying to set metadata channel to overwrite mode");
9dad1eb8
PMF
606 err = -EINVAL;
607 goto traces_error;
608 }
609
610 index = ltt_channels_get_index_from_name(channel_name);
611 if (index < 0) {
c1f20530 612 ERR("Channel %s not found", channel_name);
9dad1eb8
PMF
613 err = -ENOENT;
614 goto traces_error;
615 }
616
617 trace->channels[index].overwrite = overwrite;
618
619traces_error:
620 ltt_unlock_traces();
621 return err;
622}
9dad1eb8
PMF
623
624int ltt_trace_alloc(const char *trace_name)
625{
626 int err = 0;
b73a4c47 627 struct ust_trace *trace;
c697d411 628 unsigned int subbuf_size, subbuf_cnt;
772030fe 629//ust// unsigned long flags;
9dad1eb8
PMF
630 int chan;
631 const char *channel_name;
632
633 ltt_lock_traces();
634
763f41e5
DS
635 if (_ltt_trace_find(trace_name)) { /* Trace already allocated */
636 err = 1;
637 goto traces_error;
638 }
639
9dad1eb8
PMF
640 trace = _ltt_trace_find_setup(trace_name);
641 if (!trace) {
c1f20530 642 ERR("Trace not found %s", trace_name);
9dad1eb8
PMF
643 err = -ENOENT;
644 goto traces_error;
645 }
646
205f7ca7
DG
647 urcu_ref_init(&trace->urcu_ref);
648 urcu_ref_init(&trace->ltt_transport_urcu_ref);
649//ust// init_waitqueue_head(&trace->urcu_ref_wq);
9dad1eb8 650 trace->active = 0;
b6bf28ec 651//ust// get_trace_clock();
9dad1eb8
PMF
652 trace->freq_scale = trace_clock_freq_scale();
653
654 if (!trace->transport) {
c1f20530 655 ERR("Transport is not set");
9dad1eb8
PMF
656 err = -EINVAL;
657 goto transport_error;
658 }
b6bf28ec 659//ust// if (!try_module_get(trace->transport->owner)) {
c1f20530 660//ust// ERR("Can't lock transport module");
b6bf28ec
PMF
661//ust// err = -ENODEV;
662//ust// goto transport_error;
663//ust// }
9dad1eb8
PMF
664 trace->ops = &trace->transport->ops;
665
b6bf28ec
PMF
666//ust// err = trace->ops->create_dirs(trace);
667//ust// if (err) {
c1f20530 668//ust// ERR("Can't create dir for trace %s", trace_name);
b6bf28ec
PMF
669//ust// goto dirs_error;
670//ust// }
9dad1eb8 671
b6bf28ec 672//ust// local_irq_save(flags);
9dad1eb8
PMF
673 trace->start_freq = trace_clock_frequency();
674 trace->start_tsc = trace_clock_read64();
204141ee 675 gettimeofday(&trace->start_time, NULL); //ust// changed /* FIXME: is this ok? */
b6bf28ec 676//ust// local_irq_restore(flags);
9dad1eb8
PMF
677
678 for (chan = 0; chan < trace->nr_channels; chan++) {
679 if (!(trace->channels[chan].active))
680 continue;
681
682 channel_name = ltt_channels_get_name_from_index(chan);
683 WARN_ON(!channel_name);
684 subbuf_size = trace->channels[chan].subbuf_size;
685 subbuf_cnt = trace->channels[chan].subbuf_cnt;
686 prepare_chan_size_num(&subbuf_size, &subbuf_cnt);
687 err = trace->ops->create_channel(trace_name, trace,
9dad1eb8
PMF
688 channel_name,
689 &trace->channels[chan],
690 subbuf_size,
691 subbuf_cnt,
692 trace->channels[chan].overwrite);
693 if (err != 0) {
c1f20530 694 ERR("Cannot create channel %s", channel_name);
9dad1eb8
PMF
695 goto create_channel_error;
696 }
697 }
698
0222e121
MD
699 cds_list_del(&trace->list);
700//ust// if (cds_list_empty(&ltt_traces.head)) {
b6bf28ec
PMF
701//ust// mod_timer(&ltt_async_wakeup_timer,
702//ust// jiffies + LTT_PERCPU_TIMER_INTERVAL);
703//ust// set_kernel_trace_flag_all_tasks();
704//ust// }
0222e121 705 cds_list_add_rcu(&trace->list, &ltt_traces.head);
b6bf28ec 706//ust// synchronize_sched();
9dad1eb8
PMF
707
708 ltt_unlock_traces();
709
710 return 0;
711
712create_channel_error:
713 for (chan--; chan >= 0; chan--)
714 if (trace->channels[chan].active)
715 trace->ops->remove_channel(&trace->channels[chan]);
716
772030fe 717//ust// dirs_error:
b6bf28ec 718//ust// module_put(trace->transport->owner);
9dad1eb8 719transport_error:
b6bf28ec 720//ust// put_trace_clock();
9dad1eb8
PMF
721traces_error:
722 ltt_unlock_traces();
723 return err;
724}
9dad1eb8
PMF
725
726/*
727 * It is worked as a wrapper for current version of ltt_control.ko.
728 * We will make a new ltt_control based on debugfs, and control each channel's
729 * buffer.
730 */
772030fe
PMF
731//ust// static int ltt_trace_create(const char *trace_name, const char *trace_type,
732//ust// enum trace_mode mode,
733//ust// unsigned int subbuf_size_low, unsigned int n_subbufs_low,
734//ust// unsigned int subbuf_size_med, unsigned int n_subbufs_med,
735//ust// unsigned int subbuf_size_high, unsigned int n_subbufs_high)
736//ust// {
737//ust// int err = 0;
738//ust//
739//ust// err = ltt_trace_setup(trace_name);
740//ust// if (IS_ERR_VALUE(err))
741//ust// return err;
742//ust//
743//ust// err = ltt_trace_set_type(trace_name, trace_type);
744//ust// if (IS_ERR_VALUE(err))
745//ust// return err;
746//ust//
747//ust// err = ltt_trace_alloc(trace_name);
748//ust// if (IS_ERR_VALUE(err))
749//ust// return err;
750//ust//
751//ust// return err;
752//ust// }
9dad1eb8
PMF
753
754/* Must be called while sure that trace is in the list. */
b73a4c47 755static int _ltt_trace_destroy(struct ust_trace *trace)
9dad1eb8
PMF
756{
757 int err = -EPERM;
758
759 if (trace == NULL) {
760 err = -ENOENT;
761 goto traces_error;
762 }
763 if (trace->active) {
c1f20530 764 ERR("Can't destroy trace %s : tracer is active", trace->trace_name);
9dad1eb8
PMF
765 err = -EBUSY;
766 goto active_error;
767 }
768 /* Everything went fine */
0222e121 769 cds_list_del_rcu(&trace->list);
a3272941 770 synchronize_rcu();
0222e121 771 if (cds_list_empty(&ltt_traces.head)) {
b6bf28ec 772//ust// clear_kernel_trace_flag_all_tasks();
9dad1eb8
PMF
773 /*
774 * We stop the asynchronous delivery of reader wakeup, but
775 * we must make one last check for reader wakeups pending
776 * later in __ltt_trace_destroy.
777 */
b6bf28ec 778//ust// del_timer_sync(&ltt_async_wakeup_timer);
9dad1eb8
PMF
779 }
780 return 0;
781
782 /* error handling */
783active_error:
784traces_error:
785 return err;
786}
787
788/* Sleepable part of the destroy */
31d392f1 789static void __ltt_trace_destroy(struct ust_trace *trace, int drop)
9dad1eb8
PMF
790{
791 int i;
b5b073e2 792 struct ust_channel *chan;
9dad1eb8 793
31d392f1
PMF
794 if(!drop) {
795 for (i = 0; i < trace->nr_channels; i++) {
796 chan = &trace->channels[i];
797 if (chan->active)
798 trace->ops->finish_channel(chan);
799 }
9dad1eb8
PMF
800 }
801
9dad1eb8
PMF
802 /*
803 * The currently destroyed trace is not in the trace list anymore,
804 * so it's safe to call the async wakeup ourself. It will deliver
805 * the last subbuffers.
806 */
807 trace_async_wakeup(trace);
808
809 for (i = 0; i < trace->nr_channels; i++) {
810 chan = &trace->channels[i];
811 if (chan->active)
812 trace->ops->remove_channel(chan);
813 }
814
205f7ca7 815 urcu_ref_put(&trace->ltt_transport_urcu_ref, ltt_release_transport);
9dad1eb8 816
b6bf28ec 817//ust// module_put(trace->transport->owner);
9dad1eb8
PMF
818
819 /*
820 * Wait for lttd readers to release the files, therefore making sure
821 * the last subbuffers have been read.
822 */
b6bf28ec
PMF
823//ust// if (atomic_read(&trace->kref.refcount) > 1) {
824//ust// int ret = 0;
825//ust// __wait_event_interruptible(trace->kref_wq,
826//ust// (atomic_read(&trace->kref.refcount) == 1), ret);
827//ust// }
205f7ca7 828 urcu_ref_put(&trace->urcu_ref, ltt_release_trace);
9dad1eb8
PMF
829}
830
31d392f1 831int ltt_trace_destroy(const char *trace_name, int drop)
9dad1eb8
PMF
832{
833 int err = 0;
b73a4c47 834 struct ust_trace *trace;
9dad1eb8
PMF
835
836 ltt_lock_traces();
837
838 trace = _ltt_trace_find(trace_name);
839 if (trace) {
840 err = _ltt_trace_destroy(trace);
841 if (err)
842 goto error;
843
844 ltt_unlock_traces();
845
31d392f1 846 __ltt_trace_destroy(trace, drop);
b6bf28ec 847//ust// put_trace_clock();
9dad1eb8
PMF
848
849 return 0;
850 }
851
852 trace = _ltt_trace_find_setup(trace_name);
853 if (trace) {
854 _ltt_trace_free(trace);
855 ltt_unlock_traces();
856 return 0;
857 }
858
859 err = -ENOENT;
860
861 /* Error handling */
862error:
863 ltt_unlock_traces();
864 return err;
865}
9dad1eb8
PMF
866
867/* must be called from within a traces lock. */
b73a4c47 868static int _ltt_trace_start(struct ust_trace *trace)
9dad1eb8
PMF
869{
870 int err = 0;
871
872 if (trace == NULL) {
873 err = -ENOENT;
874 goto traces_error;
875 }
876 if (trace->active)
c1f20530 877 DBG("Tracing already active for trace %s", trace->trace_name);
b6bf28ec
PMF
878//ust// if (!try_module_get(ltt_run_filter_owner)) {
879//ust// err = -ENODEV;
c1f20530 880//ust// ERR("Cannot lock filter module");
b6bf28ec
PMF
881//ust// goto get_ltt_run_filter_error;
882//ust// }
9dad1eb8
PMF
883 trace->active = 1;
884 /* Read by trace points without protection : be careful */
885 ltt_traces.num_active_traces++;
886 return err;
887
888 /* error handling */
772030fe 889//ust// get_ltt_run_filter_error:
9dad1eb8
PMF
890traces_error:
891 return err;
892}
893
894int ltt_trace_start(const char *trace_name)
895{
896 int err = 0;
b73a4c47 897 struct ust_trace *trace;
9dad1eb8
PMF
898
899 ltt_lock_traces();
900
901 trace = _ltt_trace_find(trace_name);
902 err = _ltt_trace_start(trace);
903 if (err)
904 goto no_trace;
905
906 ltt_unlock_traces();
907
908 /*
d558d653 909 * Call the process-wide state dump.
9dad1eb8
PMF
910 * Notice that there is no protection on the trace : that's exactly
911 * why we iterate on the list and check for trace equality instead of
d558d653
MD
912 * directly using this trace handle inside the logging function: we want
913 * to record events only in a single trace in the trace session list.
9dad1eb8
PMF
914 */
915
9c67dc50 916 ltt_dump_marker_state(trace);
9dad1eb8 917
b6bf28ec
PMF
918//ust// if (!try_module_get(ltt_statedump_owner)) {
919//ust// err = -ENODEV;
c1f20530 920//ust// ERR("Cannot lock state dump module");
b6bf28ec 921//ust// } else {
9dad1eb8 922 ltt_statedump_functor(trace);
b6bf28ec
PMF
923//ust// module_put(ltt_statedump_owner);
924//ust// }
9dad1eb8
PMF
925
926 return err;
927
928 /* Error handling */
929no_trace:
930 ltt_unlock_traces();
931 return err;
932}
9dad1eb8
PMF
933
934/* must be called from within traces lock */
b73a4c47 935static int _ltt_trace_stop(struct ust_trace *trace)
9dad1eb8
PMF
936{
937 int err = -EPERM;
938
939 if (trace == NULL) {
940 err = -ENOENT;
941 goto traces_error;
942 }
943 if (!trace->active)
c1f20530 944 DBG("LTT : Tracing not active for trace %s", trace->trace_name);
9dad1eb8
PMF
945 if (trace->active) {
946 trace->active = 0;
947 ltt_traces.num_active_traces--;
b6bf28ec 948//ust// synchronize_sched(); /* Wait for each tracing to be finished */
9dad1eb8 949 }
b6bf28ec 950//ust// module_put(ltt_run_filter_owner);
9dad1eb8
PMF
951 /* Everything went fine */
952 return 0;
953
954 /* Error handling */
955traces_error:
956 return err;
957}
958
959int ltt_trace_stop(const char *trace_name)
960{
961 int err = 0;
b73a4c47 962 struct ust_trace *trace;
9dad1eb8
PMF
963
964 ltt_lock_traces();
965 trace = _ltt_trace_find(trace_name);
966 err = _ltt_trace_stop(trace);
967 ltt_unlock_traces();
968 return err;
969}
9dad1eb8
PMF
970
971/**
972 * ltt_filter_control - Trace filter control in-kernel API
973 * @msg: Action to perform on the filter
974 * @trace_name: Trace on which the action must be done
975 */
976int ltt_filter_control(enum ltt_filter_control_msg msg, const char *trace_name)
977{
978 int err;
b73a4c47 979 struct ust_trace *trace;
9dad1eb8 980
c1f20530 981 DBG("ltt_filter_control : trace %s", trace_name);
9dad1eb8
PMF
982 ltt_lock_traces();
983 trace = _ltt_trace_find(trace_name);
984 if (trace == NULL) {
c1f20530 985 ERR("Trace does not exist. Cannot proxy control request");
9dad1eb8
PMF
986 err = -ENOENT;
987 goto trace_error;
988 }
b6bf28ec
PMF
989//ust// if (!try_module_get(ltt_filter_control_owner)) {
990//ust// err = -ENODEV;
991//ust// goto get_module_error;
992//ust// }
9dad1eb8
PMF
993 switch (msg) {
994 case LTT_FILTER_DEFAULT_ACCEPT:
c1f20530 995 DBG("Proxy filter default accept %s", trace_name);
9dad1eb8
PMF
996 err = (*ltt_filter_control_functor)(msg, trace);
997 break;
998 case LTT_FILTER_DEFAULT_REJECT:
c1f20530 999 DBG("Proxy filter default reject %s", trace_name);
9dad1eb8
PMF
1000 err = (*ltt_filter_control_functor)(msg, trace);
1001 break;
1002 default:
1003 err = -EPERM;
1004 }
b6bf28ec 1005//ust// module_put(ltt_filter_control_owner);
9dad1eb8 1006
772030fe 1007//ust// get_module_error:
9dad1eb8
PMF
1008trace_error:
1009 ltt_unlock_traces();
1010 return err;
1011}
This page took 0.080146 seconds and 4 git commands to generate.