| From compudj@mail.openrapids.net Thu Apr 5 07:40:26 2012 |
| From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| Date: Thu, 5 Apr 2012 10:40:20 -0400 |
| Subject: [PATCH LTSI staging] LTTng update to v2.0.1 |
| To: Greg KH <gregkh@linuxfoundation.org> |
| Cc: Tim Bird <tim.bird@am.sony.com>, ltsi-dev@lists.linuxfoundation.org |
| Message-ID: <20120405144020.GA31482@Krystal> |
| Content-Disposition: inline |
| |
| |
| Update LTTng driver (in LTSI tree) to v2.0.1 from |
| git://git.lttng.org/lttng-modules.git, the external module package on which |
| development has continued. |
| |
| Changelog: |
| |
| 2012-03-29 LTTng modules 2.0.1 |
| * Fix: is_compat_task !CONFIG_COMPAT compile error on kernels >= 3.3 |
| |
| 2012-03-20 LTTng modules 2.0.0 |
| * First STABLE version |
| * Add version name |
| |
| 2012-03-20 LTTng modules 2.0.0-rc4 |
| * Update README and add version name place-holder |
| |
| 2012-03-16 LTTng modules 2.0.0-rc3 |
| * Fix clock offset 32-bit multiplication overflow |
| * Fix : wrong assign of fd in state dump |
| * License cleanup, ifdef namespace cleanup |
| * Fix: ensure power of 2 check handles 64-bit size_t entirely |
| |
| 2012-03-02 LTTng modules 2.0.0-rc2 |
| * Fix: dmesg printout should not print metadata warnings |
| * Fix: use transport name as channel name |
| * Fix: Return -EINVAL instead of print warning if non power of 2 size/num_subbuf |
| |
| 2012-02-20 LTTng modules 2.0.0-rc1 |
| * Standardize version across toolchain |
| * statedump: Use old macro name for kernel 2.6.38 |
| |
| 2012-02-16 LTTng modules 2.0-pre15 |
| * Add timer instrumentation |
| * fix: need to undef mainline define |
| * fix: Include signal.h instead of irq.h for prototype match check |
| * Add signal instrumentation |
| |
| 2012-02-16 LTTng modules 2.0-pre14 |
| * syscall tracing: sys_getcpu |
| * Add sys_clone x86 instrumentation |
| * statedump: fix include circular dep |
| * Implement state dump |
| |
| 2012-02-09 LTTng modules 2.0-pre13 |
| * Update README |
| * environment: write sysname, release, version, domain to metadata |
| * Allow open /proc/lttng for read & write |
| |
| 2012-02-02 LTTng modules 2.0-pre12 |
| * Add x86 32/64 execve syscall instrumentation override |
| * Remove unused defines |
| * Add padding to ABI |
| * Use LTTNG_KERNEL_SYM_NAME_LEN |
| * Update version to 1.9.9 |
| * Add missing double-quotes to clock uuid |
| * clock: read bootid as clock monotonic ID |
| * Fix comment |
| * Cleanup comment |
| * clock: output clock description in metadata |
| * Properly fix the timekeeping overflow detection |
| * Fix init bug |
| * rename lib-ring-buffer to lttng-lib-ring-buffer |
| * Remove #warning |
| * Mass rename: ltt_*/ltt-* to LTTNG_*/LTTNG-* |
| * Update TODO |
| * Update TODO |
| * Remove debugfs file (keep only proc file) |
| * Rename lttng-debugfs-abi files to lttng-abi |
| |
| 2011-12-13 LTTng modules 2.0-pre11 |
| * Fix OOPS caused by reference of config pointer |
| * Gather detailed info from x86 64 32-bit compat syscall instrumentation |
| * lttng lib: ring buffer move null pointer check to open |
| * lttng lib: ring buffer remove duplicate null pointer |
| * lttng lib: ring buffer: remove stale null-pointer |
| * lttng wrapper: add missing include to kallsyms wrapper |
| * lttng: cleanup one-bit signed bitfields |
| * Add TODO file |
| * Update symbol name length max size to 256 |
| * Fix last modifications to string_from_user operations |
| * Document that depmod needs to be executed by hand |
| * Fix strlen_user fault space reservation |
| * Fix tp_copy_string_from_user handling of faults |
| * Disable block layer tracing support for kernels < 2.6.38 |
| * lttng context: perf counter, fix 32-bit vs 64-bit field size bug |
| * Update trace clock warning to match the current development plan |
| * ringbuffer: make ring buffer printk less verbose |
| * Makefile: do not run depmod manually |
| |
| Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| CC: Greg KH <gregkh@linuxfoundation.org> |
| CC: Tim Bird <tim.bird@am.sony.com> |
| CC: ltsi-dev@lists.linuxfoundation.org |
| --- |
| drivers/staging/lttng/Makefile | 28 |
| drivers/staging/lttng/README | 43 |
| drivers/staging/lttng/TODO | 18 |
| drivers/staging/lttng/instrumentation/events/lttng-module/lttng-statedump.h | 162 + |
| drivers/staging/lttng/instrumentation/events/lttng-module/signal.h | 165 + |
| drivers/staging/lttng/instrumentation/events/lttng-module/timer.h | 333 ++ |
| drivers/staging/lttng/instrumentation/events/mainline/signal.h | 166 + |
| drivers/staging/lttng/instrumentation/events/mainline/timer.h | 329 ++ |
| drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers_override.h | 53 |
| drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers_override.h | 46 |
| drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers_override.h | 3 |
| drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers_override.h | 7 |
| drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/lttng-syscalls-extractor.c | 18 |
| drivers/staging/lttng/lib/Makefile | 4 |
| drivers/staging/lttng/lib/align.h | 16 |
| drivers/staging/lttng/lib/bitfield.h | 2 |
| drivers/staging/lttng/lib/bug.h | 16 |
| drivers/staging/lttng/lib/ringbuffer/api.h | 26 |
| drivers/staging/lttng/lib/ringbuffer/backend.h | 26 |
| drivers/staging/lttng/lib/ringbuffer/backend_internal.h | 26 |
| drivers/staging/lttng/lib/ringbuffer/backend_types.h | 33 |
| drivers/staging/lttng/lib/ringbuffer/config.h | 26 |
| drivers/staging/lttng/lib/ringbuffer/frontend.h | 28 |
| drivers/staging/lttng/lib/ringbuffer/frontend_api.h | 28 |
| drivers/staging/lttng/lib/ringbuffer/frontend_internal.h | 26 |
| drivers/staging/lttng/lib/ringbuffer/frontend_types.h | 34 |
| drivers/staging/lttng/lib/ringbuffer/iterator.h | 28 |
| drivers/staging/lttng/lib/ringbuffer/nohz.h | 24 |
| drivers/staging/lttng/lib/ringbuffer/ring_buffer_backend.c | 60 |
| drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c | 112 |
| drivers/staging/lttng/lib/ringbuffer/ring_buffer_iterator.c | 46 |
| drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c | 29 |
| drivers/staging/lttng/lib/ringbuffer/ring_buffer_splice.c | 23 |
| drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c | 24 |
| drivers/staging/lttng/lib/ringbuffer/vatomic.h | 24 |
| drivers/staging/lttng/lib/ringbuffer/vfs.h | 28 |
| drivers/staging/lttng/ltt-context.c | 93 |
| drivers/staging/lttng/ltt-debugfs-abi.c | 777 ------ |
| drivers/staging/lttng/ltt-debugfs-abi.h | 153 - |
| drivers/staging/lttng/ltt-endian.h | 31 |
| drivers/staging/lttng/ltt-events.c | 1009 -------- |
| drivers/staging/lttng/ltt-events.h | 452 ---- |
| drivers/staging/lttng/ltt-probes.c | 164 - |
| drivers/staging/lttng/ltt-ring-buffer-client-discard.c | 21 |
| drivers/staging/lttng/ltt-ring-buffer-client-mmap-discard.c | 21 |
| drivers/staging/lttng/ltt-ring-buffer-client-mmap-overwrite.c | 21 |
| drivers/staging/lttng/ltt-ring-buffer-client-overwrite.c | 21 |
| drivers/staging/lttng/ltt-ring-buffer-client.h | 569 ----- |
| drivers/staging/lttng/ltt-ring-buffer-metadata-client.c | 21 |
| drivers/staging/lttng/ltt-ring-buffer-metadata-client.h | 330 -- |
| drivers/staging/lttng/ltt-ring-buffer-metadata-mmap-client.c | 21 |
| drivers/staging/lttng/ltt-tracer-core.h | 28 |
| drivers/staging/lttng/ltt-tracer.h | 67 |
| drivers/staging/lttng/lttng-abi.c | 781 ++++++ |
| drivers/staging/lttng/lttng-abi.h | 176 + |
| drivers/staging/lttng/lttng-calibrate.c | 22 |
| drivers/staging/lttng/lttng-context-nice.c | 31 |
| drivers/staging/lttng/lttng-context-perf-counters.c | 31 |
| drivers/staging/lttng/lttng-context-pid.c | 31 |
| drivers/staging/lttng/lttng-context-ppid.c | 31 |
| drivers/staging/lttng/lttng-context-prio.c | 31 |
| drivers/staging/lttng/lttng-context-procname.c | 27 |
| drivers/staging/lttng/lttng-context-tid.c | 31 |
| drivers/staging/lttng/lttng-context-vpid.c | 31 |
| drivers/staging/lttng/lttng-context-vppid.c | 31 |
| drivers/staging/lttng/lttng-context-vtid.c | 31 |
| drivers/staging/lttng/lttng-context.c | 105 |
| drivers/staging/lttng/lttng-endian.h | 43 |
| drivers/staging/lttng/lttng-events.c | 1126 ++++++++++ |
| drivers/staging/lttng/lttng-events.h | 466 ++++ |
| drivers/staging/lttng/lttng-probes.c | 176 + |
| drivers/staging/lttng/lttng-ring-buffer-client-discard.c | 33 |
| drivers/staging/lttng/lttng-ring-buffer-client-mmap-discard.c | 33 |
| drivers/staging/lttng/lttng-ring-buffer-client-mmap-overwrite.c | 33 |
| drivers/staging/lttng/lttng-ring-buffer-client-overwrite.c | 33 |
| drivers/staging/lttng/lttng-ring-buffer-client.h | 598 +++++ |
| drivers/staging/lttng/lttng-ring-buffer-metadata-client.c | 33 |
| drivers/staging/lttng/lttng-ring-buffer-metadata-client.h | 342 +++ |
| drivers/staging/lttng/lttng-ring-buffer-metadata-mmap-client.c | 33 |
| drivers/staging/lttng/lttng-statedump-impl.c | 385 +++ |
| drivers/staging/lttng/lttng-syscalls.c | 69 |
| drivers/staging/lttng/lttng-tracer-core.h | 41 |
| drivers/staging/lttng/lttng-tracer.h | 80 |
| drivers/staging/lttng/probes/Makefile | 4 |
| drivers/staging/lttng/probes/define_trace.h | 16 |
| drivers/staging/lttng/probes/lttng-events-reset.h | 16 |
| drivers/staging/lttng/probes/lttng-events.h | 79 |
| drivers/staging/lttng/probes/lttng-ftrace.c | 43 |
| drivers/staging/lttng/probes/lttng-kprobes.c | 47 |
| drivers/staging/lttng/probes/lttng-kretprobes.c | 47 |
| drivers/staging/lttng/probes/lttng-probe-block.c | 18 |
| drivers/staging/lttng/probes/lttng-probe-irq.c | 18 |
| drivers/staging/lttng/probes/lttng-probe-kvm.c | 18 |
| drivers/staging/lttng/probes/lttng-probe-lttng.c | 18 |
| drivers/staging/lttng/probes/lttng-probe-sched.c | 18 |
| drivers/staging/lttng/probes/lttng-probe-signal.c | 42 |
| drivers/staging/lttng/probes/lttng-probe-statedump.c | 45 |
| drivers/staging/lttng/probes/lttng-probe-timer.c | 43 |
| drivers/staging/lttng/probes/lttng-type-list.h | 16 |
| drivers/staging/lttng/probes/lttng-types.c | 20 |
| drivers/staging/lttng/probes/lttng-types.h | 24 |
| drivers/staging/lttng/probes/lttng.h | 16 |
| drivers/staging/lttng/wrapper/ftrace.h | 24 |
| drivers/staging/lttng/wrapper/inline_memcpy.h | 16 |
| drivers/staging/lttng/wrapper/irqdesc.c | 58 |
| drivers/staging/lttng/wrapper/irqdesc.h | 33 |
| drivers/staging/lttng/wrapper/kallsyms.h | 45 |
| drivers/staging/lttng/wrapper/perf.h | 24 |
| drivers/staging/lttng/wrapper/poll.h | 24 |
| drivers/staging/lttng/wrapper/random.c | 77 |
| drivers/staging/lttng/wrapper/random.h | 32 |
| drivers/staging/lttng/wrapper/spinlock.h | 24 |
| drivers/staging/lttng/wrapper/splice.c | 20 |
| drivers/staging/lttng/wrapper/splice.h | 26 |
| drivers/staging/lttng/wrapper/trace-clock.h | 41 |
| drivers/staging/lttng/wrapper/uuid.h | 24 |
| drivers/staging/lttng/wrapper/vmalloc.h | 24 |
| 117 files changed, 7456 insertions(+), 4357 deletions(-) |
| |
| --- a/drivers/staging/lttng/Makefile |
| +++ b/drivers/staging/lttng/Makefile |
| @@ -2,28 +2,32 @@ |
| # Makefile for the LTTng modules. |
| # |
| |
| -obj-m += ltt-ring-buffer-client-discard.o |
| -obj-m += ltt-ring-buffer-client-overwrite.o |
| -obj-m += ltt-ring-buffer-metadata-client.o |
| -obj-m += ltt-ring-buffer-client-mmap-discard.o |
| -obj-m += ltt-ring-buffer-client-mmap-overwrite.o |
| -obj-m += ltt-ring-buffer-metadata-mmap-client.o |
| +obj-m += lttng-ring-buffer-client-discard.o |
| +obj-m += lttng-ring-buffer-client-overwrite.o |
| +obj-m += lttng-ring-buffer-metadata-client.o |
| +obj-m += lttng-ring-buffer-client-mmap-discard.o |
| +obj-m += lttng-ring-buffer-client-mmap-overwrite.o |
| +obj-m += lttng-ring-buffer-metadata-mmap-client.o |
| |
| -obj-m += ltt-relay.o |
| -ltt-relay-objs := ltt-events.o ltt-debugfs-abi.o \ |
| - ltt-probes.o ltt-context.o \ |
| +obj-m += lttng-relay.o |
| +lttng-relay-objs := lttng-events.o lttng-abi.o \ |
| + lttng-probes.o lttng-context.o \ |
| lttng-context-pid.o lttng-context-procname.o \ |
| lttng-context-prio.o lttng-context-nice.o \ |
| lttng-context-vpid.o lttng-context-tid.o \ |
| lttng-context-vtid.o lttng-context-ppid.o \ |
| - lttng-context-vppid.o lttng-calibrate.o |
| + lttng-context-vppid.o lttng-calibrate.o \ |
| + wrapper/random.o |
| + |
| +obj-m += lttng-statedump.o |
| +lttng-statedump-objs := lttng-statedump-impl.o wrapper/irqdesc.o |
| |
| ifneq ($(CONFIG_HAVE_SYSCALL_TRACEPOINTS),) |
| -ltt-relay-objs += lttng-syscalls.o |
| +lttng-relay-objs += lttng-syscalls.o |
| endif |
| |
| ifneq ($(CONFIG_PERF_EVENTS),) |
| -ltt-relay-objs += $(shell \ |
| +lttng-relay-objs += $(shell \ |
| if [ $(VERSION) -ge 3 \ |
| -o \( $(VERSION) -eq 2 -a $(PATCHLEVEL) -ge 6 -a $(SUBLEVEL) -ge 33 \) ] ; then \ |
| echo "lttng-context-perf-counters.o" ; fi;) |
| --- a/drivers/staging/lttng/README |
| +++ b/drivers/staging/lttng/README |
| @@ -1,10 +1,10 @@ |
| LTTng 2.0 modules |
| |
| Mathieu Desnoyers |
| -November 1st, 2011 |
| +February 8, 2012 |
| |
| -LTTng 2.0 kernel modules is currently part of the Linux kernel staging |
| -tree. It features (new features since LTTng 0.x): |
| +LTTng 2.0 kernel modules build against a vanilla or distribution kernel, without |
| +need for additional patches. Other features: |
| |
| - Produces CTF (Common Trace Format) natively, |
| (http://www.efficios.com/ctf) |
| @@ -17,28 +17,29 @@ tree. It features (new features since LT |
| optional, specified on a per-tracing-session basis (except for |
| timestamp and event id, which are mandatory). |
| |
| -To build and install, you need to select "Staging" modules, and the |
| -LTTng kernel tracer. |
| +To build and install, you will need to enable LTTng in your kernel |
| +configuration. |
| |
| -Use lttng-tools to control the tracer. LTTng tools should automatically |
| -load the kernel modules when needed. Use Babeltrace to print traces as a |
| +Use lttng-tools to control the tracer. LTTng tools should automatically load |
| +the kernel modules when needed. Use Babeltrace to print traces as a |
| human-readable text log. These tools are available at the following URL: |
| http://lttng.org/lttng2.0 |
| |
| -Please note that the LTTng-UST 2.0 (user-space tracing counterpart of |
| -LTTng 2.0) is now ready to be used, but still only available from the |
| -git repository. |
| - |
| -So far, it has been tested on vanilla Linux kernels 2.6.38, 2.6.39 and |
| -3.0 (on x86 32/64-bit, and powerpc 32-bit at the moment, build tested on |
| -ARM). It should work fine with newer kernels and other architectures, |
| -but expect build issues with kernels older than 2.6.36. The clock source |
| -currently used is the standard gettimeofday (slower, less scalable and |
| -less precise than the LTTng 0.x clocks). Support for LTTng 0.x clocks |
| -will be added back soon into LTTng 2.0. Please note that lttng-modules |
| -2.0 can build on a Linux kernel patched with the LTTng 0.x patchset, but |
| -the lttng-modules 2.0 replace the lttng-modules 0.x, so both tracers |
| -cannot be installed at the same time for a given kernel version. |
| +So far, it has been tested on vanilla Linux kernels 2.6.38, 2.6.39, 3.0, |
| +3.1, 3.2, 3.3 (on x86 32/64-bit, and powerpc 32-bit at the moment, build |
| +tested on ARM). It should work fine with newer kernels and other |
| +architectures, but expect build issues with kernels older than 2.6.36. |
| +The clock source currently used is the standard gettimeofday (slower, |
| +less scalable and less precise than the LTTng 0.x clocks). Support for |
| +LTTng 0.x clocks will be added back soon into LTTng 2.0. Please note |
| +that lttng-modules 2.0 can build on a Linux kernel patched with the |
| +LTTng 0.x patchset, but the lttng-modules 2.0 replace the lttng-modules |
| +0.x, so both tracers cannot be installed at the same time for a given |
| +kernel version. |
| + |
| +LTTng-modules depends on having kallsyms enabled in the kernel it is |
| +built against. Ideally, if you want to have system call tracing, the |
| +"Trace Syscalls" feature should be enabled too. |
| |
| * Note about Perf PMU counters support |
| |
| --- a/drivers/staging/lttng/TODO |
| +++ b/drivers/staging/lttng/TODO |
| @@ -10,20 +10,7 @@ TODO: |
| |
| A) Cleanup/Testing |
| |
| - 1) Remove debugfs "lttng" file (keep only procfs "lttng" file). |
| - The rationale for this is that this file is needed for |
| - user-level tracing support (LTTng-UST 2.0) intended to be |
| - used on production system, and therefore should be present as |
| - part of a "usually mounted" filesystem rather than a debug |
| - filesystem. |
| - |
| - 2) Cleanup wrappers. The drivers/staging/lttng/wrapper directory |
| - contains various wrapper headers that use kallsyms lookups to |
| - work around some missing EXPORT_SYMBOL_GPL() in the mainline |
| - kernel. Ideally, those few symbols should become exported to |
| - modules by the kernel. |
| - |
| - 3) Test lib ring buffer snapshot feature. |
| + 1) Test lib ring buffer snapshot feature. |
| When working on the lttngtop project, Julien Desfossez |
| reported that he needed to push the consumer position |
| forward explicitely with lib_ring_buffer_put_next_subbuf. |
| @@ -70,7 +57,6 @@ B) Features |
| |
| 3) Integrate the "statedump" module from LTTng 0.x into LTTng |
| 2.0. |
| - * Dependency: addition of "dynamic enumerations" type to CTF. |
| See: http://git.lttng.org/?p=lttng-modules.git;a=shortlog;h=refs/heads/v0.19-stable |
| ltt-statedump.c |
| |
| @@ -107,7 +93,7 @@ B) Features |
| allow integration between NOHZ and LTTng would be to add |
| support for such notifiers into NOHZ kernel infrastructure. |
| |
| - 10) Turn drivers/staging/lttng/ltt-probes.c probe_list into a |
| + 10) Turn lttng-probes.c probe_list into a |
| hash table. Turns O(n^2) trace systems registration (cost |
| for n systems) into O(n). (O(1) per system) |
| |
| --- /dev/null |
| +++ b/drivers/staging/lttng/instrumentation/events/lttng-module/lttng-statedump.h |
| @@ -0,0 +1,162 @@ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM lttng_statedump |
| + |
| +#if !defined(_TRACE_LTTNG_STATEDUMP_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_LTTNG_STATEDUMP_H |
| + |
| +#include <linux/tracepoint.h> |
| + |
| +TRACE_EVENT(lttng_statedump_start, |
| + TP_PROTO(struct lttng_session *session), |
| + TP_ARGS(session), |
| + TP_STRUCT__entry( |
| + ), |
| + TP_fast_assign( |
| + ), |
| + TP_printk("") |
| +) |
| + |
| +TRACE_EVENT(lttng_statedump_end, |
| + TP_PROTO(struct lttng_session *session), |
| + TP_ARGS(session), |
| + TP_STRUCT__entry( |
| + ), |
| + TP_fast_assign( |
| + ), |
| + TP_printk("") |
| +) |
| + |
| +TRACE_EVENT(lttng_statedump_process_state, |
| + TP_PROTO(struct lttng_session *session, |
| + struct task_struct *p, |
| + int type, int mode, int submode, int status), |
| + TP_ARGS(session, p, type, mode, submode, status), |
| + TP_STRUCT__entry( |
| + __field(pid_t, tid) |
| + __field(pid_t, vtid) |
| + __field(pid_t, pid) |
| + __field(pid_t, vpid) |
| + __field(pid_t, ppid) |
| + __field(pid_t, vppid) |
| + __array_text(char, name, TASK_COMM_LEN) |
| + __field(int, type) |
| + __field(int, mode) |
| + __field(int, submode) |
| + __field(int, status) |
| + ), |
| + TP_fast_assign( |
| + tp_assign(tid, p->pid) |
| + tp_assign(vtid, !p->nsproxy ? 0 : task_pid_vnr(p)) |
| + tp_assign(pid, p->tgid) |
| + tp_assign(vpid, !p->nsproxy ? 0 : task_tgid_vnr(p)) |
| + tp_assign(ppid, |
| + ({ |
| + pid_t ret; |
| + |
| + rcu_read_lock(); |
| + ret = task_tgid_nr(p->real_parent); |
| + rcu_read_unlock(); |
| + ret; |
| + })) |
| + tp_assign(vppid, |
| + ({ |
| + struct task_struct *parent; |
| + pid_t ret; |
| + |
| + rcu_read_lock(); |
| + parent = rcu_dereference(current->real_parent); |
| + if (!parent->nsproxy) |
| + ret = 0; |
| + else |
| + ret = task_tgid_nr(parent); |
| + rcu_read_unlock(); |
| + ret; |
| + })) |
| + tp_memcpy(name, p->comm, TASK_COMM_LEN) |
| + tp_assign(type, type) |
| + tp_assign(mode, mode) |
| + tp_assign(submode, submode) |
| + tp_assign(status, status) |
| + ), |
| + TP_printk("") |
| +) |
| + |
| +TRACE_EVENT(lttng_statedump_file_descriptor, |
| + TP_PROTO(struct lttng_session *session, |
| + struct task_struct *p, int fd, const char *filename), |
| + TP_ARGS(session, p, fd, filename), |
| + TP_STRUCT__entry( |
| + __field(pid_t, pid) |
| + __field(int, fd) |
| + __string(filename, filename) |
| + ), |
| + TP_fast_assign( |
| + tp_assign(pid, p->tgid) |
| + tp_assign(fd, fd) |
| + tp_strcpy(filename, filename) |
| + ), |
| + TP_printk("") |
| +) |
| + |
| +TRACE_EVENT(lttng_statedump_vm_map, |
| + TP_PROTO(struct lttng_session *session, |
| + struct task_struct *p, struct vm_area_struct *map, |
| + unsigned long inode), |
| + TP_ARGS(session, p, map, inode), |
| + TP_STRUCT__entry( |
| + __field(pid_t, pid) |
| + __field_hex(unsigned long, start) |
| + __field_hex(unsigned long, end) |
| + __field_hex(unsigned long, flags) |
| + __field(unsigned long, inode) |
| + __field(unsigned long, pgoff) |
| + ), |
| + TP_fast_assign( |
| + tp_assign(pid, p->tgid) |
| + tp_assign(start, map->vm_start) |
| + tp_assign(end, map->vm_end) |
| + tp_assign(flags, map->vm_flags) |
| + tp_assign(inode, inode) |
| + tp_assign(pgoff, map->vm_pgoff << PAGE_SHIFT) |
| + ), |
| + TP_printk("") |
| +) |
| + |
| +TRACE_EVENT(lttng_statedump_network_interface, |
| + TP_PROTO(struct lttng_session *session, |
| + struct net_device *dev, struct in_ifaddr *ifa), |
| + TP_ARGS(session, dev, ifa), |
| + TP_STRUCT__entry( |
| + __string(name, dev->name) |
| + __field_network_hex(uint32_t, address_ipv4) |
| + ), |
| + TP_fast_assign( |
| + tp_strcpy(name, dev->name) |
| + tp_assign(address_ipv4, ifa ? ifa->ifa_address : 0U) |
| + ), |
| + TP_printk("") |
| +) |
| + |
| +/* Called with desc->lock held */ |
| +TRACE_EVENT(lttng_statedump_interrupt, |
| + TP_PROTO(struct lttng_session *session, |
| + unsigned int irq, const char *chip_name, |
| + struct irqaction *action), |
| + TP_ARGS(session, irq, chip_name, action), |
| + TP_STRUCT__entry( |
| + __field(unsigned int, irq) |
| + __string(name, chip_name) |
| + __string(action, action->name) |
| + ), |
| + TP_fast_assign( |
| + tp_assign(irq, irq) |
| + tp_strcpy(name, chip_name) |
| + tp_strcpy(action, action->name) |
| + ), |
| + TP_printk("") |
| +) |
| + |
| +#endif /* _TRACE_LTTNG_STATEDUMP_H */ |
| + |
| +/* This part must be outside protection */ |
| +#include "../../../probes/define_trace.h" |
| --- /dev/null |
| +++ b/drivers/staging/lttng/instrumentation/events/lttng-module/signal.h |
| @@ -0,0 +1,165 @@ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM signal |
| + |
| +#if !defined(_TRACE_SIGNAL_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_SIGNAL_H |
| + |
| +#include <linux/tracepoint.h> |
| + |
| +#ifndef _TRACE_SIGNAL_DEF |
| +#define _TRACE_SIGNAL_DEF |
| +#include <linux/signal.h> |
| +#include <linux/sched.h> |
| +#undef TP_STORE_SIGINFO |
| +#define TP_STORE_SIGINFO(info) \ |
| + tp_assign(errno, \ |
| + (info == SEND_SIG_NOINFO || info == SEND_SIG_FORCED || info == SEND_SIG_PRIV) ? \ |
| + 0 : \ |
| + info->si_errno) \ |
| + tp_assign(code, \ |
| + (info == SEND_SIG_NOINFO || info == SEND_SIG_FORCED) ? \ |
| + SI_USER : \ |
| + ((info == SEND_SIG_PRIV) ? SI_KERNEL : info->si_code)) |
| +#endif /* _TRACE_SIGNAL_DEF */ |
| + |
| +/** |
| + * signal_generate - called when a signal is generated |
| + * @sig: signal number |
| + * @info: pointer to struct siginfo |
| + * @task: pointer to struct task_struct |
| + * |
| + * Current process sends a 'sig' signal to 'task' process with |
| + * 'info' siginfo. If 'info' is SEND_SIG_NOINFO or SEND_SIG_PRIV, |
| + * 'info' is not a pointer and you can't access its field. Instead, |
| + * SEND_SIG_NOINFO means that si_code is SI_USER, and SEND_SIG_PRIV |
| + * means that si_code is SI_KERNEL. |
| + */ |
| +TRACE_EVENT(signal_generate, |
| + |
| + TP_PROTO(int sig, struct siginfo *info, struct task_struct *task), |
| + |
| + TP_ARGS(sig, info, task), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, sig ) |
| + __field( int, errno ) |
| + __field( int, code ) |
| + __array( char, comm, TASK_COMM_LEN ) |
| + __field( pid_t, pid ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(sig, sig) |
| + TP_STORE_SIGINFO(info) |
| + tp_memcpy(comm, task->comm, TASK_COMM_LEN) |
| + tp_assign(pid, task->pid) |
| + ), |
| + |
| + TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d", |
| + __entry->sig, __entry->errno, __entry->code, |
| + __entry->comm, __entry->pid) |
| +) |
| + |
| +/** |
| + * signal_deliver - called when a signal is delivered |
| + * @sig: signal number |
| + * @info: pointer to struct siginfo |
| + * @ka: pointer to struct k_sigaction |
| + * |
| + * A 'sig' signal is delivered to current process with 'info' siginfo, |
| + * and it will be handled by 'ka'. ka->sa.sa_handler can be SIG_IGN or |
| + * SIG_DFL. |
| + * Note that some signals reported by signal_generate tracepoint can be |
| + * lost, ignored or modified (by debugger) before hitting this tracepoint. |
| + * This means, this can show which signals are actually delivered, but |
| + * matching generated signals and delivered signals may not be correct. |
| + */ |
| +TRACE_EVENT(signal_deliver, |
| + |
| + TP_PROTO(int sig, struct siginfo *info, struct k_sigaction *ka), |
| + |
| + TP_ARGS(sig, info, ka), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, sig ) |
| + __field( int, errno ) |
| + __field( int, code ) |
| + __field( unsigned long, sa_handler ) |
| + __field( unsigned long, sa_flags ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(sig, sig) |
| + TP_STORE_SIGINFO(info) |
| + tp_assign(sa_handler, (unsigned long)ka->sa.sa_handler) |
| + tp_assign(sa_flags, ka->sa.sa_flags) |
| + ), |
| + |
| + TP_printk("sig=%d errno=%d code=%d sa_handler=%lx sa_flags=%lx", |
| + __entry->sig, __entry->errno, __entry->code, |
| + __entry->sa_handler, __entry->sa_flags) |
| +) |
| + |
| +DECLARE_EVENT_CLASS(signal_queue_overflow, |
| + |
| + TP_PROTO(int sig, int group, struct siginfo *info), |
| + |
| + TP_ARGS(sig, group, info), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, sig ) |
| + __field( int, group ) |
| + __field( int, errno ) |
| + __field( int, code ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(sig, sig) |
| + tp_assign(group, group) |
| + TP_STORE_SIGINFO(info) |
| + ), |
| + |
| + TP_printk("sig=%d group=%d errno=%d code=%d", |
| + __entry->sig, __entry->group, __entry->errno, __entry->code) |
| +) |
| + |
| +/** |
| + * signal_overflow_fail - called when signal queue is overflow |
| + * @sig: signal number |
| + * @group: signal to process group or not (bool) |
| + * @info: pointer to struct siginfo |
| + * |
| + * Kernel fails to generate 'sig' signal with 'info' siginfo, because |
| + * siginfo queue is overflow, and the signal is dropped. |
| + * 'group' is not 0 if the signal will be sent to a process group. |
| + * 'sig' is always one of RT signals. |
| + */ |
| +DEFINE_EVENT(signal_queue_overflow, signal_overflow_fail, |
| + |
| + TP_PROTO(int sig, int group, struct siginfo *info), |
| + |
| + TP_ARGS(sig, group, info) |
| +) |
| + |
| +/** |
| + * signal_lose_info - called when siginfo is lost |
| + * @sig: signal number |
| + * @group: signal to process group or not (bool) |
| + * @info: pointer to struct siginfo |
| + * |
| + * Kernel generates 'sig' signal but loses 'info' siginfo, because siginfo |
| + * queue is overflow. |
| + * 'group' is not 0 if the signal will be sent to a process group. |
| + * 'sig' is always one of non-RT signals. |
| + */ |
| +DEFINE_EVENT(signal_queue_overflow, signal_lose_info, |
| + |
| + TP_PROTO(int sig, int group, struct siginfo *info), |
| + |
| + TP_ARGS(sig, group, info) |
| +) |
| + |
| +#endif /* _TRACE_SIGNAL_H */ |
| + |
| +/* This part must be outside protection */ |
| +#include "../../../probes/define_trace.h" |
| --- /dev/null |
| +++ b/drivers/staging/lttng/instrumentation/events/lttng-module/timer.h |
| @@ -0,0 +1,333 @@ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM timer |
| + |
| +#if !defined(_TRACE_TIMER_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_TIMER_H |
| + |
| +#include <linux/tracepoint.h> |
| + |
| +#ifndef _TRACE_TIMER_DEF_ |
| +#define _TRACE_TIMER_DEF_ |
| +#include <linux/hrtimer.h> |
| +#include <linux/timer.h> |
| +#endif /* _TRACE_TIMER_DEF_ */ |
| + |
| +DECLARE_EVENT_CLASS(timer_class, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, timer ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(timer, timer) |
| + ), |
| + |
| + TP_printk("timer=%p", __entry->timer) |
| +) |
| + |
| +/** |
| + * timer_init - called when the timer is initialized |
| + * @timer: pointer to struct timer_list |
| + */ |
| +DEFINE_EVENT(timer_class, timer_init, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer) |
| +) |
| + |
| +/** |
| + * timer_start - called when the timer is started |
| + * @timer: pointer to struct timer_list |
| + * @expires: the timers expiry time |
| + */ |
| +TRACE_EVENT(timer_start, |
| + |
| + TP_PROTO(struct timer_list *timer, unsigned long expires), |
| + |
| + TP_ARGS(timer, expires), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, timer ) |
| + __field( void *, function ) |
| + __field( unsigned long, expires ) |
| + __field( unsigned long, now ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(timer, timer) |
| + tp_assign(function, timer->function) |
| + tp_assign(expires, expires) |
| + tp_assign(now, jiffies) |
| + ), |
| + |
| + TP_printk("timer=%p function=%pf expires=%lu [timeout=%ld]", |
| + __entry->timer, __entry->function, __entry->expires, |
| + (long)__entry->expires - __entry->now) |
| +) |
| + |
| +/** |
| + * timer_expire_entry - called immediately before the timer callback |
| + * @timer: pointer to struct timer_list |
| + * |
| + * Allows to determine the timer latency. |
| + */ |
| +TRACE_EVENT(timer_expire_entry, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, timer ) |
| + __field( unsigned long, now ) |
| + __field( void *, function) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(timer, timer) |
| + tp_assign(now, jiffies) |
| + tp_assign(function, timer->function) |
| + ), |
| + |
| + TP_printk("timer=%p function=%pf now=%lu", __entry->timer, __entry->function,__entry->now) |
| +) |
| + |
| +/** |
| + * timer_expire_exit - called immediately after the timer callback returns |
| + * @timer: pointer to struct timer_list |
| + * |
| + * When used in combination with the timer_expire_entry tracepoint we can |
| + * determine the runtime of the timer callback function. |
| + * |
| + * NOTE: Do NOT derefernce timer in TP_fast_assign. The pointer might |
| + * be invalid. We solely track the pointer. |
| + */ |
| +DEFINE_EVENT(timer_class, timer_expire_exit, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer) |
| +) |
| + |
| +/** |
| + * timer_cancel - called when the timer is canceled |
| + * @timer: pointer to struct timer_list |
| + */ |
| +DEFINE_EVENT(timer_class, timer_cancel, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer) |
| +) |
| + |
| +/** |
| + * hrtimer_init - called when the hrtimer is initialized |
| + * @timer: pointer to struct hrtimer |
| + * @clockid: the hrtimers clock |
| + * @mode: the hrtimers mode |
| + */ |
| +TRACE_EVENT(hrtimer_init, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer, clockid_t clockid, |
| + enum hrtimer_mode mode), |
| + |
| + TP_ARGS(hrtimer, clockid, mode), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + __field( clockid_t, clockid ) |
| + __field( enum hrtimer_mode, mode ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(hrtimer, hrtimer) |
| + tp_assign(clockid, clockid) |
| + tp_assign(mode, mode) |
| + ), |
| + |
| + TP_printk("hrtimer=%p clockid=%s mode=%s", __entry->hrtimer, |
| + __entry->clockid == CLOCK_REALTIME ? |
| + "CLOCK_REALTIME" : "CLOCK_MONOTONIC", |
| + __entry->mode == HRTIMER_MODE_ABS ? |
| + "HRTIMER_MODE_ABS" : "HRTIMER_MODE_REL") |
| +) |
| + |
| +/** |
| + * hrtimer_start - called when the hrtimer is started |
| + * @timer: pointer to struct hrtimer |
| + */ |
| +TRACE_EVENT(hrtimer_start, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + __field( void *, function ) |
| + __field( s64, expires ) |
| + __field( s64, softexpires ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(hrtimer, hrtimer) |
| + tp_assign(function, hrtimer->function) |
| + tp_assign(expires, hrtimer_get_expires(hrtimer).tv64) |
| + tp_assign(softexpires, hrtimer_get_softexpires(hrtimer).tv64) |
| + ), |
| + |
| + TP_printk("hrtimer=%p function=%pf expires=%llu softexpires=%llu", |
| + __entry->hrtimer, __entry->function, |
| + (unsigned long long)ktime_to_ns((ktime_t) { |
| + .tv64 = __entry->expires }), |
| + (unsigned long long)ktime_to_ns((ktime_t) { |
| + .tv64 = __entry->softexpires })) |
| +) |
| + |
| +/** |
| + * htimmer_expire_entry - called immediately before the hrtimer callback |
| + * @timer: pointer to struct hrtimer |
| + * @now: pointer to variable which contains current time of the |
| + * timers base. |
| + * |
| + * Allows to determine the timer latency. |
| + */ |
| +TRACE_EVENT(hrtimer_expire_entry, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer, ktime_t *now), |
| + |
| + TP_ARGS(hrtimer, now), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + __field( s64, now ) |
| + __field( void *, function) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(hrtimer, hrtimer) |
| + tp_assign(now, now->tv64) |
| + tp_assign(function, hrtimer->function) |
| + ), |
| + |
| + TP_printk("hrtimer=%p function=%pf now=%llu", __entry->hrtimer, __entry->function, |
| + (unsigned long long)ktime_to_ns((ktime_t) { .tv64 = __entry->now })) |
| +) |
| + |
| +DECLARE_EVENT_CLASS(hrtimer_class, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(hrtimer, hrtimer) |
| + ), |
| + |
| + TP_printk("hrtimer=%p", __entry->hrtimer) |
| +) |
| + |
| +/** |
| + * hrtimer_expire_exit - called immediately after the hrtimer callback returns |
| + * @timer: pointer to struct hrtimer |
| + * |
| + * When used in combination with the hrtimer_expire_entry tracepoint we can |
| + * determine the runtime of the callback function. |
| + */ |
| +DEFINE_EVENT(hrtimer_class, hrtimer_expire_exit, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer) |
| +) |
| + |
| +/** |
| + * hrtimer_cancel - called when the hrtimer is canceled |
| + * @hrtimer: pointer to struct hrtimer |
| + */ |
| +DEFINE_EVENT(hrtimer_class, hrtimer_cancel, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer) |
| +) |
| + |
| +/** |
| + * itimer_state - called when itimer is started or canceled |
| + * @which: name of the interval timer |
| + * @value: the itimers value, itimer is canceled if value->it_value is |
| + * zero, otherwise it is started |
| + * @expires: the itimers expiry time |
| + */ |
| +TRACE_EVENT(itimer_state, |
| + |
| + TP_PROTO(int which, const struct itimerval *const value, |
| + cputime_t expires), |
| + |
| + TP_ARGS(which, value, expires), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, which ) |
| + __field( cputime_t, expires ) |
| + __field( long, value_sec ) |
| + __field( long, value_usec ) |
| + __field( long, interval_sec ) |
| + __field( long, interval_usec ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(which, which) |
| + tp_assign(expires, expires) |
| + tp_assign(value_sec, value->it_value.tv_sec) |
| + tp_assign(value_usec, value->it_value.tv_usec) |
| + tp_assign(interval_sec, value->it_interval.tv_sec) |
| + tp_assign(interval_usec, value->it_interval.tv_usec) |
| + ), |
| + |
| + TP_printk("which=%d expires=%llu it_value=%ld.%ld it_interval=%ld.%ld", |
| + __entry->which, (unsigned long long)__entry->expires, |
| + __entry->value_sec, __entry->value_usec, |
| + __entry->interval_sec, __entry->interval_usec) |
| +) |
| + |
| +/** |
| + * itimer_expire - called when itimer expires |
| + * @which: type of the interval timer |
| + * @pid: pid of the process which owns the timer |
| + * @now: current time, used to calculate the latency of itimer |
| + */ |
| +TRACE_EVENT(itimer_expire, |
| + |
| + TP_PROTO(int which, struct pid *pid, cputime_t now), |
| + |
| + TP_ARGS(which, pid, now), |
| + |
| + TP_STRUCT__entry( |
| + __field( int , which ) |
| + __field( pid_t, pid ) |
| + __field( cputime_t, now ) |
| + ), |
| + |
| + TP_fast_assign( |
| + tp_assign(which, which) |
| + tp_assign(now, now) |
| + tp_assign(pid, pid_nr(pid)) |
| + ), |
| + |
| + TP_printk("which=%d pid=%d now=%llu", __entry->which, |
| + (int) __entry->pid, (unsigned long long)__entry->now) |
| +) |
| + |
| +#endif /* _TRACE_TIMER_H */ |
| + |
| +/* This part must be outside protection */ |
| +#include "../../../probes/define_trace.h" |
| --- /dev/null |
| +++ b/drivers/staging/lttng/instrumentation/events/mainline/signal.h |
| @@ -0,0 +1,166 @@ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM signal |
| + |
| +#if !defined(_TRACE_SIGNAL_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_SIGNAL_H |
| + |
| +#include <linux/signal.h> |
| +#include <linux/sched.h> |
| +#include <linux/tracepoint.h> |
| + |
| +#define TP_STORE_SIGINFO(__entry, info) \ |
| + do { \ |
| + if (info == SEND_SIG_NOINFO || \ |
| + info == SEND_SIG_FORCED) { \ |
| + __entry->errno = 0; \ |
| + __entry->code = SI_USER; \ |
| + } else if (info == SEND_SIG_PRIV) { \ |
| + __entry->errno = 0; \ |
| + __entry->code = SI_KERNEL; \ |
| + } else { \ |
| + __entry->errno = info->si_errno; \ |
| + __entry->code = info->si_code; \ |
| + } \ |
| + } while (0) |
| + |
| +/** |
| + * signal_generate - called when a signal is generated |
| + * @sig: signal number |
| + * @info: pointer to struct siginfo |
| + * @task: pointer to struct task_struct |
| + * |
| + * Current process sends a 'sig' signal to 'task' process with |
| + * 'info' siginfo. If 'info' is SEND_SIG_NOINFO or SEND_SIG_PRIV, |
| + * 'info' is not a pointer and you can't access its field. Instead, |
| + * SEND_SIG_NOINFO means that si_code is SI_USER, and SEND_SIG_PRIV |
| + * means that si_code is SI_KERNEL. |
| + */ |
| +TRACE_EVENT(signal_generate, |
| + |
| + TP_PROTO(int sig, struct siginfo *info, struct task_struct *task), |
| + |
| + TP_ARGS(sig, info, task), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, sig ) |
| + __field( int, errno ) |
| + __field( int, code ) |
| + __array( char, comm, TASK_COMM_LEN ) |
| + __field( pid_t, pid ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->sig = sig; |
| + TP_STORE_SIGINFO(__entry, info); |
| + memcpy(__entry->comm, task->comm, TASK_COMM_LEN); |
| + __entry->pid = task->pid; |
| + ), |
| + |
| + TP_printk("sig=%d errno=%d code=%d comm=%s pid=%d", |
| + __entry->sig, __entry->errno, __entry->code, |
| + __entry->comm, __entry->pid) |
| +); |
| + |
| +/** |
| + * signal_deliver - called when a signal is delivered |
| + * @sig: signal number |
| + * @info: pointer to struct siginfo |
| + * @ka: pointer to struct k_sigaction |
| + * |
| + * A 'sig' signal is delivered to current process with 'info' siginfo, |
| + * and it will be handled by 'ka'. ka->sa.sa_handler can be SIG_IGN or |
| + * SIG_DFL. |
| + * Note that some signals reported by signal_generate tracepoint can be |
| + * lost, ignored or modified (by debugger) before hitting this tracepoint. |
| + * This means, this can show which signals are actually delivered, but |
| + * matching generated signals and delivered signals may not be correct. |
| + */ |
| +TRACE_EVENT(signal_deliver, |
| + |
| + TP_PROTO(int sig, struct siginfo *info, struct k_sigaction *ka), |
| + |
| + TP_ARGS(sig, info, ka), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, sig ) |
| + __field( int, errno ) |
| + __field( int, code ) |
| + __field( unsigned long, sa_handler ) |
| + __field( unsigned long, sa_flags ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->sig = sig; |
| + TP_STORE_SIGINFO(__entry, info); |
| + __entry->sa_handler = (unsigned long)ka->sa.sa_handler; |
| + __entry->sa_flags = ka->sa.sa_flags; |
| + ), |
| + |
| + TP_printk("sig=%d errno=%d code=%d sa_handler=%lx sa_flags=%lx", |
| + __entry->sig, __entry->errno, __entry->code, |
| + __entry->sa_handler, __entry->sa_flags) |
| +); |
| + |
| +DECLARE_EVENT_CLASS(signal_queue_overflow, |
| + |
| + TP_PROTO(int sig, int group, struct siginfo *info), |
| + |
| + TP_ARGS(sig, group, info), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, sig ) |
| + __field( int, group ) |
| + __field( int, errno ) |
| + __field( int, code ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->sig = sig; |
| + __entry->group = group; |
| + TP_STORE_SIGINFO(__entry, info); |
| + ), |
| + |
| + TP_printk("sig=%d group=%d errno=%d code=%d", |
| + __entry->sig, __entry->group, __entry->errno, __entry->code) |
| +); |
| + |
| +/** |
| + * signal_overflow_fail - called when signal queue is overflow |
| + * @sig: signal number |
| + * @group: signal to process group or not (bool) |
| + * @info: pointer to struct siginfo |
| + * |
| + * Kernel fails to generate 'sig' signal with 'info' siginfo, because |
| + * siginfo queue is overflow, and the signal is dropped. |
| + * 'group' is not 0 if the signal will be sent to a process group. |
| + * 'sig' is always one of RT signals. |
| + */ |
| +DEFINE_EVENT(signal_queue_overflow, signal_overflow_fail, |
| + |
| + TP_PROTO(int sig, int group, struct siginfo *info), |
| + |
| + TP_ARGS(sig, group, info) |
| +); |
| + |
| +/** |
| + * signal_lose_info - called when siginfo is lost |
| + * @sig: signal number |
| + * @group: signal to process group or not (bool) |
| + * @info: pointer to struct siginfo |
| + * |
| + * Kernel generates 'sig' signal but loses 'info' siginfo, because siginfo |
| + * queue is overflow. |
| + * 'group' is not 0 if the signal will be sent to a process group. |
| + * 'sig' is always one of non-RT signals. |
| + */ |
| +DEFINE_EVENT(signal_queue_overflow, signal_lose_info, |
| + |
| + TP_PROTO(int sig, int group, struct siginfo *info), |
| + |
| + TP_ARGS(sig, group, info) |
| +); |
| + |
| +#endif /* _TRACE_SIGNAL_H */ |
| + |
| +/* This part must be outside protection */ |
| +#include <trace/define_trace.h> |
| --- /dev/null |
| +++ b/drivers/staging/lttng/instrumentation/events/mainline/timer.h |
| @@ -0,0 +1,329 @@ |
| +#undef TRACE_SYSTEM |
| +#define TRACE_SYSTEM timer |
| + |
| +#if !defined(_TRACE_TIMER_H) || defined(TRACE_HEADER_MULTI_READ) |
| +#define _TRACE_TIMER_H |
| + |
| +#include <linux/tracepoint.h> |
| +#include <linux/hrtimer.h> |
| +#include <linux/timer.h> |
| + |
| +DECLARE_EVENT_CLASS(timer_class, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, timer ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->timer = timer; |
| + ), |
| + |
| + TP_printk("timer=%p", __entry->timer) |
| +); |
| + |
| +/** |
| + * timer_init - called when the timer is initialized |
| + * @timer: pointer to struct timer_list |
| + */ |
| +DEFINE_EVENT(timer_class, timer_init, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer) |
| +); |
| + |
| +/** |
| + * timer_start - called when the timer is started |
| + * @timer: pointer to struct timer_list |
| + * @expires: the timers expiry time |
| + */ |
| +TRACE_EVENT(timer_start, |
| + |
| + TP_PROTO(struct timer_list *timer, unsigned long expires), |
| + |
| + TP_ARGS(timer, expires), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, timer ) |
| + __field( void *, function ) |
| + __field( unsigned long, expires ) |
| + __field( unsigned long, now ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->timer = timer; |
| + __entry->function = timer->function; |
| + __entry->expires = expires; |
| + __entry->now = jiffies; |
| + ), |
| + |
| + TP_printk("timer=%p function=%pf expires=%lu [timeout=%ld]", |
| + __entry->timer, __entry->function, __entry->expires, |
| + (long)__entry->expires - __entry->now) |
| +); |
| + |
| +/** |
| + * timer_expire_entry - called immediately before the timer callback |
| + * @timer: pointer to struct timer_list |
| + * |
| + * Allows to determine the timer latency. |
| + */ |
| +TRACE_EVENT(timer_expire_entry, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, timer ) |
| + __field( unsigned long, now ) |
| + __field( void *, function) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->timer = timer; |
| + __entry->now = jiffies; |
| + __entry->function = timer->function; |
| + ), |
| + |
| + TP_printk("timer=%p function=%pf now=%lu", __entry->timer, __entry->function,__entry->now) |
| +); |
| + |
| +/** |
| + * timer_expire_exit - called immediately after the timer callback returns |
| + * @timer: pointer to struct timer_list |
| + * |
| + * When used in combination with the timer_expire_entry tracepoint we can |
| + * determine the runtime of the timer callback function. |
| + * |
| + * NOTE: Do NOT derefernce timer in TP_fast_assign. The pointer might |
| + * be invalid. We solely track the pointer. |
| + */ |
| +DEFINE_EVENT(timer_class, timer_expire_exit, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer) |
| +); |
| + |
| +/** |
| + * timer_cancel - called when the timer is canceled |
| + * @timer: pointer to struct timer_list |
| + */ |
| +DEFINE_EVENT(timer_class, timer_cancel, |
| + |
| + TP_PROTO(struct timer_list *timer), |
| + |
| + TP_ARGS(timer) |
| +); |
| + |
| +/** |
| + * hrtimer_init - called when the hrtimer is initialized |
| + * @timer: pointer to struct hrtimer |
| + * @clockid: the hrtimers clock |
| + * @mode: the hrtimers mode |
| + */ |
| +TRACE_EVENT(hrtimer_init, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer, clockid_t clockid, |
| + enum hrtimer_mode mode), |
| + |
| + TP_ARGS(hrtimer, clockid, mode), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + __field( clockid_t, clockid ) |
| + __field( enum hrtimer_mode, mode ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->hrtimer = hrtimer; |
| + __entry->clockid = clockid; |
| + __entry->mode = mode; |
| + ), |
| + |
| + TP_printk("hrtimer=%p clockid=%s mode=%s", __entry->hrtimer, |
| + __entry->clockid == CLOCK_REALTIME ? |
| + "CLOCK_REALTIME" : "CLOCK_MONOTONIC", |
| + __entry->mode == HRTIMER_MODE_ABS ? |
| + "HRTIMER_MODE_ABS" : "HRTIMER_MODE_REL") |
| +); |
| + |
| +/** |
| + * hrtimer_start - called when the hrtimer is started |
| + * @timer: pointer to struct hrtimer |
| + */ |
| +TRACE_EVENT(hrtimer_start, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + __field( void *, function ) |
| + __field( s64, expires ) |
| + __field( s64, softexpires ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->hrtimer = hrtimer; |
| + __entry->function = hrtimer->function; |
| + __entry->expires = hrtimer_get_expires(hrtimer).tv64; |
| + __entry->softexpires = hrtimer_get_softexpires(hrtimer).tv64; |
| + ), |
| + |
| + TP_printk("hrtimer=%p function=%pf expires=%llu softexpires=%llu", |
| + __entry->hrtimer, __entry->function, |
| + (unsigned long long)ktime_to_ns((ktime_t) { |
| + .tv64 = __entry->expires }), |
| + (unsigned long long)ktime_to_ns((ktime_t) { |
| + .tv64 = __entry->softexpires })) |
| +); |
| + |
| +/** |
| + * htimmer_expire_entry - called immediately before the hrtimer callback |
| + * @timer: pointer to struct hrtimer |
| + * @now: pointer to variable which contains current time of the |
| + * timers base. |
| + * |
| + * Allows to determine the timer latency. |
| + */ |
| +TRACE_EVENT(hrtimer_expire_entry, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer, ktime_t *now), |
| + |
| + TP_ARGS(hrtimer, now), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + __field( s64, now ) |
| + __field( void *, function) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->hrtimer = hrtimer; |
| + __entry->now = now->tv64; |
| + __entry->function = hrtimer->function; |
| + ), |
| + |
| + TP_printk("hrtimer=%p function=%pf now=%llu", __entry->hrtimer, __entry->function, |
| + (unsigned long long)ktime_to_ns((ktime_t) { .tv64 = __entry->now })) |
| + ); |
| + |
| +DECLARE_EVENT_CLASS(hrtimer_class, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer), |
| + |
| + TP_STRUCT__entry( |
| + __field( void *, hrtimer ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->hrtimer = hrtimer; |
| + ), |
| + |
| + TP_printk("hrtimer=%p", __entry->hrtimer) |
| +); |
| + |
| +/** |
| + * hrtimer_expire_exit - called immediately after the hrtimer callback returns |
| + * @timer: pointer to struct hrtimer |
| + * |
| + * When used in combination with the hrtimer_expire_entry tracepoint we can |
| + * determine the runtime of the callback function. |
| + */ |
| +DEFINE_EVENT(hrtimer_class, hrtimer_expire_exit, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer) |
| +); |
| + |
| +/** |
| + * hrtimer_cancel - called when the hrtimer is canceled |
| + * @hrtimer: pointer to struct hrtimer |
| + */ |
| +DEFINE_EVENT(hrtimer_class, hrtimer_cancel, |
| + |
| + TP_PROTO(struct hrtimer *hrtimer), |
| + |
| + TP_ARGS(hrtimer) |
| +); |
| + |
| +/** |
| + * itimer_state - called when itimer is started or canceled |
| + * @which: name of the interval timer |
| + * @value: the itimers value, itimer is canceled if value->it_value is |
| + * zero, otherwise it is started |
| + * @expires: the itimers expiry time |
| + */ |
| +TRACE_EVENT(itimer_state, |
| + |
| + TP_PROTO(int which, const struct itimerval *const value, |
| + cputime_t expires), |
| + |
| + TP_ARGS(which, value, expires), |
| + |
| + TP_STRUCT__entry( |
| + __field( int, which ) |
| + __field( cputime_t, expires ) |
| + __field( long, value_sec ) |
| + __field( long, value_usec ) |
| + __field( long, interval_sec ) |
| + __field( long, interval_usec ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->which = which; |
| + __entry->expires = expires; |
| + __entry->value_sec = value->it_value.tv_sec; |
| + __entry->value_usec = value->it_value.tv_usec; |
| + __entry->interval_sec = value->it_interval.tv_sec; |
| + __entry->interval_usec = value->it_interval.tv_usec; |
| + ), |
| + |
| + TP_printk("which=%d expires=%llu it_value=%ld.%ld it_interval=%ld.%ld", |
| + __entry->which, (unsigned long long)__entry->expires, |
| + __entry->value_sec, __entry->value_usec, |
| + __entry->interval_sec, __entry->interval_usec) |
| +); |
| + |
| +/** |
| + * itimer_expire - called when itimer expires |
| + * @which: type of the interval timer |
| + * @pid: pid of the process which owns the timer |
| + * @now: current time, used to calculate the latency of itimer |
| + */ |
| +TRACE_EVENT(itimer_expire, |
| + |
| + TP_PROTO(int which, struct pid *pid, cputime_t now), |
| + |
| + TP_ARGS(which, pid, now), |
| + |
| + TP_STRUCT__entry( |
| + __field( int , which ) |
| + __field( pid_t, pid ) |
| + __field( cputime_t, now ) |
| + ), |
| + |
| + TP_fast_assign( |
| + __entry->which = which; |
| + __entry->now = now; |
| + __entry->pid = pid_nr(pid); |
| + ), |
| + |
| + TP_printk("which=%d pid=%d now=%llu", __entry->which, |
| + (int) __entry->pid, (unsigned long long)__entry->now) |
| +); |
| + |
| +#endif /* _TRACE_TIMER_H */ |
| + |
| +/* This part must be outside protection */ |
| +#include <trace/define_trace.h> |
| --- a/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers_override.h |
| +++ b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers_override.h |
| @@ -1,3 +1,56 @@ |
| +#define OVERRIDE_32_sys_execve |
| +#define OVERRIDE_64_sys_execve |
| + |
| +#ifndef CREATE_SYSCALL_TABLE |
| + |
| +SC_TRACE_EVENT(sys_execve, |
| + TP_PROTO(const char *filename, char *const *argv, char *const *envp), |
| + TP_ARGS(filename, argv, envp), |
| + TP_STRUCT__entry(__string_from_user(filename, filename) |
| + __field_hex(char *const *, argv) |
| + __field_hex(char *const *, envp)), |
| + TP_fast_assign(tp_copy_string_from_user(filename, filename) |
| + tp_assign(argv, argv) |
| + tp_assign(envp, envp)), |
| + TP_printk() |
| +) |
| + |
| +SC_TRACE_EVENT(sys_clone, |
| + TP_PROTO(unsigned long clone_flags, unsigned long newsp, |
| + void __user *parent_tid, |
| + void __user *child_tid), |
| + TP_ARGS(clone_flags, newsp, parent_tid, child_tid), |
| + TP_STRUCT__entry( |
| + __field_hex(unsigned long, clone_flags) |
| + __field_hex(unsigned long, newsp) |
| + __field_hex(void *, parent_tid) |
| + __field_hex(void *, child_tid)), |
| + TP_fast_assign( |
| + tp_assign(clone_flags, clone_flags) |
| + tp_assign(newsp, newsp) |
| + tp_assign(parent_tid, parent_tid) |
| + tp_assign(child_tid, child_tid)), |
| + TP_printk() |
| +) |
| + |
| +/* present in 32, missing in 64 due to old kernel headers */ |
| +#define OVERRIDE_32_sys_getcpu |
| +#define OVERRIDE_64_sys_getcpu |
| +SC_TRACE_EVENT(sys_getcpu, |
| + TP_PROTO(unsigned __user *cpup, unsigned __user *nodep, void *tcache), |
| + TP_ARGS(cpup, nodep, tcache), |
| + TP_STRUCT__entry( |
| + __field_hex(unsigned *, cpup) |
| + __field_hex(unsigned *, nodep) |
| + __field_hex(void *, tcache)), |
| + TP_fast_assign( |
| + tp_assign(cpup, cpup) |
| + tp_assign(nodep, nodep) |
| + tp_assign(tcache, tcache)), |
| + TP_printk() |
| +) |
| + |
| +#endif /* CREATE_SYSCALL_TABLE */ |
| /* |
| * This is a place-holder for override defines for system calls with |
| * pointers (all architectures). |
| --- a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers_override.h |
| +++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers_override.h |
| @@ -1,17 +1,33 @@ |
| -#ifndef CONFIG_UID16 |
| |
| -#define OVERRIDE_32_sys_getgroups16 |
| -#define OVERRIDE_32_sys_setgroups16 |
| -#define OVERRIDE_32_sys_lchown16 |
| -#define OVERRIDE_32_sys_getresuid16 |
| -#define OVERRIDE_32_sys_getresgid16 |
| -#define OVERRIDE_32_sys_chown16 |
| - |
| -#define OVERRIDE_TABLE_32_sys_getgroups16 |
| -#define OVERRIDE_TABLE_32_sys_setgroups16 |
| -#define OVERRIDE_TABLE_32_sys_lchown16 |
| -#define OVERRIDE_TABLE_32_sys_getresuid16 |
| -#define OVERRIDE_TABLE_32_sys_getresgid16 |
| -#define OVERRIDE_TABLE_32_sys_chown16 |
| +#ifndef CREATE_SYSCALL_TABLE |
| + |
| +# ifndef CONFIG_UID16 |
| +# define OVERRIDE_32_sys_getgroups16 |
| +# define OVERRIDE_32_sys_setgroups16 |
| +# define OVERRIDE_32_sys_lchown16 |
| +# define OVERRIDE_32_sys_getresuid16 |
| +# define OVERRIDE_32_sys_getresgid16 |
| +# define OVERRIDE_32_sys_chown16 |
| +# endif |
| + |
| +#else /* CREATE_SYSCALL_TABLE */ |
| + |
| +# ifndef CONFIG_UID16 |
| +# define OVERRIDE_TABLE_32_sys_getgroups16 |
| +# define OVERRIDE_TABLE_32_sys_setgroups16 |
| +# define OVERRIDE_TABLE_32_sys_lchown16 |
| +# define OVERRIDE_TABLE_32_sys_getresuid16 |
| +# define OVERRIDE_TABLE_32_sys_getresgid16 |
| +# define OVERRIDE_TABLE_32_sys_chown16 |
| +# endif |
| + |
| +#define OVERRIDE_TABLE_32_sys_execve |
| +TRACE_SYSCALL_TABLE(sys_execve, sys_execve, 11, 3) |
| +#define OVERRIDE_TABLE_32_sys_clone |
| +TRACE_SYSCALL_TABLE(sys_clone, sys_clone, 120, 5) |
| +#define OVERRIDE_TABLE_32_sys_getcpu |
| +TRACE_SYSCALL_TABLE(sys_getcpu, sys_getcpu, 318, 3) |
| + |
| +#endif /* CREATE_SYSCALL_TABLE */ |
| + |
| |
| -#endif |
| --- a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers_override.h |
| +++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers_override.h |
| @@ -1,3 +1,6 @@ |
| /* |
| * this is a place-holder for x86_64 interger syscall definition override. |
| */ |
| +/* |
| + * this is a place-holder for x86_64 interger syscall definition override. |
| + */ |
| --- a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers_override.h |
| +++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers_override.h |
| @@ -2,4 +2,11 @@ |
| |
| #else /* CREATE_SYSCALL_TABLE */ |
| |
| +#define OVERRIDE_TABLE_64_sys_clone |
| +TRACE_SYSCALL_TABLE(sys_clone, sys_clone, 56, 5) |
| +#define OVERRIDE_TABLE_64_sys_execve |
| +TRACE_SYSCALL_TABLE(sys_execve, sys_execve, 59, 3) |
| +#define OVERRIDE_TABLE_64_sys_getcpu |
| +TRACE_SYSCALL_TABLE(sys_getcpu, sys_getcpu, 309, 3) |
| + |
| #endif /* CREATE_SYSCALL_TABLE */ |
| --- a/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/lttng-syscalls-extractor.c |
| +++ b/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/lttng-syscalls-extractor.c |
| @@ -1,10 +1,24 @@ |
| /* |
| + * lttng-syscalls-extractor.c |
| + * |
| + * Dump syscall metadata to console. |
| + * |
| * Copyright 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * Copyright 2011 - Julien Desfossez <julien.desfossez@polymtl.ca> |
| * |
| - * Dump syscall metadata to console. |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License as published by |
| + * the Free Software Foundation; either version 2 of the License, or |
| + * (at your option) any later version. |
| + * |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| * |
| - * GPLv2 license. |
| + * You should have received a copy of the GNU General Public License along |
| + * with this program; if not, write to the Free Software Foundation, Inc., |
| + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| */ |
| |
| #include <linux/module.h> |
| --- a/drivers/staging/lttng/lib/Makefile |
| +++ b/drivers/staging/lttng/lib/Makefile |
| @@ -1,6 +1,6 @@ |
| -obj-m += lib-ring-buffer.o |
| +obj-m += lttng-lib-ring-buffer.o |
| |
| -lib-ring-buffer-objs := \ |
| +lttng-lib-ring-buffer-objs := \ |
| ringbuffer/ring_buffer_backend.o \ |
| ringbuffer/ring_buffer_frontend.o \ |
| ringbuffer/ring_buffer_iterator.o \ |
| --- a/drivers/staging/lttng/lib/align.h |
| +++ b/drivers/staging/lttng/lib/align.h |
| @@ -4,9 +4,21 @@ |
| /* |
| * lib/align.h |
| * |
| - * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #ifdef __KERNEL__ |
| --- a/drivers/staging/lttng/lib/bitfield.h |
| +++ b/drivers/staging/lttng/lib/bitfield.h |
| @@ -19,7 +19,7 @@ |
| * all copies or substantial portions of the Software. |
| */ |
| |
| -#include "../ltt-endian.h" |
| +#include "../lttng-endian.h" |
| |
| #ifndef CHAR_BIT |
| #define CHAR_BIT 8 |
| --- a/drivers/staging/lttng/lib/bug.h |
| +++ b/drivers/staging/lttng/lib/bug.h |
| @@ -4,9 +4,21 @@ |
| /* |
| * lib/bug.h |
| * |
| - * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /** |
| --- a/drivers/staging/lttng/lib/ringbuffer/api.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/api.h |
| @@ -1,14 +1,26 @@ |
| -#ifndef _LINUX_RING_BUFFER_API_H |
| -#define _LINUX_RING_BUFFER_API_H |
| +#ifndef _LIB_RING_BUFFER_API_H |
| +#define _LIB_RING_BUFFER_API_H |
| |
| /* |
| - * linux/ringbuffer/api.h |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers "mathieu.desnoyers@efficios.com" |
| + * lib/ringbuffer/api.h |
| * |
| * Ring Buffer API. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "../../wrapper/ringbuffer/backend.h" |
| @@ -22,4 +34,4 @@ |
| */ |
| #include "../../wrapper/ringbuffer/frontend_api.h" |
| |
| -#endif /* _LINUX_RING_BUFFER_API_H */ |
| +#endif /* _LIB_RING_BUFFER_API_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/backend.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/backend.h |
| @@ -1,14 +1,26 @@ |
| -#ifndef _LINUX_RING_BUFFER_BACKEND_H |
| -#define _LINUX_RING_BUFFER_BACKEND_H |
| +#ifndef _LIB_RING_BUFFER_BACKEND_H |
| +#define _LIB_RING_BUFFER_BACKEND_H |
| |
| /* |
| - * linux/ringbuffer/backend.h |
| - * |
| - * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/backend.h |
| * |
| * Ring buffer backend (API). |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| * |
| * Credits to Steven Rostedt for proposing to use an extra-subbuffer owned by |
| * the reader in flight recorder mode. |
| @@ -247,4 +259,4 @@ ssize_t lib_ring_buffer_file_splice_read |
| size_t len, unsigned int flags); |
| loff_t lib_ring_buffer_no_llseek(struct file *file, loff_t offset, int origin); |
| |
| -#endif /* _LINUX_RING_BUFFER_BACKEND_H */ |
| +#endif /* _LIB_RING_BUFFER_BACKEND_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/backend_internal.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/backend_internal.h |
| @@ -1,14 +1,26 @@ |
| -#ifndef _LINUX_RING_BUFFER_BACKEND_INTERNAL_H |
| -#define _LINUX_RING_BUFFER_BACKEND_INTERNAL_H |
| +#ifndef _LIB_RING_BUFFER_BACKEND_INTERNAL_H |
| +#define _LIB_RING_BUFFER_BACKEND_INTERNAL_H |
| |
| /* |
| - * linux/ringbuffer/backend_internal.h |
| - * |
| - * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/backend_internal.h |
| * |
| * Ring buffer backend (internal helpers). |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2008-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "../../wrapper/ringbuffer/config.h" |
| @@ -446,4 +458,4 @@ void lib_ring_buffer_do_memset(char *des |
| dest[i] = c; |
| } |
| |
| -#endif /* _LINUX_RING_BUFFER_BACKEND_INTERNAL_H */ |
| +#endif /* _LIB_RING_BUFFER_BACKEND_INTERNAL_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/backend_types.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/backend_types.h |
| @@ -1,14 +1,26 @@ |
| -#ifndef _LINUX_RING_BUFFER_BACKEND_TYPES_H |
| -#define _LINUX_RING_BUFFER_BACKEND_TYPES_H |
| +#ifndef _LIB_RING_BUFFER_BACKEND_TYPES_H |
| +#define _LIB_RING_BUFFER_BACKEND_TYPES_H |
| |
| /* |
| - * linux/ringbuffer/backend_types.h |
| - * |
| - * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/backend_types.h |
| * |
| * Ring buffer backend (types). |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2008-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/cpumask.h> |
| @@ -72,9 +84,14 @@ struct channel_backend { |
| u64 start_tsc; /* Channel creation TSC value */ |
| void *priv; /* Client-specific information */ |
| struct notifier_block cpu_hp_notifier; /* CPU hotplug notifier */ |
| - const struct lib_ring_buffer_config *config; /* Ring buffer configuration */ |
| + /* |
| + * We need to copy config because the module containing the |
| + * source config can vanish before the last reference to this |
| + * channel's streams is released. |
| + */ |
| + struct lib_ring_buffer_config config; /* Ring buffer configuration */ |
| cpumask_var_t cpumask; /* Allocated per-cpu buffers cpumask */ |
| char name[NAME_MAX]; /* Channel name */ |
| }; |
| |
| -#endif /* _LINUX_RING_BUFFER_BACKEND_TYPES_H */ |
| +#endif /* _LIB_RING_BUFFER_BACKEND_TYPES_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/config.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/config.h |
| @@ -1,15 +1,27 @@ |
| -#ifndef _LINUX_RING_BUFFER_CONFIG_H |
| -#define _LINUX_RING_BUFFER_CONFIG_H |
| +#ifndef _LIB_RING_BUFFER_CONFIG_H |
| +#define _LIB_RING_BUFFER_CONFIG_H |
| |
| /* |
| - * linux/ringbuffer/config.h |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/config.h |
| * |
| * Ring buffer configuration header. Note: after declaring the standard inline |
| * functions, clients should also include linux/ringbuffer/api.h. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/types.h> |
| @@ -295,4 +307,4 @@ int lib_ring_buffer_check_config(const s |
| |
| #include "../../wrapper/ringbuffer/vatomic.h" |
| |
| -#endif /* _LINUX_RING_BUFFER_CONFIG_H */ |
| +#endif /* _LIB_RING_BUFFER_CONFIG_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/frontend.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/frontend.h |
| @@ -1,19 +1,31 @@ |
| -#ifndef _LINUX_RING_BUFFER_FRONTEND_H |
| -#define _LINUX_RING_BUFFER_FRONTEND_H |
| +#ifndef _LIB_RING_BUFFER_FRONTEND_H |
| +#define _LIB_RING_BUFFER_FRONTEND_H |
| |
| /* |
| - * linux/ringbuffer/frontend.h |
| - * |
| - * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/frontend.h |
| * |
| * Ring Buffer Library Synchronization Header (API). |
| * |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * Author: |
| * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| * See ring_buffer_frontend.c for more information on wait-free algorithms. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include <linux/pipe_fs_i.h> |
| @@ -225,4 +237,4 @@ unsigned long lib_ring_buffer_get_record |
| return v_read(config, &buf->backend.records_read); |
| } |
| |
| -#endif /* _LINUX_RING_BUFFER_FRONTEND_H */ |
| +#endif /* _LIB_RING_BUFFER_FRONTEND_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/frontend_api.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/frontend_api.h |
| @@ -1,20 +1,32 @@ |
| -#ifndef _LINUX_RING_BUFFER_FRONTEND_API_H |
| -#define _LINUX_RING_BUFFER_FRONTEND_API_H |
| +#ifndef _LIB_RING_BUFFER_FRONTEND_API_H |
| +#define _LIB_RING_BUFFER_FRONTEND_API_H |
| |
| /* |
| - * linux/ringbuffer/frontend_api.h |
| - * |
| - * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/frontend_api.h |
| * |
| * Ring Buffer Library Synchronization Header (buffer write API). |
| * |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * Author: |
| * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| * See ring_buffer_frontend.c for more information on wait-free algorithms. |
| * See linux/ringbuffer/frontend.h for channel allocation and read-side API. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include "../../wrapper/ringbuffer/frontend.h" |
| @@ -355,4 +367,4 @@ void lib_ring_buffer_record_enable(const |
| atomic_dec(&buf->record_disabled); |
| } |
| |
| -#endif /* _LINUX_RING_BUFFER_FRONTEND_API_H */ |
| +#endif /* _LIB_RING_BUFFER_FRONTEND_API_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/frontend_internal.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/frontend_internal.h |
| @@ -1,19 +1,31 @@ |
| -#ifndef _LINUX_RING_BUFFER_FRONTEND_INTERNAL_H |
| -#define _LINUX_RING_BUFFER_FRONTEND_INTERNAL_H |
| +#ifndef _LIB_RING_BUFFER_FRONTEND_INTERNAL_H |
| +#define _LIB_RING_BUFFER_FRONTEND_INTERNAL_H |
| |
| /* |
| * linux/ringbuffer/frontend_internal.h |
| * |
| - * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * Ring Buffer Library Synchronization Header (internal helpers). |
| * |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * Author: |
| * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| * See ring_buffer_frontend.c for more information on wait-free algorithms. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include "../../wrapper/ringbuffer/config.h" |
| @@ -421,4 +433,4 @@ extern void lib_ring_buffer_free(struct |
| /* Keep track of trap nesting inside ring buffer code */ |
| DECLARE_PER_CPU(unsigned int, lib_ring_buffer_nesting); |
| |
| -#endif /* _LINUX_RING_BUFFER_FRONTEND_INTERNAL_H */ |
| +#endif /* _LIB_RING_BUFFER_FRONTEND_INTERNAL_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/frontend_types.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/frontend_types.h |
| @@ -1,19 +1,31 @@ |
| -#ifndef _LINUX_RING_BUFFER_FRONTEND_TYPES_H |
| -#define _LINUX_RING_BUFFER_FRONTEND_TYPES_H |
| +#ifndef _LIB_RING_BUFFER_FRONTEND_TYPES_H |
| +#define _LIB_RING_BUFFER_FRONTEND_TYPES_H |
| |
| /* |
| - * linux/ringbuffer/frontend_types.h |
| - * |
| - * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/frontend_types.h |
| * |
| * Ring Buffer Library Synchronization Header (types). |
| * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * Author: |
| * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| * See ring_buffer_frontend.c for more information on wait-free algorithms. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include <linux/kref.h> |
| @@ -138,9 +150,9 @@ struct lib_ring_buffer { |
| unsigned long get_subbuf_consumed; /* Read-side consumed */ |
| unsigned long prod_snapshot; /* Producer count snapshot */ |
| unsigned long cons_snapshot; /* Consumer count snapshot */ |
| - uint get_subbuf:1; /* Sub-buffer being held by reader */ |
| - uint switch_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ |
| - uint read_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ |
| + uint get_subbuf:1, /* Sub-buffer being held by reader */ |
| + switch_timer_enabled:1, /* Protected by ring_buffer_nohz_lock */ |
| + read_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ |
| }; |
| |
| static inline |
| @@ -173,4 +185,4 @@ void *channel_get_private(struct channel |
| _____ret; \ |
| }) |
| |
| -#endif /* _LINUX_RING_BUFFER_FRONTEND_TYPES_H */ |
| +#endif /* _LIB_RING_BUFFER_FRONTEND_TYPES_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/iterator.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/iterator.h |
| @@ -1,17 +1,29 @@ |
| -#ifndef _LINUX_RING_BUFFER_ITERATOR_H |
| -#define _LINUX_RING_BUFFER_ITERATOR_H |
| +#ifndef _LIB_RING_BUFFER_ITERATOR_H |
| +#define _LIB_RING_BUFFER_ITERATOR_H |
| |
| /* |
| - * linux/ringbuffer/iterator.h |
| - * |
| - * (C) Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/iterator.h |
| * |
| * Ring buffer and channel iterators. |
| * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * Author: |
| * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include "../../wrapper/ringbuffer/backend.h" |
| @@ -67,4 +79,4 @@ void channel_iterator_free(struct channe |
| void channel_iterator_reset(struct channel *chan); |
| void lib_ring_buffer_iterator_reset(struct lib_ring_buffer *buf); |
| |
| -#endif /* _LINUX_RING_BUFFER_ITERATOR_H */ |
| +#endif /* _LIB_RING_BUFFER_ITERATOR_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/nohz.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/nohz.h |
| @@ -1,12 +1,24 @@ |
| -#ifndef _LINUX_RING_BUFFER_NOHZ_H |
| -#define _LINUX_RING_BUFFER_NOHZ_H |
| +#ifndef _LIB_RING_BUFFER_NOHZ_H |
| +#define _LIB_RING_BUFFER_NOHZ_H |
| |
| /* |
| - * ringbuffer/nohz.h |
| + * lib/ringbuffer/nohz.h |
| * |
| - * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #ifdef CONFIG_LIB_RING_BUFFER |
| @@ -27,4 +39,4 @@ static inline void lib_ring_buffer_tick_ |
| } |
| #endif |
| |
| -#endif /* _LINUX_RING_BUFFER_NOHZ_H */ |
| +#endif /* _LIB_RING_BUFFER_NOHZ_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_backend.c |
| +++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_backend.c |
| @@ -1,9 +1,21 @@ |
| /* |
| * ring_buffer_backend.c |
| * |
| - * Copyright (C) 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/stddef.h> |
| @@ -155,7 +167,7 @@ pages_error: |
| int lib_ring_buffer_backend_create(struct lib_ring_buffer_backend *bufb, |
| struct channel_backend *chanb, int cpu) |
| { |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| |
| bufb->chan = container_of(chanb, struct channel, backend); |
| bufb->cpu = cpu; |
| @@ -187,7 +199,7 @@ void lib_ring_buffer_backend_free(struct |
| void lib_ring_buffer_backend_reset(struct lib_ring_buffer_backend *bufb) |
| { |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| unsigned long num_subbuf_alloc; |
| unsigned int i; |
| |
| @@ -221,7 +233,7 @@ void lib_ring_buffer_backend_reset(struc |
| void channel_backend_reset(struct channel_backend *chanb) |
| { |
| struct channel *chan = container_of(chanb, struct channel, backend); |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| |
| /* |
| * Don't reset buf_size, subbuf_size, subbuf_size_order, |
| @@ -248,7 +260,7 @@ int __cpuinit lib_ring_buffer_cpu_hp_cal |
| unsigned int cpu = (unsigned long)hcpu; |
| struct channel_backend *chanb = container_of(nb, struct channel_backend, |
| cpu_hp_notifier); |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| struct lib_ring_buffer *buf; |
| int ret; |
| |
| @@ -307,18 +319,18 @@ int channel_backend_init(struct channel_ |
| if (!name) |
| return -EPERM; |
| |
| - if (!(subbuf_size && num_subbuf)) |
| - return -EPERM; |
| - |
| /* Check that the subbuffer size is larger than a page. */ |
| if (subbuf_size < PAGE_SIZE) |
| return -EINVAL; |
| |
| /* |
| - * Make sure the number of subbuffers and subbuffer size are power of 2. |
| + * Make sure the number of subbuffers and subbuffer size are |
| + * power of 2 and nonzero. |
| */ |
| - CHAN_WARN_ON(chanb, hweight32(subbuf_size) != 1); |
| - CHAN_WARN_ON(chanb, hweight32(num_subbuf) != 1); |
| + if (!subbuf_size || (subbuf_size & (subbuf_size - 1))) |
| + return -EINVAL; |
| + if (!num_subbuf || (num_subbuf & (num_subbuf - 1))) |
| + return -EINVAL; |
| |
| ret = subbuffer_id_check_index(config, num_subbuf); |
| if (ret) |
| @@ -334,7 +346,7 @@ int channel_backend_init(struct channel_ |
| (config->mode == RING_BUFFER_OVERWRITE) ? 1 : 0; |
| chanb->num_subbuf = num_subbuf; |
| strlcpy(chanb->name, name, NAME_MAX); |
| - chanb->config = config; |
| + memcpy(&chanb->config, config, sizeof(chanb->config)); |
| |
| if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { |
| if (!zalloc_cpumask_var(&chanb->cpumask, GFP_KERNEL)) |
| @@ -421,7 +433,7 @@ free_cpumask: |
| */ |
| void channel_backend_unregister_notifiers(struct channel_backend *chanb) |
| { |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| |
| if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) |
| unregister_hotcpu_notifier(&chanb->cpu_hp_notifier); |
| @@ -435,7 +447,7 @@ void channel_backend_unregister_notifier |
| */ |
| void channel_backend_free(struct channel_backend *chanb) |
| { |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| unsigned int i; |
| |
| if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { |
| @@ -469,7 +481,7 @@ void _lib_ring_buffer_write(struct lib_r |
| const void *src, size_t len, ssize_t pagecpy) |
| { |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| size_t sbidx, index; |
| struct lib_ring_buffer_backend_pages *rpages; |
| unsigned long sb_bindex, id; |
| @@ -515,7 +527,7 @@ void _lib_ring_buffer_memset(struct lib_ |
| int c, size_t len, ssize_t pagecpy) |
| { |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| size_t sbidx, index; |
| struct lib_ring_buffer_backend_pages *rpages; |
| unsigned long sb_bindex, id; |
| @@ -564,7 +576,7 @@ void _lib_ring_buffer_copy_from_user(str |
| ssize_t pagecpy) |
| { |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| size_t sbidx, index; |
| struct lib_ring_buffer_backend_pages *rpages; |
| unsigned long sb_bindex, id; |
| @@ -616,7 +628,7 @@ size_t lib_ring_buffer_read(struct lib_r |
| void *dest, size_t len) |
| { |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| size_t index; |
| ssize_t pagecpy, orig_len; |
| struct lib_ring_buffer_backend_pages *rpages; |
| @@ -668,7 +680,7 @@ int __lib_ring_buffer_copy_to_user(struc |
| size_t offset, void __user *dest, size_t len) |
| { |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| size_t index; |
| ssize_t pagecpy; |
| struct lib_ring_buffer_backend_pages *rpages; |
| @@ -719,7 +731,7 @@ int lib_ring_buffer_read_cstr(struct lib |
| void *dest, size_t len) |
| { |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| size_t index; |
| ssize_t pagecpy, pagelen, strpagelen, orig_offset; |
| char *str; |
| @@ -777,7 +789,7 @@ struct page **lib_ring_buffer_read_get_p |
| size_t index; |
| struct lib_ring_buffer_backend_pages *rpages; |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| unsigned long sb_bindex, id; |
| |
| offset &= chanb->buf_size - 1; |
| @@ -808,7 +820,7 @@ void *lib_ring_buffer_read_offset_addres |
| size_t index; |
| struct lib_ring_buffer_backend_pages *rpages; |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| unsigned long sb_bindex, id; |
| |
| offset &= chanb->buf_size - 1; |
| @@ -838,7 +850,7 @@ void *lib_ring_buffer_offset_address(str |
| size_t sbidx, index; |
| struct lib_ring_buffer_backend_pages *rpages; |
| struct channel_backend *chanb = &bufb->chan->backend; |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| unsigned long sb_bindex, id; |
| |
| offset &= chanb->buf_size - 1; |
| --- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c |
| +++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c |
| @@ -1,7 +1,22 @@ |
| /* |
| * ring_buffer_frontend.c |
| * |
| - * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * |
| * Ring buffer wait-free buffer synchronization. Producer-consumer and flight |
| * recorder (overwrite) modes. See thesis: |
| @@ -34,8 +49,6 @@ |
| * - splice one subbuffer worth of data to a pipe |
| * - splice the data from pipe to disk/network |
| * - put_subbuf |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include <linux/delay.h> |
| @@ -103,7 +116,7 @@ void lib_ring_buffer_free(struct lib_rin |
| void lib_ring_buffer_reset(struct lib_ring_buffer *buf) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned int i; |
| |
| /* |
| @@ -161,7 +174,7 @@ EXPORT_SYMBOL_GPL(channel_reset); |
| int lib_ring_buffer_create(struct lib_ring_buffer *buf, |
| struct channel_backend *chanb, int cpu) |
| { |
| - const struct lib_ring_buffer_config *config = chanb->config; |
| + const struct lib_ring_buffer_config *config = &chanb->config; |
| struct channel *chan = container_of(chanb, struct channel, backend); |
| void *priv = chanb->priv; |
| size_t subbuf_header_size; |
| @@ -253,7 +266,7 @@ static void switch_buffer_timer(unsigned |
| { |
| struct lib_ring_buffer *buf = (struct lib_ring_buffer *)data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| /* |
| * Only flush buffers periodically if readers are active. |
| @@ -275,7 +288,7 @@ static void switch_buffer_timer(unsigned |
| static void lib_ring_buffer_start_switch_timer(struct lib_ring_buffer *buf) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (!chan->switch_timer_interval || buf->switch_timer_enabled) |
| return; |
| @@ -311,7 +324,7 @@ static void read_buffer_timer(unsigned l |
| { |
| struct lib_ring_buffer *buf = (struct lib_ring_buffer *)data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| CHAN_WARN_ON(chan, !buf->backend.allocated); |
| |
| @@ -335,7 +348,7 @@ static void read_buffer_timer(unsigned l |
| static void lib_ring_buffer_start_read_timer(struct lib_ring_buffer *buf) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (config->wakeup != RING_BUFFER_WAKEUP_BY_TIMER |
| || !chan->read_timer_interval |
| @@ -360,7 +373,7 @@ static void lib_ring_buffer_start_read_t |
| static void lib_ring_buffer_stop_read_timer(struct lib_ring_buffer *buf) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (config->wakeup != RING_BUFFER_WAKEUP_BY_TIMER |
| || !chan->read_timer_interval |
| @@ -397,7 +410,7 @@ int __cpuinit lib_ring_buffer_cpu_hp_cal |
| struct channel *chan = container_of(nb, struct channel, |
| cpu_hp_notifier); |
| struct lib_ring_buffer *buf = per_cpu_ptr(chan->backend.buf, cpu); |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (!chan->cpu_hp_enable) |
| return NOTIFY_DONE; |
| @@ -452,7 +465,7 @@ static int notrace ring_buffer_tick_nohz |
| { |
| struct channel *chan = container_of(nb, struct channel, |
| tick_nohz_notifier); |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer *buf; |
| int cpu = smp_processor_id(); |
| |
| @@ -524,7 +537,7 @@ void notrace lib_ring_buffer_tick_nohz_r |
| */ |
| static void channel_unregister_notifiers(struct channel *chan) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| int cpu; |
| |
| channel_iterator_unregister_notifiers(chan); |
| @@ -708,7 +721,7 @@ void channel_release(struct kref *kref) |
| void *channel_destroy(struct channel *chan) |
| { |
| int cpu; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| void *priv; |
| |
| channel_unregister_notifiers(chan); |
| @@ -818,7 +831,7 @@ int lib_ring_buffer_snapshot(struct lib_ |
| unsigned long *consumed, unsigned long *produced) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long consumed_cur, write_offset; |
| int finalized; |
| |
| @@ -909,7 +922,7 @@ int lib_ring_buffer_get_subbuf(struct li |
| unsigned long consumed) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long consumed_cur, consumed_idx, commit_count, write_offset; |
| int ret; |
| int finalized; |
| @@ -1055,7 +1068,7 @@ void lib_ring_buffer_put_subbuf(struct l |
| { |
| struct lib_ring_buffer_backend *bufb = &buf->backend; |
| struct channel *chan = bufb->chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long read_sb_bindex, consumed_idx, consumed; |
| |
| CHAN_WARN_ON(chan, atomic_long_read(&buf->active_readers) != 1); |
| @@ -1114,7 +1127,7 @@ void lib_ring_buffer_print_subbuffer_err |
| unsigned long cons_offset, |
| int cpu) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long cons_idx, commit_count, commit_count_sb; |
| |
| cons_idx = subbuf_index(cons_offset, chan); |
| @@ -1140,7 +1153,7 @@ void lib_ring_buffer_print_buffer_errors |
| struct channel *chan, |
| void *priv, int cpu) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long write_offset, cons_offset; |
| |
| /* |
| @@ -1170,27 +1183,34 @@ static |
| void lib_ring_buffer_print_errors(struct channel *chan, |
| struct lib_ring_buffer *buf, int cpu) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| void *priv = chan->backend.priv; |
| |
| - printk(KERN_DEBUG "ring buffer %s, cpu %d: %lu records written, " |
| - "%lu records overrun\n", |
| - chan->backend.name, cpu, |
| - v_read(config, &buf->records_count), |
| - v_read(config, &buf->records_overrun)); |
| - |
| - if (v_read(config, &buf->records_lost_full) |
| - || v_read(config, &buf->records_lost_wrap) |
| - || v_read(config, &buf->records_lost_big)) |
| - printk(KERN_WARNING |
| - "ring buffer %s, cpu %d: records were lost. Caused by:\n" |
| - " [ %lu buffer full, %lu nest buffer wrap-around, " |
| - "%lu event too big ]\n", |
| - chan->backend.name, cpu, |
| - v_read(config, &buf->records_lost_full), |
| - v_read(config, &buf->records_lost_wrap), |
| - v_read(config, &buf->records_lost_big)); |
| - |
| + if (!strcmp(chan->backend.name, "relay-metadata")) { |
| + printk(KERN_DEBUG "ring buffer %s: %lu records written, " |
| + "%lu records overrun\n", |
| + chan->backend.name, |
| + v_read(config, &buf->records_count), |
| + v_read(config, &buf->records_overrun)); |
| + } else { |
| + printk(KERN_DEBUG "ring buffer %s, cpu %d: %lu records written, " |
| + "%lu records overrun\n", |
| + chan->backend.name, cpu, |
| + v_read(config, &buf->records_count), |
| + v_read(config, &buf->records_overrun)); |
| + |
| + if (v_read(config, &buf->records_lost_full) |
| + || v_read(config, &buf->records_lost_wrap) |
| + || v_read(config, &buf->records_lost_big)) |
| + printk(KERN_WARNING |
| + "ring buffer %s, cpu %d: records were lost. Caused by:\n" |
| + " [ %lu buffer full, %lu nest buffer wrap-around, " |
| + "%lu event too big ]\n", |
| + chan->backend.name, cpu, |
| + v_read(config, &buf->records_lost_full), |
| + v_read(config, &buf->records_lost_wrap), |
| + v_read(config, &buf->records_lost_big)); |
| + } |
| lib_ring_buffer_print_buffer_errors(buf, chan, priv, cpu); |
| } |
| |
| @@ -1205,7 +1225,7 @@ void lib_ring_buffer_switch_old_start(st |
| struct switch_offsets *offsets, |
| u64 tsc) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long oldidx = subbuf_index(offsets->old, chan); |
| unsigned long commit_count; |
| |
| @@ -1249,7 +1269,7 @@ void lib_ring_buffer_switch_old_end(stru |
| struct switch_offsets *offsets, |
| u64 tsc) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long oldidx = subbuf_index(offsets->old - 1, chan); |
| unsigned long commit_count, padding_size, data_size; |
| |
| @@ -1292,7 +1312,7 @@ void lib_ring_buffer_switch_new_start(st |
| struct switch_offsets *offsets, |
| u64 tsc) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long beginidx = subbuf_index(offsets->begin, chan); |
| unsigned long commit_count; |
| |
| @@ -1334,7 +1354,7 @@ void lib_ring_buffer_switch_new_end(stru |
| struct switch_offsets *offsets, |
| u64 tsc) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long endidx = subbuf_index(offsets->end - 1, chan); |
| unsigned long commit_count, padding_size, data_size; |
| |
| @@ -1376,7 +1396,7 @@ int lib_ring_buffer_try_switch_slow(enum |
| struct switch_offsets *offsets, |
| u64 *tsc) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long off; |
| |
| offsets->begin = v_read(config, &buf->offset); |
| @@ -1435,7 +1455,7 @@ int lib_ring_buffer_try_switch_slow(enum |
| void lib_ring_buffer_switch_slow(struct lib_ring_buffer *buf, enum switch_mode mode) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct switch_offsets offsets; |
| unsigned long oldidx; |
| u64 tsc; |
| @@ -1496,7 +1516,7 @@ int lib_ring_buffer_try_reserve_slow(str |
| struct switch_offsets *offsets, |
| struct lib_ring_buffer_ctx *ctx) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long reserve_commit_diff; |
| |
| offsets->begin = v_read(config, &buf->offset); |
| @@ -1631,7 +1651,7 @@ int lib_ring_buffer_try_reserve_slow(str |
| int lib_ring_buffer_reserve_slow(struct lib_ring_buffer_ctx *ctx) |
| { |
| struct channel *chan = ctx->chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer *buf; |
| struct switch_offsets offsets; |
| int ret; |
| --- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_iterator.c |
| +++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_iterator.c |
| @@ -1,16 +1,28 @@ |
| /* |
| * ring_buffer_iterator.c |
| * |
| - * (C) Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * Ring buffer and channel iterators. Get each event of a channel in order. Uses |
| * a prio heap for per-cpu buffers, giving a O(log(NR_CPUS)) algorithmic |
| * complexity for the "get next event" operation. |
| * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * Author: |
| * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include "../../wrapper/ringbuffer/iterator.h" |
| @@ -40,7 +52,7 @@ |
| ssize_t lib_ring_buffer_get_next_record(struct channel *chan, |
| struct lib_ring_buffer *buf) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer_iter *iter = &buf->iter; |
| int ret; |
| |
| @@ -225,7 +237,7 @@ void lib_ring_buffer_wait_for_qs(const s |
| ssize_t channel_get_next_record(struct channel *chan, |
| struct lib_ring_buffer **ret_buf) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer *buf; |
| struct lttng_ptr_heap *heap; |
| ssize_t len; |
| @@ -333,7 +345,7 @@ void lib_ring_buffer_iterator_init(struc |
| } |
| |
| /* Add to list of buffers without any current record */ |
| - if (chan->backend.config->alloc == RING_BUFFER_ALLOC_PER_CPU) |
| + if (chan->backend.config.alloc == RING_BUFFER_ALLOC_PER_CPU) |
| list_add(&buf->iter.empty_node, &chan->iter.empty_head); |
| } |
| |
| @@ -347,7 +359,7 @@ int __cpuinit channel_iterator_cpu_hotpl |
| struct channel *chan = container_of(nb, struct channel, |
| hp_iter_notifier); |
| struct lib_ring_buffer *buf = per_cpu_ptr(chan->backend.buf, cpu); |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (!chan->hp_iter_enable) |
| return NOTIFY_DONE; |
| @@ -369,7 +381,7 @@ int __cpuinit channel_iterator_cpu_hotpl |
| |
| int channel_iterator_init(struct channel *chan) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer *buf; |
| |
| if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { |
| @@ -413,7 +425,7 @@ int channel_iterator_init(struct channel |
| |
| void channel_iterator_unregister_notifiers(struct channel *chan) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { |
| chan->hp_iter_enable = 0; |
| @@ -423,7 +435,7 @@ void channel_iterator_unregister_notifie |
| |
| void channel_iterator_free(struct channel *chan) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) |
| lttng_heap_free(&chan->iter.heap); |
| @@ -432,7 +444,7 @@ void channel_iterator_free(struct channe |
| int lib_ring_buffer_iterator_open(struct lib_ring_buffer *buf) |
| { |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| CHAN_WARN_ON(chan, config->output != RING_BUFFER_ITERATOR); |
| return lib_ring_buffer_open_read(buf); |
| } |
| @@ -451,7 +463,7 @@ EXPORT_SYMBOL_GPL(lib_ring_buffer_iterat |
| |
| int channel_iterator_open(struct channel *chan) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer *buf; |
| int ret = 0, cpu; |
| |
| @@ -484,7 +496,7 @@ EXPORT_SYMBOL_GPL(channel_iterator_open) |
| |
| void channel_iterator_release(struct channel *chan) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer *buf; |
| int cpu; |
| |
| @@ -527,7 +539,7 @@ void lib_ring_buffer_iterator_reset(stru |
| |
| void channel_iterator_reset(struct channel *chan) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| struct lib_ring_buffer *buf; |
| int cpu; |
| |
| @@ -558,7 +570,7 @@ ssize_t channel_ring_buffer_file_read(st |
| struct lib_ring_buffer *buf, |
| int fusionmerge) |
| { |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| size_t read_count = 0, read_offset; |
| ssize_t len; |
| |
| @@ -706,7 +718,7 @@ ssize_t channel_file_read(struct file *f |
| { |
| struct inode *inode = filp->f_dentry->d_inode; |
| struct channel *chan = inode->i_private; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) |
| return channel_ring_buffer_file_read(filp, user_buf, count, |
| --- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c |
| +++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c |
| @@ -3,11 +3,23 @@ |
| * |
| * Copyright (C) 2002-2005 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp |
| * Copyright (C) 1999-2005 - Karim Yaghmour <karim@opersys.com> |
| - * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2008-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Re-using content from kernel/relay.c. |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License as published by |
| + * the Free Software Foundation; only version 2 of the License. |
| * |
| - * This file is released under the GPL v2. |
| + * This program is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| + * GNU General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU General Public License along |
| + * with this program; if not, write to the Free Software Foundation, Inc., |
| + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| + * |
| + * Re-using code from kernel/relay.c, hence the GPLv2 license for this |
| + * file. |
| */ |
| |
| #include <linux/module.h> |
| @@ -24,12 +36,16 @@ static int lib_ring_buffer_fault(struct |
| { |
| struct lib_ring_buffer *buf = vma->vm_private_data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| pgoff_t pgoff = vmf->pgoff; |
| struct page **page; |
| void **virt; |
| unsigned long offset, sb_bindex; |
| |
| + |
| + if (!buf) |
| + return VM_FAULT_OOM; |
| + |
| /* |
| * Verify that faults are only done on the range of pages owned by the |
| * reader. |
| @@ -74,12 +90,15 @@ static int lib_ring_buffer_mmap_buf(stru |
| { |
| unsigned long length = vma->vm_end - vma->vm_start; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned long mmap_buf_len; |
| |
| if (config->output != RING_BUFFER_MMAP) |
| return -EINVAL; |
| |
| + if (!buf) |
| + return -EBADF; |
| + |
| mmap_buf_len = chan->backend.buf_size; |
| if (chan->backend.extra_reader_sb) |
| mmap_buf_len += chan->backend.subbuf_size; |
| --- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_splice.c |
| +++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_splice.c |
| @@ -3,11 +3,24 @@ |
| * |
| * Copyright (C) 2002-2005 - Tom Zanussi <zanussi@us.ibm.com>, IBM Corp |
| * Copyright (C) 1999-2005 - Karim Yaghmour <karim@opersys.com> |
| - * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2008-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Re-using content from kernel/relay.c. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| * |
| - * This file is released under the GPL v2. |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| + * Re-using code from kernel/relay.c, which is why it is licensed under |
| + * the GPLv2. |
| */ |
| |
| #include <linux/module.h> |
| @@ -69,7 +82,7 @@ static int subbuf_splice_actor(struct fi |
| { |
| struct lib_ring_buffer *buf = in->private_data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| unsigned int poff, subbuf_pages, nr_pages; |
| struct page *pages[PIPE_DEF_BUFFERS]; |
| struct partial_page partial[PIPE_DEF_BUFFERS]; |
| @@ -151,7 +164,7 @@ ssize_t lib_ring_buffer_splice_read(stru |
| { |
| struct lib_ring_buffer *buf = in->private_data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| ssize_t spliced; |
| int ret; |
| |
| --- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c |
| +++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c |
| @@ -1,11 +1,23 @@ |
| /* |
| * ring_buffer_vfs.c |
| * |
| - * Copyright (C) 2009-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * Ring Buffer VFS file operations. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| @@ -88,7 +100,7 @@ unsigned int lib_ring_buffer_poll(struct |
| unsigned int mask = 0; |
| struct lib_ring_buffer *buf = filp->private_data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| int finalized, disabled; |
| |
| if (filp->f_mode & FMODE_READ) { |
| @@ -165,7 +177,7 @@ long lib_ring_buffer_ioctl(struct file * |
| { |
| struct lib_ring_buffer *buf = filp->private_data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (lib_ring_buffer_channel_is_disabled(chan)) |
| return -EIO; |
| @@ -262,7 +274,7 @@ long lib_ring_buffer_compat_ioctl(struct |
| { |
| struct lib_ring_buffer *buf = filp->private_data; |
| struct channel *chan = buf->backend.chan; |
| - const struct lib_ring_buffer_config *config = chan->backend.config; |
| + const struct lib_ring_buffer_config *config = &chan->backend.config; |
| |
| if (lib_ring_buffer_channel_is_disabled(chan)) |
| return -EIO; |
| --- a/drivers/staging/lttng/lib/ringbuffer/vatomic.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/vatomic.h |
| @@ -1,12 +1,24 @@ |
| -#ifndef _LINUX_RING_BUFFER_VATOMIC_H |
| -#define _LINUX_RING_BUFFER_VATOMIC_H |
| +#ifndef _LIB_RING_BUFFER_VATOMIC_H |
| +#define _LIB_RING_BUFFER_VATOMIC_H |
| |
| /* |
| - * linux/ringbuffer/vatomic.h |
| + * lib/ringbuffer/vatomic.h |
| * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <asm/atomic.h> |
| @@ -82,4 +94,4 @@ long v_cmpxchg(const struct lib_ring_buf |
| return atomic_long_cmpxchg(&v_a->a, old, _new); |
| } |
| |
| -#endif /* _LINUX_RING_BUFFER_VATOMIC_H */ |
| +#endif /* _LIB_RING_BUFFER_VATOMIC_H */ |
| --- a/drivers/staging/lttng/lib/ringbuffer/vfs.h |
| +++ b/drivers/staging/lttng/lib/ringbuffer/vfs.h |
| @@ -1,17 +1,29 @@ |
| -#ifndef _LINUX_RING_BUFFER_VFS_H |
| -#define _LINUX_RING_BUFFER_VFS_H |
| +#ifndef _LIB_RING_BUFFER_VFS_H |
| +#define _LIB_RING_BUFFER_VFS_H |
| |
| /* |
| - * linux/ringbuffer/vfs.h |
| - * |
| - * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lib/ringbuffer/vfs.h |
| * |
| * Wait-free ring buffer VFS file operations. |
| * |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| * Author: |
| * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| */ |
| |
| #include <linux/fs.h> |
| @@ -86,4 +98,4 @@ long lib_ring_buffer_compat_ioctl(struct |
| /* flush the current sub-buffer */ |
| #define RING_BUFFER_FLUSH _IO(0xF6, 0x0C) |
| |
| -#endif /* _LINUX_RING_BUFFER_VFS_H */ |
| +#endif /* _LIB_RING_BUFFER_VFS_H */ |
| --- a/drivers/staging/lttng/ltt-context.c |
| +++ /dev/null |
| @@ -1,93 +0,0 @@ |
| -/* |
| - * ltt-context.c |
| - * |
| - * Copyright 2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng trace/channel/event context management. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include <linux/list.h> |
| -#include <linux/mutex.h> |
| -#include <linux/slab.h> |
| -#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| -#include "ltt-events.h" |
| -#include "ltt-tracer.h" |
| - |
| -int lttng_find_context(struct lttng_ctx *ctx, const char *name) |
| -{ |
| - unsigned int i; |
| - |
| - for (i = 0; i < ctx->nr_fields; i++) { |
| - /* Skip allocated (but non-initialized) contexts */ |
| - if (!ctx->fields[i].event_field.name) |
| - continue; |
| - if (!strcmp(ctx->fields[i].event_field.name, name)) |
| - return 1; |
| - } |
| - return 0; |
| -} |
| -EXPORT_SYMBOL_GPL(lttng_find_context); |
| - |
| -/* |
| - * Note: as we append context information, the pointer location may change. |
| - */ |
| -struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p) |
| -{ |
| - struct lttng_ctx_field *field; |
| - struct lttng_ctx *ctx; |
| - |
| - if (!*ctx_p) { |
| - *ctx_p = kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL); |
| - if (!*ctx_p) |
| - return NULL; |
| - } |
| - ctx = *ctx_p; |
| - if (ctx->nr_fields + 1 > ctx->allocated_fields) { |
| - struct lttng_ctx_field *new_fields; |
| - |
| - ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields); |
| - new_fields = kzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL); |
| - if (!new_fields) |
| - return NULL; |
| - if (ctx->fields) |
| - memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields); |
| - kfree(ctx->fields); |
| - ctx->fields = new_fields; |
| - } |
| - field = &ctx->fields[ctx->nr_fields]; |
| - ctx->nr_fields++; |
| - return field; |
| -} |
| -EXPORT_SYMBOL_GPL(lttng_append_context); |
| - |
| -/* |
| - * Remove last context field. |
| - */ |
| -void lttng_remove_context_field(struct lttng_ctx **ctx_p, |
| - struct lttng_ctx_field *field) |
| -{ |
| - struct lttng_ctx *ctx; |
| - |
| - ctx = *ctx_p; |
| - ctx->nr_fields--; |
| - WARN_ON_ONCE(&ctx->fields[ctx->nr_fields] != field); |
| - memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field)); |
| -} |
| -EXPORT_SYMBOL_GPL(lttng_remove_context_field); |
| - |
| -void lttng_destroy_context(struct lttng_ctx *ctx) |
| -{ |
| - int i; |
| - |
| - if (!ctx) |
| - return; |
| - for (i = 0; i < ctx->nr_fields; i++) { |
| - if (ctx->fields[i].destroy) |
| - ctx->fields[i].destroy(&ctx->fields[i]); |
| - } |
| - kfree(ctx->fields); |
| - kfree(ctx); |
| -} |
| --- a/drivers/staging/lttng/ltt-debugfs-abi.c |
| +++ /dev/null |
| @@ -1,777 +0,0 @@ |
| -/* |
| - * ltt-debugfs-abi.c |
| - * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng debugfs ABI |
| - * |
| - * Mimic system calls for: |
| - * - session creation, returns a file descriptor or failure. |
| - * - channel creation, returns a file descriptor or failure. |
| - * - Operates on a session file descriptor |
| - * - Takes all channel options as parameters. |
| - * - stream get, returns a file descriptor or failure. |
| - * - Operates on a channel file descriptor. |
| - * - stream notifier get, returns a file descriptor or failure. |
| - * - Operates on a channel file descriptor. |
| - * - event creation, returns a file descriptor or failure. |
| - * - Operates on a channel file descriptor |
| - * - Takes an event name as parameter |
| - * - Takes an instrumentation source as parameter |
| - * - e.g. tracepoints, dynamic_probes... |
| - * - Takes instrumentation source specific arguments. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include <linux/debugfs.h> |
| -#include <linux/proc_fs.h> |
| -#include <linux/anon_inodes.h> |
| -#include <linux/file.h> |
| -#include <linux/uaccess.h> |
| -#include <linux/slab.h> |
| -#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| -#include "wrapper/ringbuffer/vfs.h" |
| -#include "wrapper/poll.h" |
| -#include "ltt-debugfs-abi.h" |
| -#include "ltt-events.h" |
| -#include "ltt-tracer.h" |
| - |
| -/* |
| - * This is LTTng's own personal way to create a system call as an external |
| - * module. We use ioctl() on /sys/kernel/debug/lttng. |
| - */ |
| - |
| -static struct dentry *lttng_dentry; |
| -static struct proc_dir_entry *lttng_proc_dentry; |
| -static const struct file_operations lttng_fops; |
| -static const struct file_operations lttng_session_fops; |
| -static const struct file_operations lttng_channel_fops; |
| -static const struct file_operations lttng_metadata_fops; |
| -static const struct file_operations lttng_event_fops; |
| - |
| -/* |
| - * Teardown management: opened file descriptors keep a refcount on the module, |
| - * so it can only exit when all file descriptors are closed. |
| - */ |
| - |
| -enum channel_type { |
| - PER_CPU_CHANNEL, |
| - METADATA_CHANNEL, |
| -}; |
| - |
| -static |
| -int lttng_abi_create_session(void) |
| -{ |
| - struct ltt_session *session; |
| - struct file *session_file; |
| - int session_fd, ret; |
| - |
| - session = ltt_session_create(); |
| - if (!session) |
| - return -ENOMEM; |
| - session_fd = get_unused_fd(); |
| - if (session_fd < 0) { |
| - ret = session_fd; |
| - goto fd_error; |
| - } |
| - session_file = anon_inode_getfile("[lttng_session]", |
| - <tng_session_fops, |
| - session, O_RDWR); |
| - if (IS_ERR(session_file)) { |
| - ret = PTR_ERR(session_file); |
| - goto file_error; |
| - } |
| - session->file = session_file; |
| - fd_install(session_fd, session_file); |
| - return session_fd; |
| - |
| -file_error: |
| - put_unused_fd(session_fd); |
| -fd_error: |
| - ltt_session_destroy(session); |
| - return ret; |
| -} |
| - |
| -static |
| -int lttng_abi_tracepoint_list(void) |
| -{ |
| - struct file *tracepoint_list_file; |
| - int file_fd, ret; |
| - |
| - file_fd = get_unused_fd(); |
| - if (file_fd < 0) { |
| - ret = file_fd; |
| - goto fd_error; |
| - } |
| - |
| - tracepoint_list_file = anon_inode_getfile("[lttng_session]", |
| - <tng_tracepoint_list_fops, |
| - NULL, O_RDWR); |
| - if (IS_ERR(tracepoint_list_file)) { |
| - ret = PTR_ERR(tracepoint_list_file); |
| - goto file_error; |
| - } |
| - ret = lttng_tracepoint_list_fops.open(NULL, tracepoint_list_file); |
| - if (ret < 0) |
| - goto open_error; |
| - fd_install(file_fd, tracepoint_list_file); |
| - if (file_fd < 0) { |
| - ret = file_fd; |
| - goto fd_error; |
| - } |
| - return file_fd; |
| - |
| -open_error: |
| - fput(tracepoint_list_file); |
| -file_error: |
| - put_unused_fd(file_fd); |
| -fd_error: |
| - return ret; |
| -} |
| - |
| -static |
| -long lttng_abi_tracer_version(struct file *file, |
| - struct lttng_kernel_tracer_version __user *uversion_param) |
| -{ |
| - struct lttng_kernel_tracer_version v; |
| - |
| - v.version = LTTNG_VERSION; |
| - v.patchlevel = LTTNG_PATCHLEVEL; |
| - v.sublevel = LTTNG_SUBLEVEL; |
| - |
| - if (copy_to_user(uversion_param, &v, sizeof(v))) |
| - return -EFAULT; |
| - return 0; |
| -} |
| - |
| -static |
| -long lttng_abi_add_context(struct file *file, |
| - struct lttng_kernel_context __user *ucontext_param, |
| - struct lttng_ctx **ctx, struct ltt_session *session) |
| -{ |
| - struct lttng_kernel_context context_param; |
| - |
| - if (session->been_active) |
| - return -EPERM; |
| - |
| - if (copy_from_user(&context_param, ucontext_param, sizeof(context_param))) |
| - return -EFAULT; |
| - |
| - switch (context_param.ctx) { |
| - case LTTNG_KERNEL_CONTEXT_PID: |
| - return lttng_add_pid_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_PRIO: |
| - return lttng_add_prio_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_NICE: |
| - return lttng_add_nice_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_VPID: |
| - return lttng_add_vpid_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_TID: |
| - return lttng_add_tid_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_VTID: |
| - return lttng_add_vtid_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_PPID: |
| - return lttng_add_ppid_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_VPPID: |
| - return lttng_add_vppid_to_ctx(ctx); |
| - case LTTNG_KERNEL_CONTEXT_PERF_COUNTER: |
| - context_param.u.perf_counter.name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| - return lttng_add_perf_counter_to_ctx(context_param.u.perf_counter.type, |
| - context_param.u.perf_counter.config, |
| - context_param.u.perf_counter.name, |
| - ctx); |
| - case LTTNG_KERNEL_CONTEXT_PROCNAME: |
| - return lttng_add_procname_to_ctx(ctx); |
| - default: |
| - return -EINVAL; |
| - } |
| -} |
| - |
| -/** |
| - * lttng_ioctl - lttng syscall through ioctl |
| - * |
| - * @file: the file |
| - * @cmd: the command |
| - * @arg: command arg |
| - * |
| - * This ioctl implements lttng commands: |
| - * LTTNG_KERNEL_SESSION |
| - * Returns a LTTng trace session file descriptor |
| - * LTTNG_KERNEL_TRACER_VERSION |
| - * Returns the LTTng kernel tracer version |
| - * LTTNG_KERNEL_TRACEPOINT_LIST |
| - * Returns a file descriptor listing available tracepoints |
| - * LTTNG_KERNEL_WAIT_QUIESCENT |
| - * Returns after all previously running probes have completed |
| - * |
| - * The returned session will be deleted when its file descriptor is closed. |
| - */ |
| -static |
| -long lttng_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| -{ |
| - switch (cmd) { |
| - case LTTNG_KERNEL_SESSION: |
| - return lttng_abi_create_session(); |
| - case LTTNG_KERNEL_TRACER_VERSION: |
| - return lttng_abi_tracer_version(file, |
| - (struct lttng_kernel_tracer_version __user *) arg); |
| - case LTTNG_KERNEL_TRACEPOINT_LIST: |
| - return lttng_abi_tracepoint_list(); |
| - case LTTNG_KERNEL_WAIT_QUIESCENT: |
| - synchronize_trace(); |
| - return 0; |
| - case LTTNG_KERNEL_CALIBRATE: |
| - { |
| - struct lttng_kernel_calibrate __user *ucalibrate = |
| - (struct lttng_kernel_calibrate __user *) arg; |
| - struct lttng_kernel_calibrate calibrate; |
| - int ret; |
| - |
| - if (copy_from_user(&calibrate, ucalibrate, sizeof(calibrate))) |
| - return -EFAULT; |
| - ret = lttng_calibrate(&calibrate); |
| - if (copy_to_user(ucalibrate, &calibrate, sizeof(calibrate))) |
| - return -EFAULT; |
| - return ret; |
| - } |
| - default: |
| - return -ENOIOCTLCMD; |
| - } |
| -} |
| - |
| -static const struct file_operations lttng_fops = { |
| - .owner = THIS_MODULE, |
| - .unlocked_ioctl = lttng_ioctl, |
| -#ifdef CONFIG_COMPAT |
| - .compat_ioctl = lttng_ioctl, |
| -#endif |
| -}; |
| - |
| -/* |
| - * We tolerate no failure in this function (if one happens, we print a dmesg |
| - * error, but cannot return any error, because the channel information is |
| - * invariant. |
| - */ |
| -static |
| -void lttng_metadata_create_events(struct file *channel_file) |
| -{ |
| - struct ltt_channel *channel = channel_file->private_data; |
| - static struct lttng_kernel_event metadata_params = { |
| - .instrumentation = LTTNG_KERNEL_TRACEPOINT, |
| - .name = "lttng_metadata", |
| - }; |
| - struct ltt_event *event; |
| - |
| - /* |
| - * We tolerate no failure path after event creation. It will stay |
| - * invariant for the rest of the session. |
| - */ |
| - event = ltt_event_create(channel, &metadata_params, NULL, NULL); |
| - if (!event) { |
| - goto create_error; |
| - } |
| - return; |
| - |
| -create_error: |
| - WARN_ON(1); |
| - return; /* not allowed to return error */ |
| -} |
| - |
| -static |
| -int lttng_abi_create_channel(struct file *session_file, |
| - struct lttng_kernel_channel __user *uchan_param, |
| - enum channel_type channel_type) |
| -{ |
| - struct ltt_session *session = session_file->private_data; |
| - const struct file_operations *fops = NULL; |
| - const char *transport_name; |
| - struct ltt_channel *chan; |
| - struct file *chan_file; |
| - struct lttng_kernel_channel chan_param; |
| - int chan_fd; |
| - int ret = 0; |
| - |
| - if (copy_from_user(&chan_param, uchan_param, sizeof(chan_param))) |
| - return -EFAULT; |
| - chan_fd = get_unused_fd(); |
| - if (chan_fd < 0) { |
| - ret = chan_fd; |
| - goto fd_error; |
| - } |
| - switch (channel_type) { |
| - case PER_CPU_CHANNEL: |
| - fops = <tng_channel_fops; |
| - break; |
| - case METADATA_CHANNEL: |
| - fops = <tng_metadata_fops; |
| - break; |
| - } |
| - |
| - chan_file = anon_inode_getfile("[lttng_channel]", |
| - fops, |
| - NULL, O_RDWR); |
| - if (IS_ERR(chan_file)) { |
| - ret = PTR_ERR(chan_file); |
| - goto file_error; |
| - } |
| - switch (channel_type) { |
| - case PER_CPU_CHANNEL: |
| - if (chan_param.output == LTTNG_KERNEL_SPLICE) { |
| - transport_name = chan_param.overwrite ? |
| - "relay-overwrite" : "relay-discard"; |
| - } else if (chan_param.output == LTTNG_KERNEL_MMAP) { |
| - transport_name = chan_param.overwrite ? |
| - "relay-overwrite-mmap" : "relay-discard-mmap"; |
| - } else { |
| - return -EINVAL; |
| - } |
| - break; |
| - case METADATA_CHANNEL: |
| - if (chan_param.output == LTTNG_KERNEL_SPLICE) |
| - transport_name = "relay-metadata"; |
| - else if (chan_param.output == LTTNG_KERNEL_MMAP) |
| - transport_name = "relay-metadata-mmap"; |
| - else |
| - return -EINVAL; |
| - break; |
| - default: |
| - transport_name = "<unknown>"; |
| - break; |
| - } |
| - /* |
| - * We tolerate no failure path after channel creation. It will stay |
| - * invariant for the rest of the session. |
| - */ |
| - chan = ltt_channel_create(session, transport_name, NULL, |
| - chan_param.subbuf_size, |
| - chan_param.num_subbuf, |
| - chan_param.switch_timer_interval, |
| - chan_param.read_timer_interval); |
| - if (!chan) { |
| - ret = -EINVAL; |
| - goto chan_error; |
| - } |
| - chan->file = chan_file; |
| - chan_file->private_data = chan; |
| - fd_install(chan_fd, chan_file); |
| - if (channel_type == METADATA_CHANNEL) { |
| - session->metadata = chan; |
| - lttng_metadata_create_events(chan_file); |
| - } |
| - |
| - /* The channel created holds a reference on the session */ |
| - atomic_long_inc(&session_file->f_count); |
| - |
| - return chan_fd; |
| - |
| -chan_error: |
| - fput(chan_file); |
| -file_error: |
| - put_unused_fd(chan_fd); |
| -fd_error: |
| - return ret; |
| -} |
| - |
| -/** |
| - * lttng_session_ioctl - lttng session fd ioctl |
| - * |
| - * @file: the file |
| - * @cmd: the command |
| - * @arg: command arg |
| - * |
| - * This ioctl implements lttng commands: |
| - * LTTNG_KERNEL_CHANNEL |
| - * Returns a LTTng channel file descriptor |
| - * LTTNG_KERNEL_ENABLE |
| - * Enables tracing for a session (weak enable) |
| - * LTTNG_KERNEL_DISABLE |
| - * Disables tracing for a session (strong disable) |
| - * LTTNG_KERNEL_METADATA |
| - * Returns a LTTng metadata file descriptor |
| - * |
| - * The returned channel will be deleted when its file descriptor is closed. |
| - */ |
| -static |
| -long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| -{ |
| - struct ltt_session *session = file->private_data; |
| - |
| - switch (cmd) { |
| - case LTTNG_KERNEL_CHANNEL: |
| - return lttng_abi_create_channel(file, |
| - (struct lttng_kernel_channel __user *) arg, |
| - PER_CPU_CHANNEL); |
| - case LTTNG_KERNEL_SESSION_START: |
| - case LTTNG_KERNEL_ENABLE: |
| - return ltt_session_enable(session); |
| - case LTTNG_KERNEL_SESSION_STOP: |
| - case LTTNG_KERNEL_DISABLE: |
| - return ltt_session_disable(session); |
| - case LTTNG_KERNEL_METADATA: |
| - return lttng_abi_create_channel(file, |
| - (struct lttng_kernel_channel __user *) arg, |
| - METADATA_CHANNEL); |
| - default: |
| - return -ENOIOCTLCMD; |
| - } |
| -} |
| - |
| -/* |
| - * Called when the last file reference is dropped. |
| - * |
| - * Big fat note: channels and events are invariant for the whole session after |
| - * their creation. So this session destruction also destroys all channel and |
| - * event structures specific to this session (they are not destroyed when their |
| - * individual file is released). |
| - */ |
| -static |
| -int lttng_session_release(struct inode *inode, struct file *file) |
| -{ |
| - struct ltt_session *session = file->private_data; |
| - |
| - if (session) |
| - ltt_session_destroy(session); |
| - return 0; |
| -} |
| - |
| -static const struct file_operations lttng_session_fops = { |
| - .owner = THIS_MODULE, |
| - .release = lttng_session_release, |
| - .unlocked_ioctl = lttng_session_ioctl, |
| -#ifdef CONFIG_COMPAT |
| - .compat_ioctl = lttng_session_ioctl, |
| -#endif |
| -}; |
| - |
| -static |
| -int lttng_abi_open_stream(struct file *channel_file) |
| -{ |
| - struct ltt_channel *channel = channel_file->private_data; |
| - struct lib_ring_buffer *buf; |
| - int stream_fd, ret; |
| - struct file *stream_file; |
| - |
| - buf = channel->ops->buffer_read_open(channel->chan); |
| - if (!buf) |
| - return -ENOENT; |
| - |
| - stream_fd = get_unused_fd(); |
| - if (stream_fd < 0) { |
| - ret = stream_fd; |
| - goto fd_error; |
| - } |
| - stream_file = anon_inode_getfile("[lttng_stream]", |
| - &lib_ring_buffer_file_operations, |
| - buf, O_RDWR); |
| - if (IS_ERR(stream_file)) { |
| - ret = PTR_ERR(stream_file); |
| - goto file_error; |
| - } |
| - /* |
| - * OPEN_FMODE, called within anon_inode_getfile/alloc_file, don't honor |
| - * FMODE_LSEEK, FMODE_PREAD nor FMODE_PWRITE. We need to read from this |
| - * file descriptor, so we set FMODE_PREAD here. |
| - */ |
| - stream_file->f_mode |= FMODE_PREAD; |
| - fd_install(stream_fd, stream_file); |
| - /* |
| - * The stream holds a reference to the channel within the generic ring |
| - * buffer library, so no need to hold a refcount on the channel and |
| - * session files here. |
| - */ |
| - return stream_fd; |
| - |
| -file_error: |
| - put_unused_fd(stream_fd); |
| -fd_error: |
| - channel->ops->buffer_read_close(buf); |
| - return ret; |
| -} |
| - |
| -static |
| -int lttng_abi_create_event(struct file *channel_file, |
| - struct lttng_kernel_event __user *uevent_param) |
| -{ |
| - struct ltt_channel *channel = channel_file->private_data; |
| - struct ltt_event *event; |
| - struct lttng_kernel_event event_param; |
| - int event_fd, ret; |
| - struct file *event_file; |
| - |
| - if (copy_from_user(&event_param, uevent_param, sizeof(event_param))) |
| - return -EFAULT; |
| - event_param.name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| - switch (event_param.instrumentation) { |
| - case LTTNG_KERNEL_KRETPROBE: |
| - event_param.u.kretprobe.symbol_name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| - break; |
| - case LTTNG_KERNEL_KPROBE: |
| - event_param.u.kprobe.symbol_name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| - break; |
| - case LTTNG_KERNEL_FUNCTION: |
| - event_param.u.ftrace.symbol_name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| - break; |
| - default: |
| - break; |
| - } |
| - switch (event_param.instrumentation) { |
| - default: |
| - event_fd = get_unused_fd(); |
| - if (event_fd < 0) { |
| - ret = event_fd; |
| - goto fd_error; |
| - } |
| - event_file = anon_inode_getfile("[lttng_event]", |
| - <tng_event_fops, |
| - NULL, O_RDWR); |
| - if (IS_ERR(event_file)) { |
| - ret = PTR_ERR(event_file); |
| - goto file_error; |
| - } |
| - /* |
| - * We tolerate no failure path after event creation. It |
| - * will stay invariant for the rest of the session. |
| - */ |
| - event = ltt_event_create(channel, &event_param, NULL, NULL); |
| - if (!event) { |
| - ret = -EINVAL; |
| - goto event_error; |
| - } |
| - event_file->private_data = event; |
| - fd_install(event_fd, event_file); |
| - /* The event holds a reference on the channel */ |
| - atomic_long_inc(&channel_file->f_count); |
| - break; |
| - case LTTNG_KERNEL_SYSCALL: |
| - /* |
| - * Only all-syscall tracing supported for now. |
| - */ |
| - if (event_param.name[0] != '\0') |
| - return -EINVAL; |
| - ret = lttng_syscalls_register(channel, NULL); |
| - if (ret) |
| - goto fd_error; |
| - event_fd = 0; |
| - break; |
| - } |
| - return event_fd; |
| - |
| -event_error: |
| - fput(event_file); |
| -file_error: |
| - put_unused_fd(event_fd); |
| -fd_error: |
| - return ret; |
| -} |
| - |
| -/** |
| - * lttng_channel_ioctl - lttng syscall through ioctl |
| - * |
| - * @file: the file |
| - * @cmd: the command |
| - * @arg: command arg |
| - * |
| - * This ioctl implements lttng commands: |
| - * LTTNG_KERNEL_STREAM |
| - * Returns an event stream file descriptor or failure. |
| - * (typically, one event stream records events from one CPU) |
| - * LTTNG_KERNEL_EVENT |
| - * Returns an event file descriptor or failure. |
| - * LTTNG_KERNEL_CONTEXT |
| - * Prepend a context field to each event in the channel |
| - * LTTNG_KERNEL_ENABLE |
| - * Enable recording for events in this channel (weak enable) |
| - * LTTNG_KERNEL_DISABLE |
| - * Disable recording for events in this channel (strong disable) |
| - * |
| - * Channel and event file descriptors also hold a reference on the session. |
| - */ |
| -static |
| -long lttng_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| -{ |
| - struct ltt_channel *channel = file->private_data; |
| - |
| - switch (cmd) { |
| - case LTTNG_KERNEL_STREAM: |
| - return lttng_abi_open_stream(file); |
| - case LTTNG_KERNEL_EVENT: |
| - return lttng_abi_create_event(file, (struct lttng_kernel_event __user *) arg); |
| - case LTTNG_KERNEL_CONTEXT: |
| - return lttng_abi_add_context(file, |
| - (struct lttng_kernel_context __user *) arg, |
| - &channel->ctx, channel->session); |
| - case LTTNG_KERNEL_ENABLE: |
| - return ltt_channel_enable(channel); |
| - case LTTNG_KERNEL_DISABLE: |
| - return ltt_channel_disable(channel); |
| - default: |
| - return -ENOIOCTLCMD; |
| - } |
| -} |
| - |
| -/** |
| - * lttng_metadata_ioctl - lttng syscall through ioctl |
| - * |
| - * @file: the file |
| - * @cmd: the command |
| - * @arg: command arg |
| - * |
| - * This ioctl implements lttng commands: |
| - * LTTNG_KERNEL_STREAM |
| - * Returns an event stream file descriptor or failure. |
| - * |
| - * Channel and event file descriptors also hold a reference on the session. |
| - */ |
| -static |
| -long lttng_metadata_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| -{ |
| - switch (cmd) { |
| - case LTTNG_KERNEL_STREAM: |
| - return lttng_abi_open_stream(file); |
| - default: |
| - return -ENOIOCTLCMD; |
| - } |
| -} |
| - |
| -/** |
| - * lttng_channel_poll - lttng stream addition/removal monitoring |
| - * |
| - * @file: the file |
| - * @wait: poll table |
| - */ |
| -unsigned int lttng_channel_poll(struct file *file, poll_table *wait) |
| -{ |
| - struct ltt_channel *channel = file->private_data; |
| - unsigned int mask = 0; |
| - |
| - if (file->f_mode & FMODE_READ) { |
| - poll_wait_set_exclusive(wait); |
| - poll_wait(file, channel->ops->get_hp_wait_queue(channel->chan), |
| - wait); |
| - |
| - if (channel->ops->is_disabled(channel->chan)) |
| - return POLLERR; |
| - if (channel->ops->is_finalized(channel->chan)) |
| - return POLLHUP; |
| - if (channel->ops->buffer_has_read_closed_stream(channel->chan)) |
| - return POLLIN | POLLRDNORM; |
| - return 0; |
| - } |
| - return mask; |
| - |
| -} |
| - |
| -static |
| -int lttng_channel_release(struct inode *inode, struct file *file) |
| -{ |
| - struct ltt_channel *channel = file->private_data; |
| - |
| - if (channel) |
| - fput(channel->session->file); |
| - return 0; |
| -} |
| - |
| -static const struct file_operations lttng_channel_fops = { |
| - .owner = THIS_MODULE, |
| - .release = lttng_channel_release, |
| - .poll = lttng_channel_poll, |
| - .unlocked_ioctl = lttng_channel_ioctl, |
| -#ifdef CONFIG_COMPAT |
| - .compat_ioctl = lttng_channel_ioctl, |
| -#endif |
| -}; |
| - |
| -static const struct file_operations lttng_metadata_fops = { |
| - .owner = THIS_MODULE, |
| - .release = lttng_channel_release, |
| - .unlocked_ioctl = lttng_metadata_ioctl, |
| -#ifdef CONFIG_COMPAT |
| - .compat_ioctl = lttng_metadata_ioctl, |
| -#endif |
| -}; |
| - |
| -/** |
| - * lttng_event_ioctl - lttng syscall through ioctl |
| - * |
| - * @file: the file |
| - * @cmd: the command |
| - * @arg: command arg |
| - * |
| - * This ioctl implements lttng commands: |
| - * LTTNG_KERNEL_CONTEXT |
| - * Prepend a context field to each record of this event |
| - * LTTNG_KERNEL_ENABLE |
| - * Enable recording for this event (weak enable) |
| - * LTTNG_KERNEL_DISABLE |
| - * Disable recording for this event (strong disable) |
| - */ |
| -static |
| -long lttng_event_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| -{ |
| - struct ltt_event *event = file->private_data; |
| - |
| - switch (cmd) { |
| - case LTTNG_KERNEL_CONTEXT: |
| - return lttng_abi_add_context(file, |
| - (struct lttng_kernel_context __user *) arg, |
| - &event->ctx, event->chan->session); |
| - case LTTNG_KERNEL_ENABLE: |
| - return ltt_event_enable(event); |
| - case LTTNG_KERNEL_DISABLE: |
| - return ltt_event_disable(event); |
| - default: |
| - return -ENOIOCTLCMD; |
| - } |
| -} |
| - |
| -static |
| -int lttng_event_release(struct inode *inode, struct file *file) |
| -{ |
| - struct ltt_event *event = file->private_data; |
| - |
| - if (event) |
| - fput(event->chan->file); |
| - return 0; |
| -} |
| - |
| -/* TODO: filter control ioctl */ |
| -static const struct file_operations lttng_event_fops = { |
| - .owner = THIS_MODULE, |
| - .release = lttng_event_release, |
| - .unlocked_ioctl = lttng_event_ioctl, |
| -#ifdef CONFIG_COMPAT |
| - .compat_ioctl = lttng_event_ioctl, |
| -#endif |
| -}; |
| - |
| -int __init ltt_debugfs_abi_init(void) |
| -{ |
| - int ret = 0; |
| - |
| - wrapper_vmalloc_sync_all(); |
| - lttng_dentry = debugfs_create_file("lttng", S_IWUSR, NULL, NULL, |
| - <tng_fops); |
| - if (IS_ERR(lttng_dentry)) |
| - lttng_dentry = NULL; |
| - |
| - lttng_proc_dentry = proc_create_data("lttng", S_IWUSR, NULL, |
| - <tng_fops, NULL); |
| - |
| - if (!lttng_dentry && !lttng_proc_dentry) { |
| - printk(KERN_ERR "Error creating LTTng control file\n"); |
| - ret = -ENOMEM; |
| - goto error; |
| - } |
| -error: |
| - return ret; |
| -} |
| - |
| -void __exit ltt_debugfs_abi_exit(void) |
| -{ |
| - if (lttng_dentry) |
| - debugfs_remove(lttng_dentry); |
| - if (lttng_proc_dentry) |
| - remove_proc_entry("lttng", NULL); |
| -} |
| --- a/drivers/staging/lttng/ltt-debugfs-abi.h |
| +++ /dev/null |
| @@ -1,153 +0,0 @@ |
| -#ifndef _LTT_DEBUGFS_ABI_H |
| -#define _LTT_DEBUGFS_ABI_H |
| - |
| -/* |
| - * ltt-debugfs-abi.h |
| - * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng debugfs ABI header |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/fs.h> |
| - |
| -#define LTTNG_SYM_NAME_LEN 256 |
| - |
| -enum lttng_kernel_instrumentation { |
| - LTTNG_KERNEL_TRACEPOINT = 0, |
| - LTTNG_KERNEL_KPROBE = 1, |
| - LTTNG_KERNEL_FUNCTION = 2, |
| - LTTNG_KERNEL_KRETPROBE = 3, |
| - LTTNG_KERNEL_NOOP = 4, /* not hooked */ |
| - LTTNG_KERNEL_SYSCALL = 5, |
| -}; |
| - |
| -/* |
| - * LTTng consumer mode |
| - */ |
| -enum lttng_kernel_output { |
| - LTTNG_KERNEL_SPLICE = 0, |
| - LTTNG_KERNEL_MMAP = 1, |
| -}; |
| - |
| -/* |
| - * LTTng DebugFS ABI structures. |
| - */ |
| - |
| -struct lttng_kernel_channel { |
| - int overwrite; /* 1: overwrite, 0: discard */ |
| - uint64_t subbuf_size; /* in bytes */ |
| - uint64_t num_subbuf; |
| - unsigned int switch_timer_interval; /* usecs */ |
| - unsigned int read_timer_interval; /* usecs */ |
| - enum lttng_kernel_output output; /* splice, mmap */ |
| -}; |
| - |
| -struct lttng_kernel_kretprobe { |
| - uint64_t addr; |
| - |
| - uint64_t offset; |
| - char symbol_name[LTTNG_SYM_NAME_LEN]; |
| -}; |
| - |
| -/* |
| - * Either addr is used, or symbol_name and offset. |
| - */ |
| -struct lttng_kernel_kprobe { |
| - uint64_t addr; |
| - |
| - uint64_t offset; |
| - char symbol_name[LTTNG_SYM_NAME_LEN]; |
| -}; |
| - |
| -struct lttng_kernel_function_tracer { |
| - char symbol_name[LTTNG_SYM_NAME_LEN]; |
| -}; |
| - |
| -/* |
| - * For syscall tracing, name = '\0' means "enable all". |
| - */ |
| -struct lttng_kernel_event { |
| - char name[LTTNG_SYM_NAME_LEN]; /* event name */ |
| - enum lttng_kernel_instrumentation instrumentation; |
| - /* Per instrumentation type configuration */ |
| - union { |
| - struct lttng_kernel_kretprobe kretprobe; |
| - struct lttng_kernel_kprobe kprobe; |
| - struct lttng_kernel_function_tracer ftrace; |
| - } u; |
| -}; |
| - |
| -struct lttng_kernel_tracer_version { |
| - uint32_t version; |
| - uint32_t patchlevel; |
| - uint32_t sublevel; |
| -}; |
| - |
| -enum lttng_kernel_calibrate_type { |
| - LTTNG_KERNEL_CALIBRATE_KRETPROBE, |
| -}; |
| - |
| -struct lttng_kernel_calibrate { |
| - enum lttng_kernel_calibrate_type type; /* type (input) */ |
| -}; |
| - |
| -enum lttng_kernel_context_type { |
| - LTTNG_KERNEL_CONTEXT_PID = 0, |
| - LTTNG_KERNEL_CONTEXT_PERF_COUNTER = 1, |
| - LTTNG_KERNEL_CONTEXT_PROCNAME = 2, |
| - LTTNG_KERNEL_CONTEXT_PRIO = 3, |
| - LTTNG_KERNEL_CONTEXT_NICE = 4, |
| - LTTNG_KERNEL_CONTEXT_VPID = 5, |
| - LTTNG_KERNEL_CONTEXT_TID = 6, |
| - LTTNG_KERNEL_CONTEXT_VTID = 7, |
| - LTTNG_KERNEL_CONTEXT_PPID = 8, |
| - LTTNG_KERNEL_CONTEXT_VPPID = 9, |
| -}; |
| - |
| -struct lttng_kernel_perf_counter_ctx { |
| - uint32_t type; |
| - uint64_t config; |
| - char name[LTTNG_SYM_NAME_LEN]; |
| -}; |
| - |
| -struct lttng_kernel_context { |
| - enum lttng_kernel_context_type ctx; |
| - union { |
| - struct lttng_kernel_perf_counter_ctx perf_counter; |
| - } u; |
| -}; |
| - |
| -/* LTTng file descriptor ioctl */ |
| -#define LTTNG_KERNEL_SESSION _IO(0xF6, 0x40) |
| -#define LTTNG_KERNEL_TRACER_VERSION \ |
| - _IOR(0xF6, 0x41, struct lttng_kernel_tracer_version) |
| -#define LTTNG_KERNEL_TRACEPOINT_LIST _IO(0xF6, 0x42) |
| -#define LTTNG_KERNEL_WAIT_QUIESCENT _IO(0xF6, 0x43) |
| -#define LTTNG_KERNEL_CALIBRATE \ |
| - _IOWR(0xF6, 0x44, struct lttng_kernel_calibrate) |
| - |
| -/* Session FD ioctl */ |
| -#define LTTNG_KERNEL_METADATA \ |
| - _IOW(0xF6, 0x50, struct lttng_kernel_channel) |
| -#define LTTNG_KERNEL_CHANNEL \ |
| - _IOW(0xF6, 0x51, struct lttng_kernel_channel) |
| -#define LTTNG_KERNEL_SESSION_START _IO(0xF6, 0x52) |
| -#define LTTNG_KERNEL_SESSION_STOP _IO(0xF6, 0x53) |
| - |
| -/* Channel FD ioctl */ |
| -#define LTTNG_KERNEL_STREAM _IO(0xF6, 0x60) |
| -#define LTTNG_KERNEL_EVENT \ |
| - _IOW(0xF6, 0x61, struct lttng_kernel_event) |
| - |
| -/* Event and Channel FD ioctl */ |
| -#define LTTNG_KERNEL_CONTEXT \ |
| - _IOW(0xF6, 0x70, struct lttng_kernel_context) |
| - |
| -/* Event, Channel and Session ioctl */ |
| -#define LTTNG_KERNEL_ENABLE _IO(0xF6, 0x80) |
| -#define LTTNG_KERNEL_DISABLE _IO(0xF6, 0x81) |
| - |
| -#endif /* _LTT_DEBUGFS_ABI_H */ |
| --- a/drivers/staging/lttng/ltt-endian.h |
| +++ /dev/null |
| @@ -1,31 +0,0 @@ |
| -#ifndef _LTT_ENDIAN_H |
| -#define _LTT_ENDIAN_H |
| - |
| -/* |
| - * ltt-endian.h |
| - * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#ifdef __KERNEL__ |
| -# include <asm/byteorder.h> |
| -# ifdef __BIG_ENDIAN |
| -# define __BYTE_ORDER __BIG_ENDIAN |
| -# elif defined(__LITTLE_ENDIAN) |
| -# define __BYTE_ORDER __LITTLE_ENDIAN |
| -# else |
| -# error "unknown endianness" |
| -# endif |
| -#ifndef __BIG_ENDIAN |
| -# define __BIG_ENDIAN 4321 |
| -#endif |
| -#ifndef __LITTLE_ENDIAN |
| -# define __LITTLE_ENDIAN 1234 |
| -#endif |
| -#else |
| -# include <endian.h> |
| -#endif |
| - |
| -#endif /* _LTT_ENDIAN_H */ |
| --- a/drivers/staging/lttng/ltt-events.c |
| +++ /dev/null |
| @@ -1,1009 +0,0 @@ |
| -/* |
| - * ltt-events.c |
| - * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * Holds LTTng per-session event registry. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include <linux/list.h> |
| -#include <linux/mutex.h> |
| -#include <linux/sched.h> |
| -#include <linux/slab.h> |
| -#include <linux/jiffies.h> |
| -#include "wrapper/uuid.h" |
| -#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| -#include "ltt-events.h" |
| -#include "ltt-tracer.h" |
| - |
| -static LIST_HEAD(sessions); |
| -static LIST_HEAD(ltt_transport_list); |
| -static DEFINE_MUTEX(sessions_mutex); |
| -static struct kmem_cache *event_cache; |
| - |
| -static void _ltt_event_destroy(struct ltt_event *event); |
| -static void _ltt_channel_destroy(struct ltt_channel *chan); |
| -static int _ltt_event_unregister(struct ltt_event *event); |
| -static |
| -int _ltt_event_metadata_statedump(struct ltt_session *session, |
| - struct ltt_channel *chan, |
| - struct ltt_event *event); |
| -static |
| -int _ltt_session_metadata_statedump(struct ltt_session *session); |
| - |
| -void synchronize_trace(void) |
| -{ |
| - synchronize_sched(); |
| -#ifdef CONFIG_PREEMPT_RT |
| - synchronize_rcu(); |
| -#endif |
| -} |
| - |
| -struct ltt_session *ltt_session_create(void) |
| -{ |
| - struct ltt_session *session; |
| - |
| - mutex_lock(&sessions_mutex); |
| - session = kzalloc(sizeof(struct ltt_session), GFP_KERNEL); |
| - if (!session) |
| - return NULL; |
| - INIT_LIST_HEAD(&session->chan); |
| - INIT_LIST_HEAD(&session->events); |
| - uuid_le_gen(&session->uuid); |
| - list_add(&session->list, &sessions); |
| - mutex_unlock(&sessions_mutex); |
| - return session; |
| -} |
| - |
| -void ltt_session_destroy(struct ltt_session *session) |
| -{ |
| - struct ltt_channel *chan, *tmpchan; |
| - struct ltt_event *event, *tmpevent; |
| - int ret; |
| - |
| - mutex_lock(&sessions_mutex); |
| - ACCESS_ONCE(session->active) = 0; |
| - list_for_each_entry(chan, &session->chan, list) { |
| - ret = lttng_syscalls_unregister(chan); |
| - WARN_ON(ret); |
| - } |
| - list_for_each_entry(event, &session->events, list) { |
| - ret = _ltt_event_unregister(event); |
| - WARN_ON(ret); |
| - } |
| - synchronize_trace(); /* Wait for in-flight events to complete */ |
| - list_for_each_entry_safe(event, tmpevent, &session->events, list) |
| - _ltt_event_destroy(event); |
| - list_for_each_entry_safe(chan, tmpchan, &session->chan, list) |
| - _ltt_channel_destroy(chan); |
| - list_del(&session->list); |
| - mutex_unlock(&sessions_mutex); |
| - kfree(session); |
| -} |
| - |
| -int ltt_session_enable(struct ltt_session *session) |
| -{ |
| - int ret = 0; |
| - struct ltt_channel *chan; |
| - |
| - mutex_lock(&sessions_mutex); |
| - if (session->active) { |
| - ret = -EBUSY; |
| - goto end; |
| - } |
| - |
| - /* |
| - * Snapshot the number of events per channel to know the type of header |
| - * we need to use. |
| - */ |
| - list_for_each_entry(chan, &session->chan, list) { |
| - if (chan->header_type) |
| - continue; /* don't change it if session stop/restart */ |
| - if (chan->free_event_id < 31) |
| - chan->header_type = 1; /* compact */ |
| - else |
| - chan->header_type = 2; /* large */ |
| - } |
| - |
| - ACCESS_ONCE(session->active) = 1; |
| - ACCESS_ONCE(session->been_active) = 1; |
| - ret = _ltt_session_metadata_statedump(session); |
| - if (ret) |
| - ACCESS_ONCE(session->active) = 0; |
| -end: |
| - mutex_unlock(&sessions_mutex); |
| - return ret; |
| -} |
| - |
| -int ltt_session_disable(struct ltt_session *session) |
| -{ |
| - int ret = 0; |
| - |
| - mutex_lock(&sessions_mutex); |
| - if (!session->active) { |
| - ret = -EBUSY; |
| - goto end; |
| - } |
| - ACCESS_ONCE(session->active) = 0; |
| -end: |
| - mutex_unlock(&sessions_mutex); |
| - return ret; |
| -} |
| - |
| -int ltt_channel_enable(struct ltt_channel *channel) |
| -{ |
| - int old; |
| - |
| - if (channel == channel->session->metadata) |
| - return -EPERM; |
| - old = xchg(&channel->enabled, 1); |
| - if (old) |
| - return -EEXIST; |
| - return 0; |
| -} |
| - |
| -int ltt_channel_disable(struct ltt_channel *channel) |
| -{ |
| - int old; |
| - |
| - if (channel == channel->session->metadata) |
| - return -EPERM; |
| - old = xchg(&channel->enabled, 0); |
| - if (!old) |
| - return -EEXIST; |
| - return 0; |
| -} |
| - |
| -int ltt_event_enable(struct ltt_event *event) |
| -{ |
| - int old; |
| - |
| - if (event->chan == event->chan->session->metadata) |
| - return -EPERM; |
| - old = xchg(&event->enabled, 1); |
| - if (old) |
| - return -EEXIST; |
| - return 0; |
| -} |
| - |
| -int ltt_event_disable(struct ltt_event *event) |
| -{ |
| - int old; |
| - |
| - if (event->chan == event->chan->session->metadata) |
| - return -EPERM; |
| - old = xchg(&event->enabled, 0); |
| - if (!old) |
| - return -EEXIST; |
| - return 0; |
| -} |
| - |
| -static struct ltt_transport *ltt_transport_find(const char *name) |
| -{ |
| - struct ltt_transport *transport; |
| - |
| - list_for_each_entry(transport, <t_transport_list, node) { |
| - if (!strcmp(transport->name, name)) |
| - return transport; |
| - } |
| - return NULL; |
| -} |
| - |
| -struct ltt_channel *ltt_channel_create(struct ltt_session *session, |
| - const char *transport_name, |
| - void *buf_addr, |
| - size_t subbuf_size, size_t num_subbuf, |
| - unsigned int switch_timer_interval, |
| - unsigned int read_timer_interval) |
| -{ |
| - struct ltt_channel *chan; |
| - struct ltt_transport *transport = NULL; |
| - |
| - mutex_lock(&sessions_mutex); |
| - if (session->been_active) |
| - goto active; /* Refuse to add channel to active session */ |
| - transport = ltt_transport_find(transport_name); |
| - if (!transport) { |
| - printk(KERN_WARNING "LTTng transport %s not found\n", |
| - transport_name); |
| - goto notransport; |
| - } |
| - if (!try_module_get(transport->owner)) { |
| - printk(KERN_WARNING "LTT : Can't lock transport module.\n"); |
| - goto notransport; |
| - } |
| - chan = kzalloc(sizeof(struct ltt_channel), GFP_KERNEL); |
| - if (!chan) |
| - goto nomem; |
| - chan->session = session; |
| - chan->id = session->free_chan_id++; |
| - /* |
| - * Note: the channel creation op already writes into the packet |
| - * headers. Therefore the "chan" information used as input |
| - * should be already accessible. |
| - */ |
| - chan->chan = transport->ops.channel_create("[lttng]", chan, buf_addr, |
| - subbuf_size, num_subbuf, switch_timer_interval, |
| - read_timer_interval); |
| - if (!chan->chan) |
| - goto create_error; |
| - chan->enabled = 1; |
| - chan->ops = &transport->ops; |
| - chan->transport = transport; |
| - list_add(&chan->list, &session->chan); |
| - mutex_unlock(&sessions_mutex); |
| - return chan; |
| - |
| -create_error: |
| - kfree(chan); |
| -nomem: |
| - if (transport) |
| - module_put(transport->owner); |
| -notransport: |
| -active: |
| - mutex_unlock(&sessions_mutex); |
| - return NULL; |
| -} |
| - |
| -/* |
| - * Only used internally at session destruction. |
| - */ |
| -static |
| -void _ltt_channel_destroy(struct ltt_channel *chan) |
| -{ |
| - chan->ops->channel_destroy(chan->chan); |
| - module_put(chan->transport->owner); |
| - list_del(&chan->list); |
| - lttng_destroy_context(chan->ctx); |
| - kfree(chan); |
| -} |
| - |
| -/* |
| - * Supports event creation while tracing session is active. |
| - */ |
| -struct ltt_event *ltt_event_create(struct ltt_channel *chan, |
| - struct lttng_kernel_event *event_param, |
| - void *filter, |
| - const struct lttng_event_desc *internal_desc) |
| -{ |
| - struct ltt_event *event; |
| - int ret; |
| - |
| - mutex_lock(&sessions_mutex); |
| - if (chan->free_event_id == -1UL) |
| - goto full; |
| - /* |
| - * This is O(n^2) (for each event, the loop is called at event |
| - * creation). Might require a hash if we have lots of events. |
| - */ |
| - list_for_each_entry(event, &chan->session->events, list) |
| - if (!strcmp(event->desc->name, event_param->name)) |
| - goto exist; |
| - event = kmem_cache_zalloc(event_cache, GFP_KERNEL); |
| - if (!event) |
| - goto cache_error; |
| - event->chan = chan; |
| - event->filter = filter; |
| - event->id = chan->free_event_id++; |
| - event->enabled = 1; |
| - event->instrumentation = event_param->instrumentation; |
| - /* Populate ltt_event structure before tracepoint registration. */ |
| - smp_wmb(); |
| - switch (event_param->instrumentation) { |
| - case LTTNG_KERNEL_TRACEPOINT: |
| - event->desc = ltt_event_get(event_param->name); |
| - if (!event->desc) |
| - goto register_error; |
| - ret = tracepoint_probe_register(event_param->name, |
| - event->desc->probe_callback, |
| - event); |
| - if (ret) |
| - goto register_error; |
| - break; |
| - case LTTNG_KERNEL_KPROBE: |
| - ret = lttng_kprobes_register(event_param->name, |
| - event_param->u.kprobe.symbol_name, |
| - event_param->u.kprobe.offset, |
| - event_param->u.kprobe.addr, |
| - event); |
| - if (ret) |
| - goto register_error; |
| - ret = try_module_get(event->desc->owner); |
| - WARN_ON_ONCE(!ret); |
| - break; |
| - case LTTNG_KERNEL_KRETPROBE: |
| - { |
| - struct ltt_event *event_return; |
| - |
| - /* kretprobe defines 2 events */ |
| - event_return = |
| - kmem_cache_zalloc(event_cache, GFP_KERNEL); |
| - if (!event_return) |
| - goto register_error; |
| - event_return->chan = chan; |
| - event_return->filter = filter; |
| - event_return->id = chan->free_event_id++; |
| - event_return->enabled = 1; |
| - event_return->instrumentation = event_param->instrumentation; |
| - /* |
| - * Populate ltt_event structure before kretprobe registration. |
| - */ |
| - smp_wmb(); |
| - ret = lttng_kretprobes_register(event_param->name, |
| - event_param->u.kretprobe.symbol_name, |
| - event_param->u.kretprobe.offset, |
| - event_param->u.kretprobe.addr, |
| - event, event_return); |
| - if (ret) { |
| - kmem_cache_free(event_cache, event_return); |
| - goto register_error; |
| - } |
| - /* Take 2 refs on the module: one per event. */ |
| - ret = try_module_get(event->desc->owner); |
| - WARN_ON_ONCE(!ret); |
| - ret = try_module_get(event->desc->owner); |
| - WARN_ON_ONCE(!ret); |
| - ret = _ltt_event_metadata_statedump(chan->session, chan, |
| - event_return); |
| - if (ret) { |
| - kmem_cache_free(event_cache, event_return); |
| - module_put(event->desc->owner); |
| - module_put(event->desc->owner); |
| - goto statedump_error; |
| - } |
| - list_add(&event_return->list, &chan->session->events); |
| - break; |
| - } |
| - case LTTNG_KERNEL_FUNCTION: |
| - ret = lttng_ftrace_register(event_param->name, |
| - event_param->u.ftrace.symbol_name, |
| - event); |
| - if (ret) |
| - goto register_error; |
| - ret = try_module_get(event->desc->owner); |
| - WARN_ON_ONCE(!ret); |
| - break; |
| - case LTTNG_KERNEL_NOOP: |
| - event->desc = internal_desc; |
| - if (!event->desc) |
| - goto register_error; |
| - break; |
| - default: |
| - WARN_ON_ONCE(1); |
| - } |
| - ret = _ltt_event_metadata_statedump(chan->session, chan, event); |
| - if (ret) |
| - goto statedump_error; |
| - list_add(&event->list, &chan->session->events); |
| - mutex_unlock(&sessions_mutex); |
| - return event; |
| - |
| -statedump_error: |
| - /* If a statedump error occurs, events will not be readable. */ |
| -register_error: |
| - kmem_cache_free(event_cache, event); |
| -cache_error: |
| -exist: |
| -full: |
| - mutex_unlock(&sessions_mutex); |
| - return NULL; |
| -} |
| - |
| -/* |
| - * Only used internally at session destruction. |
| - */ |
| -int _ltt_event_unregister(struct ltt_event *event) |
| -{ |
| - int ret = -EINVAL; |
| - |
| - switch (event->instrumentation) { |
| - case LTTNG_KERNEL_TRACEPOINT: |
| - ret = tracepoint_probe_unregister(event->desc->name, |
| - event->desc->probe_callback, |
| - event); |
| - if (ret) |
| - return ret; |
| - break; |
| - case LTTNG_KERNEL_KPROBE: |
| - lttng_kprobes_unregister(event); |
| - ret = 0; |
| - break; |
| - case LTTNG_KERNEL_KRETPROBE: |
| - lttng_kretprobes_unregister(event); |
| - ret = 0; |
| - break; |
| - case LTTNG_KERNEL_FUNCTION: |
| - lttng_ftrace_unregister(event); |
| - ret = 0; |
| - break; |
| - case LTTNG_KERNEL_NOOP: |
| - ret = 0; |
| - break; |
| - default: |
| - WARN_ON_ONCE(1); |
| - } |
| - return ret; |
| -} |
| - |
| -/* |
| - * Only used internally at session destruction. |
| - */ |
| -static |
| -void _ltt_event_destroy(struct ltt_event *event) |
| -{ |
| - switch (event->instrumentation) { |
| - case LTTNG_KERNEL_TRACEPOINT: |
| - ltt_event_put(event->desc); |
| - break; |
| - case LTTNG_KERNEL_KPROBE: |
| - module_put(event->desc->owner); |
| - lttng_kprobes_destroy_private(event); |
| - break; |
| - case LTTNG_KERNEL_KRETPROBE: |
| - module_put(event->desc->owner); |
| - lttng_kretprobes_destroy_private(event); |
| - break; |
| - case LTTNG_KERNEL_FUNCTION: |
| - module_put(event->desc->owner); |
| - lttng_ftrace_destroy_private(event); |
| - break; |
| - case LTTNG_KERNEL_NOOP: |
| - break; |
| - default: |
| - WARN_ON_ONCE(1); |
| - } |
| - list_del(&event->list); |
| - lttng_destroy_context(event->ctx); |
| - kmem_cache_free(event_cache, event); |
| -} |
| - |
| -/* |
| - * We have exclusive access to our metadata buffer (protected by the |
| - * sessions_mutex), so we can do racy operations such as looking for |
| - * remaining space left in packet and write, since mutual exclusion |
| - * protects us from concurrent writes. |
| - */ |
| -int lttng_metadata_printf(struct ltt_session *session, |
| - const char *fmt, ...) |
| -{ |
| - struct lib_ring_buffer_ctx ctx; |
| - struct ltt_channel *chan = session->metadata; |
| - char *str; |
| - int ret = 0, waitret; |
| - size_t len, reserve_len, pos; |
| - va_list ap; |
| - |
| - WARN_ON_ONCE(!ACCESS_ONCE(session->active)); |
| - |
| - va_start(ap, fmt); |
| - str = kvasprintf(GFP_KERNEL, fmt, ap); |
| - va_end(ap); |
| - if (!str) |
| - return -ENOMEM; |
| - |
| - len = strlen(str); |
| - pos = 0; |
| - |
| - for (pos = 0; pos < len; pos += reserve_len) { |
| - reserve_len = min_t(size_t, |
| - chan->ops->packet_avail_size(chan->chan), |
| - len - pos); |
| - lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len, |
| - sizeof(char), -1); |
| - /* |
| - * We don't care about metadata buffer's records lost |
| - * count, because we always retry here. Report error if |
| - * we need to bail out after timeout or being |
| - * interrupted. |
| - */ |
| - waitret = wait_event_interruptible_timeout(*chan->ops->get_writer_buf_wait_queue(chan->chan, -1), |
| - ({ |
| - ret = chan->ops->event_reserve(&ctx, 0); |
| - ret != -ENOBUFS || !ret; |
| - }), |
| - msecs_to_jiffies(LTTNG_METADATA_TIMEOUT_MSEC)); |
| - if (!waitret || waitret == -ERESTARTSYS || ret) { |
| - printk(KERN_WARNING "LTTng: Failure to write metadata to buffers (%s)\n", |
| - waitret == -ERESTARTSYS ? "interrupted" : |
| - (ret == -ENOBUFS ? "timeout" : "I/O error")); |
| - if (waitret == -ERESTARTSYS) |
| - ret = waitret; |
| - goto end; |
| - } |
| - chan->ops->event_write(&ctx, &str[pos], reserve_len); |
| - chan->ops->event_commit(&ctx); |
| - } |
| -end: |
| - kfree(str); |
| - return ret; |
| -} |
| - |
| -static |
| -int _ltt_field_statedump(struct ltt_session *session, |
| - const struct lttng_event_field *field) |
| -{ |
| - int ret = 0; |
| - |
| - switch (field->type.atype) { |
| - case atype_integer: |
| - ret = lttng_metadata_printf(session, |
| - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", |
| - field->type.u.basic.integer.size, |
| - field->type.u.basic.integer.alignment, |
| - field->type.u.basic.integer.signedness, |
| - (field->type.u.basic.integer.encoding == lttng_encode_none) |
| - ? "none" |
| - : (field->type.u.basic.integer.encoding == lttng_encode_UTF8) |
| - ? "UTF8" |
| - : "ASCII", |
| - field->type.u.basic.integer.base, |
| -#ifdef __BIG_ENDIAN |
| - field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| -#else |
| - field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| -#endif |
| - field->name); |
| - break; |
| - case atype_enum: |
| - ret = lttng_metadata_printf(session, |
| - " %s _%s;\n", |
| - field->type.u.basic.enumeration.name, |
| - field->name); |
| - break; |
| - case atype_array: |
| - { |
| - const struct lttng_basic_type *elem_type; |
| - |
| - elem_type = &field->type.u.array.elem_type; |
| - ret = lttng_metadata_printf(session, |
| - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", |
| - elem_type->u.basic.integer.size, |
| - elem_type->u.basic.integer.alignment, |
| - elem_type->u.basic.integer.signedness, |
| - (elem_type->u.basic.integer.encoding == lttng_encode_none) |
| - ? "none" |
| - : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8) |
| - ? "UTF8" |
| - : "ASCII", |
| - elem_type->u.basic.integer.base, |
| -#ifdef __BIG_ENDIAN |
| - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| -#else |
| - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| -#endif |
| - field->name, field->type.u.array.length); |
| - break; |
| - } |
| - case atype_sequence: |
| - { |
| - const struct lttng_basic_type *elem_type; |
| - const struct lttng_basic_type *length_type; |
| - |
| - elem_type = &field->type.u.sequence.elem_type; |
| - length_type = &field->type.u.sequence.length_type; |
| - ret = lttng_metadata_printf(session, |
| - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", |
| - length_type->u.basic.integer.size, |
| - (unsigned int) length_type->u.basic.integer.alignment, |
| - length_type->u.basic.integer.signedness, |
| - (length_type->u.basic.integer.encoding == lttng_encode_none) |
| - ? "none" |
| - : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8) |
| - ? "UTF8" |
| - : "ASCII"), |
| - length_type->u.basic.integer.base, |
| -#ifdef __BIG_ENDIAN |
| - length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| -#else |
| - length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| -#endif |
| - field->name); |
| - if (ret) |
| - return ret; |
| - |
| - ret = lttng_metadata_printf(session, |
| - " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", |
| - elem_type->u.basic.integer.size, |
| - (unsigned int) elem_type->u.basic.integer.alignment, |
| - elem_type->u.basic.integer.signedness, |
| - (elem_type->u.basic.integer.encoding == lttng_encode_none) |
| - ? "none" |
| - : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8) |
| - ? "UTF8" |
| - : "ASCII"), |
| - elem_type->u.basic.integer.base, |
| -#ifdef __BIG_ENDIAN |
| - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| -#else |
| - elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| -#endif |
| - field->name, |
| - field->name); |
| - break; |
| - } |
| - |
| - case atype_string: |
| - /* Default encoding is UTF8 */ |
| - ret = lttng_metadata_printf(session, |
| - " string%s _%s;\n", |
| - field->type.u.basic.string.encoding == lttng_encode_ASCII ? |
| - " { encoding = ASCII; }" : "", |
| - field->name); |
| - break; |
| - default: |
| - WARN_ON_ONCE(1); |
| - return -EINVAL; |
| - } |
| - return ret; |
| -} |
| - |
| -static |
| -int _ltt_context_metadata_statedump(struct ltt_session *session, |
| - struct lttng_ctx *ctx) |
| -{ |
| - int ret = 0; |
| - int i; |
| - |
| - if (!ctx) |
| - return 0; |
| - for (i = 0; i < ctx->nr_fields; i++) { |
| - const struct lttng_ctx_field *field = &ctx->fields[i]; |
| - |
| - ret = _ltt_field_statedump(session, &field->event_field); |
| - if (ret) |
| - return ret; |
| - } |
| - return ret; |
| -} |
| - |
| -static |
| -int _ltt_fields_metadata_statedump(struct ltt_session *session, |
| - struct ltt_event *event) |
| -{ |
| - const struct lttng_event_desc *desc = event->desc; |
| - int ret = 0; |
| - int i; |
| - |
| - for (i = 0; i < desc->nr_fields; i++) { |
| - const struct lttng_event_field *field = &desc->fields[i]; |
| - |
| - ret = _ltt_field_statedump(session, field); |
| - if (ret) |
| - return ret; |
| - } |
| - return ret; |
| -} |
| - |
| -static |
| -int _ltt_event_metadata_statedump(struct ltt_session *session, |
| - struct ltt_channel *chan, |
| - struct ltt_event *event) |
| -{ |
| - int ret = 0; |
| - |
| - if (event->metadata_dumped || !ACCESS_ONCE(session->active)) |
| - return 0; |
| - if (chan == session->metadata) |
| - return 0; |
| - |
| - ret = lttng_metadata_printf(session, |
| - "event {\n" |
| - " name = %s;\n" |
| - " id = %u;\n" |
| - " stream_id = %u;\n", |
| - event->desc->name, |
| - event->id, |
| - event->chan->id); |
| - if (ret) |
| - goto end; |
| - |
| - if (event->ctx) { |
| - ret = lttng_metadata_printf(session, |
| - " context := struct {\n"); |
| - if (ret) |
| - goto end; |
| - } |
| - ret = _ltt_context_metadata_statedump(session, event->ctx); |
| - if (ret) |
| - goto end; |
| - if (event->ctx) { |
| - ret = lttng_metadata_printf(session, |
| - " };\n"); |
| - if (ret) |
| - goto end; |
| - } |
| - |
| - ret = lttng_metadata_printf(session, |
| - " fields := struct {\n" |
| - ); |
| - if (ret) |
| - goto end; |
| - |
| - ret = _ltt_fields_metadata_statedump(session, event); |
| - if (ret) |
| - goto end; |
| - |
| - /* |
| - * LTTng space reservation can only reserve multiples of the |
| - * byte size. |
| - */ |
| - ret = lttng_metadata_printf(session, |
| - " };\n" |
| - "};\n\n"); |
| - if (ret) |
| - goto end; |
| - |
| - event->metadata_dumped = 1; |
| -end: |
| - return ret; |
| - |
| -} |
| - |
| -static |
| -int _ltt_channel_metadata_statedump(struct ltt_session *session, |
| - struct ltt_channel *chan) |
| -{ |
| - int ret = 0; |
| - |
| - if (chan->metadata_dumped || !ACCESS_ONCE(session->active)) |
| - return 0; |
| - if (chan == session->metadata) |
| - return 0; |
| - |
| - WARN_ON_ONCE(!chan->header_type); |
| - ret = lttng_metadata_printf(session, |
| - "stream {\n" |
| - " id = %u;\n" |
| - " event.header := %s;\n" |
| - " packet.context := struct packet_context;\n", |
| - chan->id, |
| - chan->header_type == 1 ? "struct event_header_compact" : |
| - "struct event_header_large"); |
| - if (ret) |
| - goto end; |
| - |
| - if (chan->ctx) { |
| - ret = lttng_metadata_printf(session, |
| - " event.context := struct {\n"); |
| - if (ret) |
| - goto end; |
| - } |
| - ret = _ltt_context_metadata_statedump(session, chan->ctx); |
| - if (ret) |
| - goto end; |
| - if (chan->ctx) { |
| - ret = lttng_metadata_printf(session, |
| - " };\n"); |
| - if (ret) |
| - goto end; |
| - } |
| - |
| - ret = lttng_metadata_printf(session, |
| - "};\n\n"); |
| - |
| - chan->metadata_dumped = 1; |
| -end: |
| - return ret; |
| -} |
| - |
| -static |
| -int _ltt_stream_packet_context_declare(struct ltt_session *session) |
| -{ |
| - return lttng_metadata_printf(session, |
| - "struct packet_context {\n" |
| - " uint64_t timestamp_begin;\n" |
| - " uint64_t timestamp_end;\n" |
| - " uint32_t events_discarded;\n" |
| - " uint32_t content_size;\n" |
| - " uint32_t packet_size;\n" |
| - " uint32_t cpu_id;\n" |
| - "};\n\n" |
| - ); |
| -} |
| - |
| -/* |
| - * Compact header: |
| - * id: range: 0 - 30. |
| - * id 31 is reserved to indicate an extended header. |
| - * |
| - * Large header: |
| - * id: range: 0 - 65534. |
| - * id 65535 is reserved to indicate an extended header. |
| - */ |
| -static |
| -int _ltt_event_header_declare(struct ltt_session *session) |
| -{ |
| - return lttng_metadata_printf(session, |
| - "struct event_header_compact {\n" |
| - " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" |
| - " variant <id> {\n" |
| - " struct {\n" |
| - " uint27_t timestamp;\n" |
| - " } compact;\n" |
| - " struct {\n" |
| - " uint32_t id;\n" |
| - " uint64_t timestamp;\n" |
| - " } extended;\n" |
| - " } v;\n" |
| - "} align(%u);\n" |
| - "\n" |
| - "struct event_header_large {\n" |
| - " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" |
| - " variant <id> {\n" |
| - " struct {\n" |
| - " uint32_t timestamp;\n" |
| - " } compact;\n" |
| - " struct {\n" |
| - " uint32_t id;\n" |
| - " uint64_t timestamp;\n" |
| - " } extended;\n" |
| - " } v;\n" |
| - "} align(%u);\n\n", |
| - ltt_alignof(uint32_t) * CHAR_BIT, |
| - ltt_alignof(uint16_t) * CHAR_BIT |
| - ); |
| -} |
| - |
| -/* |
| - * Output metadata into this session's metadata buffers. |
| - */ |
| -static |
| -int _ltt_session_metadata_statedump(struct ltt_session *session) |
| -{ |
| - unsigned char *uuid_c = session->uuid.b; |
| - unsigned char uuid_s[37]; |
| - struct ltt_channel *chan; |
| - struct ltt_event *event; |
| - int ret = 0; |
| - |
| - if (!ACCESS_ONCE(session->active)) |
| - return 0; |
| - if (session->metadata_dumped) |
| - goto skip_session; |
| - if (!session->metadata) { |
| - printk(KERN_WARNING "LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n"); |
| - return -EPERM; |
| - } |
| - |
| - snprintf(uuid_s, sizeof(uuid_s), |
| - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
| - uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3], |
| - uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7], |
| - uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11], |
| - uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]); |
| - |
| - ret = lttng_metadata_printf(session, |
| - "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n" |
| - "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n" |
| - "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n" |
| - "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n" |
| - "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" |
| - "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" |
| - "\n" |
| - "trace {\n" |
| - " major = %u;\n" |
| - " minor = %u;\n" |
| - " uuid = \"%s\";\n" |
| - " byte_order = %s;\n" |
| - " packet.header := struct {\n" |
| - " uint32_t magic;\n" |
| - " uint8_t uuid[16];\n" |
| - " uint32_t stream_id;\n" |
| - " };\n" |
| - "};\n\n", |
| - ltt_alignof(uint8_t) * CHAR_BIT, |
| - ltt_alignof(uint16_t) * CHAR_BIT, |
| - ltt_alignof(uint32_t) * CHAR_BIT, |
| - ltt_alignof(uint64_t) * CHAR_BIT, |
| - CTF_VERSION_MAJOR, |
| - CTF_VERSION_MINOR, |
| - uuid_s, |
| -#ifdef __BIG_ENDIAN |
| - "be" |
| -#else |
| - "le" |
| -#endif |
| - ); |
| - if (ret) |
| - goto end; |
| - |
| - ret = _ltt_stream_packet_context_declare(session); |
| - if (ret) |
| - goto end; |
| - |
| - ret = _ltt_event_header_declare(session); |
| - if (ret) |
| - goto end; |
| - |
| -skip_session: |
| - list_for_each_entry(chan, &session->chan, list) { |
| - ret = _ltt_channel_metadata_statedump(session, chan); |
| - if (ret) |
| - goto end; |
| - } |
| - |
| - list_for_each_entry(event, &session->events, list) { |
| - ret = _ltt_event_metadata_statedump(session, event->chan, event); |
| - if (ret) |
| - goto end; |
| - } |
| - session->metadata_dumped = 1; |
| -end: |
| - return ret; |
| -} |
| - |
| -/** |
| - * ltt_transport_register - LTT transport registration |
| - * @transport: transport structure |
| - * |
| - * Registers a transport which can be used as output to extract the data out of |
| - * LTTng. The module calling this registration function must ensure that no |
| - * trap-inducing code will be executed by the transport functions. E.g. |
| - * vmalloc_sync_all() must be called between a vmalloc and the moment the memory |
| - * is made visible to the transport function. This registration acts as a |
| - * vmalloc_sync_all. Therefore, only if the module allocates virtual memory |
| - * after its registration must it synchronize the TLBs. |
| - */ |
| -void ltt_transport_register(struct ltt_transport *transport) |
| -{ |
| - /* |
| - * Make sure no page fault can be triggered by the module about to be |
| - * registered. We deal with this here so we don't have to call |
| - * vmalloc_sync_all() in each module's init. |
| - */ |
| - wrapper_vmalloc_sync_all(); |
| - |
| - mutex_lock(&sessions_mutex); |
| - list_add_tail(&transport->node, <t_transport_list); |
| - mutex_unlock(&sessions_mutex); |
| -} |
| -EXPORT_SYMBOL_GPL(ltt_transport_register); |
| - |
| -/** |
| - * ltt_transport_unregister - LTT transport unregistration |
| - * @transport: transport structure |
| - */ |
| -void ltt_transport_unregister(struct ltt_transport *transport) |
| -{ |
| - mutex_lock(&sessions_mutex); |
| - list_del(&transport->node); |
| - mutex_unlock(&sessions_mutex); |
| -} |
| -EXPORT_SYMBOL_GPL(ltt_transport_unregister); |
| - |
| -static int __init ltt_events_init(void) |
| -{ |
| - int ret; |
| - |
| - event_cache = KMEM_CACHE(ltt_event, 0); |
| - if (!event_cache) |
| - return -ENOMEM; |
| - ret = ltt_debugfs_abi_init(); |
| - if (ret) |
| - goto error_abi; |
| - return 0; |
| -error_abi: |
| - kmem_cache_destroy(event_cache); |
| - return ret; |
| -} |
| - |
| -module_init(ltt_events_init); |
| - |
| -static void __exit ltt_events_exit(void) |
| -{ |
| - struct ltt_session *session, *tmpsession; |
| - |
| - ltt_debugfs_abi_exit(); |
| - list_for_each_entry_safe(session, tmpsession, &sessions, list) |
| - ltt_session_destroy(session); |
| - kmem_cache_destroy(event_cache); |
| -} |
| - |
| -module_exit(ltt_events_exit); |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); |
| -MODULE_DESCRIPTION("LTTng Events"); |
| --- a/drivers/staging/lttng/ltt-events.h |
| +++ /dev/null |
| @@ -1,452 +0,0 @@ |
| -#ifndef _LTT_EVENTS_H |
| -#define _LTT_EVENTS_H |
| - |
| -/* |
| - * ltt-events.h |
| - * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * Holds LTTng per-session event registry. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/list.h> |
| -#include <linux/kprobes.h> |
| -#include "wrapper/uuid.h" |
| -#include "ltt-debugfs-abi.h" |
| - |
| -#undef is_signed_type |
| -#define is_signed_type(type) (((type)(-1)) < 0) |
| - |
| -struct ltt_channel; |
| -struct ltt_session; |
| -struct lib_ring_buffer_ctx; |
| -struct perf_event; |
| -struct perf_event_attr; |
| - |
| -/* Type description */ |
| - |
| -/* Update the astract_types name table in lttng-types.c along with this enum */ |
| -enum abstract_types { |
| - atype_integer, |
| - atype_enum, |
| - atype_array, |
| - atype_sequence, |
| - atype_string, |
| - NR_ABSTRACT_TYPES, |
| -}; |
| - |
| -/* Update the string_encodings name table in lttng-types.c along with this enum */ |
| -enum lttng_string_encodings { |
| - lttng_encode_none = 0, |
| - lttng_encode_UTF8 = 1, |
| - lttng_encode_ASCII = 2, |
| - NR_STRING_ENCODINGS, |
| -}; |
| - |
| -struct lttng_enum_entry { |
| - unsigned long long start, end; /* start and end are inclusive */ |
| - const char *string; |
| -}; |
| - |
| -#define __type_integer(_type, _byte_order, _base, _encoding) \ |
| - { \ |
| - .atype = atype_integer, \ |
| - .u.basic.integer = \ |
| - { \ |
| - .size = sizeof(_type) * CHAR_BIT, \ |
| - .alignment = ltt_alignof(_type) * CHAR_BIT, \ |
| - .signedness = is_signed_type(_type), \ |
| - .reverse_byte_order = _byte_order != __BYTE_ORDER, \ |
| - .base = _base, \ |
| - .encoding = lttng_encode_##_encoding, \ |
| - }, \ |
| - } \ |
| - |
| -struct lttng_integer_type { |
| - unsigned int size; /* in bits */ |
| - unsigned short alignment; /* in bits */ |
| - uint signedness:1; |
| - uint reverse_byte_order:1; |
| - unsigned int base; /* 2, 8, 10, 16, for pretty print */ |
| - enum lttng_string_encodings encoding; |
| -}; |
| - |
| -union _lttng_basic_type { |
| - struct lttng_integer_type integer; |
| - struct { |
| - const char *name; |
| - } enumeration; |
| - struct { |
| - enum lttng_string_encodings encoding; |
| - } string; |
| -}; |
| - |
| -struct lttng_basic_type { |
| - enum abstract_types atype; |
| - union { |
| - union _lttng_basic_type basic; |
| - } u; |
| -}; |
| - |
| -struct lttng_type { |
| - enum abstract_types atype; |
| - union { |
| - union _lttng_basic_type basic; |
| - struct { |
| - struct lttng_basic_type elem_type; |
| - unsigned int length; /* num. elems. */ |
| - } array; |
| - struct { |
| - struct lttng_basic_type length_type; |
| - struct lttng_basic_type elem_type; |
| - } sequence; |
| - } u; |
| -}; |
| - |
| -struct lttng_enum { |
| - const char *name; |
| - struct lttng_type container_type; |
| - const struct lttng_enum_entry *entries; |
| - unsigned int len; |
| -}; |
| - |
| -/* Event field description */ |
| - |
| -struct lttng_event_field { |
| - const char *name; |
| - struct lttng_type type; |
| -}; |
| - |
| -/* |
| - * We need to keep this perf counter field separately from struct |
| - * lttng_ctx_field because cpu hotplug needs fixed-location addresses. |
| - */ |
| -struct lttng_perf_counter_field { |
| - struct notifier_block nb; |
| - int hp_enable; |
| - struct perf_event_attr *attr; |
| - struct perf_event **e; /* per-cpu array */ |
| -}; |
| - |
| -struct lttng_ctx_field { |
| - struct lttng_event_field event_field; |
| - size_t (*get_size)(size_t offset); |
| - void (*record)(struct lttng_ctx_field *field, |
| - struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan); |
| - union { |
| - struct lttng_perf_counter_field *perf_counter; |
| - } u; |
| - void (*destroy)(struct lttng_ctx_field *field); |
| -}; |
| - |
| -struct lttng_ctx { |
| - struct lttng_ctx_field *fields; |
| - unsigned int nr_fields; |
| - unsigned int allocated_fields; |
| -}; |
| - |
| -struct lttng_event_desc { |
| - const char *name; |
| - void *probe_callback; |
| - const struct lttng_event_ctx *ctx; /* context */ |
| - const struct lttng_event_field *fields; /* event payload */ |
| - unsigned int nr_fields; |
| - struct module *owner; |
| -}; |
| - |
| -struct lttng_probe_desc { |
| - const struct lttng_event_desc **event_desc; |
| - unsigned int nr_events; |
| - struct list_head head; /* chain registered probes */ |
| -}; |
| - |
| -struct lttng_krp; /* Kretprobe handling */ |
| - |
| -/* |
| - * ltt_event structure is referred to by the tracing fast path. It must be |
| - * kept small. |
| - */ |
| -struct ltt_event { |
| - unsigned int id; |
| - struct ltt_channel *chan; |
| - int enabled; |
| - const struct lttng_event_desc *desc; |
| - void *filter; |
| - struct lttng_ctx *ctx; |
| - enum lttng_kernel_instrumentation instrumentation; |
| - union { |
| - struct { |
| - struct kprobe kp; |
| - char *symbol_name; |
| - } kprobe; |
| - struct { |
| - struct lttng_krp *lttng_krp; |
| - char *symbol_name; |
| - } kretprobe; |
| - struct { |
| - char *symbol_name; |
| - } ftrace; |
| - } u; |
| - struct list_head list; /* Event list */ |
| - uint metadata_dumped:1; |
| -}; |
| - |
| -struct ltt_channel_ops { |
| - struct channel *(*channel_create)(const char *name, |
| - struct ltt_channel *ltt_chan, |
| - void *buf_addr, |
| - size_t subbuf_size, size_t num_subbuf, |
| - unsigned int switch_timer_interval, |
| - unsigned int read_timer_interval); |
| - void (*channel_destroy)(struct channel *chan); |
| - struct lib_ring_buffer *(*buffer_read_open)(struct channel *chan); |
| - int (*buffer_has_read_closed_stream)(struct channel *chan); |
| - void (*buffer_read_close)(struct lib_ring_buffer *buf); |
| - int (*event_reserve)(struct lib_ring_buffer_ctx *ctx, |
| - uint32_t event_id); |
| - void (*event_commit)(struct lib_ring_buffer_ctx *ctx); |
| - void (*event_write)(struct lib_ring_buffer_ctx *ctx, const void *src, |
| - size_t len); |
| - void (*event_write_from_user)(struct lib_ring_buffer_ctx *ctx, |
| - const void *src, size_t len); |
| - void (*event_memset)(struct lib_ring_buffer_ctx *ctx, |
| - int c, size_t len); |
| - /* |
| - * packet_avail_size returns the available size in the current |
| - * packet. Note that the size returned is only a hint, since it |
| - * may change due to concurrent writes. |
| - */ |
| - size_t (*packet_avail_size)(struct channel *chan); |
| - wait_queue_head_t *(*get_writer_buf_wait_queue)(struct channel *chan, int cpu); |
| - wait_queue_head_t *(*get_hp_wait_queue)(struct channel *chan); |
| - int (*is_finalized)(struct channel *chan); |
| - int (*is_disabled)(struct channel *chan); |
| -}; |
| - |
| -struct ltt_transport { |
| - char *name; |
| - struct module *owner; |
| - struct list_head node; |
| - struct ltt_channel_ops ops; |
| -}; |
| - |
| -struct ltt_channel { |
| - unsigned int id; |
| - struct channel *chan; /* Channel buffers */ |
| - int enabled; |
| - struct lttng_ctx *ctx; |
| - /* Event ID management */ |
| - struct ltt_session *session; |
| - struct file *file; /* File associated to channel */ |
| - unsigned int free_event_id; /* Next event ID to allocate */ |
| - struct list_head list; /* Channel list */ |
| - struct ltt_channel_ops *ops; |
| - struct ltt_transport *transport; |
| - struct ltt_event **sc_table; /* for syscall tracing */ |
| - struct ltt_event **compat_sc_table; |
| - struct ltt_event *sc_unknown; /* for unknown syscalls */ |
| - struct ltt_event *sc_compat_unknown; |
| - struct ltt_event *sc_exit; /* for syscall exit */ |
| - int header_type; /* 0: unset, 1: compact, 2: large */ |
| - uint metadata_dumped:1; |
| -}; |
| - |
| -struct ltt_session { |
| - int active; /* Is trace session active ? */ |
| - int been_active; /* Has trace session been active ? */ |
| - struct file *file; /* File associated to session */ |
| - struct ltt_channel *metadata; /* Metadata channel */ |
| - struct list_head chan; /* Channel list head */ |
| - struct list_head events; /* Event list head */ |
| - struct list_head list; /* Session list */ |
| - unsigned int free_chan_id; /* Next chan ID to allocate */ |
| - uuid_le uuid; /* Trace session unique ID */ |
| - uint metadata_dumped:1; |
| -}; |
| - |
| -struct ltt_session *ltt_session_create(void); |
| -int ltt_session_enable(struct ltt_session *session); |
| -int ltt_session_disable(struct ltt_session *session); |
| -void ltt_session_destroy(struct ltt_session *session); |
| - |
| -struct ltt_channel *ltt_channel_create(struct ltt_session *session, |
| - const char *transport_name, |
| - void *buf_addr, |
| - size_t subbuf_size, size_t num_subbuf, |
| - unsigned int switch_timer_interval, |
| - unsigned int read_timer_interval); |
| -struct ltt_channel *ltt_global_channel_create(struct ltt_session *session, |
| - int overwrite, void *buf_addr, |
| - size_t subbuf_size, size_t num_subbuf, |
| - unsigned int switch_timer_interval, |
| - unsigned int read_timer_interval); |
| - |
| -struct ltt_event *ltt_event_create(struct ltt_channel *chan, |
| - struct lttng_kernel_event *event_param, |
| - void *filter, |
| - const struct lttng_event_desc *internal_desc); |
| - |
| -int ltt_channel_enable(struct ltt_channel *channel); |
| -int ltt_channel_disable(struct ltt_channel *channel); |
| -int ltt_event_enable(struct ltt_event *event); |
| -int ltt_event_disable(struct ltt_event *event); |
| - |
| -void ltt_transport_register(struct ltt_transport *transport); |
| -void ltt_transport_unregister(struct ltt_transport *transport); |
| - |
| -void synchronize_trace(void); |
| -int ltt_debugfs_abi_init(void); |
| -void ltt_debugfs_abi_exit(void); |
| - |
| -int ltt_probe_register(struct lttng_probe_desc *desc); |
| -void ltt_probe_unregister(struct lttng_probe_desc *desc); |
| -const struct lttng_event_desc *ltt_event_get(const char *name); |
| -void ltt_event_put(const struct lttng_event_desc *desc); |
| -int ltt_probes_init(void); |
| -void ltt_probes_exit(void); |
| - |
| -#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS |
| -int lttng_syscalls_register(struct ltt_channel *chan, void *filter); |
| -int lttng_syscalls_unregister(struct ltt_channel *chan); |
| -#else |
| -static inline int lttng_syscalls_register(struct ltt_channel *chan, void *filter) |
| -{ |
| - return -ENOSYS; |
| -} |
| - |
| -static inline int lttng_syscalls_unregister(struct ltt_channel *chan) |
| -{ |
| - return 0; |
| -} |
| -#endif |
| - |
| -struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx); |
| -int lttng_find_context(struct lttng_ctx *ctx, const char *name); |
| -void lttng_remove_context_field(struct lttng_ctx **ctx, |
| - struct lttng_ctx_field *field); |
| -void lttng_destroy_context(struct lttng_ctx *ctx); |
| -int lttng_add_pid_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_procname_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_prio_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_nice_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_vpid_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_tid_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_vtid_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_ppid_to_ctx(struct lttng_ctx **ctx); |
| -int lttng_add_vppid_to_ctx(struct lttng_ctx **ctx); |
| -#if defined(CONFIG_PERF_EVENTS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) |
| -int lttng_add_perf_counter_to_ctx(uint32_t type, |
| - uint64_t config, |
| - const char *name, |
| - struct lttng_ctx **ctx); |
| -#else |
| -static inline |
| -int lttng_add_perf_counter_to_ctx(uint32_t type, |
| - uint64_t config, |
| - const char *name, |
| - struct lttng_ctx **ctx) |
| -{ |
| - return -ENOSYS; |
| -} |
| -#endif |
| - |
| -#ifdef CONFIG_KPROBES |
| -int lttng_kprobes_register(const char *name, |
| - const char *symbol_name, |
| - uint64_t offset, |
| - uint64_t addr, |
| - struct ltt_event *event); |
| -void lttng_kprobes_unregister(struct ltt_event *event); |
| -void lttng_kprobes_destroy_private(struct ltt_event *event); |
| -#else |
| -static inline |
| -int lttng_kprobes_register(const char *name, |
| - const char *symbol_name, |
| - uint64_t offset, |
| - uint64_t addr, |
| - struct ltt_event *event) |
| -{ |
| - return -ENOSYS; |
| -} |
| - |
| -static inline |
| -void lttng_kprobes_unregister(struct ltt_event *event) |
| -{ |
| -} |
| - |
| -static inline |
| -void lttng_kprobes_destroy_private(struct ltt_event *event) |
| -{ |
| -} |
| -#endif |
| - |
| -#ifdef CONFIG_KRETPROBES |
| -int lttng_kretprobes_register(const char *name, |
| - const char *symbol_name, |
| - uint64_t offset, |
| - uint64_t addr, |
| - struct ltt_event *event_entry, |
| - struct ltt_event *event_exit); |
| -void lttng_kretprobes_unregister(struct ltt_event *event); |
| -void lttng_kretprobes_destroy_private(struct ltt_event *event); |
| -#else |
| -static inline |
| -int lttng_kretprobes_register(const char *name, |
| - const char *symbol_name, |
| - uint64_t offset, |
| - uint64_t addr, |
| - struct ltt_event *event_entry, |
| - struct ltt_event *event_exit) |
| -{ |
| - return -ENOSYS; |
| -} |
| - |
| -static inline |
| -void lttng_kretprobes_unregister(struct ltt_event *event) |
| -{ |
| -} |
| - |
| -static inline |
| -void lttng_kretprobes_destroy_private(struct ltt_event *event) |
| -{ |
| -} |
| -#endif |
| - |
| -#ifdef CONFIG_DYNAMIC_FTRACE |
| -int lttng_ftrace_register(const char *name, |
| - const char *symbol_name, |
| - struct ltt_event *event); |
| -void lttng_ftrace_unregister(struct ltt_event *event); |
| -void lttng_ftrace_destroy_private(struct ltt_event *event); |
| -#else |
| -static inline |
| -int lttng_ftrace_register(const char *name, |
| - const char *symbol_name, |
| - struct ltt_event *event) |
| -{ |
| - return -ENOSYS; |
| -} |
| - |
| -static inline |
| -void lttng_ftrace_unregister(struct ltt_event *event) |
| -{ |
| -} |
| - |
| -static inline |
| -void lttng_ftrace_destroy_private(struct ltt_event *event) |
| -{ |
| -} |
| -#endif |
| - |
| -int lttng_calibrate(struct lttng_kernel_calibrate *calibrate); |
| - |
| -extern const struct file_operations lttng_tracepoint_list_fops; |
| - |
| -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) |
| -#define TRACEPOINT_HAS_DATA_ARG |
| -#endif |
| - |
| -#endif /* _LTT_EVENTS_H */ |
| --- a/drivers/staging/lttng/ltt-probes.c |
| +++ /dev/null |
| @@ -1,164 +0,0 @@ |
| -/* |
| - * ltt-probes.c |
| - * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * Holds LTTng probes registry. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include <linux/list.h> |
| -#include <linux/mutex.h> |
| -#include <linux/seq_file.h> |
| - |
| -#include "ltt-events.h" |
| - |
| -static LIST_HEAD(probe_list); |
| -static DEFINE_MUTEX(probe_mutex); |
| - |
| -static |
| -const struct lttng_event_desc *find_event(const char *name) |
| -{ |
| - struct lttng_probe_desc *probe_desc; |
| - int i; |
| - |
| - list_for_each_entry(probe_desc, &probe_list, head) { |
| - for (i = 0; i < probe_desc->nr_events; i++) { |
| - if (!strcmp(probe_desc->event_desc[i]->name, name)) |
| - return probe_desc->event_desc[i]; |
| - } |
| - } |
| - return NULL; |
| -} |
| - |
| -int ltt_probe_register(struct lttng_probe_desc *desc) |
| -{ |
| - int ret = 0; |
| - int i; |
| - |
| - mutex_lock(&probe_mutex); |
| - /* |
| - * TODO: This is O(N^2). Turn into a hash table when probe registration |
| - * overhead becomes an issue. |
| - */ |
| - for (i = 0; i < desc->nr_events; i++) { |
| - if (find_event(desc->event_desc[i]->name)) { |
| - ret = -EEXIST; |
| - goto end; |
| - } |
| - } |
| - list_add(&desc->head, &probe_list); |
| -end: |
| - mutex_unlock(&probe_mutex); |
| - return ret; |
| -} |
| -EXPORT_SYMBOL_GPL(ltt_probe_register); |
| - |
| -void ltt_probe_unregister(struct lttng_probe_desc *desc) |
| -{ |
| - mutex_lock(&probe_mutex); |
| - list_del(&desc->head); |
| - mutex_unlock(&probe_mutex); |
| -} |
| -EXPORT_SYMBOL_GPL(ltt_probe_unregister); |
| - |
| -const struct lttng_event_desc *ltt_event_get(const char *name) |
| -{ |
| - const struct lttng_event_desc *event; |
| - int ret; |
| - |
| - mutex_lock(&probe_mutex); |
| - event = find_event(name); |
| - mutex_unlock(&probe_mutex); |
| - if (!event) |
| - return NULL; |
| - ret = try_module_get(event->owner); |
| - WARN_ON_ONCE(!ret); |
| - return event; |
| -} |
| -EXPORT_SYMBOL_GPL(ltt_event_get); |
| - |
| -void ltt_event_put(const struct lttng_event_desc *event) |
| -{ |
| - module_put(event->owner); |
| -} |
| -EXPORT_SYMBOL_GPL(ltt_event_put); |
| - |
| -static |
| -void *tp_list_start(struct seq_file *m, loff_t *pos) |
| -{ |
| - struct lttng_probe_desc *probe_desc; |
| - int iter = 0, i; |
| - |
| - mutex_lock(&probe_mutex); |
| - list_for_each_entry(probe_desc, &probe_list, head) { |
| - for (i = 0; i < probe_desc->nr_events; i++) { |
| - if (iter++ >= *pos) |
| - return (void *) probe_desc->event_desc[i]; |
| - } |
| - } |
| - /* End of list */ |
| - return NULL; |
| -} |
| - |
| -static |
| -void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos) |
| -{ |
| - struct lttng_probe_desc *probe_desc; |
| - int iter = 0, i; |
| - |
| - (*ppos)++; |
| - list_for_each_entry(probe_desc, &probe_list, head) { |
| - for (i = 0; i < probe_desc->nr_events; i++) { |
| - if (iter++ >= *ppos) |
| - return (void *) probe_desc->event_desc[i]; |
| - } |
| - } |
| - /* End of list */ |
| - return NULL; |
| -} |
| - |
| -static |
| -void tp_list_stop(struct seq_file *m, void *p) |
| -{ |
| - mutex_unlock(&probe_mutex); |
| -} |
| - |
| -static |
| -int tp_list_show(struct seq_file *m, void *p) |
| -{ |
| - const struct lttng_event_desc *probe_desc = p; |
| - |
| - /* |
| - * Don't export lttng internal events (metadata). |
| - */ |
| - if (!strncmp(probe_desc->name, "lttng_", sizeof("lttng_") - 1)) |
| - return 0; |
| - seq_printf(m, "event { name = %s; };\n", |
| - probe_desc->name); |
| - return 0; |
| -} |
| - |
| -static |
| -const struct seq_operations lttng_tracepoint_list_seq_ops = { |
| - .start = tp_list_start, |
| - .next = tp_list_next, |
| - .stop = tp_list_stop, |
| - .show = tp_list_show, |
| -}; |
| - |
| -static |
| -int lttng_tracepoint_list_open(struct inode *inode, struct file *file) |
| -{ |
| - return seq_open(file, <tng_tracepoint_list_seq_ops); |
| -} |
| - |
| -const struct file_operations lttng_tracepoint_list_fops = { |
| - .owner = THIS_MODULE, |
| - .open = lttng_tracepoint_list_open, |
| - .read = seq_read, |
| - .llseek = seq_lseek, |
| - .release = seq_release, |
| -}; |
| --- a/drivers/staging/lttng/ltt-ring-buffer-client-discard.c |
| +++ /dev/null |
| @@ -1,21 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-client-discard.c |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer client (discard mode). |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include "ltt-tracer.h" |
| - |
| -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| -#define RING_BUFFER_MODE_TEMPLATE_STRING "discard" |
| -#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_SPLICE |
| -#include "ltt-ring-buffer-client.h" |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng Ring Buffer Client Discard Mode"); |
| --- a/drivers/staging/lttng/ltt-ring-buffer-client-mmap-discard.c |
| +++ /dev/null |
| @@ -1,21 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-client-discard.c |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer client (discard mode). |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include "ltt-tracer.h" |
| - |
| -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| -#define RING_BUFFER_MODE_TEMPLATE_STRING "discard-mmap" |
| -#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_MMAP |
| -#include "ltt-ring-buffer-client.h" |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng Ring Buffer Client Discard Mode"); |
| --- a/drivers/staging/lttng/ltt-ring-buffer-client-mmap-overwrite.c |
| +++ /dev/null |
| @@ -1,21 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-client-overwrite.c |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer client (overwrite mode). |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include "ltt-tracer.h" |
| - |
| -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE |
| -#define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite-mmap" |
| -#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_MMAP |
| -#include "ltt-ring-buffer-client.h" |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng Ring Buffer Client Overwrite Mode"); |
| --- a/drivers/staging/lttng/ltt-ring-buffer-client-overwrite.c |
| +++ /dev/null |
| @@ -1,21 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-client-overwrite.c |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer client (overwrite mode). |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include "ltt-tracer.h" |
| - |
| -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE |
| -#define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite" |
| -#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_SPLICE |
| -#include "ltt-ring-buffer-client.h" |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng Ring Buffer Client Overwrite Mode"); |
| --- a/drivers/staging/lttng/ltt-ring-buffer-client.h |
| +++ /dev/null |
| @@ -1,569 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-client.h |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer client template. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include <linux/types.h> |
| -#include "lib/bitfield.h" |
| -#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| -#include "wrapper/trace-clock.h" |
| -#include "ltt-events.h" |
| -#include "ltt-tracer.h" |
| -#include "wrapper/ringbuffer/frontend_types.h" |
| - |
| -/* |
| - * Keep the natural field alignment for _each field_ within this structure if |
| - * you ever add/remove a field from this header. Packed attribute is not used |
| - * because gcc generates poor code on at least powerpc and mips. Don't ever |
| - * let gcc add padding between the structure elements. |
| - * |
| - * The guarantee we have with timestamps is that all the events in a |
| - * packet are included (inclusive) within the begin/end timestamps of |
| - * the packet. Another guarantee we have is that the "timestamp begin", |
| - * as well as the event timestamps, are monotonically increasing (never |
| - * decrease) when moving forward in a stream (physically). But this |
| - * guarantee does not apply to "timestamp end", because it is sampled at |
| - * commit time, which is not ordered with respect to space reservation. |
| - */ |
| - |
| -struct packet_header { |
| - /* Trace packet header */ |
| - uint32_t magic; /* |
| - * Trace magic number. |
| - * contains endianness information. |
| - */ |
| - uint8_t uuid[16]; |
| - uint32_t stream_id; |
| - |
| - struct { |
| - /* Stream packet context */ |
| - uint64_t timestamp_begin; /* Cycle count at subbuffer start */ |
| - uint64_t timestamp_end; /* Cycle count at subbuffer end */ |
| - uint32_t events_discarded; /* |
| - * Events lost in this subbuffer since |
| - * the beginning of the trace. |
| - * (may overflow) |
| - */ |
| - uint32_t content_size; /* Size of data in subbuffer */ |
| - uint32_t packet_size; /* Subbuffer size (include padding) */ |
| - uint32_t cpu_id; /* CPU id associated with stream */ |
| - uint8_t header_end; /* End of header */ |
| - } ctx; |
| -}; |
| - |
| - |
| -static inline notrace u64 lib_ring_buffer_clock_read(struct channel *chan) |
| -{ |
| - return trace_clock_read64(); |
| -} |
| - |
| -static inline |
| -size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx) |
| -{ |
| - int i; |
| - size_t orig_offset = offset; |
| - |
| - if (likely(!ctx)) |
| - return 0; |
| - for (i = 0; i < ctx->nr_fields; i++) |
| - offset += ctx->fields[i].get_size(offset); |
| - return offset - orig_offset; |
| -} |
| - |
| -static inline |
| -void ctx_record(struct lib_ring_buffer_ctx *bufctx, |
| - struct ltt_channel *chan, |
| - struct lttng_ctx *ctx) |
| -{ |
| - int i; |
| - |
| - if (likely(!ctx)) |
| - return; |
| - for (i = 0; i < ctx->nr_fields; i++) |
| - ctx->fields[i].record(&ctx->fields[i], bufctx, chan); |
| -} |
| - |
| -/* |
| - * record_header_size - Calculate the header size and padding necessary. |
| - * @config: ring buffer instance configuration |
| - * @chan: channel |
| - * @offset: offset in the write buffer |
| - * @pre_header_padding: padding to add before the header (output) |
| - * @ctx: reservation context |
| - * |
| - * Returns the event header size (including padding). |
| - * |
| - * The payload must itself determine its own alignment from the biggest type it |
| - * contains. |
| - */ |
| -static __inline__ |
| -unsigned char record_header_size(const struct lib_ring_buffer_config *config, |
| - struct channel *chan, size_t offset, |
| - size_t *pre_header_padding, |
| - struct lib_ring_buffer_ctx *ctx) |
| -{ |
| - struct ltt_channel *ltt_chan = channel_get_private(chan); |
| - struct ltt_event *event = ctx->priv; |
| - size_t orig_offset = offset; |
| - size_t padding; |
| - |
| - switch (ltt_chan->header_type) { |
| - case 1: /* compact */ |
| - padding = lib_ring_buffer_align(offset, ltt_alignof(uint32_t)); |
| - offset += padding; |
| - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { |
| - offset += sizeof(uint32_t); /* id and timestamp */ |
| - } else { |
| - /* Minimum space taken by 5-bit id */ |
| - offset += sizeof(uint8_t); |
| - /* Align extended struct on largest member */ |
| - offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); |
| - offset += sizeof(uint32_t); /* id */ |
| - offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); |
| - offset += sizeof(uint64_t); /* timestamp */ |
| - } |
| - break; |
| - case 2: /* large */ |
| - padding = lib_ring_buffer_align(offset, ltt_alignof(uint16_t)); |
| - offset += padding; |
| - offset += sizeof(uint16_t); |
| - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { |
| - offset += lib_ring_buffer_align(offset, ltt_alignof(uint32_t)); |
| - offset += sizeof(uint32_t); /* timestamp */ |
| - } else { |
| - /* Align extended struct on largest member */ |
| - offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); |
| - offset += sizeof(uint32_t); /* id */ |
| - offset += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); |
| - offset += sizeof(uint64_t); /* timestamp */ |
| - } |
| - break; |
| - default: |
| - padding = 0; |
| - WARN_ON_ONCE(1); |
| - } |
| - offset += ctx_get_size(offset, event->ctx); |
| - offset += ctx_get_size(offset, ltt_chan->ctx); |
| - |
| - *pre_header_padding = padding; |
| - return offset - orig_offset; |
| -} |
| - |
| -#include "wrapper/ringbuffer/api.h" |
| - |
| -static |
| -void ltt_write_event_header_slow(const struct lib_ring_buffer_config *config, |
| - struct lib_ring_buffer_ctx *ctx, |
| - uint32_t event_id); |
| - |
| -/* |
| - * ltt_write_event_header |
| - * |
| - * Writes the event header to the offset (already aligned on 32-bits). |
| - * |
| - * @config: ring buffer instance configuration |
| - * @ctx: reservation context |
| - * @event_id: event ID |
| - */ |
| -static __inline__ |
| -void ltt_write_event_header(const struct lib_ring_buffer_config *config, |
| - struct lib_ring_buffer_ctx *ctx, |
| - uint32_t event_id) |
| -{ |
| - struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); |
| - struct ltt_event *event = ctx->priv; |
| - |
| - if (unlikely(ctx->rflags)) |
| - goto slow_path; |
| - |
| - switch (ltt_chan->header_type) { |
| - case 1: /* compact */ |
| - { |
| - uint32_t id_time = 0; |
| - |
| - bt_bitfield_write(&id_time, uint32_t, 0, 5, event_id); |
| - bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc); |
| - lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); |
| - break; |
| - } |
| - case 2: /* large */ |
| - { |
| - uint32_t timestamp = (uint32_t) ctx->tsc; |
| - uint16_t id = event_id; |
| - |
| - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint32_t)); |
| - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| - break; |
| - } |
| - default: |
| - WARN_ON_ONCE(1); |
| - } |
| - |
| - ctx_record(ctx, ltt_chan, ltt_chan->ctx); |
| - ctx_record(ctx, ltt_chan, event->ctx); |
| - lib_ring_buffer_align_ctx(ctx, ctx->largest_align); |
| - |
| - return; |
| - |
| -slow_path: |
| - ltt_write_event_header_slow(config, ctx, event_id); |
| -} |
| - |
| -static |
| -void ltt_write_event_header_slow(const struct lib_ring_buffer_config *config, |
| - struct lib_ring_buffer_ctx *ctx, |
| - uint32_t event_id) |
| -{ |
| - struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); |
| - struct ltt_event *event = ctx->priv; |
| - |
| - switch (ltt_chan->header_type) { |
| - case 1: /* compact */ |
| - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { |
| - uint32_t id_time = 0; |
| - |
| - bt_bitfield_write(&id_time, uint32_t, 0, 5, event_id); |
| - bt_bitfield_write(&id_time, uint32_t, 5, 27, ctx->tsc); |
| - lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); |
| - } else { |
| - uint8_t id = 0; |
| - uint64_t timestamp = ctx->tsc; |
| - |
| - bt_bitfield_write(&id, uint8_t, 0, 5, 31); |
| - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| - /* Align extended struct on largest member */ |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); |
| - lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); |
| - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| - } |
| - break; |
| - case 2: /* large */ |
| - { |
| - if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTT_RFLAG_EXTENDED))) { |
| - uint32_t timestamp = (uint32_t) ctx->tsc; |
| - uint16_t id = event_id; |
| - |
| - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint32_t)); |
| - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| - } else { |
| - uint16_t id = 65535; |
| - uint64_t timestamp = ctx->tsc; |
| - |
| - lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| - /* Align extended struct on largest member */ |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); |
| - lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(uint64_t)); |
| - lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| - } |
| - break; |
| - } |
| - default: |
| - WARN_ON_ONCE(1); |
| - } |
| - ctx_record(ctx, ltt_chan, ltt_chan->ctx); |
| - ctx_record(ctx, ltt_chan, event->ctx); |
| - lib_ring_buffer_align_ctx(ctx, ctx->largest_align); |
| -} |
| - |
| -static const struct lib_ring_buffer_config client_config; |
| - |
| -static u64 client_ring_buffer_clock_read(struct channel *chan) |
| -{ |
| - return lib_ring_buffer_clock_read(chan); |
| -} |
| - |
| -static |
| -size_t client_record_header_size(const struct lib_ring_buffer_config *config, |
| - struct channel *chan, size_t offset, |
| - size_t *pre_header_padding, |
| - struct lib_ring_buffer_ctx *ctx) |
| -{ |
| - return record_header_size(config, chan, offset, |
| - pre_header_padding, ctx); |
| -} |
| - |
| -/** |
| - * client_packet_header_size - called on buffer-switch to a new sub-buffer |
| - * |
| - * Return header size without padding after the structure. Don't use packed |
| - * structure because gcc generates inefficient code on some architectures |
| - * (powerpc, mips..) |
| - */ |
| -static size_t client_packet_header_size(void) |
| -{ |
| - return offsetof(struct packet_header, ctx.header_end); |
| -} |
| - |
| -static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc, |
| - unsigned int subbuf_idx) |
| -{ |
| - struct channel *chan = buf->backend.chan; |
| - struct packet_header *header = |
| - (struct packet_header *) |
| - lib_ring_buffer_offset_address(&buf->backend, |
| - subbuf_idx * chan->backend.subbuf_size); |
| - struct ltt_channel *ltt_chan = channel_get_private(chan); |
| - struct ltt_session *session = ltt_chan->session; |
| - |
| - header->magic = CTF_MAGIC_NUMBER; |
| - memcpy(header->uuid, session->uuid.b, sizeof(session->uuid)); |
| - header->stream_id = ltt_chan->id; |
| - header->ctx.timestamp_begin = tsc; |
| - header->ctx.timestamp_end = 0; |
| - header->ctx.events_discarded = 0; |
| - header->ctx.content_size = 0xFFFFFFFF; /* for debugging */ |
| - header->ctx.packet_size = 0xFFFFFFFF; |
| - header->ctx.cpu_id = buf->backend.cpu; |
| -} |
| - |
| -/* |
| - * offset is assumed to never be 0 here : never deliver a completely empty |
| - * subbuffer. data_size is between 1 and subbuf_size. |
| - */ |
| -static void client_buffer_end(struct lib_ring_buffer *buf, u64 tsc, |
| - unsigned int subbuf_idx, unsigned long data_size) |
| -{ |
| - struct channel *chan = buf->backend.chan; |
| - struct packet_header *header = |
| - (struct packet_header *) |
| - lib_ring_buffer_offset_address(&buf->backend, |
| - subbuf_idx * chan->backend.subbuf_size); |
| - unsigned long records_lost = 0; |
| - |
| - header->ctx.timestamp_end = tsc; |
| - header->ctx.content_size = data_size * CHAR_BIT; /* in bits */ |
| - header->ctx.packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ |
| - records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf); |
| - records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); |
| - records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); |
| - header->ctx.events_discarded = records_lost; |
| -} |
| - |
| -static int client_buffer_create(struct lib_ring_buffer *buf, void *priv, |
| - int cpu, const char *name) |
| -{ |
| - return 0; |
| -} |
| - |
| -static void client_buffer_finalize(struct lib_ring_buffer *buf, void *priv, int cpu) |
| -{ |
| -} |
| - |
| -static const struct lib_ring_buffer_config client_config = { |
| - .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, |
| - .cb.record_header_size = client_record_header_size, |
| - .cb.subbuffer_header_size = client_packet_header_size, |
| - .cb.buffer_begin = client_buffer_begin, |
| - .cb.buffer_end = client_buffer_end, |
| - .cb.buffer_create = client_buffer_create, |
| - .cb.buffer_finalize = client_buffer_finalize, |
| - |
| - .tsc_bits = 32, |
| - .alloc = RING_BUFFER_ALLOC_PER_CPU, |
| - .sync = RING_BUFFER_SYNC_PER_CPU, |
| - .mode = RING_BUFFER_MODE_TEMPLATE, |
| - .backend = RING_BUFFER_PAGE, |
| - .output = RING_BUFFER_OUTPUT_TEMPLATE, |
| - .oops = RING_BUFFER_OOPS_CONSISTENCY, |
| - .ipi = RING_BUFFER_IPI_BARRIER, |
| - .wakeup = RING_BUFFER_WAKEUP_BY_TIMER, |
| -}; |
| - |
| -static |
| -struct channel *_channel_create(const char *name, |
| - struct ltt_channel *ltt_chan, void *buf_addr, |
| - size_t subbuf_size, size_t num_subbuf, |
| - unsigned int switch_timer_interval, |
| - unsigned int read_timer_interval) |
| -{ |
| - return channel_create(&client_config, name, ltt_chan, buf_addr, |
| - subbuf_size, num_subbuf, switch_timer_interval, |
| - read_timer_interval); |
| -} |
| - |
| -static |
| -void ltt_channel_destroy(struct channel *chan) |
| -{ |
| - channel_destroy(chan); |
| -} |
| - |
| -static |
| -struct lib_ring_buffer *ltt_buffer_read_open(struct channel *chan) |
| -{ |
| - struct lib_ring_buffer *buf; |
| - int cpu; |
| - |
| - for_each_channel_cpu(cpu, chan) { |
| - buf = channel_get_ring_buffer(&client_config, chan, cpu); |
| - if (!lib_ring_buffer_open_read(buf)) |
| - return buf; |
| - } |
| - return NULL; |
| -} |
| - |
| -static |
| -int ltt_buffer_has_read_closed_stream(struct channel *chan) |
| -{ |
| - struct lib_ring_buffer *buf; |
| - int cpu; |
| - |
| - for_each_channel_cpu(cpu, chan) { |
| - buf = channel_get_ring_buffer(&client_config, chan, cpu); |
| - if (!atomic_long_read(&buf->active_readers)) |
| - return 1; |
| - } |
| - return 0; |
| -} |
| - |
| -static |
| -void ltt_buffer_read_close(struct lib_ring_buffer *buf) |
| -{ |
| - lib_ring_buffer_release_read(buf); |
| -} |
| - |
| -static |
| -int ltt_event_reserve(struct lib_ring_buffer_ctx *ctx, |
| - uint32_t event_id) |
| -{ |
| - struct ltt_channel *ltt_chan = channel_get_private(ctx->chan); |
| - int ret, cpu; |
| - |
| - cpu = lib_ring_buffer_get_cpu(&client_config); |
| - if (cpu < 0) |
| - return -EPERM; |
| - ctx->cpu = cpu; |
| - |
| - switch (ltt_chan->header_type) { |
| - case 1: /* compact */ |
| - if (event_id > 30) |
| - ctx->rflags |= LTT_RFLAG_EXTENDED; |
| - break; |
| - case 2: /* large */ |
| - if (event_id > 65534) |
| - ctx->rflags |= LTT_RFLAG_EXTENDED; |
| - break; |
| - default: |
| - WARN_ON_ONCE(1); |
| - } |
| - |
| - ret = lib_ring_buffer_reserve(&client_config, ctx); |
| - if (ret) |
| - goto put; |
| - ltt_write_event_header(&client_config, ctx, event_id); |
| - return 0; |
| -put: |
| - lib_ring_buffer_put_cpu(&client_config); |
| - return ret; |
| -} |
| - |
| -static |
| -void ltt_event_commit(struct lib_ring_buffer_ctx *ctx) |
| -{ |
| - lib_ring_buffer_commit(&client_config, ctx); |
| - lib_ring_buffer_put_cpu(&client_config); |
| -} |
| - |
| -static |
| -void ltt_event_write(struct lib_ring_buffer_ctx *ctx, const void *src, |
| - size_t len) |
| -{ |
| - lib_ring_buffer_write(&client_config, ctx, src, len); |
| -} |
| - |
| -static |
| -void ltt_event_write_from_user(struct lib_ring_buffer_ctx *ctx, |
| - const void __user *src, size_t len) |
| -{ |
| - lib_ring_buffer_copy_from_user(&client_config, ctx, src, len); |
| -} |
| - |
| -static |
| -void ltt_event_memset(struct lib_ring_buffer_ctx *ctx, |
| - int c, size_t len) |
| -{ |
| - lib_ring_buffer_memset(&client_config, ctx, c, len); |
| -} |
| - |
| -static |
| -wait_queue_head_t *ltt_get_writer_buf_wait_queue(struct channel *chan, int cpu) |
| -{ |
| - struct lib_ring_buffer *buf = channel_get_ring_buffer(&client_config, |
| - chan, cpu); |
| - return &buf->write_wait; |
| -} |
| - |
| -static |
| -wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan) |
| -{ |
| - return &chan->hp_wait; |
| -} |
| - |
| -static |
| -int ltt_is_finalized(struct channel *chan) |
| -{ |
| - return lib_ring_buffer_channel_is_finalized(chan); |
| -} |
| - |
| -static |
| -int ltt_is_disabled(struct channel *chan) |
| -{ |
| - return lib_ring_buffer_channel_is_disabled(chan); |
| -} |
| - |
| -static struct ltt_transport ltt_relay_transport = { |
| - .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING, |
| - .owner = THIS_MODULE, |
| - .ops = { |
| - .channel_create = _channel_create, |
| - .channel_destroy = ltt_channel_destroy, |
| - .buffer_read_open = ltt_buffer_read_open, |
| - .buffer_has_read_closed_stream = |
| - ltt_buffer_has_read_closed_stream, |
| - .buffer_read_close = ltt_buffer_read_close, |
| - .event_reserve = ltt_event_reserve, |
| - .event_commit = ltt_event_commit, |
| - .event_write = ltt_event_write, |
| - .event_write_from_user = ltt_event_write_from_user, |
| - .event_memset = ltt_event_memset, |
| - .packet_avail_size = NULL, /* Would be racy anyway */ |
| - .get_writer_buf_wait_queue = ltt_get_writer_buf_wait_queue, |
| - .get_hp_wait_queue = ltt_get_hp_wait_queue, |
| - .is_finalized = ltt_is_finalized, |
| - .is_disabled = ltt_is_disabled, |
| - }, |
| -}; |
| - |
| -static int __init ltt_ring_buffer_client_init(void) |
| -{ |
| - /* |
| - * This vmalloc sync all also takes care of the lib ring buffer |
| - * vmalloc'd module pages when it is built as a module into LTTng. |
| - */ |
| - wrapper_vmalloc_sync_all(); |
| - ltt_transport_register(<t_relay_transport); |
| - return 0; |
| -} |
| - |
| -module_init(ltt_ring_buffer_client_init); |
| - |
| -static void __exit ltt_ring_buffer_client_exit(void) |
| -{ |
| - ltt_transport_unregister(<t_relay_transport); |
| -} |
| - |
| -module_exit(ltt_ring_buffer_client_exit); |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng ring buffer " RING_BUFFER_MODE_TEMPLATE_STRING |
| - " client"); |
| --- a/drivers/staging/lttng/ltt-ring-buffer-metadata-client.c |
| +++ /dev/null |
| @@ -1,21 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-metadata-client.c |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer metadta client. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include "ltt-tracer.h" |
| - |
| -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| -#define RING_BUFFER_MODE_TEMPLATE_STRING "metadata" |
| -#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_SPLICE |
| -#include "ltt-ring-buffer-metadata-client.h" |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng Ring Buffer Metadata Client"); |
| --- a/drivers/staging/lttng/ltt-ring-buffer-metadata-client.h |
| +++ /dev/null |
| @@ -1,330 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-client.h |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer client template. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include <linux/types.h> |
| -#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| -#include "ltt-events.h" |
| -#include "ltt-tracer.h" |
| - |
| -struct metadata_packet_header { |
| - uint32_t magic; /* 0x75D11D57 */ |
| - uint8_t uuid[16]; /* Unique Universal Identifier */ |
| - uint32_t checksum; /* 0 if unused */ |
| - uint32_t content_size; /* in bits */ |
| - uint32_t packet_size; /* in bits */ |
| - uint8_t compression_scheme; /* 0 if unused */ |
| - uint8_t encryption_scheme; /* 0 if unused */ |
| - uint8_t checksum_scheme; /* 0 if unused */ |
| - uint8_t major; /* CTF spec major version number */ |
| - uint8_t minor; /* CTF spec minor version number */ |
| - uint8_t header_end[0]; |
| -}; |
| - |
| -struct metadata_record_header { |
| - uint8_t header_end[0]; /* End of header */ |
| -}; |
| - |
| -static const struct lib_ring_buffer_config client_config; |
| - |
| -static inline |
| -u64 lib_ring_buffer_clock_read(struct channel *chan) |
| -{ |
| - return 0; |
| -} |
| - |
| -static inline |
| -unsigned char record_header_size(const struct lib_ring_buffer_config *config, |
| - struct channel *chan, size_t offset, |
| - size_t *pre_header_padding, |
| - struct lib_ring_buffer_ctx *ctx) |
| -{ |
| - return 0; |
| -} |
| - |
| -#include "wrapper/ringbuffer/api.h" |
| - |
| -static u64 client_ring_buffer_clock_read(struct channel *chan) |
| -{ |
| - return 0; |
| -} |
| - |
| -static |
| -size_t client_record_header_size(const struct lib_ring_buffer_config *config, |
| - struct channel *chan, size_t offset, |
| - size_t *pre_header_padding, |
| - struct lib_ring_buffer_ctx *ctx) |
| -{ |
| - return 0; |
| -} |
| - |
| -/** |
| - * client_packet_header_size - called on buffer-switch to a new sub-buffer |
| - * |
| - * Return header size without padding after the structure. Don't use packed |
| - * structure because gcc generates inefficient code on some architectures |
| - * (powerpc, mips..) |
| - */ |
| -static size_t client_packet_header_size(void) |
| -{ |
| - return offsetof(struct metadata_packet_header, header_end); |
| -} |
| - |
| -static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc, |
| - unsigned int subbuf_idx) |
| -{ |
| - struct channel *chan = buf->backend.chan; |
| - struct metadata_packet_header *header = |
| - (struct metadata_packet_header *) |
| - lib_ring_buffer_offset_address(&buf->backend, |
| - subbuf_idx * chan->backend.subbuf_size); |
| - struct ltt_channel *ltt_chan = channel_get_private(chan); |
| - struct ltt_session *session = ltt_chan->session; |
| - |
| - header->magic = TSDL_MAGIC_NUMBER; |
| - memcpy(header->uuid, session->uuid.b, sizeof(session->uuid)); |
| - header->checksum = 0; /* 0 if unused */ |
| - header->content_size = 0xFFFFFFFF; /* in bits, for debugging */ |
| - header->packet_size = 0xFFFFFFFF; /* in bits, for debugging */ |
| - header->compression_scheme = 0; /* 0 if unused */ |
| - header->encryption_scheme = 0; /* 0 if unused */ |
| - header->checksum_scheme = 0; /* 0 if unused */ |
| - header->major = CTF_SPEC_MAJOR; |
| - header->minor = CTF_SPEC_MINOR; |
| -} |
| - |
| -/* |
| - * offset is assumed to never be 0 here : never deliver a completely empty |
| - * subbuffer. data_size is between 1 and subbuf_size. |
| - */ |
| -static void client_buffer_end(struct lib_ring_buffer *buf, u64 tsc, |
| - unsigned int subbuf_idx, unsigned long data_size) |
| -{ |
| - struct channel *chan = buf->backend.chan; |
| - struct metadata_packet_header *header = |
| - (struct metadata_packet_header *) |
| - lib_ring_buffer_offset_address(&buf->backend, |
| - subbuf_idx * chan->backend.subbuf_size); |
| - unsigned long records_lost = 0; |
| - |
| - header->content_size = data_size * CHAR_BIT; /* in bits */ |
| - header->packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ |
| - /* |
| - * We do not care about the records lost count, because the metadata |
| - * channel waits and retry. |
| - */ |
| - (void) lib_ring_buffer_get_records_lost_full(&client_config, buf); |
| - records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); |
| - records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); |
| - WARN_ON_ONCE(records_lost != 0); |
| -} |
| - |
| -static int client_buffer_create(struct lib_ring_buffer *buf, void *priv, |
| - int cpu, const char *name) |
| -{ |
| - return 0; |
| -} |
| - |
| -static void client_buffer_finalize(struct lib_ring_buffer *buf, void *priv, int cpu) |
| -{ |
| -} |
| - |
| -static const struct lib_ring_buffer_config client_config = { |
| - .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, |
| - .cb.record_header_size = client_record_header_size, |
| - .cb.subbuffer_header_size = client_packet_header_size, |
| - .cb.buffer_begin = client_buffer_begin, |
| - .cb.buffer_end = client_buffer_end, |
| - .cb.buffer_create = client_buffer_create, |
| - .cb.buffer_finalize = client_buffer_finalize, |
| - |
| - .tsc_bits = 0, |
| - .alloc = RING_BUFFER_ALLOC_GLOBAL, |
| - .sync = RING_BUFFER_SYNC_GLOBAL, |
| - .mode = RING_BUFFER_MODE_TEMPLATE, |
| - .backend = RING_BUFFER_PAGE, |
| - .output = RING_BUFFER_OUTPUT_TEMPLATE, |
| - .oops = RING_BUFFER_OOPS_CONSISTENCY, |
| - .ipi = RING_BUFFER_IPI_BARRIER, |
| - .wakeup = RING_BUFFER_WAKEUP_BY_TIMER, |
| -}; |
| - |
| -static |
| -struct channel *_channel_create(const char *name, |
| - struct ltt_channel *ltt_chan, void *buf_addr, |
| - size_t subbuf_size, size_t num_subbuf, |
| - unsigned int switch_timer_interval, |
| - unsigned int read_timer_interval) |
| -{ |
| - return channel_create(&client_config, name, ltt_chan, buf_addr, |
| - subbuf_size, num_subbuf, switch_timer_interval, |
| - read_timer_interval); |
| -} |
| - |
| -static |
| -void ltt_channel_destroy(struct channel *chan) |
| -{ |
| - channel_destroy(chan); |
| -} |
| - |
| -static |
| -struct lib_ring_buffer *ltt_buffer_read_open(struct channel *chan) |
| -{ |
| - struct lib_ring_buffer *buf; |
| - |
| - buf = channel_get_ring_buffer(&client_config, chan, 0); |
| - if (!lib_ring_buffer_open_read(buf)) |
| - return buf; |
| - return NULL; |
| -} |
| - |
| -static |
| -int ltt_buffer_has_read_closed_stream(struct channel *chan) |
| -{ |
| - struct lib_ring_buffer *buf; |
| - int cpu; |
| - |
| - for_each_channel_cpu(cpu, chan) { |
| - buf = channel_get_ring_buffer(&client_config, chan, cpu); |
| - if (!atomic_long_read(&buf->active_readers)) |
| - return 1; |
| - } |
| - return 0; |
| -} |
| - |
| -static |
| -void ltt_buffer_read_close(struct lib_ring_buffer *buf) |
| -{ |
| - lib_ring_buffer_release_read(buf); |
| -} |
| - |
| -static |
| -int ltt_event_reserve(struct lib_ring_buffer_ctx *ctx, uint32_t event_id) |
| -{ |
| - return lib_ring_buffer_reserve(&client_config, ctx); |
| -} |
| - |
| -static |
| -void ltt_event_commit(struct lib_ring_buffer_ctx *ctx) |
| -{ |
| - lib_ring_buffer_commit(&client_config, ctx); |
| -} |
| - |
| -static |
| -void ltt_event_write(struct lib_ring_buffer_ctx *ctx, const void *src, |
| - size_t len) |
| -{ |
| - lib_ring_buffer_write(&client_config, ctx, src, len); |
| -} |
| - |
| -static |
| -void ltt_event_write_from_user(struct lib_ring_buffer_ctx *ctx, |
| - const void __user *src, size_t len) |
| -{ |
| - lib_ring_buffer_copy_from_user(&client_config, ctx, src, len); |
| -} |
| - |
| -static |
| -void ltt_event_memset(struct lib_ring_buffer_ctx *ctx, |
| - int c, size_t len) |
| -{ |
| - lib_ring_buffer_memset(&client_config, ctx, c, len); |
| -} |
| - |
| -static |
| -size_t ltt_packet_avail_size(struct channel *chan) |
| - |
| -{ |
| - unsigned long o_begin; |
| - struct lib_ring_buffer *buf; |
| - |
| - buf = chan->backend.buf; /* Only for global buffer ! */ |
| - o_begin = v_read(&client_config, &buf->offset); |
| - if (subbuf_offset(o_begin, chan) != 0) { |
| - return chan->backend.subbuf_size - subbuf_offset(o_begin, chan); |
| - } else { |
| - return chan->backend.subbuf_size - subbuf_offset(o_begin, chan) |
| - - sizeof(struct metadata_packet_header); |
| - } |
| -} |
| - |
| -static |
| -wait_queue_head_t *ltt_get_writer_buf_wait_queue(struct channel *chan, int cpu) |
| -{ |
| - struct lib_ring_buffer *buf = channel_get_ring_buffer(&client_config, |
| - chan, cpu); |
| - return &buf->write_wait; |
| -} |
| - |
| -static |
| -wait_queue_head_t *ltt_get_hp_wait_queue(struct channel *chan) |
| -{ |
| - return &chan->hp_wait; |
| -} |
| - |
| -static |
| -int ltt_is_finalized(struct channel *chan) |
| -{ |
| - return lib_ring_buffer_channel_is_finalized(chan); |
| -} |
| - |
| -static |
| -int ltt_is_disabled(struct channel *chan) |
| -{ |
| - return lib_ring_buffer_channel_is_disabled(chan); |
| -} |
| - |
| -static struct ltt_transport ltt_relay_transport = { |
| - .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING, |
| - .owner = THIS_MODULE, |
| - .ops = { |
| - .channel_create = _channel_create, |
| - .channel_destroy = ltt_channel_destroy, |
| - .buffer_read_open = ltt_buffer_read_open, |
| - .buffer_has_read_closed_stream = |
| - ltt_buffer_has_read_closed_stream, |
| - .buffer_read_close = ltt_buffer_read_close, |
| - .event_reserve = ltt_event_reserve, |
| - .event_commit = ltt_event_commit, |
| - .event_write_from_user = ltt_event_write_from_user, |
| - .event_memset = ltt_event_memset, |
| - .event_write = ltt_event_write, |
| - .packet_avail_size = ltt_packet_avail_size, |
| - .get_writer_buf_wait_queue = ltt_get_writer_buf_wait_queue, |
| - .get_hp_wait_queue = ltt_get_hp_wait_queue, |
| - .is_finalized = ltt_is_finalized, |
| - .is_disabled = ltt_is_disabled, |
| - }, |
| -}; |
| - |
| -static int __init ltt_ring_buffer_client_init(void) |
| -{ |
| - /* |
| - * This vmalloc sync all also takes care of the lib ring buffer |
| - * vmalloc'd module pages when it is built as a module into LTTng. |
| - */ |
| - wrapper_vmalloc_sync_all(); |
| - ltt_transport_register(<t_relay_transport); |
| - return 0; |
| -} |
| - |
| -module_init(ltt_ring_buffer_client_init); |
| - |
| -static void __exit ltt_ring_buffer_client_exit(void) |
| -{ |
| - ltt_transport_unregister(<t_relay_transport); |
| -} |
| - |
| -module_exit(ltt_ring_buffer_client_exit); |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng ring buffer " RING_BUFFER_MODE_TEMPLATE_STRING |
| - " client"); |
| --- a/drivers/staging/lttng/ltt-ring-buffer-metadata-mmap-client.c |
| +++ /dev/null |
| @@ -1,21 +0,0 @@ |
| -/* |
| - * ltt-ring-buffer-metadata-client.c |
| - * |
| - * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * LTTng lib ring buffer metadta client. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/module.h> |
| -#include "ltt-tracer.h" |
| - |
| -#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| -#define RING_BUFFER_MODE_TEMPLATE_STRING "metadata-mmap" |
| -#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_MMAP |
| -#include "ltt-ring-buffer-metadata-client.h" |
| - |
| -MODULE_LICENSE("GPL and additional rights"); |
| -MODULE_AUTHOR("Mathieu Desnoyers"); |
| -MODULE_DESCRIPTION("LTTng Ring Buffer Metadata Client"); |
| --- a/drivers/staging/lttng/ltt-tracer-core.h |
| +++ /dev/null |
| @@ -1,28 +0,0 @@ |
| -#ifndef LTT_TRACER_CORE_H |
| -#define LTT_TRACER_CORE_H |
| - |
| -/* |
| - * ltt-tracer-core.h |
| - * |
| - * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * This contains the core definitions for the Linux Trace Toolkit. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <linux/list.h> |
| -#include <linux/percpu.h> |
| - |
| -#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
| -/* Align data on its natural alignment */ |
| -#define RING_BUFFER_ALIGN |
| -#endif |
| - |
| -#include "wrapper/ringbuffer/config.h" |
| - |
| -struct ltt_session; |
| -struct ltt_channel; |
| -struct ltt_event; |
| - |
| -#endif /* LTT_TRACER_CORE_H */ |
| --- a/drivers/staging/lttng/ltt-tracer.h |
| +++ /dev/null |
| @@ -1,67 +0,0 @@ |
| -#ifndef _LTT_TRACER_H |
| -#define _LTT_TRACER_H |
| - |
| -/* |
| - * ltt-tracer.h |
| - * |
| - * Copyright (C) 2005-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| - * This contains the definitions for the Linux Trace Toolkit tracer. |
| - * |
| - * Dual LGPL v2.1/GPL v2 license. |
| - */ |
| - |
| -#include <stdarg.h> |
| -#include <linux/types.h> |
| -#include <linux/limits.h> |
| -#include <linux/list.h> |
| -#include <linux/cache.h> |
| -#include <linux/timex.h> |
| -#include <linux/wait.h> |
| -#include <asm/atomic.h> |
| -#include <asm/local.h> |
| - |
| -#include "wrapper/trace-clock.h" |
| -#include "ltt-tracer-core.h" |
| -#include "ltt-events.h" |
| - |
| -#define LTTNG_VERSION 0 |
| -#define LTTNG_PATCHLEVEL 9 |
| -#define LTTNG_SUBLEVEL 1 |
| - |
| -#ifndef CHAR_BIT |
| -#define CHAR_BIT 8 |
| -#endif |
| - |
| -/* Number of bytes to log with a read/write event */ |
| -#define LTT_LOG_RW_SIZE 32L |
| -#define LTT_MAX_SMALL_SIZE 0xFFFFU |
| - |
| -#ifdef RING_BUFFER_ALIGN |
| -#define ltt_alignof(type) __alignof__(type) |
| -#else |
| -#define ltt_alignof(type) 1 |
| -#endif |
| - |
| -/* Tracer properties */ |
| -#define CTF_MAGIC_NUMBER 0xC1FC1FC1 |
| -#define TSDL_MAGIC_NUMBER 0x75D11D57 |
| - |
| -/* CTF specification version followed */ |
| -#define CTF_SPEC_MAJOR 1 |
| -#define CTF_SPEC_MINOR 8 |
| - |
| -/* Tracer major/minor versions */ |
| -#define CTF_VERSION_MAJOR 0 |
| -#define CTF_VERSION_MINOR 1 |
| - |
| -/* |
| - * Number of milliseconds to retry before failing metadata writes on buffer full |
| - * condition. (10 seconds) |
| - */ |
| -#define LTTNG_METADATA_TIMEOUT_MSEC 10000 |
| - |
| -#define LTT_RFLAG_EXTENDED RING_BUFFER_RFLAG_END |
| -#define LTT_RFLAG_END (LTT_RFLAG_EXTENDED << 1) |
| - |
| -#endif /* _LTT_TRACER_H */ |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-abi.c |
| @@ -0,0 +1,781 @@ |
| +/* |
| + * lttng-abi.c |
| + * |
| + * LTTng ABI |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| + * |
| + * Mimic system calls for: |
| + * - session creation, returns a file descriptor or failure. |
| + * - channel creation, returns a file descriptor or failure. |
| + * - Operates on a session file descriptor |
| + * - Takes all channel options as parameters. |
| + * - stream get, returns a file descriptor or failure. |
| + * - Operates on a channel file descriptor. |
| + * - stream notifier get, returns a file descriptor or failure. |
| + * - Operates on a channel file descriptor. |
| + * - event creation, returns a file descriptor or failure. |
| + * - Operates on a channel file descriptor |
| + * - Takes an event name as parameter |
| + * - Takes an instrumentation source as parameter |
| + * - e.g. tracepoints, dynamic_probes... |
| + * - Takes instrumentation source specific arguments. |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include <linux/proc_fs.h> |
| +#include <linux/anon_inodes.h> |
| +#include <linux/file.h> |
| +#include <linux/uaccess.h> |
| +#include <linux/slab.h> |
| +#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| +#include "wrapper/ringbuffer/vfs.h" |
| +#include "wrapper/poll.h" |
| +#include "lttng-abi.h" |
| +#include "lttng-events.h" |
| +#include "lttng-tracer.h" |
| + |
| +/* |
| + * This is LTTng's own personal way to create a system call as an external |
| + * module. We use ioctl() on /proc/lttng. |
| + */ |
| + |
| +static struct proc_dir_entry *lttng_proc_dentry; |
| +static const struct file_operations lttng_fops; |
| +static const struct file_operations lttng_session_fops; |
| +static const struct file_operations lttng_channel_fops; |
| +static const struct file_operations lttng_metadata_fops; |
| +static const struct file_operations lttng_event_fops; |
| + |
| +/* |
| + * Teardown management: opened file descriptors keep a refcount on the module, |
| + * so it can only exit when all file descriptors are closed. |
| + */ |
| + |
| +enum channel_type { |
| + PER_CPU_CHANNEL, |
| + METADATA_CHANNEL, |
| +}; |
| + |
| +static |
| +int lttng_abi_create_session(void) |
| +{ |
| + struct lttng_session *session; |
| + struct file *session_file; |
| + int session_fd, ret; |
| + |
| + session = lttng_session_create(); |
| + if (!session) |
| + return -ENOMEM; |
| + session_fd = get_unused_fd(); |
| + if (session_fd < 0) { |
| + ret = session_fd; |
| + goto fd_error; |
| + } |
| + session_file = anon_inode_getfile("[lttng_session]", |
| + <tng_session_fops, |
| + session, O_RDWR); |
| + if (IS_ERR(session_file)) { |
| + ret = PTR_ERR(session_file); |
| + goto file_error; |
| + } |
| + session->file = session_file; |
| + fd_install(session_fd, session_file); |
| + return session_fd; |
| + |
| +file_error: |
| + put_unused_fd(session_fd); |
| +fd_error: |
| + lttng_session_destroy(session); |
| + return ret; |
| +} |
| + |
| +static |
| +int lttng_abi_tracepoint_list(void) |
| +{ |
| + struct file *tracepoint_list_file; |
| + int file_fd, ret; |
| + |
| + file_fd = get_unused_fd(); |
| + if (file_fd < 0) { |
| + ret = file_fd; |
| + goto fd_error; |
| + } |
| + |
| + tracepoint_list_file = anon_inode_getfile("[lttng_session]", |
| + <tng_tracepoint_list_fops, |
| + NULL, O_RDWR); |
| + if (IS_ERR(tracepoint_list_file)) { |
| + ret = PTR_ERR(tracepoint_list_file); |
| + goto file_error; |
| + } |
| + ret = lttng_tracepoint_list_fops.open(NULL, tracepoint_list_file); |
| + if (ret < 0) |
| + goto open_error; |
| + fd_install(file_fd, tracepoint_list_file); |
| + if (file_fd < 0) { |
| + ret = file_fd; |
| + goto fd_error; |
| + } |
| + return file_fd; |
| + |
| +open_error: |
| + fput(tracepoint_list_file); |
| +file_error: |
| + put_unused_fd(file_fd); |
| +fd_error: |
| + return ret; |
| +} |
| + |
| +static |
| +long lttng_abi_tracer_version(struct file *file, |
| + struct lttng_kernel_tracer_version __user *uversion_param) |
| +{ |
| + struct lttng_kernel_tracer_version v; |
| + |
| + v.major = LTTNG_MODULES_MAJOR_VERSION; |
| + v.minor = LTTNG_MODULES_MINOR_VERSION; |
| + v.patchlevel = LTTNG_MODULES_PATCHLEVEL_VERSION; |
| + |
| + if (copy_to_user(uversion_param, &v, sizeof(v))) |
| + return -EFAULT; |
| + return 0; |
| +} |
| + |
| +static |
| +long lttng_abi_add_context(struct file *file, |
| + struct lttng_kernel_context __user *ucontext_param, |
| + struct lttng_ctx **ctx, struct lttng_session *session) |
| +{ |
| + struct lttng_kernel_context context_param; |
| + |
| + if (session->been_active) |
| + return -EPERM; |
| + |
| + if (copy_from_user(&context_param, ucontext_param, sizeof(context_param))) |
| + return -EFAULT; |
| + |
| + switch (context_param.ctx) { |
| + case LTTNG_KERNEL_CONTEXT_PID: |
| + return lttng_add_pid_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_PRIO: |
| + return lttng_add_prio_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_NICE: |
| + return lttng_add_nice_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_VPID: |
| + return lttng_add_vpid_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_TID: |
| + return lttng_add_tid_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_VTID: |
| + return lttng_add_vtid_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_PPID: |
| + return lttng_add_ppid_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_VPPID: |
| + return lttng_add_vppid_to_ctx(ctx); |
| + case LTTNG_KERNEL_CONTEXT_PERF_COUNTER: |
| + context_param.u.perf_counter.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| + return lttng_add_perf_counter_to_ctx(context_param.u.perf_counter.type, |
| + context_param.u.perf_counter.config, |
| + context_param.u.perf_counter.name, |
| + ctx); |
| + case LTTNG_KERNEL_CONTEXT_PROCNAME: |
| + return lttng_add_procname_to_ctx(ctx); |
| + default: |
| + return -EINVAL; |
| + } |
| +} |
| + |
| +/** |
| + * lttng_ioctl - lttng syscall through ioctl |
| + * |
| + * @file: the file |
| + * @cmd: the command |
| + * @arg: command arg |
| + * |
| + * This ioctl implements lttng commands: |
| + * LTTNG_KERNEL_SESSION |
| + * Returns a LTTng trace session file descriptor |
| + * LTTNG_KERNEL_TRACER_VERSION |
| + * Returns the LTTng kernel tracer version |
| + * LTTNG_KERNEL_TRACEPOINT_LIST |
| + * Returns a file descriptor listing available tracepoints |
| + * LTTNG_KERNEL_WAIT_QUIESCENT |
| + * Returns after all previously running probes have completed |
| + * |
| + * The returned session will be deleted when its file descriptor is closed. |
| + */ |
| +static |
| +long lttng_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| +{ |
| + switch (cmd) { |
| + case LTTNG_KERNEL_SESSION: |
| + return lttng_abi_create_session(); |
| + case LTTNG_KERNEL_TRACER_VERSION: |
| + return lttng_abi_tracer_version(file, |
| + (struct lttng_kernel_tracer_version __user *) arg); |
| + case LTTNG_KERNEL_TRACEPOINT_LIST: |
| + return lttng_abi_tracepoint_list(); |
| + case LTTNG_KERNEL_WAIT_QUIESCENT: |
| + synchronize_trace(); |
| + return 0; |
| + case LTTNG_KERNEL_CALIBRATE: |
| + { |
| + struct lttng_kernel_calibrate __user *ucalibrate = |
| + (struct lttng_kernel_calibrate __user *) arg; |
| + struct lttng_kernel_calibrate calibrate; |
| + int ret; |
| + |
| + if (copy_from_user(&calibrate, ucalibrate, sizeof(calibrate))) |
| + return -EFAULT; |
| + ret = lttng_calibrate(&calibrate); |
| + if (copy_to_user(ucalibrate, &calibrate, sizeof(calibrate))) |
| + return -EFAULT; |
| + return ret; |
| + } |
| + default: |
| + return -ENOIOCTLCMD; |
| + } |
| +} |
| + |
| +static const struct file_operations lttng_fops = { |
| + .owner = THIS_MODULE, |
| + .unlocked_ioctl = lttng_ioctl, |
| +#ifdef CONFIG_COMPAT |
| + .compat_ioctl = lttng_ioctl, |
| +#endif |
| +}; |
| + |
| +/* |
| + * We tolerate no failure in this function (if one happens, we print a dmesg |
| + * error, but cannot return any error, because the channel information is |
| + * invariant. |
| + */ |
| +static |
| +void lttng_metadata_create_events(struct file *channel_file) |
| +{ |
| + struct lttng_channel *channel = channel_file->private_data; |
| + static struct lttng_kernel_event metadata_params = { |
| + .instrumentation = LTTNG_KERNEL_TRACEPOINT, |
| + .name = "lttng_metadata", |
| + }; |
| + struct lttng_event *event; |
| + |
| + /* |
| + * We tolerate no failure path after event creation. It will stay |
| + * invariant for the rest of the session. |
| + */ |
| + event = lttng_event_create(channel, &metadata_params, NULL, NULL); |
| + if (!event) { |
| + goto create_error; |
| + } |
| + return; |
| + |
| +create_error: |
| + WARN_ON(1); |
| + return; /* not allowed to return error */ |
| +} |
| + |
| +static |
| +int lttng_abi_create_channel(struct file *session_file, |
| + struct lttng_kernel_channel __user *uchan_param, |
| + enum channel_type channel_type) |
| +{ |
| + struct lttng_session *session = session_file->private_data; |
| + const struct file_operations *fops = NULL; |
| + const char *transport_name; |
| + struct lttng_channel *chan; |
| + struct file *chan_file; |
| + struct lttng_kernel_channel chan_param; |
| + int chan_fd; |
| + int ret = 0; |
| + |
| + if (copy_from_user(&chan_param, uchan_param, sizeof(chan_param))) |
| + return -EFAULT; |
| + chan_fd = get_unused_fd(); |
| + if (chan_fd < 0) { |
| + ret = chan_fd; |
| + goto fd_error; |
| + } |
| + switch (channel_type) { |
| + case PER_CPU_CHANNEL: |
| + fops = <tng_channel_fops; |
| + break; |
| + case METADATA_CHANNEL: |
| + fops = <tng_metadata_fops; |
| + break; |
| + } |
| + |
| + chan_file = anon_inode_getfile("[lttng_channel]", |
| + fops, |
| + NULL, O_RDWR); |
| + if (IS_ERR(chan_file)) { |
| + ret = PTR_ERR(chan_file); |
| + goto file_error; |
| + } |
| + switch (channel_type) { |
| + case PER_CPU_CHANNEL: |
| + if (chan_param.output == LTTNG_KERNEL_SPLICE) { |
| + transport_name = chan_param.overwrite ? |
| + "relay-overwrite" : "relay-discard"; |
| + } else if (chan_param.output == LTTNG_KERNEL_MMAP) { |
| + transport_name = chan_param.overwrite ? |
| + "relay-overwrite-mmap" : "relay-discard-mmap"; |
| + } else { |
| + return -EINVAL; |
| + } |
| + break; |
| + case METADATA_CHANNEL: |
| + if (chan_param.output == LTTNG_KERNEL_SPLICE) |
| + transport_name = "relay-metadata"; |
| + else if (chan_param.output == LTTNG_KERNEL_MMAP) |
| + transport_name = "relay-metadata-mmap"; |
| + else |
| + return -EINVAL; |
| + break; |
| + default: |
| + transport_name = "<unknown>"; |
| + break; |
| + } |
| + /* |
| + * We tolerate no failure path after channel creation. It will stay |
| + * invariant for the rest of the session. |
| + */ |
| + chan = lttng_channel_create(session, transport_name, NULL, |
| + chan_param.subbuf_size, |
| + chan_param.num_subbuf, |
| + chan_param.switch_timer_interval, |
| + chan_param.read_timer_interval); |
| + if (!chan) { |
| + ret = -EINVAL; |
| + goto chan_error; |
| + } |
| + chan->file = chan_file; |
| + chan_file->private_data = chan; |
| + fd_install(chan_fd, chan_file); |
| + if (channel_type == METADATA_CHANNEL) { |
| + session->metadata = chan; |
| + lttng_metadata_create_events(chan_file); |
| + } |
| + |
| + /* The channel created holds a reference on the session */ |
| + atomic_long_inc(&session_file->f_count); |
| + |
| + return chan_fd; |
| + |
| +chan_error: |
| + fput(chan_file); |
| +file_error: |
| + put_unused_fd(chan_fd); |
| +fd_error: |
| + return ret; |
| +} |
| + |
| +/** |
| + * lttng_session_ioctl - lttng session fd ioctl |
| + * |
| + * @file: the file |
| + * @cmd: the command |
| + * @arg: command arg |
| + * |
| + * This ioctl implements lttng commands: |
| + * LTTNG_KERNEL_CHANNEL |
| + * Returns a LTTng channel file descriptor |
| + * LTTNG_KERNEL_ENABLE |
| + * Enables tracing for a session (weak enable) |
| + * LTTNG_KERNEL_DISABLE |
| + * Disables tracing for a session (strong disable) |
| + * LTTNG_KERNEL_METADATA |
| + * Returns a LTTng metadata file descriptor |
| + * |
| + * The returned channel will be deleted when its file descriptor is closed. |
| + */ |
| +static |
| +long lttng_session_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| +{ |
| + struct lttng_session *session = file->private_data; |
| + |
| + switch (cmd) { |
| + case LTTNG_KERNEL_CHANNEL: |
| + return lttng_abi_create_channel(file, |
| + (struct lttng_kernel_channel __user *) arg, |
| + PER_CPU_CHANNEL); |
| + case LTTNG_KERNEL_SESSION_START: |
| + case LTTNG_KERNEL_ENABLE: |
| + return lttng_session_enable(session); |
| + case LTTNG_KERNEL_SESSION_STOP: |
| + case LTTNG_KERNEL_DISABLE: |
| + return lttng_session_disable(session); |
| + case LTTNG_KERNEL_METADATA: |
| + return lttng_abi_create_channel(file, |
| + (struct lttng_kernel_channel __user *) arg, |
| + METADATA_CHANNEL); |
| + default: |
| + return -ENOIOCTLCMD; |
| + } |
| +} |
| + |
| +/* |
| + * Called when the last file reference is dropped. |
| + * |
| + * Big fat note: channels and events are invariant for the whole session after |
| + * their creation. So this session destruction also destroys all channel and |
| + * event structures specific to this session (they are not destroyed when their |
| + * individual file is released). |
| + */ |
| +static |
| +int lttng_session_release(struct inode *inode, struct file *file) |
| +{ |
| + struct lttng_session *session = file->private_data; |
| + |
| + if (session) |
| + lttng_session_destroy(session); |
| + return 0; |
| +} |
| + |
| +static const struct file_operations lttng_session_fops = { |
| + .owner = THIS_MODULE, |
| + .release = lttng_session_release, |
| + .unlocked_ioctl = lttng_session_ioctl, |
| +#ifdef CONFIG_COMPAT |
| + .compat_ioctl = lttng_session_ioctl, |
| +#endif |
| +}; |
| + |
| +static |
| +int lttng_abi_open_stream(struct file *channel_file) |
| +{ |
| + struct lttng_channel *channel = channel_file->private_data; |
| + struct lib_ring_buffer *buf; |
| + int stream_fd, ret; |
| + struct file *stream_file; |
| + |
| + buf = channel->ops->buffer_read_open(channel->chan); |
| + if (!buf) |
| + return -ENOENT; |
| + |
| + stream_fd = get_unused_fd(); |
| + if (stream_fd < 0) { |
| + ret = stream_fd; |
| + goto fd_error; |
| + } |
| + stream_file = anon_inode_getfile("[lttng_stream]", |
| + &lib_ring_buffer_file_operations, |
| + buf, O_RDWR); |
| + if (IS_ERR(stream_file)) { |
| + ret = PTR_ERR(stream_file); |
| + goto file_error; |
| + } |
| + /* |
| + * OPEN_FMODE, called within anon_inode_getfile/alloc_file, don't honor |
| + * FMODE_LSEEK, FMODE_PREAD nor FMODE_PWRITE. We need to read from this |
| + * file descriptor, so we set FMODE_PREAD here. |
| + */ |
| + stream_file->f_mode |= FMODE_PREAD; |
| + fd_install(stream_fd, stream_file); |
| + /* |
| + * The stream holds a reference to the channel within the generic ring |
| + * buffer library, so no need to hold a refcount on the channel and |
| + * session files here. |
| + */ |
| + return stream_fd; |
| + |
| +file_error: |
| + put_unused_fd(stream_fd); |
| +fd_error: |
| + channel->ops->buffer_read_close(buf); |
| + return ret; |
| +} |
| + |
| +static |
| +int lttng_abi_create_event(struct file *channel_file, |
| + struct lttng_kernel_event __user *uevent_param) |
| +{ |
| + struct lttng_channel *channel = channel_file->private_data; |
| + struct lttng_event *event; |
| + struct lttng_kernel_event event_param; |
| + int event_fd, ret; |
| + struct file *event_file; |
| + |
| + if (copy_from_user(&event_param, uevent_param, sizeof(event_param))) |
| + return -EFAULT; |
| + event_param.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| + switch (event_param.instrumentation) { |
| + case LTTNG_KERNEL_KRETPROBE: |
| + event_param.u.kretprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| + break; |
| + case LTTNG_KERNEL_KPROBE: |
| + event_param.u.kprobe.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| + break; |
| + case LTTNG_KERNEL_FUNCTION: |
| + event_param.u.ftrace.symbol_name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| + break; |
| + default: |
| + break; |
| + } |
| + switch (event_param.instrumentation) { |
| + default: |
| + event_fd = get_unused_fd(); |
| + if (event_fd < 0) { |
| + ret = event_fd; |
| + goto fd_error; |
| + } |
| + event_file = anon_inode_getfile("[lttng_event]", |
| + <tng_event_fops, |
| + NULL, O_RDWR); |
| + if (IS_ERR(event_file)) { |
| + ret = PTR_ERR(event_file); |
| + goto file_error; |
| + } |
| + /* |
| + * We tolerate no failure path after event creation. It |
| + * will stay invariant for the rest of the session. |
| + */ |
| + event = lttng_event_create(channel, &event_param, NULL, NULL); |
| + if (!event) { |
| + ret = -EINVAL; |
| + goto event_error; |
| + } |
| + event_file->private_data = event; |
| + fd_install(event_fd, event_file); |
| + /* The event holds a reference on the channel */ |
| + atomic_long_inc(&channel_file->f_count); |
| + break; |
| + case LTTNG_KERNEL_SYSCALL: |
| + /* |
| + * Only all-syscall tracing supported for now. |
| + */ |
| + if (event_param.name[0] != '\0') |
| + return -EINVAL; |
| + ret = lttng_syscalls_register(channel, NULL); |
| + if (ret) |
| + goto fd_error; |
| + event_fd = 0; |
| + break; |
| + } |
| + return event_fd; |
| + |
| +event_error: |
| + fput(event_file); |
| +file_error: |
| + put_unused_fd(event_fd); |
| +fd_error: |
| + return ret; |
| +} |
| + |
| +/** |
| + * lttng_channel_ioctl - lttng syscall through ioctl |
| + * |
| + * @file: the file |
| + * @cmd: the command |
| + * @arg: command arg |
| + * |
| + * This ioctl implements lttng commands: |
| + * LTTNG_KERNEL_STREAM |
| + * Returns an event stream file descriptor or failure. |
| + * (typically, one event stream records events from one CPU) |
| + * LTTNG_KERNEL_EVENT |
| + * Returns an event file descriptor or failure. |
| + * LTTNG_KERNEL_CONTEXT |
| + * Prepend a context field to each event in the channel |
| + * LTTNG_KERNEL_ENABLE |
| + * Enable recording for events in this channel (weak enable) |
| + * LTTNG_KERNEL_DISABLE |
| + * Disable recording for events in this channel (strong disable) |
| + * |
| + * Channel and event file descriptors also hold a reference on the session. |
| + */ |
| +static |
| +long lttng_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| +{ |
| + struct lttng_channel *channel = file->private_data; |
| + |
| + switch (cmd) { |
| + case LTTNG_KERNEL_STREAM: |
| + return lttng_abi_open_stream(file); |
| + case LTTNG_KERNEL_EVENT: |
| + return lttng_abi_create_event(file, (struct lttng_kernel_event __user *) arg); |
| + case LTTNG_KERNEL_CONTEXT: |
| + return lttng_abi_add_context(file, |
| + (struct lttng_kernel_context __user *) arg, |
| + &channel->ctx, channel->session); |
| + case LTTNG_KERNEL_ENABLE: |
| + return lttng_channel_enable(channel); |
| + case LTTNG_KERNEL_DISABLE: |
| + return lttng_channel_disable(channel); |
| + default: |
| + return -ENOIOCTLCMD; |
| + } |
| +} |
| + |
| +/** |
| + * lttng_metadata_ioctl - lttng syscall through ioctl |
| + * |
| + * @file: the file |
| + * @cmd: the command |
| + * @arg: command arg |
| + * |
| + * This ioctl implements lttng commands: |
| + * LTTNG_KERNEL_STREAM |
| + * Returns an event stream file descriptor or failure. |
| + * |
| + * Channel and event file descriptors also hold a reference on the session. |
| + */ |
| +static |
| +long lttng_metadata_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| +{ |
| + switch (cmd) { |
| + case LTTNG_KERNEL_STREAM: |
| + return lttng_abi_open_stream(file); |
| + default: |
| + return -ENOIOCTLCMD; |
| + } |
| +} |
| + |
| +/** |
| + * lttng_channel_poll - lttng stream addition/removal monitoring |
| + * |
| + * @file: the file |
| + * @wait: poll table |
| + */ |
| +unsigned int lttng_channel_poll(struct file *file, poll_table *wait) |
| +{ |
| + struct lttng_channel *channel = file->private_data; |
| + unsigned int mask = 0; |
| + |
| + if (file->f_mode & FMODE_READ) { |
| + poll_wait_set_exclusive(wait); |
| + poll_wait(file, channel->ops->get_hp_wait_queue(channel->chan), |
| + wait); |
| + |
| + if (channel->ops->is_disabled(channel->chan)) |
| + return POLLERR; |
| + if (channel->ops->is_finalized(channel->chan)) |
| + return POLLHUP; |
| + if (channel->ops->buffer_has_read_closed_stream(channel->chan)) |
| + return POLLIN | POLLRDNORM; |
| + return 0; |
| + } |
| + return mask; |
| + |
| +} |
| + |
| +static |
| +int lttng_channel_release(struct inode *inode, struct file *file) |
| +{ |
| + struct lttng_channel *channel = file->private_data; |
| + |
| + if (channel) |
| + fput(channel->session->file); |
| + return 0; |
| +} |
| + |
| +static const struct file_operations lttng_channel_fops = { |
| + .owner = THIS_MODULE, |
| + .release = lttng_channel_release, |
| + .poll = lttng_channel_poll, |
| + .unlocked_ioctl = lttng_channel_ioctl, |
| +#ifdef CONFIG_COMPAT |
| + .compat_ioctl = lttng_channel_ioctl, |
| +#endif |
| +}; |
| + |
| +static const struct file_operations lttng_metadata_fops = { |
| + .owner = THIS_MODULE, |
| + .release = lttng_channel_release, |
| + .unlocked_ioctl = lttng_metadata_ioctl, |
| +#ifdef CONFIG_COMPAT |
| + .compat_ioctl = lttng_metadata_ioctl, |
| +#endif |
| +}; |
| + |
| +/** |
| + * lttng_event_ioctl - lttng syscall through ioctl |
| + * |
| + * @file: the file |
| + * @cmd: the command |
| + * @arg: command arg |
| + * |
| + * This ioctl implements lttng commands: |
| + * LTTNG_KERNEL_CONTEXT |
| + * Prepend a context field to each record of this event |
| + * LTTNG_KERNEL_ENABLE |
| + * Enable recording for this event (weak enable) |
| + * LTTNG_KERNEL_DISABLE |
| + * Disable recording for this event (strong disable) |
| + */ |
| +static |
| +long lttng_event_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| +{ |
| + struct lttng_event *event = file->private_data; |
| + |
| + switch (cmd) { |
| + case LTTNG_KERNEL_CONTEXT: |
| + return lttng_abi_add_context(file, |
| + (struct lttng_kernel_context __user *) arg, |
| + &event->ctx, event->chan->session); |
| + case LTTNG_KERNEL_ENABLE: |
| + return lttng_event_enable(event); |
| + case LTTNG_KERNEL_DISABLE: |
| + return lttng_event_disable(event); |
| + default: |
| + return -ENOIOCTLCMD; |
| + } |
| +} |
| + |
| +static |
| +int lttng_event_release(struct inode *inode, struct file *file) |
| +{ |
| + struct lttng_event *event = file->private_data; |
| + |
| + if (event) |
| + fput(event->chan->file); |
| + return 0; |
| +} |
| + |
| +/* TODO: filter control ioctl */ |
| +static const struct file_operations lttng_event_fops = { |
| + .owner = THIS_MODULE, |
| + .release = lttng_event_release, |
| + .unlocked_ioctl = lttng_event_ioctl, |
| +#ifdef CONFIG_COMPAT |
| + .compat_ioctl = lttng_event_ioctl, |
| +#endif |
| +}; |
| + |
| +int __init lttng_abi_init(void) |
| +{ |
| + int ret = 0; |
| + |
| + wrapper_vmalloc_sync_all(); |
| + lttng_proc_dentry = proc_create_data("lttng", S_IRUSR | S_IWUSR, NULL, |
| + <tng_fops, NULL); |
| + |
| + if (!lttng_proc_dentry) { |
| + printk(KERN_ERR "Error creating LTTng control file\n"); |
| + ret = -ENOMEM; |
| + goto error; |
| + } |
| +error: |
| + return ret; |
| +} |
| + |
| +void __exit lttng_abi_exit(void) |
| +{ |
| + if (lttng_proc_dentry) |
| + remove_proc_entry("lttng", NULL); |
| +} |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-abi.h |
| @@ -0,0 +1,176 @@ |
| +#ifndef _LTTNG_ABI_H |
| +#define _LTTNG_ABI_H |
| + |
| +/* |
| + * lttng-abi.h |
| + * |
| + * LTTng ABI header |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/fs.h> |
| + |
| +#define LTTNG_KERNEL_SYM_NAME_LEN 256 |
| + |
| +enum lttng_kernel_instrumentation { |
| + LTTNG_KERNEL_TRACEPOINT = 0, |
| + LTTNG_KERNEL_KPROBE = 1, |
| + LTTNG_KERNEL_FUNCTION = 2, |
| + LTTNG_KERNEL_KRETPROBE = 3, |
| + LTTNG_KERNEL_NOOP = 4, /* not hooked */ |
| + LTTNG_KERNEL_SYSCALL = 5, |
| +}; |
| + |
| +/* |
| + * LTTng consumer mode |
| + */ |
| +enum lttng_kernel_output { |
| + LTTNG_KERNEL_SPLICE = 0, |
| + LTTNG_KERNEL_MMAP = 1, |
| +}; |
| + |
| +/* |
| + * LTTng DebugFS ABI structures. |
| + */ |
| +#define LTTNG_KERNEL_CHANNEL_PADDING LTTNG_KERNEL_SYM_NAME_LEN + 32 |
| +struct lttng_kernel_channel { |
| + int overwrite; /* 1: overwrite, 0: discard */ |
| + uint64_t subbuf_size; /* in bytes */ |
| + uint64_t num_subbuf; |
| + unsigned int switch_timer_interval; /* usecs */ |
| + unsigned int read_timer_interval; /* usecs */ |
| + enum lttng_kernel_output output; /* splice, mmap */ |
| + char padding[LTTNG_KERNEL_CHANNEL_PADDING]; |
| +}; |
| + |
| +struct lttng_kernel_kretprobe { |
| + uint64_t addr; |
| + |
| + uint64_t offset; |
| + char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN]; |
| +}; |
| + |
| +/* |
| + * Either addr is used, or symbol_name and offset. |
| + */ |
| +struct lttng_kernel_kprobe { |
| + uint64_t addr; |
| + |
| + uint64_t offset; |
| + char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN]; |
| +}; |
| + |
| +struct lttng_kernel_function_tracer { |
| + char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN]; |
| +}; |
| + |
| +/* |
| + * For syscall tracing, name = '\0' means "enable all". |
| + */ |
| +#define LTTNG_KERNEL_EVENT_PADDING1 16 |
| +#define LTTNG_KERNEL_EVENT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32 |
| +struct lttng_kernel_event { |
| + char name[LTTNG_KERNEL_SYM_NAME_LEN]; /* event name */ |
| + enum lttng_kernel_instrumentation instrumentation; |
| + char padding[LTTNG_KERNEL_EVENT_PADDING1]; |
| + |
| + /* Per instrumentation type configuration */ |
| + union { |
| + struct lttng_kernel_kretprobe kretprobe; |
| + struct lttng_kernel_kprobe kprobe; |
| + struct lttng_kernel_function_tracer ftrace; |
| + char padding[LTTNG_KERNEL_EVENT_PADDING2]; |
| + } u; |
| +}; |
| + |
| +struct lttng_kernel_tracer_version { |
| + uint32_t major; |
| + uint32_t minor; |
| + uint32_t patchlevel; |
| +}; |
| + |
| +enum lttng_kernel_calibrate_type { |
| + LTTNG_KERNEL_CALIBRATE_KRETPROBE, |
| +}; |
| + |
| +struct lttng_kernel_calibrate { |
| + enum lttng_kernel_calibrate_type type; /* type (input) */ |
| +}; |
| + |
| +enum lttng_kernel_context_type { |
| + LTTNG_KERNEL_CONTEXT_PID = 0, |
| + LTTNG_KERNEL_CONTEXT_PERF_COUNTER = 1, |
| + LTTNG_KERNEL_CONTEXT_PROCNAME = 2, |
| + LTTNG_KERNEL_CONTEXT_PRIO = 3, |
| + LTTNG_KERNEL_CONTEXT_NICE = 4, |
| + LTTNG_KERNEL_CONTEXT_VPID = 5, |
| + LTTNG_KERNEL_CONTEXT_TID = 6, |
| + LTTNG_KERNEL_CONTEXT_VTID = 7, |
| + LTTNG_KERNEL_CONTEXT_PPID = 8, |
| + LTTNG_KERNEL_CONTEXT_VPPID = 9, |
| +}; |
| + |
| +struct lttng_kernel_perf_counter_ctx { |
| + uint32_t type; |
| + uint64_t config; |
| + char name[LTTNG_KERNEL_SYM_NAME_LEN]; |
| +}; |
| + |
| +#define LTTNG_KERNEL_CONTEXT_PADDING1 16 |
| +#define LTTNG_KERNEL_CONTEXT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32 |
| +struct lttng_kernel_context { |
| + enum lttng_kernel_context_type ctx; |
| + char padding[LTTNG_KERNEL_CONTEXT_PADDING1]; |
| + |
| + union { |
| + struct lttng_kernel_perf_counter_ctx perf_counter; |
| + char padding[LTTNG_KERNEL_CONTEXT_PADDING2]; |
| + } u; |
| +}; |
| + |
| +/* LTTng file descriptor ioctl */ |
| +#define LTTNG_KERNEL_SESSION _IO(0xF6, 0x40) |
| +#define LTTNG_KERNEL_TRACER_VERSION \ |
| + _IOR(0xF6, 0x41, struct lttng_kernel_tracer_version) |
| +#define LTTNG_KERNEL_TRACEPOINT_LIST _IO(0xF6, 0x42) |
| +#define LTTNG_KERNEL_WAIT_QUIESCENT _IO(0xF6, 0x43) |
| +#define LTTNG_KERNEL_CALIBRATE \ |
| + _IOWR(0xF6, 0x44, struct lttng_kernel_calibrate) |
| + |
| +/* Session FD ioctl */ |
| +#define LTTNG_KERNEL_METADATA \ |
| + _IOW(0xF6, 0x50, struct lttng_kernel_channel) |
| +#define LTTNG_KERNEL_CHANNEL \ |
| + _IOW(0xF6, 0x51, struct lttng_kernel_channel) |
| +#define LTTNG_KERNEL_SESSION_START _IO(0xF6, 0x52) |
| +#define LTTNG_KERNEL_SESSION_STOP _IO(0xF6, 0x53) |
| + |
| +/* Channel FD ioctl */ |
| +#define LTTNG_KERNEL_STREAM _IO(0xF6, 0x60) |
| +#define LTTNG_KERNEL_EVENT \ |
| + _IOW(0xF6, 0x61, struct lttng_kernel_event) |
| + |
| +/* Event and Channel FD ioctl */ |
| +#define LTTNG_KERNEL_CONTEXT \ |
| + _IOW(0xF6, 0x70, struct lttng_kernel_context) |
| + |
| +/* Event, Channel and Session ioctl */ |
| +#define LTTNG_KERNEL_ENABLE _IO(0xF6, 0x80) |
| +#define LTTNG_KERNEL_DISABLE _IO(0xF6, 0x81) |
| + |
| +#endif /* _LTTNG_ABI_H */ |
| --- a/drivers/staging/lttng/lttng-calibrate.c |
| +++ b/drivers/staging/lttng/lttng-calibrate.c |
| @@ -1,15 +1,27 @@ |
| /* |
| * lttng-calibrate.c |
| * |
| - * Copyright 2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng probe calibration. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| -#include "ltt-debugfs-abi.h" |
| -#include "ltt-events.h" |
| +#include "lttng-abi.h" |
| +#include "lttng-events.h" |
| |
| noinline |
| void lttng_calibrate_kretprobe(void) |
| --- a/drivers/staging/lttng/lttng-context-nice.c |
| +++ b/drivers/staging/lttng/lttng-context-nice.c |
| @@ -1,26 +1,39 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-nice.c |
| * |
| * LTTng nice context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t nice_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(int)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(int)); |
| size += sizeof(int); |
| return size; |
| } |
| @@ -28,12 +41,12 @@ size_t nice_get_size(size_t offset) |
| static |
| void nice_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| int nice; |
| |
| nice = task_nice(current); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(nice)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(nice)); |
| chan->ops->event_write(ctx, &nice, sizeof(nice)); |
| } |
| |
| @@ -51,7 +64,7 @@ int lttng_add_nice_to_ctx(struct lttng_c |
| field->event_field.name = "nice"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(int) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(int) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(int) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(int); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-perf-counters.c |
| +++ b/drivers/staging/lttng/lttng-context-perf-counters.c |
| @@ -1,10 +1,23 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-perf-counters.c |
| * |
| * LTTng performance monitoring counters (perf-counters) integration module. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| @@ -12,18 +25,18 @@ |
| #include <linux/perf_event.h> |
| #include <linux/list.h> |
| #include <linux/string.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| #include "wrapper/perf.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t perf_counter_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(uint64_t)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); |
| size += sizeof(uint64_t); |
| return size; |
| } |
| @@ -31,7 +44,7 @@ size_t perf_counter_get_size(size_t offs |
| static |
| void perf_counter_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| struct perf_event *event; |
| uint64_t value; |
| @@ -54,7 +67,7 @@ void perf_counter_record(struct lttng_ct |
| */ |
| value = 0; |
| } |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(value)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(value)); |
| chan->ops->event_write(ctx, &value, sizeof(value)); |
| } |
| |
| @@ -230,7 +243,7 @@ int lttng_add_perf_counter_to_ctx(uint32 |
| field->event_field.name = name_alloc; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(uint64_t) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(uint64_t) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(uint64_t) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(uint64_t); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-pid.c |
| +++ b/drivers/staging/lttng/lttng-context-pid.c |
| @@ -1,26 +1,39 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-pid.c |
| * |
| * LTTng PID context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t pid_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(pid_t)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(pid_t)); |
| size += sizeof(pid_t); |
| return size; |
| } |
| @@ -28,12 +41,12 @@ size_t pid_get_size(size_t offset) |
| static |
| void pid_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| pid_t pid; |
| |
| pid = task_tgid_nr(current); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(pid)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(pid)); |
| chan->ops->event_write(ctx, &pid, sizeof(pid)); |
| } |
| |
| @@ -51,7 +64,7 @@ int lttng_add_pid_to_ctx(struct lttng_ct |
| field->event_field.name = "pid"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(pid_t) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(pid_t); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-ppid.c |
| +++ b/drivers/staging/lttng/lttng-context-ppid.c |
| @@ -1,27 +1,40 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-ppid.c |
| * |
| * LTTng PPID context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| #include <linux/syscalls.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t ppid_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(pid_t)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(pid_t)); |
| size += sizeof(pid_t); |
| return size; |
| } |
| @@ -29,14 +42,14 @@ size_t ppid_get_size(size_t offset) |
| static |
| void ppid_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| pid_t ppid; |
| |
| rcu_read_lock(); |
| ppid = task_tgid_nr(current->real_parent); |
| rcu_read_unlock(); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(ppid)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(ppid)); |
| chan->ops->event_write(ctx, &ppid, sizeof(ppid)); |
| } |
| |
| @@ -54,7 +67,7 @@ int lttng_add_ppid_to_ctx(struct lttng_c |
| field->event_field.name = "ppid"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(pid_t) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(pid_t); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-prio.c |
| +++ b/drivers/staging/lttng/lttng-context-prio.c |
| @@ -1,20 +1,33 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-prio.c |
| * |
| * LTTng priority context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| #include "wrapper/kallsyms.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| int (*wrapper_task_prio_sym)(struct task_struct *t); |
| @@ -34,7 +47,7 @@ size_t prio_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(int)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(int)); |
| size += sizeof(int); |
| return size; |
| } |
| @@ -42,12 +55,12 @@ size_t prio_get_size(size_t offset) |
| static |
| void prio_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| int prio; |
| |
| prio = wrapper_task_prio_sym(current); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(prio)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(prio)); |
| chan->ops->event_write(ctx, &prio, sizeof(prio)); |
| } |
| |
| @@ -72,7 +85,7 @@ int lttng_add_prio_to_ctx(struct lttng_c |
| field->event_field.name = "prio"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(int) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(int) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(int) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(int); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-procname.c |
| +++ b/drivers/staging/lttng/lttng-context-procname.c |
| @@ -1,19 +1,32 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-procname.c |
| * |
| * LTTng procname context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t procname_get_size(size_t offset) |
| @@ -33,7 +46,7 @@ size_t procname_get_size(size_t offset) |
| static |
| void procname_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| chan->ops->event_write(ctx, current->comm, sizeof(current->comm)); |
| } |
| @@ -53,7 +66,7 @@ int lttng_add_procname_to_ctx(struct ltt |
| field->event_field.type.atype = atype_array; |
| field->event_field.type.u.array.elem_type.atype = atype_integer; |
| field->event_field.type.u.array.elem_type.u.basic.integer.size = sizeof(char) * CHAR_BIT; |
| - field->event_field.type.u.array.elem_type.u.basic.integer.alignment = ltt_alignof(char) * CHAR_BIT; |
| + field->event_field.type.u.array.elem_type.u.basic.integer.alignment = lttng_alignof(char) * CHAR_BIT; |
| field->event_field.type.u.array.elem_type.u.basic.integer.signedness = is_signed_type(char); |
| field->event_field.type.u.array.elem_type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.array.elem_type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-tid.c |
| +++ b/drivers/staging/lttng/lttng-context-tid.c |
| @@ -1,26 +1,39 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-tid.c |
| * |
| * LTTng TID context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t tid_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(pid_t)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(pid_t)); |
| size += sizeof(pid_t); |
| return size; |
| } |
| @@ -28,12 +41,12 @@ size_t tid_get_size(size_t offset) |
| static |
| void tid_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| pid_t tid; |
| |
| tid = task_pid_nr(current); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(tid)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(tid)); |
| chan->ops->event_write(ctx, &tid, sizeof(tid)); |
| } |
| |
| @@ -51,7 +64,7 @@ int lttng_add_tid_to_ctx(struct lttng_ct |
| field->event_field.name = "tid"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(pid_t) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(pid_t); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-vpid.c |
| +++ b/drivers/staging/lttng/lttng-context-vpid.c |
| @@ -1,26 +1,39 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-vpid.c |
| * |
| * LTTng vPID context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t vpid_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(pid_t)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(pid_t)); |
| size += sizeof(pid_t); |
| return size; |
| } |
| @@ -28,7 +41,7 @@ size_t vpid_get_size(size_t offset) |
| static |
| void vpid_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| pid_t vpid; |
| |
| @@ -39,7 +52,7 @@ void vpid_record(struct lttng_ctx_field |
| vpid = 0; |
| else |
| vpid = task_tgid_vnr(current); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(vpid)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(vpid)); |
| chan->ops->event_write(ctx, &vpid, sizeof(vpid)); |
| } |
| |
| @@ -57,7 +70,7 @@ int lttng_add_vpid_to_ctx(struct lttng_c |
| field->event_field.name = "vpid"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(pid_t) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(pid_t); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-vppid.c |
| +++ b/drivers/staging/lttng/lttng-context-vppid.c |
| @@ -1,27 +1,40 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-vppid.c |
| * |
| * LTTng vPPID context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| #include <linux/syscalls.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t vppid_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(pid_t)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(pid_t)); |
| size += sizeof(pid_t); |
| return size; |
| } |
| @@ -29,7 +42,7 @@ size_t vppid_get_size(size_t offset) |
| static |
| void vppid_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| struct task_struct *parent; |
| pid_t vppid; |
| @@ -44,7 +57,7 @@ void vppid_record(struct lttng_ctx_field |
| else |
| vppid = task_tgid_vnr(parent); |
| rcu_read_unlock(); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(vppid)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(vppid)); |
| chan->ops->event_write(ctx, &vppid, sizeof(vppid)); |
| } |
| |
| @@ -62,7 +75,7 @@ int lttng_add_vppid_to_ctx(struct lttng_ |
| field->event_field.name = "vppid"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(pid_t) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(pid_t); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- a/drivers/staging/lttng/lttng-context-vtid.c |
| +++ b/drivers/staging/lttng/lttng-context-vtid.c |
| @@ -1,26 +1,39 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * lttng-context-vtid.c |
| * |
| * LTTng vTID context. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/slab.h> |
| #include <linux/sched.h> |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| #include "wrapper/ringbuffer/frontend_types.h" |
| #include "wrapper/vmalloc.h" |
| -#include "ltt-tracer.h" |
| +#include "lttng-tracer.h" |
| |
| static |
| size_t vtid_get_size(size_t offset) |
| { |
| size_t size = 0; |
| |
| - size += lib_ring_buffer_align(offset, ltt_alignof(pid_t)); |
| + size += lib_ring_buffer_align(offset, lttng_alignof(pid_t)); |
| size += sizeof(pid_t); |
| return size; |
| } |
| @@ -28,7 +41,7 @@ size_t vtid_get_size(size_t offset) |
| static |
| void vtid_record(struct lttng_ctx_field *field, |
| struct lib_ring_buffer_ctx *ctx, |
| - struct ltt_channel *chan) |
| + struct lttng_channel *chan) |
| { |
| pid_t vtid; |
| |
| @@ -39,7 +52,7 @@ void vtid_record(struct lttng_ctx_field |
| vtid = 0; |
| else |
| vtid = task_pid_vnr(current); |
| - lib_ring_buffer_align_ctx(ctx, ltt_alignof(vtid)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(vtid)); |
| chan->ops->event_write(ctx, &vtid, sizeof(vtid)); |
| } |
| |
| @@ -57,7 +70,7 @@ int lttng_add_vtid_to_ctx(struct lttng_c |
| field->event_field.name = "vtid"; |
| field->event_field.type.atype = atype_integer; |
| field->event_field.type.u.basic.integer.size = sizeof(pid_t) * CHAR_BIT; |
| - field->event_field.type.u.basic.integer.alignment = ltt_alignof(pid_t) * CHAR_BIT; |
| + field->event_field.type.u.basic.integer.alignment = lttng_alignof(pid_t) * CHAR_BIT; |
| field->event_field.type.u.basic.integer.signedness = is_signed_type(pid_t); |
| field->event_field.type.u.basic.integer.reverse_byte_order = 0; |
| field->event_field.type.u.basic.integer.base = 10; |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-context.c |
| @@ -0,0 +1,105 @@ |
| +/* |
| + * lttng-context.c |
| + * |
| + * LTTng trace/channel/event context management. |
| + * |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include <linux/list.h> |
| +#include <linux/mutex.h> |
| +#include <linux/slab.h> |
| +#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| +#include "lttng-events.h" |
| +#include "lttng-tracer.h" |
| + |
| +int lttng_find_context(struct lttng_ctx *ctx, const char *name) |
| +{ |
| + unsigned int i; |
| + |
| + for (i = 0; i < ctx->nr_fields; i++) { |
| + /* Skip allocated (but non-initialized) contexts */ |
| + if (!ctx->fields[i].event_field.name) |
| + continue; |
| + if (!strcmp(ctx->fields[i].event_field.name, name)) |
| + return 1; |
| + } |
| + return 0; |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_find_context); |
| + |
| +/* |
| + * Note: as we append context information, the pointer location may change. |
| + */ |
| +struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx_p) |
| +{ |
| + struct lttng_ctx_field *field; |
| + struct lttng_ctx *ctx; |
| + |
| + if (!*ctx_p) { |
| + *ctx_p = kzalloc(sizeof(struct lttng_ctx), GFP_KERNEL); |
| + if (!*ctx_p) |
| + return NULL; |
| + } |
| + ctx = *ctx_p; |
| + if (ctx->nr_fields + 1 > ctx->allocated_fields) { |
| + struct lttng_ctx_field *new_fields; |
| + |
| + ctx->allocated_fields = max_t(size_t, 1, 2 * ctx->allocated_fields); |
| + new_fields = kzalloc(ctx->allocated_fields * sizeof(struct lttng_ctx_field), GFP_KERNEL); |
| + if (!new_fields) |
| + return NULL; |
| + if (ctx->fields) |
| + memcpy(new_fields, ctx->fields, sizeof(*ctx->fields) * ctx->nr_fields); |
| + kfree(ctx->fields); |
| + ctx->fields = new_fields; |
| + } |
| + field = &ctx->fields[ctx->nr_fields]; |
| + ctx->nr_fields++; |
| + return field; |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_append_context); |
| + |
| +/* |
| + * Remove last context field. |
| + */ |
| +void lttng_remove_context_field(struct lttng_ctx **ctx_p, |
| + struct lttng_ctx_field *field) |
| +{ |
| + struct lttng_ctx *ctx; |
| + |
| + ctx = *ctx_p; |
| + ctx->nr_fields--; |
| + WARN_ON_ONCE(&ctx->fields[ctx->nr_fields] != field); |
| + memset(&ctx->fields[ctx->nr_fields], 0, sizeof(struct lttng_ctx_field)); |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_remove_context_field); |
| + |
| +void lttng_destroy_context(struct lttng_ctx *ctx) |
| +{ |
| + int i; |
| + |
| + if (!ctx) |
| + return; |
| + for (i = 0; i < ctx->nr_fields; i++) { |
| + if (ctx->fields[i].destroy) |
| + ctx->fields[i].destroy(&ctx->fields[i]); |
| + } |
| + kfree(ctx->fields); |
| + kfree(ctx); |
| +} |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-endian.h |
| @@ -0,0 +1,43 @@ |
| +#ifndef _LTTNG_ENDIAN_H |
| +#define _LTTNG_ENDIAN_H |
| + |
| +/* |
| + * lttng-endian.h |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#ifdef __KERNEL__ |
| +# include <asm/byteorder.h> |
| +# ifdef __BIG_ENDIAN |
| +# define __BYTE_ORDER __BIG_ENDIAN |
| +# elif defined(__LITTLE_ENDIAN) |
| +# define __BYTE_ORDER __LITTLE_ENDIAN |
| +# else |
| +# error "unknown endianness" |
| +# endif |
| +#ifndef __BIG_ENDIAN |
| +# define __BIG_ENDIAN 4321 |
| +#endif |
| +#ifndef __LITTLE_ENDIAN |
| +# define __LITTLE_ENDIAN 1234 |
| +#endif |
| +#else |
| +# include <endian.h> |
| +#endif |
| + |
| +#endif /* _LTTNG_ENDIAN_H */ |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-events.c |
| @@ -0,0 +1,1126 @@ |
| +/* |
| + * lttng-events.c |
| + * |
| + * Holds LTTng per-session event registry. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include <linux/list.h> |
| +#include <linux/mutex.h> |
| +#include <linux/sched.h> |
| +#include <linux/slab.h> |
| +#include <linux/jiffies.h> |
| +#include <linux/utsname.h> |
| +#include "wrapper/uuid.h" |
| +#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| +#include "wrapper/random.h" |
| +#include "lttng-events.h" |
| +#include "lttng-tracer.h" |
| + |
| +static LIST_HEAD(sessions); |
| +static LIST_HEAD(lttng_transport_list); |
| +static DEFINE_MUTEX(sessions_mutex); |
| +static struct kmem_cache *event_cache; |
| + |
| +static void _lttng_event_destroy(struct lttng_event *event); |
| +static void _lttng_channel_destroy(struct lttng_channel *chan); |
| +static int _lttng_event_unregister(struct lttng_event *event); |
| +static |
| +int _lttng_event_metadata_statedump(struct lttng_session *session, |
| + struct lttng_channel *chan, |
| + struct lttng_event *event); |
| +static |
| +int _lttng_session_metadata_statedump(struct lttng_session *session); |
| + |
| +void synchronize_trace(void) |
| +{ |
| + synchronize_sched(); |
| +#ifdef CONFIG_PREEMPT_RT |
| + synchronize_rcu(); |
| +#endif |
| +} |
| + |
| +struct lttng_session *lttng_session_create(void) |
| +{ |
| + struct lttng_session *session; |
| + |
| + mutex_lock(&sessions_mutex); |
| + session = kzalloc(sizeof(struct lttng_session), GFP_KERNEL); |
| + if (!session) |
| + return NULL; |
| + INIT_LIST_HEAD(&session->chan); |
| + INIT_LIST_HEAD(&session->events); |
| + uuid_le_gen(&session->uuid); |
| + list_add(&session->list, &sessions); |
| + mutex_unlock(&sessions_mutex); |
| + return session; |
| +} |
| + |
| +void lttng_session_destroy(struct lttng_session *session) |
| +{ |
| + struct lttng_channel *chan, *tmpchan; |
| + struct lttng_event *event, *tmpevent; |
| + int ret; |
| + |
| + mutex_lock(&sessions_mutex); |
| + ACCESS_ONCE(session->active) = 0; |
| + list_for_each_entry(chan, &session->chan, list) { |
| + ret = lttng_syscalls_unregister(chan); |
| + WARN_ON(ret); |
| + } |
| + list_for_each_entry(event, &session->events, list) { |
| + ret = _lttng_event_unregister(event); |
| + WARN_ON(ret); |
| + } |
| + synchronize_trace(); /* Wait for in-flight events to complete */ |
| + list_for_each_entry_safe(event, tmpevent, &session->events, list) |
| + _lttng_event_destroy(event); |
| + list_for_each_entry_safe(chan, tmpchan, &session->chan, list) |
| + _lttng_channel_destroy(chan); |
| + list_del(&session->list); |
| + mutex_unlock(&sessions_mutex); |
| + kfree(session); |
| +} |
| + |
| +int lttng_session_enable(struct lttng_session *session) |
| +{ |
| + int ret = 0; |
| + struct lttng_channel *chan; |
| + |
| + mutex_lock(&sessions_mutex); |
| + if (session->active) { |
| + ret = -EBUSY; |
| + goto end; |
| + } |
| + |
| + /* |
| + * Snapshot the number of events per channel to know the type of header |
| + * we need to use. |
| + */ |
| + list_for_each_entry(chan, &session->chan, list) { |
| + if (chan->header_type) |
| + continue; /* don't change it if session stop/restart */ |
| + if (chan->free_event_id < 31) |
| + chan->header_type = 1; /* compact */ |
| + else |
| + chan->header_type = 2; /* large */ |
| + } |
| + |
| + ACCESS_ONCE(session->active) = 1; |
| + ACCESS_ONCE(session->been_active) = 1; |
| + ret = _lttng_session_metadata_statedump(session); |
| + if (ret) { |
| + ACCESS_ONCE(session->active) = 0; |
| + goto end; |
| + } |
| + ret = lttng_statedump_start(session); |
| + if (ret) |
| + ACCESS_ONCE(session->active) = 0; |
| +end: |
| + mutex_unlock(&sessions_mutex); |
| + return ret; |
| +} |
| + |
| +int lttng_session_disable(struct lttng_session *session) |
| +{ |
| + int ret = 0; |
| + |
| + mutex_lock(&sessions_mutex); |
| + if (!session->active) { |
| + ret = -EBUSY; |
| + goto end; |
| + } |
| + ACCESS_ONCE(session->active) = 0; |
| +end: |
| + mutex_unlock(&sessions_mutex); |
| + return ret; |
| +} |
| + |
| +int lttng_channel_enable(struct lttng_channel *channel) |
| +{ |
| + int old; |
| + |
| + if (channel == channel->session->metadata) |
| + return -EPERM; |
| + old = xchg(&channel->enabled, 1); |
| + if (old) |
| + return -EEXIST; |
| + return 0; |
| +} |
| + |
| +int lttng_channel_disable(struct lttng_channel *channel) |
| +{ |
| + int old; |
| + |
| + if (channel == channel->session->metadata) |
| + return -EPERM; |
| + old = xchg(&channel->enabled, 0); |
| + if (!old) |
| + return -EEXIST; |
| + return 0; |
| +} |
| + |
| +int lttng_event_enable(struct lttng_event *event) |
| +{ |
| + int old; |
| + |
| + if (event->chan == event->chan->session->metadata) |
| + return -EPERM; |
| + old = xchg(&event->enabled, 1); |
| + if (old) |
| + return -EEXIST; |
| + return 0; |
| +} |
| + |
| +int lttng_event_disable(struct lttng_event *event) |
| +{ |
| + int old; |
| + |
| + if (event->chan == event->chan->session->metadata) |
| + return -EPERM; |
| + old = xchg(&event->enabled, 0); |
| + if (!old) |
| + return -EEXIST; |
| + return 0; |
| +} |
| + |
| +static struct lttng_transport *lttng_transport_find(const char *name) |
| +{ |
| + struct lttng_transport *transport; |
| + |
| + list_for_each_entry(transport, <tng_transport_list, node) { |
| + if (!strcmp(transport->name, name)) |
| + return transport; |
| + } |
| + return NULL; |
| +} |
| + |
| +struct lttng_channel *lttng_channel_create(struct lttng_session *session, |
| + const char *transport_name, |
| + void *buf_addr, |
| + size_t subbuf_size, size_t num_subbuf, |
| + unsigned int switch_timer_interval, |
| + unsigned int read_timer_interval) |
| +{ |
| + struct lttng_channel *chan; |
| + struct lttng_transport *transport = NULL; |
| + |
| + mutex_lock(&sessions_mutex); |
| + if (session->been_active) |
| + goto active; /* Refuse to add channel to active session */ |
| + transport = lttng_transport_find(transport_name); |
| + if (!transport) { |
| + printk(KERN_WARNING "LTTng transport %s not found\n", |
| + transport_name); |
| + goto notransport; |
| + } |
| + if (!try_module_get(transport->owner)) { |
| + printk(KERN_WARNING "LTT : Can't lock transport module.\n"); |
| + goto notransport; |
| + } |
| + chan = kzalloc(sizeof(struct lttng_channel), GFP_KERNEL); |
| + if (!chan) |
| + goto nomem; |
| + chan->session = session; |
| + chan->id = session->free_chan_id++; |
| + /* |
| + * Note: the channel creation op already writes into the packet |
| + * headers. Therefore the "chan" information used as input |
| + * should be already accessible. |
| + */ |
| + chan->chan = transport->ops.channel_create(transport_name, |
| + chan, buf_addr, subbuf_size, num_subbuf, |
| + switch_timer_interval, read_timer_interval); |
| + if (!chan->chan) |
| + goto create_error; |
| + chan->enabled = 1; |
| + chan->ops = &transport->ops; |
| + chan->transport = transport; |
| + list_add(&chan->list, &session->chan); |
| + mutex_unlock(&sessions_mutex); |
| + return chan; |
| + |
| +create_error: |
| + kfree(chan); |
| +nomem: |
| + if (transport) |
| + module_put(transport->owner); |
| +notransport: |
| +active: |
| + mutex_unlock(&sessions_mutex); |
| + return NULL; |
| +} |
| + |
| +/* |
| + * Only used internally at session destruction. |
| + */ |
| +static |
| +void _lttng_channel_destroy(struct lttng_channel *chan) |
| +{ |
| + chan->ops->channel_destroy(chan->chan); |
| + module_put(chan->transport->owner); |
| + list_del(&chan->list); |
| + lttng_destroy_context(chan->ctx); |
| + kfree(chan); |
| +} |
| + |
| +/* |
| + * Supports event creation while tracing session is active. |
| + */ |
| +struct lttng_event *lttng_event_create(struct lttng_channel *chan, |
| + struct lttng_kernel_event *event_param, |
| + void *filter, |
| + const struct lttng_event_desc *internal_desc) |
| +{ |
| + struct lttng_event *event; |
| + int ret; |
| + |
| + mutex_lock(&sessions_mutex); |
| + if (chan->free_event_id == -1UL) |
| + goto full; |
| + /* |
| + * This is O(n^2) (for each event, the loop is called at event |
| + * creation). Might require a hash if we have lots of events. |
| + */ |
| + list_for_each_entry(event, &chan->session->events, list) |
| + if (!strcmp(event->desc->name, event_param->name)) |
| + goto exist; |
| + event = kmem_cache_zalloc(event_cache, GFP_KERNEL); |
| + if (!event) |
| + goto cache_error; |
| + event->chan = chan; |
| + event->filter = filter; |
| + event->id = chan->free_event_id++; |
| + event->enabled = 1; |
| + event->instrumentation = event_param->instrumentation; |
| + /* Populate lttng_event structure before tracepoint registration. */ |
| + smp_wmb(); |
| + switch (event_param->instrumentation) { |
| + case LTTNG_KERNEL_TRACEPOINT: |
| + event->desc = lttng_event_get(event_param->name); |
| + if (!event->desc) |
| + goto register_error; |
| + ret = tracepoint_probe_register(event_param->name, |
| + event->desc->probe_callback, |
| + event); |
| + if (ret) |
| + goto register_error; |
| + break; |
| + case LTTNG_KERNEL_KPROBE: |
| + ret = lttng_kprobes_register(event_param->name, |
| + event_param->u.kprobe.symbol_name, |
| + event_param->u.kprobe.offset, |
| + event_param->u.kprobe.addr, |
| + event); |
| + if (ret) |
| + goto register_error; |
| + ret = try_module_get(event->desc->owner); |
| + WARN_ON_ONCE(!ret); |
| + break; |
| + case LTTNG_KERNEL_KRETPROBE: |
| + { |
| + struct lttng_event *event_return; |
| + |
| + /* kretprobe defines 2 events */ |
| + event_return = |
| + kmem_cache_zalloc(event_cache, GFP_KERNEL); |
| + if (!event_return) |
| + goto register_error; |
| + event_return->chan = chan; |
| + event_return->filter = filter; |
| + event_return->id = chan->free_event_id++; |
| + event_return->enabled = 1; |
| + event_return->instrumentation = event_param->instrumentation; |
| + /* |
| + * Populate lttng_event structure before kretprobe registration. |
| + */ |
| + smp_wmb(); |
| + ret = lttng_kretprobes_register(event_param->name, |
| + event_param->u.kretprobe.symbol_name, |
| + event_param->u.kretprobe.offset, |
| + event_param->u.kretprobe.addr, |
| + event, event_return); |
| + if (ret) { |
| + kmem_cache_free(event_cache, event_return); |
| + goto register_error; |
| + } |
| + /* Take 2 refs on the module: one per event. */ |
| + ret = try_module_get(event->desc->owner); |
| + WARN_ON_ONCE(!ret); |
| + ret = try_module_get(event->desc->owner); |
| + WARN_ON_ONCE(!ret); |
| + ret = _lttng_event_metadata_statedump(chan->session, chan, |
| + event_return); |
| + if (ret) { |
| + kmem_cache_free(event_cache, event_return); |
| + module_put(event->desc->owner); |
| + module_put(event->desc->owner); |
| + goto statedump_error; |
| + } |
| + list_add(&event_return->list, &chan->session->events); |
| + break; |
| + } |
| + case LTTNG_KERNEL_FUNCTION: |
| + ret = lttng_ftrace_register(event_param->name, |
| + event_param->u.ftrace.symbol_name, |
| + event); |
| + if (ret) |
| + goto register_error; |
| + ret = try_module_get(event->desc->owner); |
| + WARN_ON_ONCE(!ret); |
| + break; |
| + case LTTNG_KERNEL_NOOP: |
| + event->desc = internal_desc; |
| + if (!event->desc) |
| + goto register_error; |
| + break; |
| + default: |
| + WARN_ON_ONCE(1); |
| + } |
| + ret = _lttng_event_metadata_statedump(chan->session, chan, event); |
| + if (ret) |
| + goto statedump_error; |
| + list_add(&event->list, &chan->session->events); |
| + mutex_unlock(&sessions_mutex); |
| + return event; |
| + |
| +statedump_error: |
| + /* If a statedump error occurs, events will not be readable. */ |
| +register_error: |
| + kmem_cache_free(event_cache, event); |
| +cache_error: |
| +exist: |
| +full: |
| + mutex_unlock(&sessions_mutex); |
| + return NULL; |
| +} |
| + |
| +/* |
| + * Only used internally at session destruction. |
| + */ |
| +int _lttng_event_unregister(struct lttng_event *event) |
| +{ |
| + int ret = -EINVAL; |
| + |
| + switch (event->instrumentation) { |
| + case LTTNG_KERNEL_TRACEPOINT: |
| + ret = tracepoint_probe_unregister(event->desc->name, |
| + event->desc->probe_callback, |
| + event); |
| + if (ret) |
| + return ret; |
| + break; |
| + case LTTNG_KERNEL_KPROBE: |
| + lttng_kprobes_unregister(event); |
| + ret = 0; |
| + break; |
| + case LTTNG_KERNEL_KRETPROBE: |
| + lttng_kretprobes_unregister(event); |
| + ret = 0; |
| + break; |
| + case LTTNG_KERNEL_FUNCTION: |
| + lttng_ftrace_unregister(event); |
| + ret = 0; |
| + break; |
| + case LTTNG_KERNEL_NOOP: |
| + ret = 0; |
| + break; |
| + default: |
| + WARN_ON_ONCE(1); |
| + } |
| + return ret; |
| +} |
| + |
| +/* |
| + * Only used internally at session destruction. |
| + */ |
| +static |
| +void _lttng_event_destroy(struct lttng_event *event) |
| +{ |
| + switch (event->instrumentation) { |
| + case LTTNG_KERNEL_TRACEPOINT: |
| + lttng_event_put(event->desc); |
| + break; |
| + case LTTNG_KERNEL_KPROBE: |
| + module_put(event->desc->owner); |
| + lttng_kprobes_destroy_private(event); |
| + break; |
| + case LTTNG_KERNEL_KRETPROBE: |
| + module_put(event->desc->owner); |
| + lttng_kretprobes_destroy_private(event); |
| + break; |
| + case LTTNG_KERNEL_FUNCTION: |
| + module_put(event->desc->owner); |
| + lttng_ftrace_destroy_private(event); |
| + break; |
| + case LTTNG_KERNEL_NOOP: |
| + break; |
| + default: |
| + WARN_ON_ONCE(1); |
| + } |
| + list_del(&event->list); |
| + lttng_destroy_context(event->ctx); |
| + kmem_cache_free(event_cache, event); |
| +} |
| + |
| +/* |
| + * We have exclusive access to our metadata buffer (protected by the |
| + * sessions_mutex), so we can do racy operations such as looking for |
| + * remaining space left in packet and write, since mutual exclusion |
| + * protects us from concurrent writes. |
| + */ |
| +int lttng_metadata_printf(struct lttng_session *session, |
| + const char *fmt, ...) |
| +{ |
| + struct lib_ring_buffer_ctx ctx; |
| + struct lttng_channel *chan = session->metadata; |
| + char *str; |
| + int ret = 0, waitret; |
| + size_t len, reserve_len, pos; |
| + va_list ap; |
| + |
| + WARN_ON_ONCE(!ACCESS_ONCE(session->active)); |
| + |
| + va_start(ap, fmt); |
| + str = kvasprintf(GFP_KERNEL, fmt, ap); |
| + va_end(ap); |
| + if (!str) |
| + return -ENOMEM; |
| + |
| + len = strlen(str); |
| + pos = 0; |
| + |
| + for (pos = 0; pos < len; pos += reserve_len) { |
| + reserve_len = min_t(size_t, |
| + chan->ops->packet_avail_size(chan->chan), |
| + len - pos); |
| + lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len, |
| + sizeof(char), -1); |
| + /* |
| + * We don't care about metadata buffer's records lost |
| + * count, because we always retry here. Report error if |
| + * we need to bail out after timeout or being |
| + * interrupted. |
| + */ |
| + waitret = wait_event_interruptible_timeout(*chan->ops->get_writer_buf_wait_queue(chan->chan, -1), |
| + ({ |
| + ret = chan->ops->event_reserve(&ctx, 0); |
| + ret != -ENOBUFS || !ret; |
| + }), |
| + msecs_to_jiffies(LTTNG_METADATA_TIMEOUT_MSEC)); |
| + if (!waitret || waitret == -ERESTARTSYS || ret) { |
| + printk(KERN_WARNING "LTTng: Failure to write metadata to buffers (%s)\n", |
| + waitret == -ERESTARTSYS ? "interrupted" : |
| + (ret == -ENOBUFS ? "timeout" : "I/O error")); |
| + if (waitret == -ERESTARTSYS) |
| + ret = waitret; |
| + goto end; |
| + } |
| + chan->ops->event_write(&ctx, &str[pos], reserve_len); |
| + chan->ops->event_commit(&ctx); |
| + } |
| +end: |
| + kfree(str); |
| + return ret; |
| +} |
| + |
| +static |
| +int _lttng_field_statedump(struct lttng_session *session, |
| + const struct lttng_event_field *field) |
| +{ |
| + int ret = 0; |
| + |
| + switch (field->type.atype) { |
| + case atype_integer: |
| + ret = lttng_metadata_printf(session, |
| + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s;\n", |
| + field->type.u.basic.integer.size, |
| + field->type.u.basic.integer.alignment, |
| + field->type.u.basic.integer.signedness, |
| + (field->type.u.basic.integer.encoding == lttng_encode_none) |
| + ? "none" |
| + : (field->type.u.basic.integer.encoding == lttng_encode_UTF8) |
| + ? "UTF8" |
| + : "ASCII", |
| + field->type.u.basic.integer.base, |
| +#ifdef __BIG_ENDIAN |
| + field->type.u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| +#else |
| + field->type.u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| +#endif |
| + field->name); |
| + break; |
| + case atype_enum: |
| + ret = lttng_metadata_printf(session, |
| + " %s _%s;\n", |
| + field->type.u.basic.enumeration.name, |
| + field->name); |
| + break; |
| + case atype_array: |
| + { |
| + const struct lttng_basic_type *elem_type; |
| + |
| + elem_type = &field->type.u.array.elem_type; |
| + ret = lttng_metadata_printf(session, |
| + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[%u];\n", |
| + elem_type->u.basic.integer.size, |
| + elem_type->u.basic.integer.alignment, |
| + elem_type->u.basic.integer.signedness, |
| + (elem_type->u.basic.integer.encoding == lttng_encode_none) |
| + ? "none" |
| + : (elem_type->u.basic.integer.encoding == lttng_encode_UTF8) |
| + ? "UTF8" |
| + : "ASCII", |
| + elem_type->u.basic.integer.base, |
| +#ifdef __BIG_ENDIAN |
| + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| +#else |
| + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| +#endif |
| + field->name, field->type.u.array.length); |
| + break; |
| + } |
| + case atype_sequence: |
| + { |
| + const struct lttng_basic_type *elem_type; |
| + const struct lttng_basic_type *length_type; |
| + |
| + elem_type = &field->type.u.sequence.elem_type; |
| + length_type = &field->type.u.sequence.length_type; |
| + ret = lttng_metadata_printf(session, |
| + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } __%s_length;\n", |
| + length_type->u.basic.integer.size, |
| + (unsigned int) length_type->u.basic.integer.alignment, |
| + length_type->u.basic.integer.signedness, |
| + (length_type->u.basic.integer.encoding == lttng_encode_none) |
| + ? "none" |
| + : ((length_type->u.basic.integer.encoding == lttng_encode_UTF8) |
| + ? "UTF8" |
| + : "ASCII"), |
| + length_type->u.basic.integer.base, |
| +#ifdef __BIG_ENDIAN |
| + length_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| +#else |
| + length_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| +#endif |
| + field->name); |
| + if (ret) |
| + return ret; |
| + |
| + ret = lttng_metadata_printf(session, |
| + " integer { size = %u; align = %u; signed = %u; encoding = %s; base = %u;%s } _%s[ __%s_length ];\n", |
| + elem_type->u.basic.integer.size, |
| + (unsigned int) elem_type->u.basic.integer.alignment, |
| + elem_type->u.basic.integer.signedness, |
| + (elem_type->u.basic.integer.encoding == lttng_encode_none) |
| + ? "none" |
| + : ((elem_type->u.basic.integer.encoding == lttng_encode_UTF8) |
| + ? "UTF8" |
| + : "ASCII"), |
| + elem_type->u.basic.integer.base, |
| +#ifdef __BIG_ENDIAN |
| + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = le;" : "", |
| +#else |
| + elem_type->u.basic.integer.reverse_byte_order ? " byte_order = be;" : "", |
| +#endif |
| + field->name, |
| + field->name); |
| + break; |
| + } |
| + |
| + case atype_string: |
| + /* Default encoding is UTF8 */ |
| + ret = lttng_metadata_printf(session, |
| + " string%s _%s;\n", |
| + field->type.u.basic.string.encoding == lttng_encode_ASCII ? |
| + " { encoding = ASCII; }" : "", |
| + field->name); |
| + break; |
| + default: |
| + WARN_ON_ONCE(1); |
| + return -EINVAL; |
| + } |
| + return ret; |
| +} |
| + |
| +static |
| +int _lttng_context_metadata_statedump(struct lttng_session *session, |
| + struct lttng_ctx *ctx) |
| +{ |
| + int ret = 0; |
| + int i; |
| + |
| + if (!ctx) |
| + return 0; |
| + for (i = 0; i < ctx->nr_fields; i++) { |
| + const struct lttng_ctx_field *field = &ctx->fields[i]; |
| + |
| + ret = _lttng_field_statedump(session, &field->event_field); |
| + if (ret) |
| + return ret; |
| + } |
| + return ret; |
| +} |
| + |
| +static |
| +int _lttng_fields_metadata_statedump(struct lttng_session *session, |
| + struct lttng_event *event) |
| +{ |
| + const struct lttng_event_desc *desc = event->desc; |
| + int ret = 0; |
| + int i; |
| + |
| + for (i = 0; i < desc->nr_fields; i++) { |
| + const struct lttng_event_field *field = &desc->fields[i]; |
| + |
| + ret = _lttng_field_statedump(session, field); |
| + if (ret) |
| + return ret; |
| + } |
| + return ret; |
| +} |
| + |
| +static |
| +int _lttng_event_metadata_statedump(struct lttng_session *session, |
| + struct lttng_channel *chan, |
| + struct lttng_event *event) |
| +{ |
| + int ret = 0; |
| + |
| + if (event->metadata_dumped || !ACCESS_ONCE(session->active)) |
| + return 0; |
| + if (chan == session->metadata) |
| + return 0; |
| + |
| + ret = lttng_metadata_printf(session, |
| + "event {\n" |
| + " name = %s;\n" |
| + " id = %u;\n" |
| + " stream_id = %u;\n", |
| + event->desc->name, |
| + event->id, |
| + event->chan->id); |
| + if (ret) |
| + goto end; |
| + |
| + if (event->ctx) { |
| + ret = lttng_metadata_printf(session, |
| + " context := struct {\n"); |
| + if (ret) |
| + goto end; |
| + } |
| + ret = _lttng_context_metadata_statedump(session, event->ctx); |
| + if (ret) |
| + goto end; |
| + if (event->ctx) { |
| + ret = lttng_metadata_printf(session, |
| + " };\n"); |
| + if (ret) |
| + goto end; |
| + } |
| + |
| + ret = lttng_metadata_printf(session, |
| + " fields := struct {\n" |
| + ); |
| + if (ret) |
| + goto end; |
| + |
| + ret = _lttng_fields_metadata_statedump(session, event); |
| + if (ret) |
| + goto end; |
| + |
| + /* |
| + * LTTng space reservation can only reserve multiples of the |
| + * byte size. |
| + */ |
| + ret = lttng_metadata_printf(session, |
| + " };\n" |
| + "};\n\n"); |
| + if (ret) |
| + goto end; |
| + |
| + event->metadata_dumped = 1; |
| +end: |
| + return ret; |
| + |
| +} |
| + |
| +static |
| +int _lttng_channel_metadata_statedump(struct lttng_session *session, |
| + struct lttng_channel *chan) |
| +{ |
| + int ret = 0; |
| + |
| + if (chan->metadata_dumped || !ACCESS_ONCE(session->active)) |
| + return 0; |
| + if (chan == session->metadata) |
| + return 0; |
| + |
| + WARN_ON_ONCE(!chan->header_type); |
| + ret = lttng_metadata_printf(session, |
| + "stream {\n" |
| + " id = %u;\n" |
| + " event.header := %s;\n" |
| + " packet.context := struct packet_context;\n", |
| + chan->id, |
| + chan->header_type == 1 ? "struct event_header_compact" : |
| + "struct event_header_large"); |
| + if (ret) |
| + goto end; |
| + |
| + if (chan->ctx) { |
| + ret = lttng_metadata_printf(session, |
| + " event.context := struct {\n"); |
| + if (ret) |
| + goto end; |
| + } |
| + ret = _lttng_context_metadata_statedump(session, chan->ctx); |
| + if (ret) |
| + goto end; |
| + if (chan->ctx) { |
| + ret = lttng_metadata_printf(session, |
| + " };\n"); |
| + if (ret) |
| + goto end; |
| + } |
| + |
| + ret = lttng_metadata_printf(session, |
| + "};\n\n"); |
| + |
| + chan->metadata_dumped = 1; |
| +end: |
| + return ret; |
| +} |
| + |
| +static |
| +int _lttng_stream_packet_context_declare(struct lttng_session *session) |
| +{ |
| + return lttng_metadata_printf(session, |
| + "struct packet_context {\n" |
| + " uint64_clock_monotonic_t timestamp_begin;\n" |
| + " uint64_clock_monotonic_t timestamp_end;\n" |
| + " uint32_t events_discarded;\n" |
| + " uint32_t content_size;\n" |
| + " uint32_t packet_size;\n" |
| + " uint32_t cpu_id;\n" |
| + "};\n\n" |
| + ); |
| +} |
| + |
| +/* |
| + * Compact header: |
| + * id: range: 0 - 30. |
| + * id 31 is reserved to indicate an extended header. |
| + * |
| + * Large header: |
| + * id: range: 0 - 65534. |
| + * id 65535 is reserved to indicate an extended header. |
| + */ |
| +static |
| +int _lttng_event_header_declare(struct lttng_session *session) |
| +{ |
| + return lttng_metadata_printf(session, |
| + "struct event_header_compact {\n" |
| + " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" |
| + " variant <id> {\n" |
| + " struct {\n" |
| + " uint27_clock_monotonic_t timestamp;\n" |
| + " } compact;\n" |
| + " struct {\n" |
| + " uint32_t id;\n" |
| + " uint64_clock_monotonic_t timestamp;\n" |
| + " } extended;\n" |
| + " } v;\n" |
| + "} align(%u);\n" |
| + "\n" |
| + "struct event_header_large {\n" |
| + " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" |
| + " variant <id> {\n" |
| + " struct {\n" |
| + " uint32_clock_monotonic_t timestamp;\n" |
| + " } compact;\n" |
| + " struct {\n" |
| + " uint32_t id;\n" |
| + " uint64_clock_monotonic_t timestamp;\n" |
| + " } extended;\n" |
| + " } v;\n" |
| + "} align(%u);\n\n", |
| + lttng_alignof(uint32_t) * CHAR_BIT, |
| + lttng_alignof(uint16_t) * CHAR_BIT |
| + ); |
| +} |
| + |
| + /* |
| + * Approximation of NTP time of day to clock monotonic correlation, |
| + * taken at start of trace. |
| + * Yes, this is only an approximation. Yes, we can (and will) do better |
| + * in future versions. |
| + */ |
| +static |
| +uint64_t measure_clock_offset(void) |
| +{ |
| + uint64_t offset, monotonic[2], realtime; |
| + struct timespec rts = { 0, 0 }; |
| + unsigned long flags; |
| + |
| + /* Disable interrupts to increase correlation precision. */ |
| + local_irq_save(flags); |
| + monotonic[0] = trace_clock_read64(); |
| + getnstimeofday(&rts); |
| + monotonic[1] = trace_clock_read64(); |
| + local_irq_restore(flags); |
| + |
| + offset = (monotonic[0] + monotonic[1]) >> 1; |
| + realtime = (uint64_t) rts.tv_sec * NSEC_PER_SEC; |
| + realtime += rts.tv_nsec; |
| + offset = realtime - offset; |
| + return offset; |
| +} |
| + |
| +/* |
| + * Output metadata into this session's metadata buffers. |
| + */ |
| +static |
| +int _lttng_session_metadata_statedump(struct lttng_session *session) |
| +{ |
| + unsigned char *uuid_c = session->uuid.b; |
| + unsigned char uuid_s[37], clock_uuid_s[BOOT_ID_LEN]; |
| + struct lttng_channel *chan; |
| + struct lttng_event *event; |
| + int ret = 0; |
| + |
| + if (!ACCESS_ONCE(session->active)) |
| + return 0; |
| + if (session->metadata_dumped) |
| + goto skip_session; |
| + if (!session->metadata) { |
| + printk(KERN_WARNING "LTTng: attempt to start tracing, but metadata channel is not found. Operation abort.\n"); |
| + return -EPERM; |
| + } |
| + |
| + snprintf(uuid_s, sizeof(uuid_s), |
| + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", |
| + uuid_c[0], uuid_c[1], uuid_c[2], uuid_c[3], |
| + uuid_c[4], uuid_c[5], uuid_c[6], uuid_c[7], |
| + uuid_c[8], uuid_c[9], uuid_c[10], uuid_c[11], |
| + uuid_c[12], uuid_c[13], uuid_c[14], uuid_c[15]); |
| + |
| + ret = lttng_metadata_printf(session, |
| + "typealias integer { size = 8; align = %u; signed = false; } := uint8_t;\n" |
| + "typealias integer { size = 16; align = %u; signed = false; } := uint16_t;\n" |
| + "typealias integer { size = 32; align = %u; signed = false; } := uint32_t;\n" |
| + "typealias integer { size = 64; align = %u; signed = false; } := uint64_t;\n" |
| + "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" |
| + "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" |
| + "\n" |
| + "trace {\n" |
| + " major = %u;\n" |
| + " minor = %u;\n" |
| + " uuid = \"%s\";\n" |
| + " byte_order = %s;\n" |
| + " packet.header := struct {\n" |
| + " uint32_t magic;\n" |
| + " uint8_t uuid[16];\n" |
| + " uint32_t stream_id;\n" |
| + " };\n" |
| + "};\n\n", |
| + lttng_alignof(uint8_t) * CHAR_BIT, |
| + lttng_alignof(uint16_t) * CHAR_BIT, |
| + lttng_alignof(uint32_t) * CHAR_BIT, |
| + lttng_alignof(uint64_t) * CHAR_BIT, |
| + CTF_SPEC_MAJOR, |
| + CTF_SPEC_MINOR, |
| + uuid_s, |
| +#ifdef __BIG_ENDIAN |
| + "be" |
| +#else |
| + "le" |
| +#endif |
| + ); |
| + if (ret) |
| + goto end; |
| + |
| + ret = lttng_metadata_printf(session, |
| + "env {\n" |
| + " domain = \"kernel\";\n" |
| + " sysname = \"%s\";\n" |
| + " kernel_release = \"%s\";\n" |
| + " kernel_version = \"%s\";\n" |
| + " tracer_name = \"lttng-modules\";\n" |
| + " tracer_major = %d;\n" |
| + " tracer_minor = %d;\n" |
| + " tracer_patchlevel = %d;\n" |
| + "};\n\n", |
| + utsname()->sysname, |
| + utsname()->release, |
| + utsname()->version, |
| + LTTNG_MODULES_MAJOR_VERSION, |
| + LTTNG_MODULES_MINOR_VERSION, |
| + LTTNG_MODULES_PATCHLEVEL_VERSION |
| + ); |
| + if (ret) |
| + goto end; |
| + |
| + ret = lttng_metadata_printf(session, |
| + "clock {\n" |
| + " name = %s;\n", |
| + "monotonic" |
| + ); |
| + if (ret) |
| + goto end; |
| + |
| + if (!trace_clock_uuid(clock_uuid_s)) { |
| + ret = lttng_metadata_printf(session, |
| + " uuid = \"%s\";\n", |
| + clock_uuid_s |
| + ); |
| + if (ret) |
| + goto end; |
| + } |
| + |
| + ret = lttng_metadata_printf(session, |
| + " description = \"Monotonic Clock\";\n" |
| + " freq = %llu; /* Frequency, in Hz */\n" |
| + " /* clock value offset from Epoch is: offset * (1/freq) */\n" |
| + " offset = %llu;\n" |
| + "};\n\n", |
| + (unsigned long long) trace_clock_freq(), |
| + (unsigned long long) measure_clock_offset() |
| + ); |
| + if (ret) |
| + goto end; |
| + |
| + ret = lttng_metadata_printf(session, |
| + "typealias integer {\n" |
| + " size = 27; align = 1; signed = false;\n" |
| + " map = clock.monotonic.value;\n" |
| + "} := uint27_clock_monotonic_t;\n" |
| + "\n" |
| + "typealias integer {\n" |
| + " size = 32; align = %u; signed = false;\n" |
| + " map = clock.monotonic.value;\n" |
| + "} := uint32_clock_monotonic_t;\n" |
| + "\n" |
| + "typealias integer {\n" |
| + " size = 64; align = %u; signed = false;\n" |
| + " map = clock.monotonic.value;\n" |
| + "} := uint64_clock_monotonic_t;\n\n", |
| + lttng_alignof(uint32_t) * CHAR_BIT, |
| + lttng_alignof(uint64_t) * CHAR_BIT |
| + ); |
| + if (ret) |
| + goto end; |
| + |
| + ret = _lttng_stream_packet_context_declare(session); |
| + if (ret) |
| + goto end; |
| + |
| + ret = _lttng_event_header_declare(session); |
| + if (ret) |
| + goto end; |
| + |
| +skip_session: |
| + list_for_each_entry(chan, &session->chan, list) { |
| + ret = _lttng_channel_metadata_statedump(session, chan); |
| + if (ret) |
| + goto end; |
| + } |
| + |
| + list_for_each_entry(event, &session->events, list) { |
| + ret = _lttng_event_metadata_statedump(session, event->chan, event); |
| + if (ret) |
| + goto end; |
| + } |
| + session->metadata_dumped = 1; |
| +end: |
| + return ret; |
| +} |
| + |
| +/** |
| + * lttng_transport_register - LTT transport registration |
| + * @transport: transport structure |
| + * |
| + * Registers a transport which can be used as output to extract the data out of |
| + * LTTng. The module calling this registration function must ensure that no |
| + * trap-inducing code will be executed by the transport functions. E.g. |
| + * vmalloc_sync_all() must be called between a vmalloc and the moment the memory |
| + * is made visible to the transport function. This registration acts as a |
| + * vmalloc_sync_all. Therefore, only if the module allocates virtual memory |
| + * after its registration must it synchronize the TLBs. |
| + */ |
| +void lttng_transport_register(struct lttng_transport *transport) |
| +{ |
| + /* |
| + * Make sure no page fault can be triggered by the module about to be |
| + * registered. We deal with this here so we don't have to call |
| + * vmalloc_sync_all() in each module's init. |
| + */ |
| + wrapper_vmalloc_sync_all(); |
| + |
| + mutex_lock(&sessions_mutex); |
| + list_add_tail(&transport->node, <tng_transport_list); |
| + mutex_unlock(&sessions_mutex); |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_transport_register); |
| + |
| +/** |
| + * lttng_transport_unregister - LTT transport unregistration |
| + * @transport: transport structure |
| + */ |
| +void lttng_transport_unregister(struct lttng_transport *transport) |
| +{ |
| + mutex_lock(&sessions_mutex); |
| + list_del(&transport->node); |
| + mutex_unlock(&sessions_mutex); |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_transport_unregister); |
| + |
| +static int __init lttng_events_init(void) |
| +{ |
| + int ret; |
| + |
| + event_cache = KMEM_CACHE(lttng_event, 0); |
| + if (!event_cache) |
| + return -ENOMEM; |
| + ret = lttng_abi_init(); |
| + if (ret) |
| + goto error_abi; |
| + return 0; |
| +error_abi: |
| + kmem_cache_destroy(event_cache); |
| + return ret; |
| +} |
| + |
| +module_init(lttng_events_init); |
| + |
| +static void __exit lttng_events_exit(void) |
| +{ |
| + struct lttng_session *session, *tmpsession; |
| + |
| + lttng_abi_exit(); |
| + list_for_each_entry_safe(session, tmpsession, &sessions, list) |
| + lttng_session_destroy(session); |
| + kmem_cache_destroy(event_cache); |
| +} |
| + |
| +module_exit(lttng_events_exit); |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); |
| +MODULE_DESCRIPTION("LTTng Events"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-events.h |
| @@ -0,0 +1,466 @@ |
| +#ifndef _LTTNG_EVENTS_H |
| +#define _LTTNG_EVENTS_H |
| + |
| +/* |
| + * lttng-events.h |
| + * |
| + * Holds LTTng per-session event registry. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/list.h> |
| +#include <linux/kprobes.h> |
| +#include "wrapper/uuid.h" |
| +#include "lttng-abi.h" |
| + |
| +#undef is_signed_type |
| +#define is_signed_type(type) (((type)(-1)) < 0) |
| + |
| +struct lttng_channel; |
| +struct lttng_session; |
| +struct lib_ring_buffer_ctx; |
| +struct perf_event; |
| +struct perf_event_attr; |
| + |
| +/* Type description */ |
| + |
| +/* Update the astract_types name table in lttng-types.c along with this enum */ |
| +enum abstract_types { |
| + atype_integer, |
| + atype_enum, |
| + atype_array, |
| + atype_sequence, |
| + atype_string, |
| + NR_ABSTRACT_TYPES, |
| +}; |
| + |
| +/* Update the string_encodings name table in lttng-types.c along with this enum */ |
| +enum lttng_string_encodings { |
| + lttng_encode_none = 0, |
| + lttng_encode_UTF8 = 1, |
| + lttng_encode_ASCII = 2, |
| + NR_STRING_ENCODINGS, |
| +}; |
| + |
| +struct lttng_enum_entry { |
| + unsigned long long start, end; /* start and end are inclusive */ |
| + const char *string; |
| +}; |
| + |
| +#define __type_integer(_type, _byte_order, _base, _encoding) \ |
| + { \ |
| + .atype = atype_integer, \ |
| + .u.basic.integer = \ |
| + { \ |
| + .size = sizeof(_type) * CHAR_BIT, \ |
| + .alignment = lttng_alignof(_type) * CHAR_BIT, \ |
| + .signedness = is_signed_type(_type), \ |
| + .reverse_byte_order = _byte_order != __BYTE_ORDER, \ |
| + .base = _base, \ |
| + .encoding = lttng_encode_##_encoding, \ |
| + }, \ |
| + } \ |
| + |
| +struct lttng_integer_type { |
| + unsigned int size; /* in bits */ |
| + unsigned short alignment; /* in bits */ |
| + unsigned int signedness:1, |
| + reverse_byte_order:1; |
| + unsigned int base; /* 2, 8, 10, 16, for pretty print */ |
| + enum lttng_string_encodings encoding; |
| +}; |
| + |
| +union _lttng_basic_type { |
| + struct lttng_integer_type integer; |
| + struct { |
| + const char *name; |
| + } enumeration; |
| + struct { |
| + enum lttng_string_encodings encoding; |
| + } string; |
| +}; |
| + |
| +struct lttng_basic_type { |
| + enum abstract_types atype; |
| + union { |
| + union _lttng_basic_type basic; |
| + } u; |
| +}; |
| + |
| +struct lttng_type { |
| + enum abstract_types atype; |
| + union { |
| + union _lttng_basic_type basic; |
| + struct { |
| + struct lttng_basic_type elem_type; |
| + unsigned int length; /* num. elems. */ |
| + } array; |
| + struct { |
| + struct lttng_basic_type length_type; |
| + struct lttng_basic_type elem_type; |
| + } sequence; |
| + } u; |
| +}; |
| + |
| +struct lttng_enum { |
| + const char *name; |
| + struct lttng_type container_type; |
| + const struct lttng_enum_entry *entries; |
| + unsigned int len; |
| +}; |
| + |
| +/* Event field description */ |
| + |
| +struct lttng_event_field { |
| + const char *name; |
| + struct lttng_type type; |
| +}; |
| + |
| +/* |
| + * We need to keep this perf counter field separately from struct |
| + * lttng_ctx_field because cpu hotplug needs fixed-location addresses. |
| + */ |
| +struct lttng_perf_counter_field { |
| + struct notifier_block nb; |
| + int hp_enable; |
| + struct perf_event_attr *attr; |
| + struct perf_event **e; /* per-cpu array */ |
| +}; |
| + |
| +struct lttng_ctx_field { |
| + struct lttng_event_field event_field; |
| + size_t (*get_size)(size_t offset); |
| + void (*record)(struct lttng_ctx_field *field, |
| + struct lib_ring_buffer_ctx *ctx, |
| + struct lttng_channel *chan); |
| + union { |
| + struct lttng_perf_counter_field *perf_counter; |
| + } u; |
| + void (*destroy)(struct lttng_ctx_field *field); |
| +}; |
| + |
| +struct lttng_ctx { |
| + struct lttng_ctx_field *fields; |
| + unsigned int nr_fields; |
| + unsigned int allocated_fields; |
| +}; |
| + |
| +struct lttng_event_desc { |
| + const char *name; |
| + void *probe_callback; |
| + const struct lttng_event_ctx *ctx; /* context */ |
| + const struct lttng_event_field *fields; /* event payload */ |
| + unsigned int nr_fields; |
| + struct module *owner; |
| +}; |
| + |
| +struct lttng_probe_desc { |
| + const struct lttng_event_desc **event_desc; |
| + unsigned int nr_events; |
| + struct list_head head; /* chain registered probes */ |
| +}; |
| + |
| +struct lttng_krp; /* Kretprobe handling */ |
| + |
| +/* |
| + * lttng_event structure is referred to by the tracing fast path. It must be |
| + * kept small. |
| + */ |
| +struct lttng_event { |
| + unsigned int id; |
| + struct lttng_channel *chan; |
| + int enabled; |
| + const struct lttng_event_desc *desc; |
| + void *filter; |
| + struct lttng_ctx *ctx; |
| + enum lttng_kernel_instrumentation instrumentation; |
| + union { |
| + struct { |
| + struct kprobe kp; |
| + char *symbol_name; |
| + } kprobe; |
| + struct { |
| + struct lttng_krp *lttng_krp; |
| + char *symbol_name; |
| + } kretprobe; |
| + struct { |
| + char *symbol_name; |
| + } ftrace; |
| + } u; |
| + struct list_head list; /* Event list */ |
| + unsigned int metadata_dumped:1; |
| +}; |
| + |
| +struct lttng_channel_ops { |
| + struct channel *(*channel_create)(const char *name, |
| + struct lttng_channel *lttng_chan, |
| + void *buf_addr, |
| + size_t subbuf_size, size_t num_subbuf, |
| + unsigned int switch_timer_interval, |
| + unsigned int read_timer_interval); |
| + void (*channel_destroy)(struct channel *chan); |
| + struct lib_ring_buffer *(*buffer_read_open)(struct channel *chan); |
| + int (*buffer_has_read_closed_stream)(struct channel *chan); |
| + void (*buffer_read_close)(struct lib_ring_buffer *buf); |
| + int (*event_reserve)(struct lib_ring_buffer_ctx *ctx, |
| + uint32_t event_id); |
| + void (*event_commit)(struct lib_ring_buffer_ctx *ctx); |
| + void (*event_write)(struct lib_ring_buffer_ctx *ctx, const void *src, |
| + size_t len); |
| + void (*event_write_from_user)(struct lib_ring_buffer_ctx *ctx, |
| + const void *src, size_t len); |
| + void (*event_memset)(struct lib_ring_buffer_ctx *ctx, |
| + int c, size_t len); |
| + /* |
| + * packet_avail_size returns the available size in the current |
| + * packet. Note that the size returned is only a hint, since it |
| + * may change due to concurrent writes. |
| + */ |
| + size_t (*packet_avail_size)(struct channel *chan); |
| + wait_queue_head_t *(*get_writer_buf_wait_queue)(struct channel *chan, int cpu); |
| + wait_queue_head_t *(*get_hp_wait_queue)(struct channel *chan); |
| + int (*is_finalized)(struct channel *chan); |
| + int (*is_disabled)(struct channel *chan); |
| +}; |
| + |
| +struct lttng_transport { |
| + char *name; |
| + struct module *owner; |
| + struct list_head node; |
| + struct lttng_channel_ops ops; |
| +}; |
| + |
| +struct lttng_channel { |
| + unsigned int id; |
| + struct channel *chan; /* Channel buffers */ |
| + int enabled; |
| + struct lttng_ctx *ctx; |
| + /* Event ID management */ |
| + struct lttng_session *session; |
| + struct file *file; /* File associated to channel */ |
| + unsigned int free_event_id; /* Next event ID to allocate */ |
| + struct list_head list; /* Channel list */ |
| + struct lttng_channel_ops *ops; |
| + struct lttng_transport *transport; |
| + struct lttng_event **sc_table; /* for syscall tracing */ |
| + struct lttng_event **compat_sc_table; |
| + struct lttng_event *sc_unknown; /* for unknown syscalls */ |
| + struct lttng_event *sc_compat_unknown; |
| + struct lttng_event *sc_exit; /* for syscall exit */ |
| + int header_type; /* 0: unset, 1: compact, 2: large */ |
| + unsigned int metadata_dumped:1; |
| +}; |
| + |
| +struct lttng_session { |
| + int active; /* Is trace session active ? */ |
| + int been_active; /* Has trace session been active ? */ |
| + struct file *file; /* File associated to session */ |
| + struct lttng_channel *metadata; /* Metadata channel */ |
| + struct list_head chan; /* Channel list head */ |
| + struct list_head events; /* Event list head */ |
| + struct list_head list; /* Session list */ |
| + unsigned int free_chan_id; /* Next chan ID to allocate */ |
| + uuid_le uuid; /* Trace session unique ID */ |
| + unsigned int metadata_dumped:1; |
| +}; |
| + |
| +struct lttng_session *lttng_session_create(void); |
| +int lttng_session_enable(struct lttng_session *session); |
| +int lttng_session_disable(struct lttng_session *session); |
| +void lttng_session_destroy(struct lttng_session *session); |
| + |
| +struct lttng_channel *lttng_channel_create(struct lttng_session *session, |
| + const char *transport_name, |
| + void *buf_addr, |
| + size_t subbuf_size, size_t num_subbuf, |
| + unsigned int switch_timer_interval, |
| + unsigned int read_timer_interval); |
| +struct lttng_channel *lttng_global_channel_create(struct lttng_session *session, |
| + int overwrite, void *buf_addr, |
| + size_t subbuf_size, size_t num_subbuf, |
| + unsigned int switch_timer_interval, |
| + unsigned int read_timer_interval); |
| + |
| +struct lttng_event *lttng_event_create(struct lttng_channel *chan, |
| + struct lttng_kernel_event *event_param, |
| + void *filter, |
| + const struct lttng_event_desc *internal_desc); |
| + |
| +int lttng_channel_enable(struct lttng_channel *channel); |
| +int lttng_channel_disable(struct lttng_channel *channel); |
| +int lttng_event_enable(struct lttng_event *event); |
| +int lttng_event_disable(struct lttng_event *event); |
| + |
| +void lttng_transport_register(struct lttng_transport *transport); |
| +void lttng_transport_unregister(struct lttng_transport *transport); |
| + |
| +void synchronize_trace(void); |
| +int lttng_abi_init(void); |
| +void lttng_abi_exit(void); |
| + |
| +int lttng_probe_register(struct lttng_probe_desc *desc); |
| +void lttng_probe_unregister(struct lttng_probe_desc *desc); |
| +const struct lttng_event_desc *lttng_event_get(const char *name); |
| +void lttng_event_put(const struct lttng_event_desc *desc); |
| +int lttng_probes_init(void); |
| +void lttng_probes_exit(void); |
| + |
| +#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS |
| +int lttng_syscalls_register(struct lttng_channel *chan, void *filter); |
| +int lttng_syscalls_unregister(struct lttng_channel *chan); |
| +#else |
| +static inline int lttng_syscalls_register(struct lttng_channel *chan, void *filter) |
| +{ |
| + return -ENOSYS; |
| +} |
| + |
| +static inline int lttng_syscalls_unregister(struct lttng_channel *chan) |
| +{ |
| + return 0; |
| +} |
| +#endif |
| + |
| +struct lttng_ctx_field *lttng_append_context(struct lttng_ctx **ctx); |
| +int lttng_find_context(struct lttng_ctx *ctx, const char *name); |
| +void lttng_remove_context_field(struct lttng_ctx **ctx, |
| + struct lttng_ctx_field *field); |
| +void lttng_destroy_context(struct lttng_ctx *ctx); |
| +int lttng_add_pid_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_procname_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_prio_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_nice_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_vpid_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_tid_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_vtid_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_ppid_to_ctx(struct lttng_ctx **ctx); |
| +int lttng_add_vppid_to_ctx(struct lttng_ctx **ctx); |
| +#if defined(CONFIG_PERF_EVENTS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)) |
| +int lttng_add_perf_counter_to_ctx(uint32_t type, |
| + uint64_t config, |
| + const char *name, |
| + struct lttng_ctx **ctx); |
| +#else |
| +static inline |
| +int lttng_add_perf_counter_to_ctx(uint32_t type, |
| + uint64_t config, |
| + const char *name, |
| + struct lttng_ctx **ctx) |
| +{ |
| + return -ENOSYS; |
| +} |
| +#endif |
| + |
| +extern int lttng_statedump_start(struct lttng_session *session); |
| + |
| +#ifdef CONFIG_KPROBES |
| +int lttng_kprobes_register(const char *name, |
| + const char *symbol_name, |
| + uint64_t offset, |
| + uint64_t addr, |
| + struct lttng_event *event); |
| +void lttng_kprobes_unregister(struct lttng_event *event); |
| +void lttng_kprobes_destroy_private(struct lttng_event *event); |
| +#else |
| +static inline |
| +int lttng_kprobes_register(const char *name, |
| + const char *symbol_name, |
| + uint64_t offset, |
| + uint64_t addr, |
| + struct lttng_event *event) |
| +{ |
| + return -ENOSYS; |
| +} |
| + |
| +static inline |
| +void lttng_kprobes_unregister(struct lttng_event *event) |
| +{ |
| +} |
| + |
| +static inline |
| +void lttng_kprobes_destroy_private(struct lttng_event *event) |
| +{ |
| +} |
| +#endif |
| + |
| +#ifdef CONFIG_KRETPROBES |
| +int lttng_kretprobes_register(const char *name, |
| + const char *symbol_name, |
| + uint64_t offset, |
| + uint64_t addr, |
| + struct lttng_event *event_entry, |
| + struct lttng_event *event_exit); |
| +void lttng_kretprobes_unregister(struct lttng_event *event); |
| +void lttng_kretprobes_destroy_private(struct lttng_event *event); |
| +#else |
| +static inline |
| +int lttng_kretprobes_register(const char *name, |
| + const char *symbol_name, |
| + uint64_t offset, |
| + uint64_t addr, |
| + struct lttng_event *event_entry, |
| + struct lttng_event *event_exit) |
| +{ |
| + return -ENOSYS; |
| +} |
| + |
| +static inline |
| +void lttng_kretprobes_unregister(struct lttng_event *event) |
| +{ |
| +} |
| + |
| +static inline |
| +void lttng_kretprobes_destroy_private(struct lttng_event *event) |
| +{ |
| +} |
| +#endif |
| + |
| +#ifdef CONFIG_DYNAMIC_FTRACE |
| +int lttng_ftrace_register(const char *name, |
| + const char *symbol_name, |
| + struct lttng_event *event); |
| +void lttng_ftrace_unregister(struct lttng_event *event); |
| +void lttng_ftrace_destroy_private(struct lttng_event *event); |
| +#else |
| +static inline |
| +int lttng_ftrace_register(const char *name, |
| + const char *symbol_name, |
| + struct lttng_event *event) |
| +{ |
| + return -ENOSYS; |
| +} |
| + |
| +static inline |
| +void lttng_ftrace_unregister(struct lttng_event *event) |
| +{ |
| +} |
| + |
| +static inline |
| +void lttng_ftrace_destroy_private(struct lttng_event *event) |
| +{ |
| +} |
| +#endif |
| + |
| +int lttng_calibrate(struct lttng_kernel_calibrate *calibrate); |
| + |
| +extern const struct file_operations lttng_tracepoint_list_fops; |
| + |
| +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) |
| +#define TRACEPOINT_HAS_DATA_ARG |
| +#endif |
| + |
| +#endif /* _LTTNG_EVENTS_H */ |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-probes.c |
| @@ -0,0 +1,176 @@ |
| +/* |
| + * lttng-probes.c |
| + * |
| + * Holds LTTng probes registry. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include <linux/list.h> |
| +#include <linux/mutex.h> |
| +#include <linux/seq_file.h> |
| + |
| +#include "lttng-events.h" |
| + |
| +static LIST_HEAD(probe_list); |
| +static DEFINE_MUTEX(probe_mutex); |
| + |
| +static |
| +const struct lttng_event_desc *find_event(const char *name) |
| +{ |
| + struct lttng_probe_desc *probe_desc; |
| + int i; |
| + |
| + list_for_each_entry(probe_desc, &probe_list, head) { |
| + for (i = 0; i < probe_desc->nr_events; i++) { |
| + if (!strcmp(probe_desc->event_desc[i]->name, name)) |
| + return probe_desc->event_desc[i]; |
| + } |
| + } |
| + return NULL; |
| +} |
| + |
| +int lttng_probe_register(struct lttng_probe_desc *desc) |
| +{ |
| + int ret = 0; |
| + int i; |
| + |
| + mutex_lock(&probe_mutex); |
| + /* |
| + * TODO: This is O(N^2). Turn into a hash table when probe registration |
| + * overhead becomes an issue. |
| + */ |
| + for (i = 0; i < desc->nr_events; i++) { |
| + if (find_event(desc->event_desc[i]->name)) { |
| + ret = -EEXIST; |
| + goto end; |
| + } |
| + } |
| + list_add(&desc->head, &probe_list); |
| +end: |
| + mutex_unlock(&probe_mutex); |
| + return ret; |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_probe_register); |
| + |
| +void lttng_probe_unregister(struct lttng_probe_desc *desc) |
| +{ |
| + mutex_lock(&probe_mutex); |
| + list_del(&desc->head); |
| + mutex_unlock(&probe_mutex); |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_probe_unregister); |
| + |
| +const struct lttng_event_desc *lttng_event_get(const char *name) |
| +{ |
| + const struct lttng_event_desc *event; |
| + int ret; |
| + |
| + mutex_lock(&probe_mutex); |
| + event = find_event(name); |
| + mutex_unlock(&probe_mutex); |
| + if (!event) |
| + return NULL; |
| + ret = try_module_get(event->owner); |
| + WARN_ON_ONCE(!ret); |
| + return event; |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_event_get); |
| + |
| +void lttng_event_put(const struct lttng_event_desc *event) |
| +{ |
| + module_put(event->owner); |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_event_put); |
| + |
| +static |
| +void *tp_list_start(struct seq_file *m, loff_t *pos) |
| +{ |
| + struct lttng_probe_desc *probe_desc; |
| + int iter = 0, i; |
| + |
| + mutex_lock(&probe_mutex); |
| + list_for_each_entry(probe_desc, &probe_list, head) { |
| + for (i = 0; i < probe_desc->nr_events; i++) { |
| + if (iter++ >= *pos) |
| + return (void *) probe_desc->event_desc[i]; |
| + } |
| + } |
| + /* End of list */ |
| + return NULL; |
| +} |
| + |
| +static |
| +void *tp_list_next(struct seq_file *m, void *p, loff_t *ppos) |
| +{ |
| + struct lttng_probe_desc *probe_desc; |
| + int iter = 0, i; |
| + |
| + (*ppos)++; |
| + list_for_each_entry(probe_desc, &probe_list, head) { |
| + for (i = 0; i < probe_desc->nr_events; i++) { |
| + if (iter++ >= *ppos) |
| + return (void *) probe_desc->event_desc[i]; |
| + } |
| + } |
| + /* End of list */ |
| + return NULL; |
| +} |
| + |
| +static |
| +void tp_list_stop(struct seq_file *m, void *p) |
| +{ |
| + mutex_unlock(&probe_mutex); |
| +} |
| + |
| +static |
| +int tp_list_show(struct seq_file *m, void *p) |
| +{ |
| + const struct lttng_event_desc *probe_desc = p; |
| + |
| + /* |
| + * Don't export lttng internal event: lttng_metadata. |
| + */ |
| + if (!strcmp(probe_desc->name, "lttng_metadata")) |
| + return 0; |
| + seq_printf(m, "event { name = %s; };\n", |
| + probe_desc->name); |
| + return 0; |
| +} |
| + |
| +static |
| +const struct seq_operations lttng_tracepoint_list_seq_ops = { |
| + .start = tp_list_start, |
| + .next = tp_list_next, |
| + .stop = tp_list_stop, |
| + .show = tp_list_show, |
| +}; |
| + |
| +static |
| +int lttng_tracepoint_list_open(struct inode *inode, struct file *file) |
| +{ |
| + return seq_open(file, <tng_tracepoint_list_seq_ops); |
| +} |
| + |
| +const struct file_operations lttng_tracepoint_list_fops = { |
| + .owner = THIS_MODULE, |
| + .open = lttng_tracepoint_list_open, |
| + .read = seq_read, |
| + .llseek = seq_lseek, |
| + .release = seq_release, |
| +}; |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-client-discard.c |
| @@ -0,0 +1,33 @@ |
| +/* |
| + * lttng-ring-buffer-client-discard.c |
| + * |
| + * LTTng lib ring buffer client (discard mode). |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include "lttng-tracer.h" |
| + |
| +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| +#define RING_BUFFER_MODE_TEMPLATE_STRING "discard" |
| +#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_SPLICE |
| +#include "lttng-ring-buffer-client.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng Ring Buffer Client Discard Mode"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-client-mmap-discard.c |
| @@ -0,0 +1,33 @@ |
| +/* |
| + * lttng-ring-buffer-client-discard.c |
| + * |
| + * LTTng lib ring buffer client (discard mode). |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include "lttng-tracer.h" |
| + |
| +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| +#define RING_BUFFER_MODE_TEMPLATE_STRING "discard-mmap" |
| +#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_MMAP |
| +#include "lttng-ring-buffer-client.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng Ring Buffer Client Discard Mode"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-client-mmap-overwrite.c |
| @@ -0,0 +1,33 @@ |
| +/* |
| + * lttng-ring-buffer-client-overwrite.c |
| + * |
| + * LTTng lib ring buffer client (overwrite mode). |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include "lttng-tracer.h" |
| + |
| +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE |
| +#define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite-mmap" |
| +#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_MMAP |
| +#include "lttng-ring-buffer-client.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng Ring Buffer Client Overwrite Mode"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-client-overwrite.c |
| @@ -0,0 +1,33 @@ |
| +/* |
| + * lttng-ring-buffer-client-overwrite.c |
| + * |
| + * LTTng lib ring buffer client (overwrite mode). |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include "lttng-tracer.h" |
| + |
| +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_OVERWRITE |
| +#define RING_BUFFER_MODE_TEMPLATE_STRING "overwrite" |
| +#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_SPLICE |
| +#include "lttng-ring-buffer-client.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng Ring Buffer Client Overwrite Mode"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-client.h |
| @@ -0,0 +1,598 @@ |
| +/* |
| + * lttng-ring-buffer-client.h |
| + * |
| + * LTTng lib ring buffer client template. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include <linux/types.h> |
| +#include "lib/bitfield.h" |
| +#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| +#include "wrapper/trace-clock.h" |
| +#include "lttng-events.h" |
| +#include "lttng-tracer.h" |
| +#include "wrapper/ringbuffer/frontend_types.h" |
| + |
| +#define LTTNG_COMPACT_EVENT_BITS 5 |
| +#define LTTNG_COMPACT_TSC_BITS 27 |
| + |
| +/* |
| + * Keep the natural field alignment for _each field_ within this structure if |
| + * you ever add/remove a field from this header. Packed attribute is not used |
| + * because gcc generates poor code on at least powerpc and mips. Don't ever |
| + * let gcc add padding between the structure elements. |
| + * |
| + * The guarantee we have with timestamps is that all the events in a |
| + * packet are included (inclusive) within the begin/end timestamps of |
| + * the packet. Another guarantee we have is that the "timestamp begin", |
| + * as well as the event timestamps, are monotonically increasing (never |
| + * decrease) when moving forward in a stream (physically). But this |
| + * guarantee does not apply to "timestamp end", because it is sampled at |
| + * commit time, which is not ordered with respect to space reservation. |
| + */ |
| + |
| +struct packet_header { |
| + /* Trace packet header */ |
| + uint32_t magic; /* |
| + * Trace magic number. |
| + * contains endianness information. |
| + */ |
| + uint8_t uuid[16]; |
| + uint32_t stream_id; |
| + |
| + struct { |
| + /* Stream packet context */ |
| + uint64_t timestamp_begin; /* Cycle count at subbuffer start */ |
| + uint64_t timestamp_end; /* Cycle count at subbuffer end */ |
| + uint32_t events_discarded; /* |
| + * Events lost in this subbuffer since |
| + * the beginning of the trace. |
| + * (may overflow) |
| + */ |
| + uint32_t content_size; /* Size of data in subbuffer */ |
| + uint32_t packet_size; /* Subbuffer size (include padding) */ |
| + uint32_t cpu_id; /* CPU id associated with stream */ |
| + uint8_t header_end; /* End of header */ |
| + } ctx; |
| +}; |
| + |
| + |
| +static inline notrace u64 lib_ring_buffer_clock_read(struct channel *chan) |
| +{ |
| + return trace_clock_read64(); |
| +} |
| + |
| +static inline |
| +size_t ctx_get_size(size_t offset, struct lttng_ctx *ctx) |
| +{ |
| + int i; |
| + size_t orig_offset = offset; |
| + |
| + if (likely(!ctx)) |
| + return 0; |
| + for (i = 0; i < ctx->nr_fields; i++) |
| + offset += ctx->fields[i].get_size(offset); |
| + return offset - orig_offset; |
| +} |
| + |
| +static inline |
| +void ctx_record(struct lib_ring_buffer_ctx *bufctx, |
| + struct lttng_channel *chan, |
| + struct lttng_ctx *ctx) |
| +{ |
| + int i; |
| + |
| + if (likely(!ctx)) |
| + return; |
| + for (i = 0; i < ctx->nr_fields; i++) |
| + ctx->fields[i].record(&ctx->fields[i], bufctx, chan); |
| +} |
| + |
| +/* |
| + * record_header_size - Calculate the header size and padding necessary. |
| + * @config: ring buffer instance configuration |
| + * @chan: channel |
| + * @offset: offset in the write buffer |
| + * @pre_header_padding: padding to add before the header (output) |
| + * @ctx: reservation context |
| + * |
| + * Returns the event header size (including padding). |
| + * |
| + * The payload must itself determine its own alignment from the biggest type it |
| + * contains. |
| + */ |
| +static __inline__ |
| +unsigned char record_header_size(const struct lib_ring_buffer_config *config, |
| + struct channel *chan, size_t offset, |
| + size_t *pre_header_padding, |
| + struct lib_ring_buffer_ctx *ctx) |
| +{ |
| + struct lttng_channel *lttng_chan = channel_get_private(chan); |
| + struct lttng_event *event = ctx->priv; |
| + size_t orig_offset = offset; |
| + size_t padding; |
| + |
| + switch (lttng_chan->header_type) { |
| + case 1: /* compact */ |
| + padding = lib_ring_buffer_align(offset, lttng_alignof(uint32_t)); |
| + offset += padding; |
| + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { |
| + offset += sizeof(uint32_t); /* id and timestamp */ |
| + } else { |
| + /* Minimum space taken by LTTNG_COMPACT_EVENT_BITS id */ |
| + offset += (LTTNG_COMPACT_EVENT_BITS + CHAR_BIT - 1) / CHAR_BIT; |
| + /* Align extended struct on largest member */ |
| + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); |
| + offset += sizeof(uint32_t); /* id */ |
| + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); |
| + offset += sizeof(uint64_t); /* timestamp */ |
| + } |
| + break; |
| + case 2: /* large */ |
| + padding = lib_ring_buffer_align(offset, lttng_alignof(uint16_t)); |
| + offset += padding; |
| + offset += sizeof(uint16_t); |
| + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { |
| + offset += lib_ring_buffer_align(offset, lttng_alignof(uint32_t)); |
| + offset += sizeof(uint32_t); /* timestamp */ |
| + } else { |
| + /* Align extended struct on largest member */ |
| + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); |
| + offset += sizeof(uint32_t); /* id */ |
| + offset += lib_ring_buffer_align(offset, lttng_alignof(uint64_t)); |
| + offset += sizeof(uint64_t); /* timestamp */ |
| + } |
| + break; |
| + default: |
| + padding = 0; |
| + WARN_ON_ONCE(1); |
| + } |
| + offset += ctx_get_size(offset, event->ctx); |
| + offset += ctx_get_size(offset, lttng_chan->ctx); |
| + |
| + *pre_header_padding = padding; |
| + return offset - orig_offset; |
| +} |
| + |
| +#include "wrapper/ringbuffer/api.h" |
| + |
| +static |
| +void lttng_write_event_header_slow(const struct lib_ring_buffer_config *config, |
| + struct lib_ring_buffer_ctx *ctx, |
| + uint32_t event_id); |
| + |
| +/* |
| + * lttng_write_event_header |
| + * |
| + * Writes the event header to the offset (already aligned on 32-bits). |
| + * |
| + * @config: ring buffer instance configuration |
| + * @ctx: reservation context |
| + * @event_id: event ID |
| + */ |
| +static __inline__ |
| +void lttng_write_event_header(const struct lib_ring_buffer_config *config, |
| + struct lib_ring_buffer_ctx *ctx, |
| + uint32_t event_id) |
| +{ |
| + struct lttng_channel *lttng_chan = channel_get_private(ctx->chan); |
| + struct lttng_event *event = ctx->priv; |
| + |
| + if (unlikely(ctx->rflags)) |
| + goto slow_path; |
| + |
| + switch (lttng_chan->header_type) { |
| + case 1: /* compact */ |
| + { |
| + uint32_t id_time = 0; |
| + |
| + bt_bitfield_write(&id_time, uint32_t, |
| + 0, |
| + LTTNG_COMPACT_EVENT_BITS, |
| + event_id); |
| + bt_bitfield_write(&id_time, uint32_t, |
| + LTTNG_COMPACT_EVENT_BITS, |
| + LTTNG_COMPACT_TSC_BITS, |
| + ctx->tsc); |
| + lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); |
| + break; |
| + } |
| + case 2: /* large */ |
| + { |
| + uint32_t timestamp = (uint32_t) ctx->tsc; |
| + uint16_t id = event_id; |
| + |
| + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t)); |
| + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| + break; |
| + } |
| + default: |
| + WARN_ON_ONCE(1); |
| + } |
| + |
| + ctx_record(ctx, lttng_chan, lttng_chan->ctx); |
| + ctx_record(ctx, lttng_chan, event->ctx); |
| + lib_ring_buffer_align_ctx(ctx, ctx->largest_align); |
| + |
| + return; |
| + |
| +slow_path: |
| + lttng_write_event_header_slow(config, ctx, event_id); |
| +} |
| + |
| +static |
| +void lttng_write_event_header_slow(const struct lib_ring_buffer_config *config, |
| + struct lib_ring_buffer_ctx *ctx, |
| + uint32_t event_id) |
| +{ |
| + struct lttng_channel *lttng_chan = channel_get_private(ctx->chan); |
| + struct lttng_event *event = ctx->priv; |
| + |
| + switch (lttng_chan->header_type) { |
| + case 1: /* compact */ |
| + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { |
| + uint32_t id_time = 0; |
| + |
| + bt_bitfield_write(&id_time, uint32_t, |
| + 0, |
| + LTTNG_COMPACT_EVENT_BITS, |
| + event_id); |
| + bt_bitfield_write(&id_time, uint32_t, |
| + LTTNG_COMPACT_EVENT_BITS, |
| + LTTNG_COMPACT_TSC_BITS, ctx->tsc); |
| + lib_ring_buffer_write(config, ctx, &id_time, sizeof(id_time)); |
| + } else { |
| + uint8_t id = 0; |
| + uint64_t timestamp = ctx->tsc; |
| + |
| + bt_bitfield_write(&id, uint8_t, |
| + 0, |
| + LTTNG_COMPACT_EVENT_BITS, |
| + 31); |
| + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| + /* Align extended struct on largest member */ |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); |
| + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); |
| + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| + } |
| + break; |
| + case 2: /* large */ |
| + { |
| + if (!(ctx->rflags & (RING_BUFFER_RFLAG_FULL_TSC | LTTNG_RFLAG_EXTENDED))) { |
| + uint32_t timestamp = (uint32_t) ctx->tsc; |
| + uint16_t id = event_id; |
| + |
| + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint32_t)); |
| + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| + } else { |
| + uint16_t id = 65535; |
| + uint64_t timestamp = ctx->tsc; |
| + |
| + lib_ring_buffer_write(config, ctx, &id, sizeof(id)); |
| + /* Align extended struct on largest member */ |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); |
| + lib_ring_buffer_write(config, ctx, &event_id, sizeof(event_id)); |
| + lib_ring_buffer_align_ctx(ctx, lttng_alignof(uint64_t)); |
| + lib_ring_buffer_write(config, ctx, ×tamp, sizeof(timestamp)); |
| + } |
| + break; |
| + } |
| + default: |
| + WARN_ON_ONCE(1); |
| + } |
| + ctx_record(ctx, lttng_chan, lttng_chan->ctx); |
| + ctx_record(ctx, lttng_chan, event->ctx); |
| + lib_ring_buffer_align_ctx(ctx, ctx->largest_align); |
| +} |
| + |
| +static const struct lib_ring_buffer_config client_config; |
| + |
| +static u64 client_ring_buffer_clock_read(struct channel *chan) |
| +{ |
| + return lib_ring_buffer_clock_read(chan); |
| +} |
| + |
| +static |
| +size_t client_record_header_size(const struct lib_ring_buffer_config *config, |
| + struct channel *chan, size_t offset, |
| + size_t *pre_header_padding, |
| + struct lib_ring_buffer_ctx *ctx) |
| +{ |
| + return record_header_size(config, chan, offset, |
| + pre_header_padding, ctx); |
| +} |
| + |
| +/** |
| + * client_packet_header_size - called on buffer-switch to a new sub-buffer |
| + * |
| + * Return header size without padding after the structure. Don't use packed |
| + * structure because gcc generates inefficient code on some architectures |
| + * (powerpc, mips..) |
| + */ |
| +static size_t client_packet_header_size(void) |
| +{ |
| + return offsetof(struct packet_header, ctx.header_end); |
| +} |
| + |
| +static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc, |
| + unsigned int subbuf_idx) |
| +{ |
| + struct channel *chan = buf->backend.chan; |
| + struct packet_header *header = |
| + (struct packet_header *) |
| + lib_ring_buffer_offset_address(&buf->backend, |
| + subbuf_idx * chan->backend.subbuf_size); |
| + struct lttng_channel *lttng_chan = channel_get_private(chan); |
| + struct lttng_session *session = lttng_chan->session; |
| + |
| + header->magic = CTF_MAGIC_NUMBER; |
| + memcpy(header->uuid, session->uuid.b, sizeof(session->uuid)); |
| + header->stream_id = lttng_chan->id; |
| + header->ctx.timestamp_begin = tsc; |
| + header->ctx.timestamp_end = 0; |
| + header->ctx.events_discarded = 0; |
| + header->ctx.content_size = 0xFFFFFFFF; /* for debugging */ |
| + header->ctx.packet_size = 0xFFFFFFFF; |
| + header->ctx.cpu_id = buf->backend.cpu; |
| +} |
| + |
| +/* |
| + * offset is assumed to never be 0 here : never deliver a completely empty |
| + * subbuffer. data_size is between 1 and subbuf_size. |
| + */ |
| +static void client_buffer_end(struct lib_ring_buffer *buf, u64 tsc, |
| + unsigned int subbuf_idx, unsigned long data_size) |
| +{ |
| + struct channel *chan = buf->backend.chan; |
| + struct packet_header *header = |
| + (struct packet_header *) |
| + lib_ring_buffer_offset_address(&buf->backend, |
| + subbuf_idx * chan->backend.subbuf_size); |
| + unsigned long records_lost = 0; |
| + |
| + header->ctx.timestamp_end = tsc; |
| + header->ctx.content_size = data_size * CHAR_BIT; /* in bits */ |
| + header->ctx.packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ |
| + records_lost += lib_ring_buffer_get_records_lost_full(&client_config, buf); |
| + records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); |
| + records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); |
| + header->ctx.events_discarded = records_lost; |
| +} |
| + |
| +static int client_buffer_create(struct lib_ring_buffer *buf, void *priv, |
| + int cpu, const char *name) |
| +{ |
| + return 0; |
| +} |
| + |
| +static void client_buffer_finalize(struct lib_ring_buffer *buf, void *priv, int cpu) |
| +{ |
| +} |
| + |
| +static const struct lib_ring_buffer_config client_config = { |
| + .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, |
| + .cb.record_header_size = client_record_header_size, |
| + .cb.subbuffer_header_size = client_packet_header_size, |
| + .cb.buffer_begin = client_buffer_begin, |
| + .cb.buffer_end = client_buffer_end, |
| + .cb.buffer_create = client_buffer_create, |
| + .cb.buffer_finalize = client_buffer_finalize, |
| + |
| + .tsc_bits = LTTNG_COMPACT_TSC_BITS, |
| + .alloc = RING_BUFFER_ALLOC_PER_CPU, |
| + .sync = RING_BUFFER_SYNC_PER_CPU, |
| + .mode = RING_BUFFER_MODE_TEMPLATE, |
| + .backend = RING_BUFFER_PAGE, |
| + .output = RING_BUFFER_OUTPUT_TEMPLATE, |
| + .oops = RING_BUFFER_OOPS_CONSISTENCY, |
| + .ipi = RING_BUFFER_IPI_BARRIER, |
| + .wakeup = RING_BUFFER_WAKEUP_BY_TIMER, |
| +}; |
| + |
| +static |
| +struct channel *_channel_create(const char *name, |
| + struct lttng_channel *lttng_chan, void *buf_addr, |
| + size_t subbuf_size, size_t num_subbuf, |
| + unsigned int switch_timer_interval, |
| + unsigned int read_timer_interval) |
| +{ |
| + return channel_create(&client_config, name, lttng_chan, buf_addr, |
| + subbuf_size, num_subbuf, switch_timer_interval, |
| + read_timer_interval); |
| +} |
| + |
| +static |
| +void lttng_channel_destroy(struct channel *chan) |
| +{ |
| + channel_destroy(chan); |
| +} |
| + |
| +static |
| +struct lib_ring_buffer *lttng_buffer_read_open(struct channel *chan) |
| +{ |
| + struct lib_ring_buffer *buf; |
| + int cpu; |
| + |
| + for_each_channel_cpu(cpu, chan) { |
| + buf = channel_get_ring_buffer(&client_config, chan, cpu); |
| + if (!lib_ring_buffer_open_read(buf)) |
| + return buf; |
| + } |
| + return NULL; |
| +} |
| + |
| +static |
| +int lttng_buffer_has_read_closed_stream(struct channel *chan) |
| +{ |
| + struct lib_ring_buffer *buf; |
| + int cpu; |
| + |
| + for_each_channel_cpu(cpu, chan) { |
| + buf = channel_get_ring_buffer(&client_config, chan, cpu); |
| + if (!atomic_long_read(&buf->active_readers)) |
| + return 1; |
| + } |
| + return 0; |
| +} |
| + |
| +static |
| +void lttng_buffer_read_close(struct lib_ring_buffer *buf) |
| +{ |
| + lib_ring_buffer_release_read(buf); |
| +} |
| + |
| +static |
| +int lttng_event_reserve(struct lib_ring_buffer_ctx *ctx, |
| + uint32_t event_id) |
| +{ |
| + struct lttng_channel *lttng_chan = channel_get_private(ctx->chan); |
| + int ret, cpu; |
| + |
| + cpu = lib_ring_buffer_get_cpu(&client_config); |
| + if (cpu < 0) |
| + return -EPERM; |
| + ctx->cpu = cpu; |
| + |
| + switch (lttng_chan->header_type) { |
| + case 1: /* compact */ |
| + if (event_id > 30) |
| + ctx->rflags |= LTTNG_RFLAG_EXTENDED; |
| + break; |
| + case 2: /* large */ |
| + if (event_id > 65534) |
| + ctx->rflags |= LTTNG_RFLAG_EXTENDED; |
| + break; |
| + default: |
| + WARN_ON_ONCE(1); |
| + } |
| + |
| + ret = lib_ring_buffer_reserve(&client_config, ctx); |
| + if (ret) |
| + goto put; |
| + lttng_write_event_header(&client_config, ctx, event_id); |
| + return 0; |
| +put: |
| + lib_ring_buffer_put_cpu(&client_config); |
| + return ret; |
| +} |
| + |
| +static |
| +void lttng_event_commit(struct lib_ring_buffer_ctx *ctx) |
| +{ |
| + lib_ring_buffer_commit(&client_config, ctx); |
| + lib_ring_buffer_put_cpu(&client_config); |
| +} |
| + |
| +static |
| +void lttng_event_write(struct lib_ring_buffer_ctx *ctx, const void *src, |
| + size_t len) |
| +{ |
| + lib_ring_buffer_write(&client_config, ctx, src, len); |
| +} |
| + |
| +static |
| +void lttng_event_write_from_user(struct lib_ring_buffer_ctx *ctx, |
| + const void __user *src, size_t len) |
| +{ |
| + lib_ring_buffer_copy_from_user(&client_config, ctx, src, len); |
| +} |
| + |
| +static |
| +void lttng_event_memset(struct lib_ring_buffer_ctx *ctx, |
| + int c, size_t len) |
| +{ |
| + lib_ring_buffer_memset(&client_config, ctx, c, len); |
| +} |
| + |
| +static |
| +wait_queue_head_t *lttng_get_writer_buf_wait_queue(struct channel *chan, int cpu) |
| +{ |
| + struct lib_ring_buffer *buf = channel_get_ring_buffer(&client_config, |
| + chan, cpu); |
| + return &buf->write_wait; |
| +} |
| + |
| +static |
| +wait_queue_head_t *lttng_get_hp_wait_queue(struct channel *chan) |
| +{ |
| + return &chan->hp_wait; |
| +} |
| + |
| +static |
| +int lttng_is_finalized(struct channel *chan) |
| +{ |
| + return lib_ring_buffer_channel_is_finalized(chan); |
| +} |
| + |
| +static |
| +int lttng_is_disabled(struct channel *chan) |
| +{ |
| + return lib_ring_buffer_channel_is_disabled(chan); |
| +} |
| + |
| +static struct lttng_transport lttng_relay_transport = { |
| + .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING, |
| + .owner = THIS_MODULE, |
| + .ops = { |
| + .channel_create = _channel_create, |
| + .channel_destroy = lttng_channel_destroy, |
| + .buffer_read_open = lttng_buffer_read_open, |
| + .buffer_has_read_closed_stream = |
| + lttng_buffer_has_read_closed_stream, |
| + .buffer_read_close = lttng_buffer_read_close, |
| + .event_reserve = lttng_event_reserve, |
| + .event_commit = lttng_event_commit, |
| + .event_write = lttng_event_write, |
| + .event_write_from_user = lttng_event_write_from_user, |
| + .event_memset = lttng_event_memset, |
| + .packet_avail_size = NULL, /* Would be racy anyway */ |
| + .get_writer_buf_wait_queue = lttng_get_writer_buf_wait_queue, |
| + .get_hp_wait_queue = lttng_get_hp_wait_queue, |
| + .is_finalized = lttng_is_finalized, |
| + .is_disabled = lttng_is_disabled, |
| + }, |
| +}; |
| + |
| +static int __init lttng_ring_buffer_client_init(void) |
| +{ |
| + /* |
| + * This vmalloc sync all also takes care of the lib ring buffer |
| + * vmalloc'd module pages when it is built as a module into LTTng. |
| + */ |
| + wrapper_vmalloc_sync_all(); |
| + lttng_transport_register(<tng_relay_transport); |
| + return 0; |
| +} |
| + |
| +module_init(lttng_ring_buffer_client_init); |
| + |
| +static void __exit lttng_ring_buffer_client_exit(void) |
| +{ |
| + lttng_transport_unregister(<tng_relay_transport); |
| +} |
| + |
| +module_exit(lttng_ring_buffer_client_exit); |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng ring buffer " RING_BUFFER_MODE_TEMPLATE_STRING |
| + " client"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-metadata-client.c |
| @@ -0,0 +1,33 @@ |
| +/* |
| + * lttng-ring-buffer-metadata-client.c |
| + * |
| + * LTTng lib ring buffer metadta client. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include "lttng-tracer.h" |
| + |
| +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| +#define RING_BUFFER_MODE_TEMPLATE_STRING "metadata" |
| +#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_SPLICE |
| +#include "lttng-ring-buffer-metadata-client.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng Ring Buffer Metadata Client"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-metadata-client.h |
| @@ -0,0 +1,342 @@ |
| +/* |
| + * lttng-ring-buffer-client.h |
| + * |
| + * LTTng lib ring buffer client template. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include <linux/types.h> |
| +#include "wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| +#include "lttng-events.h" |
| +#include "lttng-tracer.h" |
| + |
| +struct metadata_packet_header { |
| + uint32_t magic; /* 0x75D11D57 */ |
| + uint8_t uuid[16]; /* Unique Universal Identifier */ |
| + uint32_t checksum; /* 0 if unused */ |
| + uint32_t content_size; /* in bits */ |
| + uint32_t packet_size; /* in bits */ |
| + uint8_t compression_scheme; /* 0 if unused */ |
| + uint8_t encryption_scheme; /* 0 if unused */ |
| + uint8_t checksum_scheme; /* 0 if unused */ |
| + uint8_t major; /* CTF spec major version number */ |
| + uint8_t minor; /* CTF spec minor version number */ |
| + uint8_t header_end[0]; |
| +}; |
| + |
| +struct metadata_record_header { |
| + uint8_t header_end[0]; /* End of header */ |
| +}; |
| + |
| +static const struct lib_ring_buffer_config client_config; |
| + |
| +static inline |
| +u64 lib_ring_buffer_clock_read(struct channel *chan) |
| +{ |
| + return 0; |
| +} |
| + |
| +static inline |
| +unsigned char record_header_size(const struct lib_ring_buffer_config *config, |
| + struct channel *chan, size_t offset, |
| + size_t *pre_header_padding, |
| + struct lib_ring_buffer_ctx *ctx) |
| +{ |
| + return 0; |
| +} |
| + |
| +#include "wrapper/ringbuffer/api.h" |
| + |
| +static u64 client_ring_buffer_clock_read(struct channel *chan) |
| +{ |
| + return 0; |
| +} |
| + |
| +static |
| +size_t client_record_header_size(const struct lib_ring_buffer_config *config, |
| + struct channel *chan, size_t offset, |
| + size_t *pre_header_padding, |
| + struct lib_ring_buffer_ctx *ctx) |
| +{ |
| + return 0; |
| +} |
| + |
| +/** |
| + * client_packet_header_size - called on buffer-switch to a new sub-buffer |
| + * |
| + * Return header size without padding after the structure. Don't use packed |
| + * structure because gcc generates inefficient code on some architectures |
| + * (powerpc, mips..) |
| + */ |
| +static size_t client_packet_header_size(void) |
| +{ |
| + return offsetof(struct metadata_packet_header, header_end); |
| +} |
| + |
| +static void client_buffer_begin(struct lib_ring_buffer *buf, u64 tsc, |
| + unsigned int subbuf_idx) |
| +{ |
| + struct channel *chan = buf->backend.chan; |
| + struct metadata_packet_header *header = |
| + (struct metadata_packet_header *) |
| + lib_ring_buffer_offset_address(&buf->backend, |
| + subbuf_idx * chan->backend.subbuf_size); |
| + struct lttng_channel *lttng_chan = channel_get_private(chan); |
| + struct lttng_session *session = lttng_chan->session; |
| + |
| + header->magic = TSDL_MAGIC_NUMBER; |
| + memcpy(header->uuid, session->uuid.b, sizeof(session->uuid)); |
| + header->checksum = 0; /* 0 if unused */ |
| + header->content_size = 0xFFFFFFFF; /* in bits, for debugging */ |
| + header->packet_size = 0xFFFFFFFF; /* in bits, for debugging */ |
| + header->compression_scheme = 0; /* 0 if unused */ |
| + header->encryption_scheme = 0; /* 0 if unused */ |
| + header->checksum_scheme = 0; /* 0 if unused */ |
| + header->major = CTF_SPEC_MAJOR; |
| + header->minor = CTF_SPEC_MINOR; |
| +} |
| + |
| +/* |
| + * offset is assumed to never be 0 here : never deliver a completely empty |
| + * subbuffer. data_size is between 1 and subbuf_size. |
| + */ |
| +static void client_buffer_end(struct lib_ring_buffer *buf, u64 tsc, |
| + unsigned int subbuf_idx, unsigned long data_size) |
| +{ |
| + struct channel *chan = buf->backend.chan; |
| + struct metadata_packet_header *header = |
| + (struct metadata_packet_header *) |
| + lib_ring_buffer_offset_address(&buf->backend, |
| + subbuf_idx * chan->backend.subbuf_size); |
| + unsigned long records_lost = 0; |
| + |
| + header->content_size = data_size * CHAR_BIT; /* in bits */ |
| + header->packet_size = PAGE_ALIGN(data_size) * CHAR_BIT; /* in bits */ |
| + /* |
| + * We do not care about the records lost count, because the metadata |
| + * channel waits and retry. |
| + */ |
| + (void) lib_ring_buffer_get_records_lost_full(&client_config, buf); |
| + records_lost += lib_ring_buffer_get_records_lost_wrap(&client_config, buf); |
| + records_lost += lib_ring_buffer_get_records_lost_big(&client_config, buf); |
| + WARN_ON_ONCE(records_lost != 0); |
| +} |
| + |
| +static int client_buffer_create(struct lib_ring_buffer *buf, void *priv, |
| + int cpu, const char *name) |
| +{ |
| + return 0; |
| +} |
| + |
| +static void client_buffer_finalize(struct lib_ring_buffer *buf, void *priv, int cpu) |
| +{ |
| +} |
| + |
| +static const struct lib_ring_buffer_config client_config = { |
| + .cb.ring_buffer_clock_read = client_ring_buffer_clock_read, |
| + .cb.record_header_size = client_record_header_size, |
| + .cb.subbuffer_header_size = client_packet_header_size, |
| + .cb.buffer_begin = client_buffer_begin, |
| + .cb.buffer_end = client_buffer_end, |
| + .cb.buffer_create = client_buffer_create, |
| + .cb.buffer_finalize = client_buffer_finalize, |
| + |
| + .tsc_bits = 0, |
| + .alloc = RING_BUFFER_ALLOC_GLOBAL, |
| + .sync = RING_BUFFER_SYNC_GLOBAL, |
| + .mode = RING_BUFFER_MODE_TEMPLATE, |
| + .backend = RING_BUFFER_PAGE, |
| + .output = RING_BUFFER_OUTPUT_TEMPLATE, |
| + .oops = RING_BUFFER_OOPS_CONSISTENCY, |
| + .ipi = RING_BUFFER_IPI_BARRIER, |
| + .wakeup = RING_BUFFER_WAKEUP_BY_TIMER, |
| +}; |
| + |
| +static |
| +struct channel *_channel_create(const char *name, |
| + struct lttng_channel *lttng_chan, void *buf_addr, |
| + size_t subbuf_size, size_t num_subbuf, |
| + unsigned int switch_timer_interval, |
| + unsigned int read_timer_interval) |
| +{ |
| + return channel_create(&client_config, name, lttng_chan, buf_addr, |
| + subbuf_size, num_subbuf, switch_timer_interval, |
| + read_timer_interval); |
| +} |
| + |
| +static |
| +void lttng_channel_destroy(struct channel *chan) |
| +{ |
| + channel_destroy(chan); |
| +} |
| + |
| +static |
| +struct lib_ring_buffer *lttng_buffer_read_open(struct channel *chan) |
| +{ |
| + struct lib_ring_buffer *buf; |
| + |
| + buf = channel_get_ring_buffer(&client_config, chan, 0); |
| + if (!lib_ring_buffer_open_read(buf)) |
| + return buf; |
| + return NULL; |
| +} |
| + |
| +static |
| +int lttng_buffer_has_read_closed_stream(struct channel *chan) |
| +{ |
| + struct lib_ring_buffer *buf; |
| + int cpu; |
| + |
| + for_each_channel_cpu(cpu, chan) { |
| + buf = channel_get_ring_buffer(&client_config, chan, cpu); |
| + if (!atomic_long_read(&buf->active_readers)) |
| + return 1; |
| + } |
| + return 0; |
| +} |
| + |
| +static |
| +void lttng_buffer_read_close(struct lib_ring_buffer *buf) |
| +{ |
| + lib_ring_buffer_release_read(buf); |
| +} |
| + |
| +static |
| +int lttng_event_reserve(struct lib_ring_buffer_ctx *ctx, uint32_t event_id) |
| +{ |
| + return lib_ring_buffer_reserve(&client_config, ctx); |
| +} |
| + |
| +static |
| +void lttng_event_commit(struct lib_ring_buffer_ctx *ctx) |
| +{ |
| + lib_ring_buffer_commit(&client_config, ctx); |
| +} |
| + |
| +static |
| +void lttng_event_write(struct lib_ring_buffer_ctx *ctx, const void *src, |
| + size_t len) |
| +{ |
| + lib_ring_buffer_write(&client_config, ctx, src, len); |
| +} |
| + |
| +static |
| +void lttng_event_write_from_user(struct lib_ring_buffer_ctx *ctx, |
| + const void __user *src, size_t len) |
| +{ |
| + lib_ring_buffer_copy_from_user(&client_config, ctx, src, len); |
| +} |
| + |
| +static |
| +void lttng_event_memset(struct lib_ring_buffer_ctx *ctx, |
| + int c, size_t len) |
| +{ |
| + lib_ring_buffer_memset(&client_config, ctx, c, len); |
| +} |
| + |
| +static |
| +size_t lttng_packet_avail_size(struct channel *chan) |
| + |
| +{ |
| + unsigned long o_begin; |
| + struct lib_ring_buffer *buf; |
| + |
| + buf = chan->backend.buf; /* Only for global buffer ! */ |
| + o_begin = v_read(&client_config, &buf->offset); |
| + if (subbuf_offset(o_begin, chan) != 0) { |
| + return chan->backend.subbuf_size - subbuf_offset(o_begin, chan); |
| + } else { |
| + return chan->backend.subbuf_size - subbuf_offset(o_begin, chan) |
| + - sizeof(struct metadata_packet_header); |
| + } |
| +} |
| + |
| +static |
| +wait_queue_head_t *lttng_get_writer_buf_wait_queue(struct channel *chan, int cpu) |
| +{ |
| + struct lib_ring_buffer *buf = channel_get_ring_buffer(&client_config, |
| + chan, cpu); |
| + return &buf->write_wait; |
| +} |
| + |
| +static |
| +wait_queue_head_t *lttng_get_hp_wait_queue(struct channel *chan) |
| +{ |
| + return &chan->hp_wait; |
| +} |
| + |
| +static |
| +int lttng_is_finalized(struct channel *chan) |
| +{ |
| + return lib_ring_buffer_channel_is_finalized(chan); |
| +} |
| + |
| +static |
| +int lttng_is_disabled(struct channel *chan) |
| +{ |
| + return lib_ring_buffer_channel_is_disabled(chan); |
| +} |
| + |
| +static struct lttng_transport lttng_relay_transport = { |
| + .name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING, |
| + .owner = THIS_MODULE, |
| + .ops = { |
| + .channel_create = _channel_create, |
| + .channel_destroy = lttng_channel_destroy, |
| + .buffer_read_open = lttng_buffer_read_open, |
| + .buffer_has_read_closed_stream = |
| + lttng_buffer_has_read_closed_stream, |
| + .buffer_read_close = lttng_buffer_read_close, |
| + .event_reserve = lttng_event_reserve, |
| + .event_commit = lttng_event_commit, |
| + .event_write_from_user = lttng_event_write_from_user, |
| + .event_memset = lttng_event_memset, |
| + .event_write = lttng_event_write, |
| + .packet_avail_size = lttng_packet_avail_size, |
| + .get_writer_buf_wait_queue = lttng_get_writer_buf_wait_queue, |
| + .get_hp_wait_queue = lttng_get_hp_wait_queue, |
| + .is_finalized = lttng_is_finalized, |
| + .is_disabled = lttng_is_disabled, |
| + }, |
| +}; |
| + |
| +static int __init lttng_ring_buffer_client_init(void) |
| +{ |
| + /* |
| + * This vmalloc sync all also takes care of the lib ring buffer |
| + * vmalloc'd module pages when it is built as a module into LTTng. |
| + */ |
| + wrapper_vmalloc_sync_all(); |
| + lttng_transport_register(<tng_relay_transport); |
| + return 0; |
| +} |
| + |
| +module_init(lttng_ring_buffer_client_init); |
| + |
| +static void __exit lttng_ring_buffer_client_exit(void) |
| +{ |
| + lttng_transport_unregister(<tng_relay_transport); |
| +} |
| + |
| +module_exit(lttng_ring_buffer_client_exit); |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng ring buffer " RING_BUFFER_MODE_TEMPLATE_STRING |
| + " client"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-ring-buffer-metadata-mmap-client.c |
| @@ -0,0 +1,33 @@ |
| +/* |
| + * lttng-ring-buffer-metadata-client.c |
| + * |
| + * LTTng lib ring buffer metadta client. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include "lttng-tracer.h" |
| + |
| +#define RING_BUFFER_MODE_TEMPLATE RING_BUFFER_DISCARD |
| +#define RING_BUFFER_MODE_TEMPLATE_STRING "metadata-mmap" |
| +#define RING_BUFFER_OUTPUT_TEMPLATE RING_BUFFER_MMAP |
| +#include "lttng-ring-buffer-metadata-client.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers"); |
| +MODULE_DESCRIPTION("LTTng Ring Buffer Metadata Client"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-statedump-impl.c |
| @@ -0,0 +1,385 @@ |
| +/* |
| + * lttng-statedump.c |
| + * |
| + * Linux Trace Toolkit Next Generation Kernel State Dump |
| + * |
| + * Copyright 2005 Jean-Hugues Deschenes <jean-hugues.deschenes@polymtl.ca> |
| + * Copyright 2006-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * |
| + * Changes: |
| + * Eric Clement: Add listing of network IP interface |
| + * 2006, 2007 Mathieu Desnoyers Fix kernel threads |
| + * Various updates |
| + */ |
| + |
| +#include <linux/init.h> |
| +#include <linux/module.h> |
| +#include <linux/netlink.h> |
| +#include <linux/inet.h> |
| +#include <linux/ip.h> |
| +#include <linux/kthread.h> |
| +#include <linux/proc_fs.h> |
| +#include <linux/file.h> |
| +#include <linux/interrupt.h> |
| +#include <linux/irqnr.h> |
| +#include <linux/cpu.h> |
| +#include <linux/netdevice.h> |
| +#include <linux/inetdevice.h> |
| +#include <linux/sched.h> |
| +#include <linux/mm.h> |
| +#include <linux/fdtable.h> |
| +#include <linux/swap.h> |
| +#include <linux/wait.h> |
| +#include <linux/mutex.h> |
| + |
| +#include "lttng-events.h" |
| +#include "wrapper/irqdesc.h" |
| + |
| +#ifdef CONFIG_GENERIC_HARDIRQS |
| +#include <linux/irq.h> |
| +#endif |
| + |
| +/* Define the tracepoints, but do not build the probes */ |
| +#define CREATE_TRACE_POINTS |
| +#define TRACE_INCLUDE_PATH ../instrumentation/events/lttng-module |
| +#define TRACE_INCLUDE_FILE lttng-statedump |
| +#include "instrumentation/events/lttng-module/lttng-statedump.h" |
| + |
| +/* |
| + * Protected by the trace lock. |
| + */ |
| +static struct delayed_work cpu_work[NR_CPUS]; |
| +static DECLARE_WAIT_QUEUE_HEAD(statedump_wq); |
| +static atomic_t kernel_threads_to_run; |
| + |
| +enum lttng_thread_type { |
| + LTTNG_USER_THREAD = 0, |
| + LTTNG_KERNEL_THREAD = 1, |
| +}; |
| + |
| +enum lttng_execution_mode { |
| + LTTNG_USER_MODE = 0, |
| + LTTNG_SYSCALL = 1, |
| + LTTNG_TRAP = 2, |
| + LTTNG_IRQ = 3, |
| + LTTNG_SOFTIRQ = 4, |
| + LTTNG_MODE_UNKNOWN = 5, |
| +}; |
| + |
| +enum lttng_execution_submode { |
| + LTTNG_NONE = 0, |
| + LTTNG_UNKNOWN = 1, |
| +}; |
| + |
| +enum lttng_process_status { |
| + LTTNG_UNNAMED = 0, |
| + LTTNG_WAIT_FORK = 1, |
| + LTTNG_WAIT_CPU = 2, |
| + LTTNG_EXIT = 3, |
| + LTTNG_ZOMBIE = 4, |
| + LTTNG_WAIT = 5, |
| + LTTNG_RUN = 6, |
| + LTTNG_DEAD = 7, |
| +}; |
| + |
| +#ifdef CONFIG_INET |
| +static |
| +void lttng_enumerate_device(struct lttng_session *session, |
| + struct net_device *dev) |
| +{ |
| + struct in_device *in_dev; |
| + struct in_ifaddr *ifa; |
| + |
| + if (dev->flags & IFF_UP) { |
| + in_dev = in_dev_get(dev); |
| + if (in_dev) { |
| + for (ifa = in_dev->ifa_list; ifa != NULL; |
| + ifa = ifa->ifa_next) { |
| + trace_lttng_statedump_network_interface( |
| + session, dev, ifa); |
| + } |
| + in_dev_put(in_dev); |
| + } |
| + } else { |
| + trace_lttng_statedump_network_interface( |
| + session, dev, NULL); |
| + } |
| +} |
| + |
| +static |
| +int lttng_enumerate_network_ip_interface(struct lttng_session *session) |
| +{ |
| + struct net_device *dev; |
| + |
| + read_lock(&dev_base_lock); |
| + for_each_netdev(&init_net, dev) |
| + lttng_enumerate_device(session, dev); |
| + read_unlock(&dev_base_lock); |
| + |
| + return 0; |
| +} |
| +#else /* CONFIG_INET */ |
| +static inline |
| +int lttng_enumerate_network_ip_interface(struct lttng_session *session) |
| +{ |
| + return 0; |
| +} |
| +#endif /* CONFIG_INET */ |
| + |
| + |
| +static |
| +void lttng_enumerate_task_fd(struct lttng_session *session, |
| + struct task_struct *p, char *tmp) |
| +{ |
| + struct fdtable *fdt; |
| + struct file *filp; |
| + unsigned int i; |
| + const unsigned char *path; |
| + |
| + task_lock(p); |
| + if (!p->files) |
| + goto unlock_task; |
| + spin_lock(&p->files->file_lock); |
| + fdt = files_fdtable(p->files); |
| + for (i = 0; i < fdt->max_fds; i++) { |
| + filp = fcheck_files(p->files, i); |
| + if (!filp) |
| + continue; |
| + path = d_path(&filp->f_path, tmp, PAGE_SIZE); |
| + /* Make sure we give at least some info */ |
| + trace_lttng_statedump_file_descriptor(session, p, i, |
| + IS_ERR(path) ? |
| + filp->f_dentry->d_name.name : |
| + path); |
| + } |
| + spin_unlock(&p->files->file_lock); |
| +unlock_task: |
| + task_unlock(p); |
| +} |
| + |
| +static |
| +int lttng_enumerate_file_descriptors(struct lttng_session *session) |
| +{ |
| + struct task_struct *p; |
| + char *tmp = (char *) __get_free_page(GFP_KERNEL); |
| + |
| + /* Enumerate active file descriptors */ |
| + rcu_read_lock(); |
| + for_each_process(p) |
| + lttng_enumerate_task_fd(session, p, tmp); |
| + rcu_read_unlock(); |
| + free_page((unsigned long) tmp); |
| + return 0; |
| +} |
| + |
| +static |
| +void lttng_enumerate_task_vm_maps(struct lttng_session *session, |
| + struct task_struct *p) |
| +{ |
| + struct mm_struct *mm; |
| + struct vm_area_struct *map; |
| + unsigned long ino; |
| + |
| + /* get_task_mm does a task_lock... */ |
| + mm = get_task_mm(p); |
| + if (!mm) |
| + return; |
| + |
| + map = mm->mmap; |
| + if (map) { |
| + down_read(&mm->mmap_sem); |
| + while (map) { |
| + if (map->vm_file) |
| + ino = map->vm_file->f_dentry->d_inode->i_ino; |
| + else |
| + ino = 0; |
| + trace_lttng_statedump_vm_map(session, p, map, ino); |
| + map = map->vm_next; |
| + } |
| + up_read(&mm->mmap_sem); |
| + } |
| + mmput(mm); |
| +} |
| + |
| +static |
| +int lttng_enumerate_vm_maps(struct lttng_session *session) |
| +{ |
| + struct task_struct *p; |
| + |
| + rcu_read_lock(); |
| + for_each_process(p) |
| + lttng_enumerate_task_vm_maps(session, p); |
| + rcu_read_unlock(); |
| + return 0; |
| +} |
| + |
| +#ifdef CONFIG_GENERIC_HARDIRQS |
| + |
| +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39)) |
| +#define irq_desc_get_chip(desc) get_irq_desc_chip(desc) |
| +#endif |
| + |
| +static |
| +void lttng_list_interrupts(struct lttng_session *session) |
| +{ |
| + unsigned int irq; |
| + unsigned long flags = 0; |
| + struct irq_desc *desc; |
| + |
| +#define irq_to_desc wrapper_irq_to_desc |
| + /* needs irq_desc */ |
| + for_each_irq_desc(irq, desc) { |
| + struct irqaction *action; |
| + const char *irq_chip_name = |
| + irq_desc_get_chip(desc)->name ? : "unnamed_irq_chip"; |
| + |
| + local_irq_save(flags); |
| + raw_spin_lock(&desc->lock); |
| + for (action = desc->action; action; action = action->next) { |
| + trace_lttng_statedump_interrupt(session, |
| + irq, irq_chip_name, action); |
| + } |
| + raw_spin_unlock(&desc->lock); |
| + local_irq_restore(flags); |
| + } |
| +#undef irq_to_desc |
| +} |
| +#else |
| +static inline |
| +void list_interrupts(struct lttng_session *session) |
| +{ |
| +} |
| +#endif |
| + |
| +static |
| +int lttng_enumerate_process_states(struct lttng_session *session) |
| +{ |
| + struct task_struct *g, *p; |
| + |
| + rcu_read_lock(); |
| + for_each_process(g) { |
| + p = g; |
| + do { |
| + enum lttng_execution_mode mode = |
| + LTTNG_MODE_UNKNOWN; |
| + enum lttng_execution_submode submode = |
| + LTTNG_UNKNOWN; |
| + enum lttng_process_status status; |
| + enum lttng_thread_type type; |
| + |
| + task_lock(p); |
| + if (p->exit_state == EXIT_ZOMBIE) |
| + status = LTTNG_ZOMBIE; |
| + else if (p->exit_state == EXIT_DEAD) |
| + status = LTTNG_DEAD; |
| + else if (p->state == TASK_RUNNING) { |
| + /* Is this a forked child that has not run yet? */ |
| + if (list_empty(&p->rt.run_list)) |
| + status = LTTNG_WAIT_FORK; |
| + else |
| + /* |
| + * All tasks are considered as wait_cpu; |
| + * the viewer will sort out if the task |
| + * was really running at this time. |
| + */ |
| + status = LTTNG_WAIT_CPU; |
| + } else if (p->state & |
| + (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)) { |
| + /* Task is waiting for something to complete */ |
| + status = LTTNG_WAIT; |
| + } else |
| + status = LTTNG_UNNAMED; |
| + submode = LTTNG_NONE; |
| + |
| + /* |
| + * Verification of t->mm is to filter out kernel |
| + * threads; Viewer will further filter out if a |
| + * user-space thread was in syscall mode or not. |
| + */ |
| + if (p->mm) |
| + type = LTTNG_USER_THREAD; |
| + else |
| + type = LTTNG_KERNEL_THREAD; |
| + trace_lttng_statedump_process_state(session, |
| + p, type, mode, submode, status); |
| + task_unlock(p); |
| + } while_each_thread(g, p); |
| + } |
| + rcu_read_unlock(); |
| + |
| + return 0; |
| +} |
| + |
| +static |
| +void lttng_statedump_work_func(struct work_struct *work) |
| +{ |
| + if (atomic_dec_and_test(&kernel_threads_to_run)) |
| + /* If we are the last thread, wake up do_lttng_statedump */ |
| + wake_up(&statedump_wq); |
| +} |
| + |
| +static |
| +int do_lttng_statedump(struct lttng_session *session) |
| +{ |
| + int cpu; |
| + |
| + printk(KERN_DEBUG "LTT state dump thread start\n"); |
| + trace_lttng_statedump_start(session); |
| + lttng_enumerate_process_states(session); |
| + lttng_enumerate_file_descriptors(session); |
| + lttng_enumerate_vm_maps(session); |
| + lttng_list_interrupts(session); |
| + lttng_enumerate_network_ip_interface(session); |
| + |
| + /* TODO lttng_dump_idt_table(session); */ |
| + /* TODO lttng_dump_softirq_vec(session); */ |
| + /* TODO lttng_list_modules(session); */ |
| + /* TODO lttng_dump_swap_files(session); */ |
| + |
| + /* |
| + * Fire off a work queue on each CPU. Their sole purpose in life |
| + * is to guarantee that each CPU has been in a state where is was in |
| + * syscall mode (i.e. not in a trap, an IRQ or a soft IRQ). |
| + */ |
| + get_online_cpus(); |
| + atomic_set(&kernel_threads_to_run, num_online_cpus()); |
| + for_each_online_cpu(cpu) { |
| + INIT_DELAYED_WORK(&cpu_work[cpu], lttng_statedump_work_func); |
| + schedule_delayed_work_on(cpu, &cpu_work[cpu], 0); |
| + } |
| + /* Wait for all threads to run */ |
| + __wait_event(statedump_wq, (atomic_read(&kernel_threads_to_run) != 0)); |
| + put_online_cpus(); |
| + /* Our work is done */ |
| + printk(KERN_DEBUG "LTT state dump end\n"); |
| + trace_lttng_statedump_end(session); |
| + return 0; |
| +} |
| + |
| +/* |
| + * Called with session mutex held. |
| + */ |
| +int lttng_statedump_start(struct lttng_session *session) |
| +{ |
| + printk(KERN_DEBUG "LTTng: state dump begin\n"); |
| + return do_lttng_statedump(session); |
| +} |
| +EXPORT_SYMBOL_GPL(lttng_statedump_start); |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Jean-Hugues Deschenes"); |
| +MODULE_DESCRIPTION("Linux Trace Toolkit Next Generation Statedump"); |
| --- a/drivers/staging/lttng/lttng-syscalls.c |
| +++ b/drivers/staging/lttng/lttng-syscalls.c |
| @@ -1,11 +1,23 @@ |
| /* |
| * lttng-syscalls.c |
| * |
| - * Copyright 2010-2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng syscall probes. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| @@ -14,13 +26,12 @@ |
| #include <asm/ptrace.h> |
| #include <asm/syscall.h> |
| |
| -#include "ltt-events.h" |
| +#include "lttng-events.h" |
| |
| #ifndef CONFIG_COMPAT |
| -static inline int is_compat_task(void) |
| -{ |
| - return 0; |
| -} |
| +# ifndef is_compat_task |
| +# define is_compat_task() (0) |
| +# endif |
| #endif |
| |
| static |
| @@ -141,7 +152,7 @@ const struct trace_syscall_entry compat_ |
| |
| #undef CREATE_SYSCALL_TABLE |
| |
| -static void syscall_entry_unknown(struct ltt_event *event, |
| +static void syscall_entry_unknown(struct lttng_event *event, |
| struct pt_regs *regs, unsigned int id) |
| { |
| unsigned long args[UNKNOWN_SYSCALL_NRARGS]; |
| @@ -155,8 +166,8 @@ static void syscall_entry_unknown(struct |
| |
| void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) |
| { |
| - struct ltt_channel *chan = __data; |
| - struct ltt_event *event, *unknown_event; |
| + struct lttng_channel *chan = __data; |
| + struct lttng_event *event, *unknown_event; |
| const struct trace_syscall_entry *table, *entry; |
| size_t table_len; |
| |
| @@ -275,7 +286,7 @@ void syscall_entry_probe(void *__data, s |
| /* noinline to diminish caller stack size */ |
| static |
| int fill_table(const struct trace_syscall_entry *table, size_t table_len, |
| - struct ltt_event **chan_table, struct ltt_channel *chan, void *filter) |
| + struct lttng_event **chan_table, struct lttng_channel *chan, void *filter) |
| { |
| const struct lttng_event_desc *desc; |
| unsigned int i; |
| @@ -296,10 +307,10 @@ int fill_table(const struct trace_syscal |
| if (chan_table[i]) |
| continue; |
| memset(&ev, 0, sizeof(ev)); |
| - strncpy(ev.name, desc->name, LTTNG_SYM_NAME_LEN); |
| - ev.name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| + strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); |
| + ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| ev.instrumentation = LTTNG_KERNEL_NOOP; |
| - chan_table[i] = ltt_event_create(chan, &ev, filter, |
| + chan_table[i] = lttng_event_create(chan, &ev, filter, |
| desc); |
| if (!chan_table[i]) { |
| /* |
| @@ -314,7 +325,7 @@ int fill_table(const struct trace_syscal |
| return 0; |
| } |
| |
| -int lttng_syscalls_register(struct ltt_channel *chan, void *filter) |
| +int lttng_syscalls_register(struct lttng_channel *chan, void *filter) |
| { |
| struct lttng_kernel_event ev; |
| int ret; |
| @@ -323,7 +334,7 @@ int lttng_syscalls_register(struct ltt_c |
| |
| if (!chan->sc_table) { |
| /* create syscall table mapping syscall to events */ |
| - chan->sc_table = kzalloc(sizeof(struct ltt_event *) |
| + chan->sc_table = kzalloc(sizeof(struct lttng_event *) |
| * ARRAY_SIZE(sc_table), GFP_KERNEL); |
| if (!chan->sc_table) |
| return -ENOMEM; |
| @@ -332,7 +343,7 @@ int lttng_syscalls_register(struct ltt_c |
| #ifdef CONFIG_COMPAT |
| if (!chan->compat_sc_table) { |
| /* create syscall table mapping compat syscall to events */ |
| - chan->compat_sc_table = kzalloc(sizeof(struct ltt_event *) |
| + chan->compat_sc_table = kzalloc(sizeof(struct lttng_event *) |
| * ARRAY_SIZE(compat_sc_table), GFP_KERNEL); |
| if (!chan->compat_sc_table) |
| return -ENOMEM; |
| @@ -343,10 +354,10 @@ int lttng_syscalls_register(struct ltt_c |
| &__event_desc___sys_unknown; |
| |
| memset(&ev, 0, sizeof(ev)); |
| - strncpy(ev.name, desc->name, LTTNG_SYM_NAME_LEN); |
| - ev.name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| + strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); |
| + ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| ev.instrumentation = LTTNG_KERNEL_NOOP; |
| - chan->sc_unknown = ltt_event_create(chan, &ev, filter, |
| + chan->sc_unknown = lttng_event_create(chan, &ev, filter, |
| desc); |
| if (!chan->sc_unknown) { |
| return -EINVAL; |
| @@ -358,10 +369,10 @@ int lttng_syscalls_register(struct ltt_c |
| &__event_desc___compat_sys_unknown; |
| |
| memset(&ev, 0, sizeof(ev)); |
| - strncpy(ev.name, desc->name, LTTNG_SYM_NAME_LEN); |
| - ev.name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| + strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); |
| + ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| ev.instrumentation = LTTNG_KERNEL_NOOP; |
| - chan->sc_compat_unknown = ltt_event_create(chan, &ev, filter, |
| + chan->sc_compat_unknown = lttng_event_create(chan, &ev, filter, |
| desc); |
| if (!chan->sc_compat_unknown) { |
| return -EINVAL; |
| @@ -373,10 +384,10 @@ int lttng_syscalls_register(struct ltt_c |
| &__event_desc___exit_syscall; |
| |
| memset(&ev, 0, sizeof(ev)); |
| - strncpy(ev.name, desc->name, LTTNG_SYM_NAME_LEN); |
| - ev.name[LTTNG_SYM_NAME_LEN - 1] = '\0'; |
| + strncpy(ev.name, desc->name, LTTNG_KERNEL_SYM_NAME_LEN); |
| + ev.name[LTTNG_KERNEL_SYM_NAME_LEN - 1] = '\0'; |
| ev.instrumentation = LTTNG_KERNEL_NOOP; |
| - chan->sc_exit = ltt_event_create(chan, &ev, filter, |
| + chan->sc_exit = lttng_event_create(chan, &ev, filter, |
| desc); |
| if (!chan->sc_exit) { |
| return -EINVAL; |
| @@ -414,7 +425,7 @@ int lttng_syscalls_register(struct ltt_c |
| /* |
| * Only called at session destruction. |
| */ |
| -int lttng_syscalls_unregister(struct ltt_channel *chan) |
| +int lttng_syscalls_unregister(struct lttng_channel *chan) |
| { |
| int ret; |
| |
| @@ -429,7 +440,7 @@ int lttng_syscalls_unregister(struct ltt |
| (void *) syscall_entry_probe, chan); |
| if (ret) |
| return ret; |
| - /* ltt_event destroy will be performed by ltt_session_destroy() */ |
| + /* lttng_event destroy will be performed by lttng_session_destroy() */ |
| kfree(chan->sc_table); |
| #ifdef CONFIG_COMPAT |
| kfree(chan->compat_sc_table); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-tracer-core.h |
| @@ -0,0 +1,41 @@ |
| +#ifndef LTTNG_TRACER_CORE_H |
| +#define LTTNG_TRACER_CORE_H |
| + |
| +/* |
| + * lttng-tracer-core.h |
| + * |
| + * This contains the core definitions for the Linux Trace Toolkit Next |
| + * Generation tracer. |
| + * |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/list.h> |
| +#include <linux/percpu.h> |
| + |
| +#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS |
| +/* Align data on its natural alignment */ |
| +#define RING_BUFFER_ALIGN |
| +#endif |
| + |
| +#include "wrapper/ringbuffer/config.h" |
| + |
| +struct lttng_session; |
| +struct lttng_channel; |
| +struct lttng_event; |
| + |
| +#endif /* LTTNG_TRACER_CORE_H */ |
| --- /dev/null |
| +++ b/drivers/staging/lttng/lttng-tracer.h |
| @@ -0,0 +1,80 @@ |
| +#ifndef _LTTNG_TRACER_H |
| +#define _LTTNG_TRACER_H |
| + |
| +/* |
| + * lttng-tracer.h |
| + * |
| + * This contains the definitions for the Linux Trace Toolkit Next |
| + * Generation tracer. |
| + * |
| + * Copyright (C) 2005-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <stdarg.h> |
| +#include <linux/types.h> |
| +#include <linux/limits.h> |
| +#include <linux/list.h> |
| +#include <linux/cache.h> |
| +#include <linux/timex.h> |
| +#include <linux/wait.h> |
| +#include <asm/atomic.h> |
| +#include <asm/local.h> |
| + |
| +#include "wrapper/trace-clock.h" |
| +#include "lttng-tracer-core.h" |
| +#include "lttng-events.h" |
| + |
| +#define LTTNG_MODULES_MAJOR_VERSION 2 |
| +#define LTTNG_MODULES_MINOR_VERSION 0 |
| +#define LTTNG_MODULES_PATCHLEVEL_VERSION 1 |
| + |
| +#define LTTNG_VERSION_NAME "Annedd'ale" |
| +#define LTTNG_VERSION_DESCRIPTION \ |
| + "New type of beer, 100% from Quebec, flavored with sapin beaumier needles, with a touch of hops." |
| + |
| +#ifndef CHAR_BIT |
| +#define CHAR_BIT 8 |
| +#endif |
| + |
| +/* Number of bytes to log with a read/write event */ |
| +#define LTTNG_LOG_RW_SIZE 32L |
| +#define LTTNG_MAX_SMALL_SIZE 0xFFFFU |
| + |
| +#ifdef RING_BUFFER_ALIGN |
| +#define lttng_alignof(type) __alignof__(type) |
| +#else |
| +#define lttng_alignof(type) 1 |
| +#endif |
| + |
| +/* Tracer properties */ |
| +#define CTF_MAGIC_NUMBER 0xC1FC1FC1 |
| +#define TSDL_MAGIC_NUMBER 0x75D11D57 |
| + |
| +/* CTF specification version followed */ |
| +#define CTF_SPEC_MAJOR 1 |
| +#define CTF_SPEC_MINOR 8 |
| + |
| +/* |
| + * Number of milliseconds to retry before failing metadata writes on buffer full |
| + * condition. (10 seconds) |
| + */ |
| +#define LTTNG_METADATA_TIMEOUT_MSEC 10000 |
| + |
| +#define LTTNG_RFLAG_EXTENDED RING_BUFFER_RFLAG_END |
| +#define LTTNG_RFLAG_END (LTTNG_RFLAG_EXTENDED << 1) |
| + |
| +#endif /* _LTTNG_TRACER_H */ |
| --- a/drivers/staging/lttng/probes/Makefile |
| +++ b/drivers/staging/lttng/probes/Makefile |
| @@ -9,6 +9,10 @@ obj-m += lttng-probe-lttng.o |
| |
| obj-m += lttng-probe-sched.o |
| obj-m += lttng-probe-irq.o |
| +obj-m += lttng-probe-signal.o |
| +obj-m += lttng-probe-timer.o |
| + |
| +obj-m += lttng-probe-statedump.o |
| |
| ifneq ($(CONFIG_KVM),) |
| obj-m += lttng-probe-kvm.o |
| --- a/drivers/staging/lttng/probes/define_trace.h |
| +++ b/drivers/staging/lttng/probes/define_trace.h |
| @@ -2,9 +2,21 @@ |
| * define_trace.h |
| * |
| * Copyright (C) 2009 Steven Rostedt <rostedt@goodmis.org> |
| - * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* |
| --- a/drivers/staging/lttng/probes/lttng-events-reset.h |
| +++ b/drivers/staging/lttng/probes/lttng-events-reset.h |
| @@ -1,9 +1,21 @@ |
| /* |
| * lttng-events-reset.h |
| * |
| - * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* Reset macros used within TRACE_EVENT to "nothing" */ |
| --- a/drivers/staging/lttng/probes/lttng-events.h |
| +++ b/drivers/staging/lttng/probes/lttng-events.h |
| @@ -2,9 +2,21 @@ |
| * lttng-events.h |
| * |
| * Copyright (C) 2009 Steven Rostedt <rostedt@goodmis.org> |
| - * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/debugfs.h> |
| @@ -12,8 +24,8 @@ |
| #include "lttng-types.h" |
| #include "../wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| #include "../wrapper/ringbuffer/frontend_types.h" |
| -#include "../ltt-events.h" |
| -#include "../ltt-tracer-core.h" |
| +#include "../lttng-events.h" |
| +#include "../lttng-tracer-core.h" |
| |
| /* |
| * Macro declarations used for all stages. |
| @@ -319,19 +331,19 @@ static __used struct lttng_probe_desc TP |
| |
| #undef __field_full |
| #define __field_full(_type, _item, _order, _base) \ |
| - __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(_type)); \ |
| + __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ |
| __event_len += sizeof(_type); |
| |
| #undef __array_enc_ext |
| #define __array_enc_ext(_type, _item, _length, _order, _base, _encoding) \ |
| - __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(_type)); \ |
| + __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ |
| __event_len += sizeof(_type) * (_length); |
| |
| #undef __dynamic_array_enc_ext |
| #define __dynamic_array_enc_ext(_type, _item, _length, _order, _base, _encoding)\ |
| - __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(u32)); \ |
| + __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(u32)); \ |
| __event_len += sizeof(u32); \ |
| - __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(_type)); \ |
| + __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ |
| __dynamic_len[__dynamic_len_idx] = (_length); \ |
| __event_len += sizeof(_type) * __dynamic_len[__dynamic_len_idx]; \ |
| __dynamic_len_idx++; |
| @@ -382,16 +394,16 @@ static inline size_t __event_get_size__# |
| |
| #undef __field_full |
| #define __field_full(_type, _item, _order, _base) \ |
| - __event_align = max_t(size_t, __event_align, ltt_alignof(_type)); |
| + __event_align = max_t(size_t, __event_align, lttng_alignof(_type)); |
| |
| #undef __array_enc_ext |
| #define __array_enc_ext(_type, _item, _length, _order, _base, _encoding) \ |
| - __event_align = max_t(size_t, __event_align, ltt_alignof(_type)); |
| + __event_align = max_t(size_t, __event_align, lttng_alignof(_type)); |
| |
| #undef __dynamic_array_enc_ext |
| #define __dynamic_array_enc_ext(_type, _item, _length, _order, _base, _encoding)\ |
| - __event_align = max_t(size_t, __event_align, ltt_alignof(u32)); \ |
| - __event_align = max_t(size_t, __event_align, ltt_alignof(_type)); |
| + __event_align = max_t(size_t, __event_align, lttng_alignof(u32)); \ |
| + __event_align = max_t(size_t, __event_align, lttng_alignof(_type)); |
| |
| #undef __string |
| #define __string(_item, _src) |
| @@ -506,7 +518,7 @@ __end_field_##_item: |
| __assign_##dest: \ |
| { \ |
| __typeof__(__typemap.dest) __tmp = (src); \ |
| - lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__tmp)); \ |
| + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__tmp)); \ |
| __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp));\ |
| } \ |
| goto __end_field_##dest; |
| @@ -516,7 +528,7 @@ __assign_##dest: \ |
| __assign_##dest: \ |
| if (0) \ |
| (void) __typemap.dest; \ |
| - lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest)); \ |
| + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__typemap.dest)); \ |
| __chan->ops->event_write(&__ctx, src, len); \ |
| goto __end_field_##dest; |
| |
| @@ -525,12 +537,12 @@ __assign_##dest: \ |
| __assign_##dest##_1: \ |
| { \ |
| u32 __tmpl = __dynamic_len[__dynamic_len_idx]; \ |
| - lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(u32)); \ |
| + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(u32)); \ |
| __chan->ops->event_write(&__ctx, &__tmpl, sizeof(u32)); \ |
| } \ |
| goto __end_field_##dest##_1; \ |
| __assign_##dest##_2: \ |
| - lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest)); \ |
| + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__typemap.dest)); \ |
| __chan->ops->event_write(&__ctx, src, \ |
| sizeof(__typemap.dest) * __get_dynamic_array_len(dest));\ |
| goto __end_field_##dest##_2; |
| @@ -540,7 +552,7 @@ __assign_##dest##_2: \ |
| __assign_##dest: \ |
| if (0) \ |
| (void) __typemap.dest; \ |
| - lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest)); \ |
| + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__typemap.dest)); \ |
| __chan->ops->event_write_from_user(&__ctx, src, len); \ |
| goto __end_field_##dest; |
| |
| @@ -555,7 +567,7 @@ __assign_##dest##_2: \ |
| \ |
| if (0) \ |
| (void) __typemap.dest; \ |
| - lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest));\ |
| + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__typemap.dest));\ |
| __ustrlen = __get_dynamic_array_len(dest); \ |
| if (likely(__ustrlen > 1)) { \ |
| __chan->ops->event_write_from_user(&__ctx, src, \ |
| @@ -592,12 +604,23 @@ __assign_##dest##_2: \ |
| #undef TP_fast_assign |
| #define TP_fast_assign(args...) args |
| |
| +/* |
| + * For state dump, check that "session" argument (mandatory) matches the |
| + * session this event belongs to. Ensures that we write state dump data only |
| + * into the started session, not into all sessions. |
| + */ |
| +#ifdef TP_SESSION_CHECK |
| +#define _TP_SESSION_CHECK(session, csession) (session == csession) |
| +#else /* TP_SESSION_CHECK */ |
| +#define _TP_SESSION_CHECK(session, csession) 1 |
| +#endif /* TP_SESSION_CHECK */ |
| + |
| #undef DECLARE_EVENT_CLASS |
| #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ |
| static void __event_probe__##_name(void *__data, _proto) \ |
| { \ |
| - struct ltt_event *__event = __data; \ |
| - struct ltt_channel *__chan = __event->chan; \ |
| + struct lttng_event *__event = __data; \ |
| + struct lttng_channel *__chan = __event->chan; \ |
| struct lib_ring_buffer_ctx __ctx; \ |
| size_t __event_len, __event_align; \ |
| size_t __dynamic_len_idx = 0; \ |
| @@ -605,8 +628,12 @@ static void __event_probe__##_name(void |
| struct __event_typemap__##_name __typemap; \ |
| int __ret; \ |
| \ |
| - if (0) \ |
| + if (0) { \ |
| (void) __dynamic_len_idx; /* don't warn if unused */ \ |
| + (void) __typemap; /* don't warn if unused */ \ |
| + } \ |
| + if (!_TP_SESSION_CHECK(session, __chan->session)) \ |
| + return; \ |
| if (unlikely(!ACCESS_ONCE(__chan->session->active))) \ |
| return; \ |
| if (unlikely(!ACCESS_ONCE(__chan->enabled))) \ |
| @@ -632,12 +659,14 @@ static void __event_probe__##_name(void |
| #define DECLARE_EVENT_CLASS_NOARGS(_name, _tstruct, _assign, _print) \ |
| static void __event_probe__##_name(void *__data) \ |
| { \ |
| - struct ltt_event *__event = __data; \ |
| - struct ltt_channel *__chan = __event->chan; \ |
| + struct lttng_event *__event = __data; \ |
| + struct lttng_channel *__chan = __event->chan; \ |
| struct lib_ring_buffer_ctx __ctx; \ |
| size_t __event_len, __event_align; \ |
| int __ret; \ |
| \ |
| + if (!_TP_SESSION_CHECK(session, __chan->session)) \ |
| + return; \ |
| if (unlikely(!ACCESS_ONCE(__chan->session->active))) \ |
| return; \ |
| if (unlikely(!ACCESS_ONCE(__chan->enabled))) \ |
| @@ -680,14 +709,14 @@ static void __event_probe__##_name(void |
| static int TP_ID(__lttng_events_init__, TRACE_SYSTEM)(void) |
| { |
| wrapper_vmalloc_sync_all(); |
| - return ltt_probe_register(&TP_ID(__probe_desc___, TRACE_SYSTEM)); |
| + return lttng_probe_register(&TP_ID(__probe_desc___, TRACE_SYSTEM)); |
| } |
| |
| module_init_eval(__lttng_events_init__, TRACE_SYSTEM); |
| |
| static void TP_ID(__lttng_events_exit__, TRACE_SYSTEM)(void) |
| { |
| - ltt_probe_unregister(&TP_ID(__probe_desc___, TRACE_SYSTEM)); |
| + lttng_probe_unregister(&TP_ID(__probe_desc___, TRACE_SYSTEM)); |
| } |
| |
| module_exit_eval(__lttng_events_exit__, TRACE_SYSTEM); |
| --- a/drivers/staging/lttng/probes/lttng-ftrace.c |
| +++ b/drivers/staging/lttng/probes/lttng-ftrace.c |
| @@ -1,10 +1,23 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * probes/lttng-ftrace.c |
| * |
| * LTTng function tracer integration module. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* |
| @@ -20,17 +33,17 @@ |
| #include <linux/module.h> |
| #include <linux/ftrace.h> |
| #include <linux/slab.h> |
| -#include "../ltt-events.h" |
| +#include "../lttng-events.h" |
| #include "../wrapper/ringbuffer/frontend_types.h" |
| #include "../wrapper/ftrace.h" |
| #include "../wrapper/vmalloc.h" |
| -#include "../ltt-tracer.h" |
| +#include "../lttng-tracer.h" |
| |
| static |
| void lttng_ftrace_handler(unsigned long ip, unsigned long parent_ip, void **data) |
| { |
| - struct ltt_event *event = *data; |
| - struct ltt_channel *chan = event->chan; |
| + struct lttng_event *event = *data; |
| + struct lttng_channel *chan = event->chan; |
| struct lib_ring_buffer_ctx ctx; |
| struct { |
| unsigned long ip; |
| @@ -46,13 +59,13 @@ void lttng_ftrace_handler(unsigned long |
| return; |
| |
| lib_ring_buffer_ctx_init(&ctx, chan->chan, event, |
| - sizeof(payload), ltt_alignof(payload), -1); |
| + sizeof(payload), lttng_alignof(payload), -1); |
| ret = chan->ops->event_reserve(&ctx, event->id); |
| if (ret < 0) |
| return; |
| payload.ip = ip; |
| payload.parent_ip = parent_ip; |
| - lib_ring_buffer_align_ctx(&ctx, ltt_alignof(payload)); |
| + lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload)); |
| chan->ops->event_write(&ctx, &payload, sizeof(payload)); |
| chan->ops->event_commit(&ctx); |
| return; |
| @@ -62,7 +75,7 @@ void lttng_ftrace_handler(unsigned long |
| * Create event description |
| */ |
| static |
| -int lttng_create_ftrace_event(const char *name, struct ltt_event *event) |
| +int lttng_create_ftrace_event(const char *name, struct lttng_event *event) |
| { |
| struct lttng_event_field *fields; |
| struct lttng_event_desc *desc; |
| @@ -86,7 +99,7 @@ int lttng_create_ftrace_event(const char |
| fields[0].name = "ip"; |
| fields[0].type.atype = atype_integer; |
| fields[0].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT; |
| - fields[0].type.u.basic.integer.alignment = ltt_alignof(unsigned long) * CHAR_BIT; |
| + fields[0].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT; |
| fields[0].type.u.basic.integer.signedness = is_signed_type(unsigned long); |
| fields[0].type.u.basic.integer.reverse_byte_order = 0; |
| fields[0].type.u.basic.integer.base = 16; |
| @@ -95,7 +108,7 @@ int lttng_create_ftrace_event(const char |
| fields[1].name = "parent_ip"; |
| fields[1].type.atype = atype_integer; |
| fields[1].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT; |
| - fields[1].type.u.basic.integer.alignment = ltt_alignof(unsigned long) * CHAR_BIT; |
| + fields[1].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT; |
| fields[1].type.u.basic.integer.signedness = is_signed_type(unsigned long); |
| fields[1].type.u.basic.integer.reverse_byte_order = 0; |
| fields[1].type.u.basic.integer.base = 16; |
| @@ -120,7 +133,7 @@ struct ftrace_probe_ops lttng_ftrace_ops |
| |
| int lttng_ftrace_register(const char *name, |
| const char *symbol_name, |
| - struct ltt_event *event) |
| + struct lttng_event *event) |
| { |
| int ret; |
| |
| @@ -151,14 +164,14 @@ error: |
| } |
| EXPORT_SYMBOL_GPL(lttng_ftrace_register); |
| |
| -void lttng_ftrace_unregister(struct ltt_event *event) |
| +void lttng_ftrace_unregister(struct lttng_event *event) |
| { |
| wrapper_unregister_ftrace_function_probe(event->u.ftrace.symbol_name, |
| <tng_ftrace_ops, event); |
| } |
| EXPORT_SYMBOL_GPL(lttng_ftrace_unregister); |
| |
| -void lttng_ftrace_destroy_private(struct ltt_event *event) |
| +void lttng_ftrace_destroy_private(struct lttng_event *event) |
| { |
| kfree(event->u.ftrace.symbol_name); |
| kfree(event->desc->fields); |
| --- a/drivers/staging/lttng/probes/lttng-kprobes.c |
| +++ b/drivers/staging/lttng/probes/lttng-kprobes.c |
| @@ -1,26 +1,39 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * probes/lttng-kprobes.c |
| * |
| * LTTng kprobes integration module. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/kprobes.h> |
| #include <linux/slab.h> |
| -#include "../ltt-events.h" |
| +#include "../lttng-events.h" |
| #include "../wrapper/ringbuffer/frontend_types.h" |
| #include "../wrapper/vmalloc.h" |
| -#include "../ltt-tracer.h" |
| +#include "../lttng-tracer.h" |
| |
| static |
| int lttng_kprobes_handler_pre(struct kprobe *p, struct pt_regs *regs) |
| { |
| - struct ltt_event *event = |
| - container_of(p, struct ltt_event, u.kprobe.kp); |
| - struct ltt_channel *chan = event->chan; |
| + struct lttng_event *event = |
| + container_of(p, struct lttng_event, u.kprobe.kp); |
| + struct lttng_channel *chan = event->chan; |
| struct lib_ring_buffer_ctx ctx; |
| int ret; |
| unsigned long data = (unsigned long) p->addr; |
| @@ -33,11 +46,11 @@ int lttng_kprobes_handler_pre(struct kpr |
| return 0; |
| |
| lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(data), |
| - ltt_alignof(data), -1); |
| + lttng_alignof(data), -1); |
| ret = chan->ops->event_reserve(&ctx, event->id); |
| if (ret < 0) |
| return 0; |
| - lib_ring_buffer_align_ctx(&ctx, ltt_alignof(data)); |
| + lib_ring_buffer_align_ctx(&ctx, lttng_alignof(data)); |
| chan->ops->event_write(&ctx, &data, sizeof(data)); |
| chan->ops->event_commit(&ctx); |
| return 0; |
| @@ -47,7 +60,7 @@ int lttng_kprobes_handler_pre(struct kpr |
| * Create event description |
| */ |
| static |
| -int lttng_create_kprobe_event(const char *name, struct ltt_event *event) |
| +int lttng_create_kprobe_event(const char *name, struct lttng_event *event) |
| { |
| struct lttng_event_field *field; |
| struct lttng_event_desc *desc; |
| @@ -71,7 +84,7 @@ int lttng_create_kprobe_event(const char |
| field->name = "ip"; |
| field->type.atype = atype_integer; |
| field->type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT; |
| - field->type.u.basic.integer.alignment = ltt_alignof(unsigned long) * CHAR_BIT; |
| + field->type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT; |
| field->type.u.basic.integer.signedness = is_signed_type(unsigned long); |
| field->type.u.basic.integer.reverse_byte_order = 0; |
| field->type.u.basic.integer.base = 16; |
| @@ -92,7 +105,7 @@ int lttng_kprobes_register(const char *n |
| const char *symbol_name, |
| uint64_t offset, |
| uint64_t addr, |
| - struct ltt_event *event) |
| + struct lttng_event *event) |
| { |
| int ret; |
| |
| @@ -107,14 +120,14 @@ int lttng_kprobes_register(const char *n |
| event->u.kprobe.kp.pre_handler = lttng_kprobes_handler_pre; |
| if (symbol_name) { |
| event->u.kprobe.symbol_name = |
| - kzalloc(LTTNG_SYM_NAME_LEN * sizeof(char), |
| + kzalloc(LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char), |
| GFP_KERNEL); |
| if (!event->u.kprobe.symbol_name) { |
| ret = -ENOMEM; |
| goto name_error; |
| } |
| memcpy(event->u.kprobe.symbol_name, symbol_name, |
| - LTTNG_SYM_NAME_LEN * sizeof(char)); |
| + LTTNG_KERNEL_SYM_NAME_LEN * sizeof(char)); |
| event->u.kprobe.kp.symbol_name = |
| event->u.kprobe.symbol_name; |
| } |
| @@ -144,13 +157,13 @@ error: |
| } |
| EXPORT_SYMBOL_GPL(lttng_kprobes_register); |
| |
| -void lttng_kprobes_unregister(struct ltt_event *event) |
| +void lttng_kprobes_unregister(struct lttng_event *event) |
| { |
| unregister_kprobe(&event->u.kprobe.kp); |
| } |
| EXPORT_SYMBOL_GPL(lttng_kprobes_unregister); |
| |
| -void lttng_kprobes_destroy_private(struct ltt_event *event) |
| +void lttng_kprobes_destroy_private(struct lttng_event *event) |
| { |
| kfree(event->u.kprobe.symbol_name); |
| kfree(event->desc->fields); |
| --- a/drivers/staging/lttng/probes/lttng-kretprobes.c |
| +++ b/drivers/staging/lttng/probes/lttng-kretprobes.c |
| @@ -1,20 +1,33 @@ |
| /* |
| - * (C) Copyright 2009-2011 - |
| - * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * probes/lttng-kretprobes.c |
| * |
| * LTTng kretprobes integration module. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2009-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/kprobes.h> |
| #include <linux/slab.h> |
| #include <linux/kref.h> |
| -#include "../ltt-events.h" |
| +#include "../lttng-events.h" |
| #include "../wrapper/ringbuffer/frontend_types.h" |
| #include "../wrapper/vmalloc.h" |
| -#include "../ltt-tracer.h" |
| +#include "../lttng-tracer.h" |
| |
| enum lttng_kretprobe_type { |
| EVENT_ENTRY = 0, |
| @@ -23,7 +36,7 @@ enum lttng_kretprobe_type { |
| |
| struct lttng_krp { |
| struct kretprobe krp; |
| - struct ltt_event *event[2]; /* ENTRY and RETURN */ |
| + struct lttng_event *event[2]; /* ENTRY and RETURN */ |
| struct kref kref_register; |
| struct kref kref_alloc; |
| }; |
| @@ -35,9 +48,9 @@ int _lttng_kretprobes_handler(struct kre |
| { |
| struct lttng_krp *lttng_krp = |
| container_of(krpi->rp, struct lttng_krp, krp); |
| - struct ltt_event *event = |
| + struct lttng_event *event = |
| lttng_krp->event[type]; |
| - struct ltt_channel *chan = event->chan; |
| + struct lttng_channel *chan = event->chan; |
| struct lib_ring_buffer_ctx ctx; |
| int ret; |
| struct { |
| @@ -56,11 +69,11 @@ int _lttng_kretprobes_handler(struct kre |
| payload.parent_ip = (unsigned long) krpi->ret_addr; |
| |
| lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(payload), |
| - ltt_alignof(payload), -1); |
| + lttng_alignof(payload), -1); |
| ret = chan->ops->event_reserve(&ctx, event->id); |
| if (ret < 0) |
| return 0; |
| - lib_ring_buffer_align_ctx(&ctx, ltt_alignof(payload)); |
| + lib_ring_buffer_align_ctx(&ctx, lttng_alignof(payload)); |
| chan->ops->event_write(&ctx, &payload, sizeof(payload)); |
| chan->ops->event_commit(&ctx); |
| return 0; |
| @@ -84,7 +97,7 @@ int lttng_kretprobes_handler_return(stru |
| * Create event description |
| */ |
| static |
| -int lttng_create_kprobe_event(const char *name, struct ltt_event *event, |
| +int lttng_create_kprobe_event(const char *name, struct lttng_event *event, |
| enum lttng_kretprobe_type type) |
| { |
| struct lttng_event_field *fields; |
| @@ -125,7 +138,7 @@ int lttng_create_kprobe_event(const char |
| fields[0].name = "ip"; |
| fields[0].type.atype = atype_integer; |
| fields[0].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT; |
| - fields[0].type.u.basic.integer.alignment = ltt_alignof(unsigned long) * CHAR_BIT; |
| + fields[0].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT; |
| fields[0].type.u.basic.integer.signedness = is_signed_type(unsigned long); |
| fields[0].type.u.basic.integer.reverse_byte_order = 0; |
| fields[0].type.u.basic.integer.base = 16; |
| @@ -134,7 +147,7 @@ int lttng_create_kprobe_event(const char |
| fields[1].name = "parent_ip"; |
| fields[1].type.atype = atype_integer; |
| fields[1].type.u.basic.integer.size = sizeof(unsigned long) * CHAR_BIT; |
| - fields[1].type.u.basic.integer.alignment = ltt_alignof(unsigned long) * CHAR_BIT; |
| + fields[1].type.u.basic.integer.alignment = lttng_alignof(unsigned long) * CHAR_BIT; |
| fields[1].type.u.basic.integer.signedness = is_signed_type(unsigned long); |
| fields[1].type.u.basic.integer.reverse_byte_order = 0; |
| fields[1].type.u.basic.integer.base = 16; |
| @@ -156,8 +169,8 @@ int lttng_kretprobes_register(const char |
| const char *symbol_name, |
| uint64_t offset, |
| uint64_t addr, |
| - struct ltt_event *event_entry, |
| - struct ltt_event *event_return) |
| + struct lttng_event *event_entry, |
| + struct lttng_event *event_return) |
| { |
| int ret; |
| struct lttng_krp *lttng_krp; |
| @@ -247,7 +260,7 @@ void _lttng_kretprobes_unregister_releas |
| unregister_kretprobe(<tng_krp->krp); |
| } |
| |
| -void lttng_kretprobes_unregister(struct ltt_event *event) |
| +void lttng_kretprobes_unregister(struct lttng_event *event) |
| { |
| kref_put(&event->u.kretprobe.lttng_krp->kref_register, |
| _lttng_kretprobes_unregister_release); |
| @@ -262,7 +275,7 @@ void _lttng_kretprobes_release(struct kr |
| kfree(lttng_krp->krp.kp.symbol_name); |
| } |
| |
| -void lttng_kretprobes_destroy_private(struct ltt_event *event) |
| +void lttng_kretprobes_destroy_private(struct lttng_event *event) |
| { |
| kfree(event->desc->fields); |
| kfree(event->desc->name); |
| --- a/drivers/staging/lttng/probes/lttng-probe-block.c |
| +++ b/drivers/staging/lttng/probes/lttng-probe-block.c |
| @@ -1,11 +1,23 @@ |
| /* |
| * probes/lttng-probe-block.c |
| * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng block probes. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| --- a/drivers/staging/lttng/probes/lttng-probe-irq.c |
| +++ b/drivers/staging/lttng/probes/lttng-probe-irq.c |
| @@ -1,11 +1,23 @@ |
| /* |
| * probes/lttng-probe-irq.c |
| * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng irq probes. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| --- a/drivers/staging/lttng/probes/lttng-probe-kvm.c |
| +++ b/drivers/staging/lttng/probes/lttng-probe-kvm.c |
| @@ -1,11 +1,23 @@ |
| /* |
| * probes/lttng-probe-kvm.c |
| * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng kvm probes. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| --- a/drivers/staging/lttng/probes/lttng-probe-lttng.c |
| +++ b/drivers/staging/lttng/probes/lttng-probe-lttng.c |
| @@ -1,11 +1,23 @@ |
| /* |
| * probes/lttng-probe-core.c |
| * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng core probes. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| --- a/drivers/staging/lttng/probes/lttng-probe-sched.c |
| +++ b/drivers/staging/lttng/probes/lttng-probe-sched.c |
| @@ -1,11 +1,23 @@ |
| /* |
| * probes/lttng-probe-sched.c |
| * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng sched probes. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| --- /dev/null |
| +++ b/drivers/staging/lttng/probes/lttng-probe-signal.c |
| @@ -0,0 +1,42 @@ |
| +/* |
| + * probes/lttng-probe-signal.c |
| + * |
| + * LTTng signal probes. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| + |
| +/* |
| + * Create the tracepoint static inlines from the kernel to validate that our |
| + * trace event macros match the kernel we run on. |
| + */ |
| +#include <trace/events/signal.h> |
| + |
| +/* |
| + * Create LTTng tracepoint probes. |
| + */ |
| +#define LTTNG_PACKAGE_BUILD |
| +#define CREATE_TRACE_POINTS |
| +#define TRACE_INCLUDE_PATH ../instrumentation/events/lttng-module |
| + |
| +#include "../instrumentation/events/lttng-module/signal.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); |
| +MODULE_DESCRIPTION("LTTng signal probes"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/probes/lttng-probe-statedump.c |
| @@ -0,0 +1,45 @@ |
| +/* |
| + * probes/lttng-probe-statedump.c |
| + * |
| + * LTTng statedump probes. |
| + * |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| +#include <linux/interrupt.h> |
| +#include <linux/netlink.h> |
| +#include <linux/inet.h> |
| +#include <linux/ip.h> |
| +#include <linux/netdevice.h> |
| +#include <linux/inetdevice.h> |
| +#include "../lttng-events.h" |
| + |
| +/* |
| + * Create LTTng tracepoint probes. |
| + */ |
| +#define LTTNG_PACKAGE_BUILD |
| +#define CREATE_TRACE_POINTS |
| +#define TP_SESSION_CHECK |
| +#define TRACE_INCLUDE_PATH ../instrumentation/events/lttng-module |
| +#define TRACE_INCLUDE_FILE lttng-statedump |
| + |
| +#include "../instrumentation/events/lttng-module/lttng-statedump.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); |
| +MODULE_DESCRIPTION("LTTng statedump probes"); |
| --- /dev/null |
| +++ b/drivers/staging/lttng/probes/lttng-probe-timer.c |
| @@ -0,0 +1,43 @@ |
| +/* |
| + * probes/lttng-probe-timer.c |
| + * |
| + * LTTng timer probes. |
| + * |
| + * Copyright (C) 2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/module.h> |
| + |
| +/* |
| + * Create the tracepoint static inlines from the kernel to validate that our |
| + * trace event macros match the kernel we run on. |
| + */ |
| +#include <linux/sched.h> |
| +#include <trace/events/timer.h> |
| + |
| +/* |
| + * Create LTTng tracepoint probes. |
| + */ |
| +#define LTTNG_PACKAGE_BUILD |
| +#define CREATE_TRACE_POINTS |
| +#define TRACE_INCLUDE_PATH ../instrumentation/events/lttng-module |
| + |
| +#include "../instrumentation/events/lttng-module/timer.h" |
| + |
| +MODULE_LICENSE("GPL and additional rights"); |
| +MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); |
| +MODULE_DESCRIPTION("LTTng timer probes"); |
| --- a/drivers/staging/lttng/probes/lttng-type-list.h |
| +++ b/drivers/staging/lttng/probes/lttng-type-list.h |
| @@ -1,9 +1,21 @@ |
| /* |
| * lttng-type-list.h |
| * |
| - * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| /* Type list, used to create metadata */ |
| --- a/drivers/staging/lttng/probes/lttng-types.c |
| +++ b/drivers/staging/lttng/probes/lttng-types.c |
| @@ -1,17 +1,29 @@ |
| /* |
| * probes/lttng-types.c |
| * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng types. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/module.h> |
| #include <linux/types.h> |
| #include "../wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
| -#include "../ltt-events.h" |
| +#include "../lttng-events.h" |
| #include "lttng-types.h" |
| #include <linux/hrtimer.h> |
| |
| --- a/drivers/staging/lttng/probes/lttng-types.h |
| +++ b/drivers/staging/lttng/probes/lttng-types.h |
| @@ -8,18 +8,30 @@ |
| /* |
| * probes/lttng-types.h |
| * |
| - * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| - * |
| * LTTng types. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/seq_file.h> |
| #include "lttng.h" |
| -#include "../ltt-events.h" |
| -#include "../ltt-tracer.h" |
| -#include "../ltt-endian.h" |
| +#include "../lttng-events.h" |
| +#include "../lttng-tracer.h" |
| +#include "../lttng-endian.h" |
| |
| #endif /* _LTTNG_PROBES_LTTNG_TYPES_H */ |
| |
| --- a/drivers/staging/lttng/probes/lttng.h |
| +++ b/drivers/staging/lttng/probes/lttng.h |
| @@ -4,9 +4,21 @@ |
| /* |
| * lttng.h |
| * |
| - * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #undef PARAMS |
| --- a/drivers/staging/lttng/wrapper/ftrace.h |
| +++ b/drivers/staging/lttng/wrapper/ftrace.h |
| @@ -1,14 +1,28 @@ |
| -#ifndef _LTT_WRAPPER_FTRACE_H |
| -#define _LTT_WRAPPER_FTRACE_H |
| +#ifndef _LTTNG_WRAPPER_FTRACE_H |
| +#define _LTTNG_WRAPPER_FTRACE_H |
| |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/ftrace.h |
| * |
| * wrapper around vmalloc_sync_all. Using KALLSYMS to get its address when |
| * available, else we need to have a kernel that exports this function to GPL |
| * modules. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/ftrace.h> |
| @@ -67,4 +81,4 @@ void wrapper_unregister_ftrace_function_ |
| } |
| #endif |
| |
| -#endif /* _LTT_WRAPPER_FTRACE_H */ |
| +#endif /* _LTTNG_WRAPPER_FTRACE_H */ |
| --- a/drivers/staging/lttng/wrapper/inline_memcpy.h |
| +++ b/drivers/staging/lttng/wrapper/inline_memcpy.h |
| @@ -1,9 +1,21 @@ |
| /* |
| * wrapper/inline_memcpy.h |
| * |
| - * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #if !defined(__HAVE_ARCH_INLINE_MEMCPY) && !defined(inline_memcpy) |
| --- /dev/null |
| +++ b/drivers/staging/lttng/wrapper/irqdesc.c |
| @@ -0,0 +1,58 @@ |
| +/* |
| + * wrapper/irqdesc.c |
| + * |
| + * wrapper around irq_to_desc. Using KALLSYMS to get its address when |
| + * available, else we need to have a kernel that exports this function to GPL |
| + * modules. |
| + * |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#ifdef CONFIG_KALLSYMS |
| + |
| +#include <linux/kallsyms.h> |
| +#include <linux/interrupt.h> |
| +#include <linux/irqnr.h> |
| +#include "kallsyms.h" |
| +#include "irqdesc.h" |
| + |
| +static |
| +struct irq_desc *(*irq_to_desc_sym)(unsigned int irq); |
| + |
| +struct irq_desc *wrapper_irq_to_desc(unsigned int irq) |
| +{ |
| + if (!irq_to_desc_sym) |
| + irq_to_desc_sym = (void *) kallsyms_lookup_funcptr("irq_to_desc"); |
| + if (irq_to_desc_sym) { |
| + return irq_to_desc_sym(irq); |
| + } else { |
| + printk(KERN_WARNING "LTTng: irq_to_desc symbol lookup failed.\n"); |
| + return NULL; |
| + } |
| +} |
| + |
| +#else |
| + |
| +#include <linux/interrupt.h> |
| +#include <linux/irqnr.h> |
| + |
| +struct irq_desc *wrapper_irq_to_desc(unsigned int irq) |
| +{ |
| + return irq_to_desc(irq); |
| +} |
| + |
| +#endif |
| --- /dev/null |
| +++ b/drivers/staging/lttng/wrapper/irqdesc.h |
| @@ -0,0 +1,33 @@ |
| +#ifndef _LTTNG_WRAPPER_IRQDESC_H |
| +#define _LTTNG_WRAPPER_IRQDESC_H |
| + |
| +/* |
| + * wrapper/irqdesc.h |
| + * |
| + * wrapper around irq_to_desc. Using KALLSYMS to get its address when |
| + * available, else we need to have a kernel that exports this function to GPL |
| + * modules. |
| + * |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#include <linux/interrupt.h> |
| +#include <linux/irqnr.h> |
| + |
| +struct irq_desc *wrapper_irq_to_desc(unsigned int irq); |
| + |
| +#endif /* _LTTNG_WRAPPER_IRQDESC_H */ |
| --- a/drivers/staging/lttng/wrapper/kallsyms.h |
| +++ b/drivers/staging/lttng/wrapper/kallsyms.h |
| @@ -1,18 +1,49 @@ |
| -#ifndef _LTT_WRAPPER_KALLSYMS_H |
| -#define _LTT_WRAPPER_KALLSYMS_H |
| - |
| -#include <linux/kallsyms.h> |
| +#ifndef _LTTNG_WRAPPER_KALLSYMS_H |
| +#define _LTTNG_WRAPPER_KALLSYMS_H |
| |
| /* |
| - * Copyright (C) 2011 Avik Sil (avik.sil@linaro.org) |
| + * wrapper/kallsyms.h |
| * |
| * wrapper around kallsyms_lookup_name. Implements arch-dependent code for |
| * arches where the address of the start of the function body is different |
| * from the pointer which can be used to call the function, e.g. ARM THUMB2. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011 Avik Sil (avik.sil@linaro.org) |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + * Copyright (C) 2011 Avik Sil (avik.sil@linaro.org) |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| +#include <linux/kallsyms.h> |
| + |
| static inline |
| unsigned long kallsyms_lookup_funcptr(const char *name) |
| { |
| @@ -27,4 +58,4 @@ unsigned long kallsyms_lookup_funcptr(co |
| #endif |
| return addr; |
| } |
| -#endif /* _LTT_WRAPPER_KALLSYMS_H */ |
| +#endif /* _LTTNG_WRAPPER_KALLSYMS_H */ |
| --- a/drivers/staging/lttng/wrapper/perf.h |
| +++ b/drivers/staging/lttng/wrapper/perf.h |
| @@ -1,10 +1,24 @@ |
| -#ifndef _LTT_WRAPPER_PERF_H |
| -#define _LTT_WRAPPER_PERF_H |
| +#ifndef _LTTNG_WRAPPER_PERF_H |
| +#define _LTTNG_WRAPPER_PERF_H |
| |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/perf.h |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2010-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/perf_event.h> |
| @@ -29,4 +43,4 @@ wrapper_perf_event_create_kernel_counter |
| } |
| #endif |
| |
| -#endif /* _LTT_WRAPPER_PERF_H */ |
| +#endif /* _LTTNG_WRAPPER_PERF_H */ |
| --- a/drivers/staging/lttng/wrapper/poll.h |
| +++ b/drivers/staging/lttng/wrapper/poll.h |
| @@ -2,12 +2,32 @@ |
| #define _LTTNG_WRAPPER_POLL_H |
| |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/poll.h |
| * |
| * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| -#include <linux/poll.h> |
| + #include <linux/poll.h> |
| + |
| +/* |
| + * Note: poll_wait_set_exclusive() is defined as no-op. Thundering herd |
| + * effect can be noticed with large number of consumer threads. |
| + */ |
| |
| #define poll_wait_set_exclusive(poll_table) |
| |
| --- /dev/null |
| +++ b/drivers/staging/lttng/wrapper/random.c |
| @@ -0,0 +1,77 @@ |
| +/* |
| + * wrapper/random.c |
| + * |
| + * wrapper around bootid read. Using KALLSYMS to get its address when |
| + * available, else we need to have a kernel that exports this function to GPL |
| + * modules. |
| + * |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +/* boot_id depends on sysctl */ |
| +#if defined(CONFIG_SYSCTL) |
| + |
| +#include <linux/fs.h> |
| +#include <linux/file.h> |
| +#include <linux/sched.h> |
| +#include <linux/uaccess.h> |
| +#include "random.h" |
| + |
| +/* |
| + * Returns string boot id. |
| + */ |
| +int wrapper_get_bootid(char *bootid) |
| +{ |
| + struct file *file; |
| + int ret; |
| + ssize_t len; |
| + mm_segment_t old_fs; |
| + |
| + file = filp_open("/proc/sys/kernel/random/boot_id", O_RDONLY, 0); |
| + if (IS_ERR(file)) |
| + return PTR_ERR(file); |
| + |
| + old_fs = get_fs(); |
| + set_fs(KERNEL_DS); |
| + |
| + if (!file->f_op || !file->f_op->read) { |
| + ret = -EINVAL; |
| + goto end; |
| + } |
| + |
| + len = file->f_op->read(file, bootid, BOOT_ID_LEN - 1, &file->f_pos); |
| + if (len != BOOT_ID_LEN - 1) { |
| + ret = -EINVAL; |
| + goto end; |
| + } |
| + |
| + bootid[BOOT_ID_LEN - 1] = '\0'; |
| + ret = 0; |
| +end: |
| + set_fs(old_fs); |
| + filp_close(file, current->files); |
| + return ret; |
| +} |
| + |
| +#else |
| + |
| +int wrapper_get_bootid(char *bootid) |
| +{ |
| + return -ENOSYS; |
| +} |
| + |
| +#endif |
| --- /dev/null |
| +++ b/drivers/staging/lttng/wrapper/random.h |
| @@ -0,0 +1,32 @@ |
| +#ifndef _LTTNG_WRAPPER_RANDOM_H |
| +#define _LTTNG_WRAPPER_RANDOM_H |
| + |
| +/* |
| + * wrapper/random.h |
| + * |
| + * wrapper around bootid read. Using KALLSYMS to get its address when |
| + * available, else we need to have a kernel that exports this function to GPL |
| + * modules. |
| + * |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| + */ |
| + |
| +#define BOOT_ID_LEN 37 |
| + |
| +int wrapper_get_bootid(char *bootid); |
| + |
| +#endif /* _LTTNG_WRAPPER_RANDOM_H */ |
| --- a/drivers/staging/lttng/wrapper/spinlock.h |
| +++ b/drivers/staging/lttng/wrapper/spinlock.h |
| @@ -1,10 +1,24 @@ |
| -#ifndef _LTT_WRAPPER_SPINLOCK_H |
| -#define _LTT_WRAPPER_SPINLOCK_H |
| +#ifndef _LTTNG_WRAPPER_SPINLOCK_H |
| +#define _LTTNG_WRAPPER_SPINLOCK_H |
| |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/spinlock.h |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/version.h> |
| @@ -23,4 +37,4 @@ |
| |
| |
| #endif |
| -#endif /* _LTT_WRAPPER_SPINLOCK_H */ |
| +#endif /* _LTTNG_WRAPPER_SPINLOCK_H */ |
| --- a/drivers/staging/lttng/wrapper/splice.c |
| +++ b/drivers/staging/lttng/wrapper/splice.c |
| @@ -1,11 +1,25 @@ |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/splice.c |
| * |
| - * wrapper around vmalloc_sync_all. Using KALLSYMS to get its address when |
| + * wrapper around splice_to_pipe. Using KALLSYMS to get its address when |
| * available, else we need to have a kernel that exports this function to GPL |
| * modules. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #ifdef CONFIG_KALLSYMS |
| --- a/drivers/staging/lttng/wrapper/splice.h |
| +++ b/drivers/staging/lttng/wrapper/splice.h |
| @@ -1,14 +1,28 @@ |
| -#ifndef _LTT_WRAPPER_SPLICE_H |
| -#define _LTT_WRAPPER_SPLICE_H |
| +#ifndef _LTTNG_WRAPPER_SPLICE_H |
| +#define _LTTNG_WRAPPER_SPLICE_H |
| |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/splice.h |
| * |
| - * wrapper around vmalloc_sync_all. Using KALLSYMS to get its address when |
| + * wrapper around splice_to_pipe. Using KALLSYMS to get its address when |
| * available, else we need to have a kernel that exports this function to GPL |
| * modules. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/splice.h> |
| @@ -20,4 +34,4 @@ ssize_t wrapper_splice_to_pipe(struct pi |
| #define PIPE_DEF_BUFFERS 16 |
| #endif |
| |
| -#endif /* _LTT_WRAPPER_SPLICE_H */ |
| +#endif /* _LTTNG_WRAPPER_SPLICE_H */ |
| --- a/drivers/staging/lttng/wrapper/trace-clock.h |
| +++ b/drivers/staging/lttng/wrapper/trace-clock.h |
| @@ -1,15 +1,29 @@ |
| +#ifndef _LTTNG_TRACE_CLOCK_H |
| +#define _LTTNG_TRACE_CLOCK_H |
| + |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/trace-clock.h |
| * |
| * Contains LTTng trace clock mapping to LTTng trace clock or mainline monotonic |
| * clock. This wrapper depends on CONFIG_HIGH_RES_TIMERS=y. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| -#ifndef _LTT_TRACE_CLOCK_H |
| -#define _LTT_TRACE_CLOCK_H |
| - |
| #ifdef CONFIG_HAVE_TRACE_CLOCK |
| #include <linux/trace-clock.h> |
| #else /* CONFIG_HAVE_TRACE_CLOCK */ |
| @@ -18,6 +32,7 @@ |
| #include <linux/ktime.h> |
| #include <linux/time.h> |
| #include <linux/hrtimer.h> |
| +#include "random.h" |
| |
| static inline u64 trace_clock_monotonic_wrapper(void) |
| { |
| @@ -44,18 +59,24 @@ static inline u64 trace_clock_read64(voi |
| return (u64) trace_clock_monotonic_wrapper(); |
| } |
| |
| -static inline u64 trace_clock_frequency(void) |
| +static inline u64 trace_clock_freq(void) |
| { |
| - return (u64)NSEC_PER_SEC; |
| + return (u64) NSEC_PER_SEC; |
| } |
| |
| -static inline u32 trace_clock_freq_scale(void) |
| +static inline int trace_clock_uuid(char *uuid) |
| { |
| - return 1; |
| + return wrapper_get_bootid(uuid); |
| } |
| |
| static inline int get_trace_clock(void) |
| { |
| + /* |
| + * LTTng: Using mainline kernel monotonic clock. NMIs will not be |
| + * traced, and expect significant performance degradation compared to |
| + * the LTTng trace clocks. Integration of the LTTng 0.x trace clocks |
| + * into LTTng 2.0 is planned in a near future. |
| + */ |
| printk(KERN_WARNING "LTTng: Using mainline kernel monotonic clock.\n"); |
| printk(KERN_WARNING " * NMIs will not be traced,\n"); |
| printk(KERN_WARNING " * expect significant performance degradation compared to the\n"); |
| @@ -72,4 +93,4 @@ static inline void put_trace_clock(void) |
| |
| #endif /* CONFIG_HAVE_TRACE_CLOCK */ |
| |
| -#endif /* _LTT_TRACE_CLOCK_H */ |
| +#endif /* _LTTNG_TRACE_CLOCK_H */ |
| --- a/drivers/staging/lttng/wrapper/uuid.h |
| +++ b/drivers/staging/lttng/wrapper/uuid.h |
| @@ -1,10 +1,24 @@ |
| -#ifndef _LTT_WRAPPER_UUID_H |
| -#define _LTT_WRAPPER_UUID_H |
| +#ifndef _LTTNG_WRAPPER_UUID_H |
| +#define _LTTNG_WRAPPER_UUID_H |
| |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/uuid.h |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <linux/version.h> |
| @@ -26,4 +40,4 @@ void uuid_le_gen(uuid_le *u) |
| } |
| |
| #endif |
| -#endif /* _LTT_WRAPPER_UUID_H */ |
| +#endif /* _LTTNG_WRAPPER_UUID_H */ |
| --- a/drivers/staging/lttng/wrapper/vmalloc.h |
| +++ b/drivers/staging/lttng/wrapper/vmalloc.h |
| @@ -1,14 +1,28 @@ |
| -#ifndef _LTT_WRAPPER_VMALLOC_H |
| -#define _LTT_WRAPPER_VMALLOC_H |
| +#ifndef _LTTNG_WRAPPER_VMALLOC_H |
| +#define _LTTNG_WRAPPER_VMALLOC_H |
| |
| /* |
| - * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) |
| + * wrapper/vmalloc.h |
| * |
| * wrapper around vmalloc_sync_all. Using KALLSYMS to get its address when |
| * available, else we need to have a kernel that exports this function to GPL |
| * modules. |
| * |
| - * Dual LGPL v2.1/GPL v2 license. |
| + * Copyright (C) 2011-2012 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| + * |
| + * This library is free software; you can redistribute it and/or |
| + * modify it under the terms of the GNU Lesser General Public |
| + * License as published by the Free Software Foundation; only |
| + * version 2.1 of the License. |
| + * |
| + * This library is distributed in the hope that it will be useful, |
| + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| + * Lesser General Public License for more details. |
| + * |
| + * You should have received a copy of the GNU Lesser General Public |
| + * License along with this library; if not, write to the Free Software |
| + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #ifdef CONFIG_KALLSYMS |
| @@ -46,4 +60,4 @@ void wrapper_vmalloc_sync_all(void) |
| } |
| #endif |
| |
| -#endif /* _LTT_WRAPPER_VMALLOC_H */ |
| +#endif /* _LTTNG_WRAPPER_VMALLOC_H */ |