diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-25 17:38:35 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-25 17:38:35 -0700 |
commit | 29ec9a84a9dd42d5d04c8deb12bdd6598c64241b (patch) | |
tree | 8948f8ce5c3ac9eef05503a18e990a4c9b2d87ab | |
parent | bfd0d2ec9956717c87da97bf5e39b09dcc00435d (diff) | |
download | ltsi-kernel-29ec9a84a9dd42d5d04c8deb12bdd6598c64241b.tar.gz |
Update to latest version of LTTNG (v2.0.1)
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | patches.lttng/lttng-update-to-v2.0.1.patch | 14289 | ||||
-rw-r--r-- | series | 2 |
2 files changed, 14290 insertions, 1 deletions
diff --git a/patches.lttng/lttng-update-to-v2.0.1.patch b/patches.lttng/lttng-update-to-v2.0.1.patch new file mode 100644 index 0000000000000..e12c0f0510eb5 --- /dev/null +++ b/patches.lttng/lttng-update-to-v2.0.1.patch @@ -0,0 +1,14289 @@ +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 */ @@ -93,4 +93,4 @@ patches.lttng/0073-staging-lttng-cleanup-one-bit-signed-bitfields.patch patches.lttng/0172-staging-lttng-Fix-recent-modifications-to-string_fro.patch patches.lttng/0173-staging-lttng-TODO-update-lttng-reported-to-work-fin.patch patches.lttng/0174-staging-lttng-Update-max-symbol-length-to-256.patch - +patches.lttng/lttng-update-to-v2.0.1.patch |