diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-12 23:19:51 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-12 23:19:51 -0800 |
commit | 75d4f3c6c359d26fa9a4493162bc256ea4d69d37 (patch) | |
tree | 59361861a01d01f062ae5bb684fa1f2b543ac654 | |
parent | 6781f657257a44acac89cccf49251389daacc370 (diff) | |
download | ltsi-kernel-75d4f3c6c359d26fa9a4493162bc256ea4d69d37.tar.gz |
LTTng patches added
28 files changed, 27546 insertions, 0 deletions
diff --git a/patches.lttng/0001-lttng-lib-ring-buffer.patch b/patches.lttng/0001-lttng-lib-ring-buffer.patch new file mode 100644 index 0000000000000..9d27c5fd9687a --- /dev/null +++ b/patches.lttng/0001-lttng-lib-ring-buffer.patch @@ -0,0 +1,6804 @@ +From c844b2f5cfea185bcc5b5344ee642b3e3ee7ff03 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:09 -0500 +Subject: lttng lib: ring buffer + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/lib/ringbuffer/api.h | 25 + + drivers/staging/lttng/lib/ringbuffer/backend.h | 250 +++ + .../lttng/lib/ringbuffer/backend_internal.h | 449 +++++ + .../staging/lttng/lib/ringbuffer/backend_types.h | 80 + + drivers/staging/lttng/lib/ringbuffer/config.h | 298 ++++ + drivers/staging/lttng/lib/ringbuffer/frontend.h | 228 +++ + .../staging/lttng/lib/ringbuffer/frontend_api.h | 358 ++++ + .../lttng/lib/ringbuffer/frontend_internal.h | 424 +++++ + .../staging/lttng/lib/ringbuffer/frontend_types.h | 176 ++ + drivers/staging/lttng/lib/ringbuffer/iterator.h | 70 + + drivers/staging/lttng/lib/ringbuffer/nohz.h | 30 + + .../lttng/lib/ringbuffer/ring_buffer_backend.c | 854 ++++++++++ + .../lttng/lib/ringbuffer/ring_buffer_frontend.c | 1721 ++++++++++++++++++++ + .../lttng/lib/ringbuffer/ring_buffer_iterator.c | 798 +++++++++ + .../lttng/lib/ringbuffer/ring_buffer_mmap.c | 115 ++ + .../lttng/lib/ringbuffer/ring_buffer_splice.c | 202 +++ + .../staging/lttng/lib/ringbuffer/ring_buffer_vfs.c | 387 +++++ + drivers/staging/lttng/lib/ringbuffer/vatomic.h | 85 + + drivers/staging/lttng/lib/ringbuffer/vfs.h | 89 + + 19 files changed, 6639 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/lib/ringbuffer/api.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/backend.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/backend_internal.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/backend_types.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/config.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/frontend.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/frontend_api.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/frontend_internal.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/frontend_types.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/iterator.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/nohz.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/ring_buffer_backend.c + create mode 100644 drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c + create mode 100644 drivers/staging/lttng/lib/ringbuffer/ring_buffer_iterator.c + create mode 100644 drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c + create mode 100644 drivers/staging/lttng/lib/ringbuffer/ring_buffer_splice.c + create mode 100644 drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c + create mode 100644 drivers/staging/lttng/lib/ringbuffer/vatomic.h + create mode 100644 drivers/staging/lttng/lib/ringbuffer/vfs.h + +diff --git a/drivers/staging/lttng/lib/ringbuffer/api.h b/drivers/staging/lttng/lib/ringbuffer/api.h +new file mode 100644 +index 0000000..f8a1145 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/api.h +@@ -0,0 +1,25 @@ ++#ifndef _LINUX_RING_BUFFER_API_H ++#define _LINUX_RING_BUFFER_API_H ++ ++/* ++ * linux/ringbuffer/api.h ++ * ++ * Copyright (C) 2010 - Mathieu Desnoyers "mathieu.desnoyers@efficios.com" ++ * ++ * Ring Buffer API. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include "../../wrapper/ringbuffer/backend.h" ++#include "../../wrapper/ringbuffer/frontend.h" ++#include "../../wrapper/ringbuffer/vfs.h" ++ ++/* ++ * ring_buffer_frontend_api.h contains static inline functions that depend on ++ * client static inlines. Hence the inclusion of this "api" header only ++ * within the client. ++ */ ++#include "../../wrapper/ringbuffer/frontend_api.h" ++ ++#endif /* _LINUX_RING_BUFFER_API_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/backend.h b/drivers/staging/lttng/lib/ringbuffer/backend.h +new file mode 100644 +index 0000000..541dc53 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/backend.h +@@ -0,0 +1,250 @@ ++#ifndef _LINUX_RING_BUFFER_BACKEND_H ++#define _LINUX_RING_BUFFER_BACKEND_H ++ ++/* ++ * linux/ringbuffer/backend.h ++ * ++ * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring buffer backend (API). ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ * ++ * Credits to Steven Rostedt for proposing to use an extra-subbuffer owned by ++ * the reader in flight recorder mode. ++ */ ++ ++#include <linux/types.h> ++#include <linux/sched.h> ++#include <linux/timer.h> ++#include <linux/wait.h> ++#include <linux/poll.h> ++#include <linux/list.h> ++#include <linux/fs.h> ++#include <linux/mm.h> ++ ++/* Internal helpers */ ++#include "../../wrapper/ringbuffer/backend_internal.h" ++#include "../../wrapper/ringbuffer/frontend_internal.h" ++ ++/* Ring buffer backend API */ ++ ++/* Ring buffer backend access (read/write) */ ++ ++extern size_t lib_ring_buffer_read(struct lib_ring_buffer_backend *bufb, ++ size_t offset, void *dest, size_t len); ++ ++extern int __lib_ring_buffer_copy_to_user(struct lib_ring_buffer_backend *bufb, ++ size_t offset, void __user *dest, ++ size_t len); ++ ++extern int lib_ring_buffer_read_cstr(struct lib_ring_buffer_backend *bufb, ++ size_t offset, void *dest, size_t len); ++ ++extern struct page ** ++lib_ring_buffer_read_get_page(struct lib_ring_buffer_backend *bufb, size_t offset, ++ void ***virt); ++ ++/* ++ * Return the address where a given offset is located. ++ * Should be used to get the current subbuffer header pointer. Given we know ++ * it's never on a page boundary, it's safe to write directly to this address, ++ * as long as the write is never bigger than a page size. ++ */ ++extern void * ++lib_ring_buffer_offset_address(struct lib_ring_buffer_backend *bufb, ++ size_t offset); ++extern void * ++lib_ring_buffer_read_offset_address(struct lib_ring_buffer_backend *bufb, ++ size_t offset); ++ ++/** ++ * lib_ring_buffer_write - write data to a buffer backend ++ * @config : ring buffer instance configuration ++ * @ctx: ring buffer context. (input arguments only) ++ * @src : source pointer to copy from ++ * @len : length of data to copy ++ * ++ * This function copies "len" bytes of data from a source pointer to a buffer ++ * backend, at the current context offset. This is more or less a buffer ++ * backend-specific memcpy() operation. Calls the slow path (_ring_buffer_write) ++ * if copy is crossing a page boundary. ++ */ ++static inline ++void lib_ring_buffer_write(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_ctx *ctx, ++ const void *src, size_t len) ++{ ++ struct lib_ring_buffer_backend *bufb = &ctx->buf->backend; ++ struct channel_backend *chanb = &ctx->chan->backend; ++ size_t sbidx, index; ++ size_t offset = ctx->buf_offset; ++ ssize_t pagecpy; ++ struct lib_ring_buffer_backend_pages *rpages; ++ unsigned long sb_bindex, id; ++ ++ offset &= chanb->buf_size - 1; ++ sbidx = offset >> chanb->subbuf_size_order; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ pagecpy = min_t(size_t, len, (-offset) & ~PAGE_MASK); ++ id = bufb->buf_wsb[sbidx].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(ctx->chan, ++ config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ if (likely(pagecpy == len)) ++ lib_ring_buffer_do_copy(config, ++ rpages->p[index].virt ++ + (offset & ~PAGE_MASK), ++ src, len); ++ else ++ _lib_ring_buffer_write(bufb, offset, src, len, 0); ++ ctx->buf_offset += len; ++} ++ ++/** ++ * lib_ring_buffer_memset - write len bytes of c to a buffer backend ++ * @config : ring buffer instance configuration ++ * @bufb : ring buffer backend ++ * @offset : offset within the buffer ++ * @c : the byte to copy ++ * @len : number of bytes to copy ++ * ++ * This function writes "len" bytes of "c" to a buffer backend, at a specific ++ * offset. This is more or less a buffer backend-specific memset() operation. ++ * Calls the slow path (_ring_buffer_memset) if write is crossing a page ++ * boundary. ++ */ ++static inline ++void lib_ring_buffer_memset(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_ctx *ctx, int c, size_t len) ++{ ++ ++ struct lib_ring_buffer_backend *bufb = &ctx->buf->backend; ++ struct channel_backend *chanb = &ctx->chan->backend; ++ size_t sbidx, index; ++ size_t offset = ctx->buf_offset; ++ ssize_t pagecpy; ++ struct lib_ring_buffer_backend_pages *rpages; ++ unsigned long sb_bindex, id; ++ ++ offset &= chanb->buf_size - 1; ++ sbidx = offset >> chanb->subbuf_size_order; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ pagecpy = min_t(size_t, len, (-offset) & ~PAGE_MASK); ++ id = bufb->buf_wsb[sbidx].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(ctx->chan, ++ config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ if (likely(pagecpy == len)) ++ lib_ring_buffer_do_memset(rpages->p[index].virt ++ + (offset & ~PAGE_MASK), ++ c, len); ++ else ++ _lib_ring_buffer_memset(bufb, offset, c, len, 0); ++ ctx->buf_offset += len; ++} ++ ++/** ++ * lib_ring_buffer_copy_from_user - write userspace data to a buffer backend ++ * @config : ring buffer instance configuration ++ * @ctx: ring buffer context. (input arguments only) ++ * @src : userspace source pointer to copy from ++ * @len : length of data to copy ++ * ++ * This function copies "len" bytes of data from a userspace pointer to a ++ * buffer backend, at the current context offset. This is more or less a buffer ++ * backend-specific memcpy() operation. Calls the slow path ++ * (_ring_buffer_write_from_user) if copy is crossing a page boundary. ++ */ ++static inline ++void lib_ring_buffer_copy_from_user(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_ctx *ctx, ++ const void __user *src, size_t len) ++{ ++ struct lib_ring_buffer_backend *bufb = &ctx->buf->backend; ++ struct channel_backend *chanb = &ctx->chan->backend; ++ size_t sbidx, index; ++ size_t offset = ctx->buf_offset; ++ ssize_t pagecpy; ++ struct lib_ring_buffer_backend_pages *rpages; ++ unsigned long sb_bindex, id; ++ unsigned long ret; ++ ++ offset &= chanb->buf_size - 1; ++ sbidx = offset >> chanb->subbuf_size_order; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ pagecpy = min_t(size_t, len, (-offset) & ~PAGE_MASK); ++ id = bufb->buf_wsb[sbidx].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(ctx->chan, ++ config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ ++ if (unlikely(!access_ok(VERIFY_READ, src, len))) ++ goto fill_buffer; ++ ++ if (likely(pagecpy == len)) { ++ ret = lib_ring_buffer_do_copy_from_user( ++ rpages->p[index].virt + (offset & ~PAGE_MASK), ++ src, len); ++ if (unlikely(ret > 0)) { ++ len -= (pagecpy - ret); ++ offset += (pagecpy - ret); ++ goto fill_buffer; ++ } ++ } else { ++ _lib_ring_buffer_copy_from_user(bufb, offset, src, len, 0); ++ } ++ ctx->buf_offset += len; ++ ++ return; ++ ++fill_buffer: ++ /* ++ * In the error path we call the slow path version to avoid ++ * the pollution of static inline code. ++ */ ++ _lib_ring_buffer_memset(bufb, offset, 0, len, 0); ++} ++ ++/* ++ * This accessor counts the number of unread records in a buffer. ++ * It only provides a consistent value if no reads not writes are performed ++ * concurrently. ++ */ ++static inline ++unsigned long lib_ring_buffer_get_records_unread( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ struct lib_ring_buffer_backend *bufb = &buf->backend; ++ struct lib_ring_buffer_backend_pages *pages; ++ unsigned long records_unread = 0, sb_bindex, id; ++ unsigned int i; ++ ++ for (i = 0; i < bufb->chan->backend.num_subbuf; i++) { ++ id = bufb->buf_wsb[i].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ pages = bufb->array[sb_bindex]; ++ records_unread += v_read(config, &pages->records_unread); ++ } ++ if (config->mode == RING_BUFFER_OVERWRITE) { ++ id = bufb->buf_rsb.id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ pages = bufb->array[sb_bindex]; ++ records_unread += v_read(config, &pages->records_unread); ++ } ++ return records_unread; ++} ++ ++ssize_t lib_ring_buffer_file_splice_read(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, ++ 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 */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/backend_internal.h b/drivers/staging/lttng/lib/ringbuffer/backend_internal.h +new file mode 100644 +index 0000000..442f357 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/backend_internal.h +@@ -0,0 +1,449 @@ ++#ifndef _LINUX_RING_BUFFER_BACKEND_INTERNAL_H ++#define _LINUX_RING_BUFFER_BACKEND_INTERNAL_H ++ ++/* ++ * linux/ringbuffer/backend_internal.h ++ * ++ * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring buffer backend (internal helpers). ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include "../../wrapper/ringbuffer/config.h" ++#include "../../wrapper/ringbuffer/backend_types.h" ++#include "../../wrapper/ringbuffer/frontend_types.h" ++#include <linux/string.h> ++#include <linux/uaccess.h> ++ ++/* Ring buffer backend API presented to the frontend */ ++ ++/* Ring buffer and channel backend create/free */ ++ ++int lib_ring_buffer_backend_create(struct lib_ring_buffer_backend *bufb, ++ struct channel_backend *chan, int cpu); ++void channel_backend_unregister_notifiers(struct channel_backend *chanb); ++void lib_ring_buffer_backend_free(struct lib_ring_buffer_backend *bufb); ++int channel_backend_init(struct channel_backend *chanb, ++ const char *name, ++ const struct lib_ring_buffer_config *config, ++ void *priv, size_t subbuf_size, ++ size_t num_subbuf); ++void channel_backend_free(struct channel_backend *chanb); ++ ++void lib_ring_buffer_backend_reset(struct lib_ring_buffer_backend *bufb); ++void channel_backend_reset(struct channel_backend *chanb); ++ ++int lib_ring_buffer_backend_init(void); ++void lib_ring_buffer_backend_exit(void); ++ ++extern void _lib_ring_buffer_write(struct lib_ring_buffer_backend *bufb, ++ size_t offset, const void *src, size_t len, ++ ssize_t pagecpy); ++extern void _lib_ring_buffer_memset(struct lib_ring_buffer_backend *bufb, ++ size_t offset, int c, size_t len, ++ ssize_t pagecpy); ++extern void _lib_ring_buffer_copy_from_user(struct lib_ring_buffer_backend *bufb, ++ size_t offset, const void *src, ++ size_t len, ssize_t pagecpy); ++ ++/* ++ * Subbuffer ID bits for overwrite mode. Need to fit within a single word to be ++ * exchanged atomically. ++ * ++ * Top half word, except lowest bit, belongs to "offset", which is used to keep ++ * to count the produced buffers. For overwrite mode, this provides the ++ * consumer with the capacity to read subbuffers in order, handling the ++ * situation where producers would write up to 2^15 buffers (or 2^31 for 64-bit ++ * systems) concurrently with a single execution of get_subbuf (between offset ++ * sampling and subbuffer ID exchange). ++ */ ++ ++#define HALF_ULONG_BITS (BITS_PER_LONG >> 1) ++ ++#define SB_ID_OFFSET_SHIFT (HALF_ULONG_BITS + 1) ++#define SB_ID_OFFSET_COUNT (1UL << SB_ID_OFFSET_SHIFT) ++#define SB_ID_OFFSET_MASK (~(SB_ID_OFFSET_COUNT - 1)) ++/* ++ * Lowest bit of top word half belongs to noref. Used only for overwrite mode. ++ */ ++#define SB_ID_NOREF_SHIFT (SB_ID_OFFSET_SHIFT - 1) ++#define SB_ID_NOREF_COUNT (1UL << SB_ID_NOREF_SHIFT) ++#define SB_ID_NOREF_MASK SB_ID_NOREF_COUNT ++/* ++ * In overwrite mode: lowest half of word is used for index. ++ * Limit of 2^16 subbuffers per buffer on 32-bit, 2^32 on 64-bit. ++ * In producer-consumer mode: whole word used for index. ++ */ ++#define SB_ID_INDEX_SHIFT 0 ++#define SB_ID_INDEX_COUNT (1UL << SB_ID_INDEX_SHIFT) ++#define SB_ID_INDEX_MASK (SB_ID_NOREF_COUNT - 1) ++ ++/* ++ * Construct the subbuffer id from offset, index and noref. Use only the index ++ * for producer-consumer mode (offset and noref are only used in overwrite ++ * mode). ++ */ ++static inline ++unsigned long subbuffer_id(const struct lib_ring_buffer_config *config, ++ unsigned long offset, unsigned long noref, ++ unsigned long index) ++{ ++ if (config->mode == RING_BUFFER_OVERWRITE) ++ return (offset << SB_ID_OFFSET_SHIFT) ++ | (noref << SB_ID_NOREF_SHIFT) ++ | index; ++ else ++ return index; ++} ++ ++/* ++ * Compare offset with the offset contained within id. Return 1 if the offset ++ * bits are identical, else 0. ++ */ ++static inline ++int subbuffer_id_compare_offset(const struct lib_ring_buffer_config *config, ++ unsigned long id, unsigned long offset) ++{ ++ return (id & SB_ID_OFFSET_MASK) == (offset << SB_ID_OFFSET_SHIFT); ++} ++ ++static inline ++unsigned long subbuffer_id_get_index(const struct lib_ring_buffer_config *config, ++ unsigned long id) ++{ ++ if (config->mode == RING_BUFFER_OVERWRITE) ++ return id & SB_ID_INDEX_MASK; ++ else ++ return id; ++} ++ ++static inline ++unsigned long subbuffer_id_is_noref(const struct lib_ring_buffer_config *config, ++ unsigned long id) ++{ ++ if (config->mode == RING_BUFFER_OVERWRITE) ++ return !!(id & SB_ID_NOREF_MASK); ++ else ++ return 1; ++} ++ ++/* ++ * Only used by reader on subbuffer ID it has exclusive access to. No volatile ++ * needed. ++ */ ++static inline ++void subbuffer_id_set_noref(const struct lib_ring_buffer_config *config, ++ unsigned long *id) ++{ ++ if (config->mode == RING_BUFFER_OVERWRITE) ++ *id |= SB_ID_NOREF_MASK; ++} ++ ++static inline ++void subbuffer_id_set_noref_offset(const struct lib_ring_buffer_config *config, ++ unsigned long *id, unsigned long offset) ++{ ++ unsigned long tmp; ++ ++ if (config->mode == RING_BUFFER_OVERWRITE) { ++ tmp = *id; ++ tmp &= ~SB_ID_OFFSET_MASK; ++ tmp |= offset << SB_ID_OFFSET_SHIFT; ++ tmp |= SB_ID_NOREF_MASK; ++ /* Volatile store, read concurrently by readers. */ ++ ACCESS_ONCE(*id) = tmp; ++ } ++} ++ ++/* No volatile access, since already used locally */ ++static inline ++void subbuffer_id_clear_noref(const struct lib_ring_buffer_config *config, ++ unsigned long *id) ++{ ++ if (config->mode == RING_BUFFER_OVERWRITE) ++ *id &= ~SB_ID_NOREF_MASK; ++} ++ ++/* ++ * For overwrite mode, cap the number of subbuffers per buffer to: ++ * 2^16 on 32-bit architectures ++ * 2^32 on 64-bit architectures ++ * This is required to fit in the index part of the ID. Return 0 on success, ++ * -EPERM on failure. ++ */ ++static inline ++int subbuffer_id_check_index(const struct lib_ring_buffer_config *config, ++ unsigned long num_subbuf) ++{ ++ if (config->mode == RING_BUFFER_OVERWRITE) ++ return (num_subbuf > (1UL << HALF_ULONG_BITS)) ? -EPERM : 0; ++ else ++ return 0; ++} ++ ++static inline ++void subbuffer_count_record(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ unsigned long idx) ++{ ++ unsigned long sb_bindex; ++ ++ sb_bindex = subbuffer_id_get_index(config, bufb->buf_wsb[idx].id); ++ v_inc(config, &bufb->array[sb_bindex]->records_commit); ++} ++ ++/* ++ * Reader has exclusive subbuffer access for record consumption. No need to ++ * perform the decrement atomically. ++ */ ++static inline ++void subbuffer_consume_record(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb) ++{ ++ unsigned long sb_bindex; ++ ++ sb_bindex = subbuffer_id_get_index(config, bufb->buf_rsb.id); ++ CHAN_WARN_ON(bufb->chan, ++ !v_read(config, &bufb->array[sb_bindex]->records_unread)); ++ /* Non-atomic decrement protected by exclusive subbuffer access */ ++ _v_dec(config, &bufb->array[sb_bindex]->records_unread); ++ v_inc(config, &bufb->records_read); ++} ++ ++static inline ++unsigned long subbuffer_get_records_count( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ unsigned long idx) ++{ ++ unsigned long sb_bindex; ++ ++ sb_bindex = subbuffer_id_get_index(config, bufb->buf_wsb[idx].id); ++ return v_read(config, &bufb->array[sb_bindex]->records_commit); ++} ++ ++/* ++ * Must be executed at subbuffer delivery when the writer has _exclusive_ ++ * subbuffer access. See ring_buffer_check_deliver() for details. ++ * ring_buffer_get_records_count() must be called to get the records count ++ * before this function, because it resets the records_commit count. ++ */ ++static inline ++unsigned long subbuffer_count_records_overrun( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ unsigned long idx) ++{ ++ struct lib_ring_buffer_backend_pages *pages; ++ unsigned long overruns, sb_bindex; ++ ++ sb_bindex = subbuffer_id_get_index(config, bufb->buf_wsb[idx].id); ++ pages = bufb->array[sb_bindex]; ++ overruns = v_read(config, &pages->records_unread); ++ v_set(config, &pages->records_unread, ++ v_read(config, &pages->records_commit)); ++ v_set(config, &pages->records_commit, 0); ++ ++ return overruns; ++} ++ ++static inline ++void subbuffer_set_data_size(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ unsigned long idx, ++ unsigned long data_size) ++{ ++ struct lib_ring_buffer_backend_pages *pages; ++ unsigned long sb_bindex; ++ ++ sb_bindex = subbuffer_id_get_index(config, bufb->buf_wsb[idx].id); ++ pages = bufb->array[sb_bindex]; ++ pages->data_size = data_size; ++} ++ ++static inline ++unsigned long subbuffer_get_read_data_size( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb) ++{ ++ struct lib_ring_buffer_backend_pages *pages; ++ unsigned long sb_bindex; ++ ++ sb_bindex = subbuffer_id_get_index(config, bufb->buf_rsb.id); ++ pages = bufb->array[sb_bindex]; ++ return pages->data_size; ++} ++ ++static inline ++unsigned long subbuffer_get_data_size( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ unsigned long idx) ++{ ++ struct lib_ring_buffer_backend_pages *pages; ++ unsigned long sb_bindex; ++ ++ sb_bindex = subbuffer_id_get_index(config, bufb->buf_wsb[idx].id); ++ pages = bufb->array[sb_bindex]; ++ return pages->data_size; ++} ++ ++/** ++ * lib_ring_buffer_clear_noref - Clear the noref subbuffer flag, called by ++ * writer. ++ */ ++static inline ++void lib_ring_buffer_clear_noref(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ unsigned long idx) ++{ ++ unsigned long id, new_id; ++ ++ if (config->mode != RING_BUFFER_OVERWRITE) ++ return; ++ ++ /* ++ * Performing a volatile access to read the sb_pages, because we want to ++ * read a coherent version of the pointer and the associated noref flag. ++ */ ++ id = ACCESS_ONCE(bufb->buf_wsb[idx].id); ++ for (;;) { ++ /* This check is called on the fast path for each record. */ ++ if (likely(!subbuffer_id_is_noref(config, id))) { ++ /* ++ * Store after load dependency ordering the writes to ++ * the subbuffer after load and test of the noref flag ++ * matches the memory barrier implied by the cmpxchg() ++ * in update_read_sb_index(). ++ */ ++ return; /* Already writing to this buffer */ ++ } ++ new_id = id; ++ subbuffer_id_clear_noref(config, &new_id); ++ new_id = cmpxchg(&bufb->buf_wsb[idx].id, id, new_id); ++ if (likely(new_id == id)) ++ break; ++ id = new_id; ++ } ++} ++ ++/** ++ * lib_ring_buffer_set_noref_offset - Set the noref subbuffer flag and offset, ++ * called by writer. ++ */ ++static inline ++void lib_ring_buffer_set_noref_offset(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ unsigned long idx, unsigned long offset) ++{ ++ if (config->mode != RING_BUFFER_OVERWRITE) ++ return; ++ ++ /* ++ * Because ring_buffer_set_noref() is only called by a single thread ++ * (the one which updated the cc_sb value), there are no concurrent ++ * updates to take care of: other writers have not updated cc_sb, so ++ * they cannot set the noref flag, and concurrent readers cannot modify ++ * the pointer because the noref flag is not set yet. ++ * The smp_wmb() in ring_buffer_commit() takes care of ordering writes ++ * to the subbuffer before this set noref operation. ++ * subbuffer_set_noref() uses a volatile store to deal with concurrent ++ * readers of the noref flag. ++ */ ++ CHAN_WARN_ON(bufb->chan, ++ subbuffer_id_is_noref(config, bufb->buf_wsb[idx].id)); ++ /* ++ * Memory barrier that ensures counter stores are ordered before set ++ * noref and offset. ++ */ ++ smp_mb(); ++ subbuffer_id_set_noref_offset(config, &bufb->buf_wsb[idx].id, offset); ++} ++ ++/** ++ * update_read_sb_index - Read-side subbuffer index update. ++ */ ++static inline ++int update_read_sb_index(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ struct channel_backend *chanb, ++ unsigned long consumed_idx, ++ unsigned long consumed_count) ++{ ++ unsigned long old_id, new_id; ++ ++ if (config->mode == RING_BUFFER_OVERWRITE) { ++ /* ++ * Exchange the target writer subbuffer with our own unused ++ * subbuffer. No need to use ACCESS_ONCE() here to read the ++ * old_wpage, because the value read will be confirmed by the ++ * following cmpxchg(). ++ */ ++ old_id = bufb->buf_wsb[consumed_idx].id; ++ if (unlikely(!subbuffer_id_is_noref(config, old_id))) ++ return -EAGAIN; ++ /* ++ * Make sure the offset count we are expecting matches the one ++ * indicated by the writer. ++ */ ++ if (unlikely(!subbuffer_id_compare_offset(config, old_id, ++ consumed_count))) ++ return -EAGAIN; ++ CHAN_WARN_ON(bufb->chan, ++ !subbuffer_id_is_noref(config, bufb->buf_rsb.id)); ++ subbuffer_id_set_noref_offset(config, &bufb->buf_rsb.id, ++ consumed_count); ++ new_id = cmpxchg(&bufb->buf_wsb[consumed_idx].id, old_id, ++ bufb->buf_rsb.id); ++ if (unlikely(old_id != new_id)) ++ return -EAGAIN; ++ bufb->buf_rsb.id = new_id; ++ } else { ++ /* No page exchange, use the writer page directly */ ++ bufb->buf_rsb.id = bufb->buf_wsb[consumed_idx].id; ++ } ++ return 0; ++} ++ ++/* ++ * Use the architecture-specific memcpy implementation for constant-sized ++ * inputs, but rely on an inline memcpy for length statically unknown. ++ * The function call to memcpy is just way too expensive for a fast path. ++ */ ++#define lib_ring_buffer_do_copy(config, dest, src, len) \ ++do { \ ++ size_t __len = (len); \ ++ if (__builtin_constant_p(len)) \ ++ memcpy(dest, src, __len); \ ++ else \ ++ inline_memcpy(dest, src, __len); \ ++} while (0) ++ ++/* ++ * We use __copy_from_user to copy userspace data since we already ++ * did the access_ok for the whole range. ++ */ ++static inline ++unsigned long lib_ring_buffer_do_copy_from_user(void *dest, ++ const void __user *src, ++ unsigned long len) ++{ ++ return __copy_from_user(dest, src, len); ++} ++ ++/* ++ * write len bytes to dest with c ++ */ ++static inline ++void lib_ring_buffer_do_memset(char *dest, int c, ++ unsigned long len) ++{ ++ unsigned long i; ++ ++ for (i = 0; i < len; i++) ++ dest[i] = c; ++} ++ ++#endif /* _LINUX_RING_BUFFER_BACKEND_INTERNAL_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/backend_types.h b/drivers/staging/lttng/lib/ringbuffer/backend_types.h +new file mode 100644 +index 0000000..1d301de +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/backend_types.h +@@ -0,0 +1,80 @@ ++#ifndef _LINUX_RING_BUFFER_BACKEND_TYPES_H ++#define _LINUX_RING_BUFFER_BACKEND_TYPES_H ++ ++/* ++ * linux/ringbuffer/backend_types.h ++ * ++ * Copyright (C) 2008-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring buffer backend (types). ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/cpumask.h> ++#include <linux/types.h> ++ ++struct lib_ring_buffer_backend_page { ++ void *virt; /* page virtual address (cached) */ ++ struct page *page; /* pointer to page structure */ ++}; ++ ++struct lib_ring_buffer_backend_pages { ++ unsigned long mmap_offset; /* offset of the subbuffer in mmap */ ++ union v_atomic records_commit; /* current records committed count */ ++ union v_atomic records_unread; /* records to read */ ++ unsigned long data_size; /* Amount of data to read from subbuf */ ++ struct lib_ring_buffer_backend_page p[]; ++}; ++ ++struct lib_ring_buffer_backend_subbuffer { ++ /* Identifier for subbuf backend pages. Exchanged atomically. */ ++ unsigned long id; /* backend subbuffer identifier */ ++}; ++ ++/* ++ * Forward declaration of frontend-specific channel and ring_buffer. ++ */ ++struct channel; ++struct lib_ring_buffer; ++ ++struct lib_ring_buffer_backend { ++ /* Array of ring_buffer_backend_subbuffer for writer */ ++ struct lib_ring_buffer_backend_subbuffer *buf_wsb; ++ /* ring_buffer_backend_subbuffer for reader */ ++ struct lib_ring_buffer_backend_subbuffer buf_rsb; ++ /* ++ * Pointer array of backend pages, for whole buffer. ++ * Indexed by ring_buffer_backend_subbuffer identifier (id) index. ++ */ ++ struct lib_ring_buffer_backend_pages **array; ++ unsigned int num_pages_per_subbuf; ++ ++ struct channel *chan; /* Associated channel */ ++ int cpu; /* This buffer's cpu. -1 if global. */ ++ union v_atomic records_read; /* Number of records read */ ++ unsigned int allocated:1; /* Bool: is buffer allocated ? */ ++}; ++ ++struct channel_backend { ++ unsigned long buf_size; /* Size of the buffer */ ++ unsigned long subbuf_size; /* Sub-buffer size */ ++ unsigned int subbuf_size_order; /* Order of sub-buffer size */ ++ unsigned int num_subbuf_order; /* ++ * Order of number of sub-buffers/buffer ++ * for writer. ++ */ ++ unsigned int buf_size_order; /* Order of buffer size */ ++ int extra_reader_sb:1; /* Bool: has extra reader subbuffer */ ++ struct lib_ring_buffer *buf; /* Channel per-cpu buffers */ ++ ++ unsigned long num_subbuf; /* Number of sub-buffers for writer */ ++ 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 */ ++ cpumask_var_t cpumask; /* Allocated per-cpu buffers cpumask */ ++ char name[NAME_MAX]; /* Channel name */ ++}; ++ ++#endif /* _LINUX_RING_BUFFER_BACKEND_TYPES_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/config.h b/drivers/staging/lttng/lib/ringbuffer/config.h +new file mode 100644 +index 0000000..fd73d55 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/config.h +@@ -0,0 +1,298 @@ ++#ifndef _LINUX_RING_BUFFER_CONFIG_H ++#define _LINUX_RING_BUFFER_CONFIG_H ++ ++/* ++ * linux/ringbuffer/config.h ++ * ++ * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * 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. ++ */ ++ ++#include <linux/types.h> ++#include <linux/percpu.h> ++#include "../align.h" ++ ++struct lib_ring_buffer; ++struct channel; ++struct lib_ring_buffer_config; ++struct lib_ring_buffer_ctx; ++ ++/* ++ * Ring buffer client callbacks. Only used by slow path, never on fast path. ++ * For the fast path, record_header_size(), ring_buffer_clock_read() should be ++ * provided as inline functions too. These may simply return 0 if not used by ++ * the client. ++ */ ++struct lib_ring_buffer_client_cb { ++ /* Mandatory callbacks */ ++ ++ /* A static inline version is also required for fast path */ ++ u64 (*ring_buffer_clock_read) (struct channel *chan); ++ size_t (*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); ++ ++ /* Slow path only, at subbuffer switch */ ++ size_t (*subbuffer_header_size) (void); ++ void (*buffer_begin) (struct lib_ring_buffer *buf, u64 tsc, ++ unsigned int subbuf_idx); ++ void (*buffer_end) (struct lib_ring_buffer *buf, u64 tsc, ++ unsigned int subbuf_idx, unsigned long data_size); ++ ++ /* Optional callbacks (can be set to NULL) */ ++ ++ /* Called at buffer creation/finalize */ ++ int (*buffer_create) (struct lib_ring_buffer *buf, void *priv, ++ int cpu, const char *name); ++ /* ++ * Clients should guarantee that no new reader handle can be opened ++ * after finalize. ++ */ ++ void (*buffer_finalize) (struct lib_ring_buffer *buf, void *priv, int cpu); ++ ++ /* ++ * Extract header length, payload length and timestamp from event ++ * record. Used by buffer iterators. Timestamp is only used by channel ++ * iterator. ++ */ ++ void (*record_get) (const struct lib_ring_buffer_config *config, ++ struct channel *chan, struct lib_ring_buffer *buf, ++ size_t offset, size_t *header_len, ++ size_t *payload_len, u64 *timestamp); ++}; ++ ++/* ++ * Ring buffer instance configuration. ++ * ++ * Declare as "static const" within the client object to ensure the inline fast ++ * paths can be optimized. ++ * ++ * alloc/sync pairs: ++ * ++ * RING_BUFFER_ALLOC_PER_CPU and RING_BUFFER_SYNC_PER_CPU : ++ * Per-cpu buffers with per-cpu synchronization. Tracing must be performed ++ * with preemption disabled (lib_ring_buffer_get_cpu() and ++ * lib_ring_buffer_put_cpu()). ++ * ++ * RING_BUFFER_ALLOC_PER_CPU and RING_BUFFER_SYNC_GLOBAL : ++ * Per-cpu buffer with global synchronization. Tracing can be performed with ++ * preemption enabled, statistically stays on the local buffers. ++ * ++ * RING_BUFFER_ALLOC_GLOBAL and RING_BUFFER_SYNC_PER_CPU : ++ * Should only be used for buffers belonging to a single thread or protected ++ * by mutual exclusion by the client. Note that periodical sub-buffer switch ++ * should be disabled in this kind of configuration. ++ * ++ * RING_BUFFER_ALLOC_GLOBAL and RING_BUFFER_SYNC_GLOBAL : ++ * Global shared buffer with global synchronization. ++ * ++ * wakeup: ++ * ++ * RING_BUFFER_WAKEUP_BY_TIMER uses per-cpu deferrable timers to poll the ++ * buffers and wake up readers if data is ready. Mainly useful for tracers which ++ * don't want to call into the wakeup code on the tracing path. Use in ++ * combination with "read_timer_interval" channel_create() argument. ++ * ++ * RING_BUFFER_WAKEUP_BY_WRITER directly wakes up readers when a subbuffer is ++ * ready to read. Lower latencies before the reader is woken up. Mainly suitable ++ * for drivers. ++ * ++ * RING_BUFFER_WAKEUP_NONE does not perform any wakeup whatsoever. The client ++ * has the responsibility to perform wakeups. ++ */ ++struct lib_ring_buffer_config { ++ enum { ++ RING_BUFFER_ALLOC_PER_CPU, ++ RING_BUFFER_ALLOC_GLOBAL, ++ } alloc; ++ enum { ++ RING_BUFFER_SYNC_PER_CPU, /* Wait-free */ ++ RING_BUFFER_SYNC_GLOBAL, /* Lock-free */ ++ } sync; ++ enum { ++ RING_BUFFER_OVERWRITE, /* Overwrite when buffer full */ ++ RING_BUFFER_DISCARD, /* Discard when buffer full */ ++ } mode; ++ enum { ++ RING_BUFFER_SPLICE, ++ RING_BUFFER_MMAP, ++ RING_BUFFER_READ, /* TODO */ ++ RING_BUFFER_ITERATOR, ++ RING_BUFFER_NONE, ++ } output; ++ enum { ++ RING_BUFFER_PAGE, ++ RING_BUFFER_VMAP, /* TODO */ ++ RING_BUFFER_STATIC, /* TODO */ ++ } backend; ++ enum { ++ RING_BUFFER_NO_OOPS_CONSISTENCY, ++ RING_BUFFER_OOPS_CONSISTENCY, ++ } oops; ++ enum { ++ RING_BUFFER_IPI_BARRIER, ++ RING_BUFFER_NO_IPI_BARRIER, ++ } ipi; ++ enum { ++ RING_BUFFER_WAKEUP_BY_TIMER, /* wake up performed by timer */ ++ RING_BUFFER_WAKEUP_BY_WRITER, /* ++ * writer wakes up reader, ++ * not lock-free ++ * (takes spinlock). ++ */ ++ } wakeup; ++ /* ++ * tsc_bits: timestamp bits saved at each record. ++ * 0 and 64 disable the timestamp compression scheme. ++ */ ++ unsigned int tsc_bits; ++ struct lib_ring_buffer_client_cb cb; ++}; ++ ++/* ++ * ring buffer context ++ * ++ * Context passed to lib_ring_buffer_reserve(), lib_ring_buffer_commit(), ++ * lib_ring_buffer_try_discard_reserve(), lib_ring_buffer_align_ctx() and ++ * lib_ring_buffer_write(). ++ */ ++struct lib_ring_buffer_ctx { ++ /* input received by lib_ring_buffer_reserve(), saved here. */ ++ struct channel *chan; /* channel */ ++ void *priv; /* client private data */ ++ size_t data_size; /* size of payload */ ++ int largest_align; /* ++ * alignment of the largest element ++ * in the payload ++ */ ++ int cpu; /* processor id */ ++ ++ /* output from lib_ring_buffer_reserve() */ ++ struct lib_ring_buffer *buf; /* ++ * buffer corresponding to processor id ++ * for this channel ++ */ ++ size_t slot_size; /* size of the reserved slot */ ++ unsigned long buf_offset; /* offset following the record header */ ++ unsigned long pre_offset; /* ++ * Initial offset position _before_ ++ * the record is written. Positioned ++ * prior to record header alignment ++ * padding. ++ */ ++ u64 tsc; /* time-stamp counter value */ ++ unsigned int rflags; /* reservation flags */ ++}; ++ ++/** ++ * lib_ring_buffer_ctx_init - initialize ring buffer context ++ * @ctx: ring buffer context to initialize ++ * @chan: channel ++ * @priv: client private data ++ * @data_size: size of record data payload ++ * @largest_align: largest alignment within data payload types ++ * @cpu: processor id ++ */ ++static inline ++void lib_ring_buffer_ctx_init(struct lib_ring_buffer_ctx *ctx, ++ struct channel *chan, void *priv, ++ size_t data_size, int largest_align, ++ int cpu) ++{ ++ ctx->chan = chan; ++ ctx->priv = priv; ++ ctx->data_size = data_size; ++ ctx->largest_align = largest_align; ++ ctx->cpu = cpu; ++ ctx->rflags = 0; ++} ++ ++/* ++ * Reservation flags. ++ * ++ * RING_BUFFER_RFLAG_FULL_TSC ++ * ++ * This flag is passed to record_header_size() and to the primitive used to ++ * write the record header. It indicates that the full 64-bit time value is ++ * needed in the record header. If this flag is not set, the record header needs ++ * only to contain "tsc_bits" bit of time value. ++ * ++ * Reservation flags can be added by the client, starting from ++ * "(RING_BUFFER_FLAGS_END << 0)". It can be used to pass information from ++ * record_header_size() to lib_ring_buffer_write_record_header(). ++ */ ++#define RING_BUFFER_RFLAG_FULL_TSC (1U << 0) ++#define RING_BUFFER_RFLAG_END (1U << 1) ++ ++/* ++ * We need to define RING_BUFFER_ALIGN_ATTR so it is known early at ++ * compile-time. We have to duplicate the "config->align" information and the ++ * definition here because config->align is used both in the slow and fast ++ * paths, but RING_BUFFER_ALIGN_ATTR is only available for the client code. ++ */ ++#ifdef RING_BUFFER_ALIGN ++ ++# define RING_BUFFER_ALIGN_ATTR /* Default arch alignment */ ++ ++/* ++ * Calculate the offset needed to align the type. ++ * size_of_type must be non-zero. ++ */ ++static inline ++unsigned int lib_ring_buffer_align(size_t align_drift, size_t size_of_type) ++{ ++ return offset_align(align_drift, size_of_type); ++} ++ ++#else ++ ++# define RING_BUFFER_ALIGN_ATTR __attribute__((packed)) ++ ++/* ++ * Calculate the offset needed to align the type. ++ * size_of_type must be non-zero. ++ */ ++static inline ++unsigned int lib_ring_buffer_align(size_t align_drift, size_t size_of_type) ++{ ++ return 0; ++} ++ ++#endif ++ ++/** ++ * lib_ring_buffer_align_ctx - Align context offset on "alignment" ++ * @ctx: ring buffer context. ++ */ ++static inline ++void lib_ring_buffer_align_ctx(struct lib_ring_buffer_ctx *ctx, ++ size_t alignment) ++{ ++ ctx->buf_offset += lib_ring_buffer_align(ctx->buf_offset, ++ alignment); ++} ++ ++/* ++ * lib_ring_buffer_check_config() returns 0 on success. ++ * Used internally to check for valid configurations at channel creation. ++ */ ++static inline ++int lib_ring_buffer_check_config(const struct lib_ring_buffer_config *config, ++ unsigned int switch_timer_interval, ++ unsigned int read_timer_interval) ++{ ++ if (config->alloc == RING_BUFFER_ALLOC_GLOBAL ++ && config->sync == RING_BUFFER_SYNC_PER_CPU ++ && switch_timer_interval) ++ return -EINVAL; ++ return 0; ++} ++ ++#include "../../wrapper/ringbuffer/vatomic.h" ++ ++#endif /* _LINUX_RING_BUFFER_CONFIG_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/frontend.h b/drivers/staging/lttng/lib/ringbuffer/frontend.h +new file mode 100644 +index 0000000..01af77a +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/frontend.h +@@ -0,0 +1,228 @@ ++#ifndef _LINUX_RING_BUFFER_FRONTEND_H ++#define _LINUX_RING_BUFFER_FRONTEND_H ++ ++/* ++ * linux/ringbuffer/frontend.h ++ * ++ * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring Buffer Library Synchronization Header (API). ++ * ++ * 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> ++#include <linux/rcupdate.h> ++#include <linux/cpumask.h> ++#include <linux/module.h> ++#include <linux/bitops.h> ++#include <linux/splice.h> ++#include <linux/string.h> ++#include <linux/timer.h> ++#include <linux/sched.h> ++#include <linux/cache.h> ++#include <linux/time.h> ++#include <linux/slab.h> ++#include <linux/init.h> ++#include <linux/stat.h> ++#include <linux/cpu.h> ++#include <linux/fs.h> ++ ++#include <asm/atomic.h> ++#include <asm/local.h> ++ ++/* Internal helpers */ ++#include "../../wrapper/ringbuffer/frontend_internal.h" ++ ++/* Buffer creation/removal and setup operations */ ++ ++/* ++ * switch_timer_interval is the time interval (in us) to fill sub-buffers with ++ * padding to let readers get those sub-buffers. Used for live streaming. ++ * ++ * read_timer_interval is the time interval (in us) to wake up pending readers. ++ * ++ * buf_addr is a pointer the the beginning of the preallocated buffer contiguous ++ * address mapping. It is used only by RING_BUFFER_STATIC configuration. It can ++ * be set to NULL for other backends. ++ */ ++ ++extern ++struct channel *channel_create(const struct lib_ring_buffer_config *config, ++ const char *name, void *priv, ++ void *buf_addr, ++ size_t subbuf_size, size_t num_subbuf, ++ unsigned int switch_timer_interval, ++ unsigned int read_timer_interval); ++ ++/* ++ * channel_destroy returns the private data pointer. It finalizes all channel's ++ * buffers, waits for readers to release all references, and destroys the ++ * channel. ++ */ ++extern ++void *channel_destroy(struct channel *chan); ++ ++ ++/* Buffer read operations */ ++ ++/* ++ * Iteration on channel cpumask needs to issue a read barrier to match the write ++ * barrier in cpu hotplug. It orders the cpumask read before read of per-cpu ++ * buffer data. The per-cpu buffer is never removed by cpu hotplug; teardown is ++ * only performed at channel destruction. ++ */ ++#define for_each_channel_cpu(cpu, chan) \ ++ for ((cpu) = -1; \ ++ ({ (cpu) = cpumask_next(cpu, (chan)->backend.cpumask); \ ++ smp_read_barrier_depends(); (cpu) < nr_cpu_ids; });) ++ ++extern struct lib_ring_buffer *channel_get_ring_buffer( ++ const struct lib_ring_buffer_config *config, ++ struct channel *chan, int cpu); ++extern int lib_ring_buffer_open_read(struct lib_ring_buffer *buf); ++extern void lib_ring_buffer_release_read(struct lib_ring_buffer *buf); ++ ++/* ++ * Read sequence: snapshot, many get_subbuf/put_subbuf, move_consumer. ++ */ ++extern int lib_ring_buffer_snapshot(struct lib_ring_buffer *buf, ++ unsigned long *consumed, ++ unsigned long *produced); ++extern void lib_ring_buffer_move_consumer(struct lib_ring_buffer *buf, ++ unsigned long consumed_new); ++ ++extern int lib_ring_buffer_get_subbuf(struct lib_ring_buffer *buf, ++ unsigned long consumed); ++extern void lib_ring_buffer_put_subbuf(struct lib_ring_buffer *buf); ++ ++/* ++ * lib_ring_buffer_get_next_subbuf/lib_ring_buffer_put_next_subbuf are helpers ++ * to read sub-buffers sequentially. ++ */ ++static inline int lib_ring_buffer_get_next_subbuf(struct lib_ring_buffer *buf) ++{ ++ int ret; ++ ++ ret = lib_ring_buffer_snapshot(buf, &buf->cons_snapshot, ++ &buf->prod_snapshot); ++ if (ret) ++ return ret; ++ ret = lib_ring_buffer_get_subbuf(buf, buf->cons_snapshot); ++ return ret; ++} ++ ++static inline void lib_ring_buffer_put_next_subbuf(struct lib_ring_buffer *buf) ++{ ++ lib_ring_buffer_put_subbuf(buf); ++ lib_ring_buffer_move_consumer(buf, subbuf_align(buf->cons_snapshot, ++ buf->backend.chan)); ++} ++ ++extern void channel_reset(struct channel *chan); ++extern void lib_ring_buffer_reset(struct lib_ring_buffer *buf); ++ ++static inline ++unsigned long lib_ring_buffer_get_offset(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return v_read(config, &buf->offset); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_consumed(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return atomic_long_read(&buf->consumed); ++} ++ ++/* ++ * Must call lib_ring_buffer_is_finalized before reading counters (memory ++ * ordering enforced with respect to trace teardown). ++ */ ++static inline ++int lib_ring_buffer_is_finalized(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ int finalized = ACCESS_ONCE(buf->finalized); ++ /* ++ * Read finalized before counters. ++ */ ++ smp_rmb(); ++ return finalized; ++} ++ ++static inline ++int lib_ring_buffer_channel_is_finalized(const struct channel *chan) ++{ ++ return chan->finalized; ++} ++ ++static inline ++int lib_ring_buffer_channel_is_disabled(const struct channel *chan) ++{ ++ return atomic_read(&chan->record_disabled); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_read_data_size( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return subbuffer_get_read_data_size(config, &buf->backend); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_records_count( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return v_read(config, &buf->records_count); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_records_overrun( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return v_read(config, &buf->records_overrun); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_records_lost_full( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return v_read(config, &buf->records_lost_full); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_records_lost_wrap( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return v_read(config, &buf->records_lost_wrap); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_records_lost_big( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return v_read(config, &buf->records_lost_big); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_records_read( ++ const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ return v_read(config, &buf->backend.records_read); ++} ++ ++#endif /* _LINUX_RING_BUFFER_FRONTEND_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/frontend_api.h b/drivers/staging/lttng/lib/ringbuffer/frontend_api.h +new file mode 100644 +index 0000000..391e593 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/frontend_api.h +@@ -0,0 +1,358 @@ ++#ifndef _LINUX_RING_BUFFER_FRONTEND_API_H ++#define _LINUX_RING_BUFFER_FRONTEND_API_H ++ ++/* ++ * linux/ringbuffer/frontend_api.h ++ * ++ * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring Buffer Library Synchronization Header (buffer write API). ++ * ++ * 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" ++#include <linux/errno.h> ++ ++/** ++ * lib_ring_buffer_get_cpu - Precedes ring buffer reserve/commit. ++ * ++ * Disables preemption (acts as a RCU read-side critical section) and keeps a ++ * ring buffer nesting count as supplementary safety net to ensure tracer client ++ * code will never trigger an endless recursion. Returns the processor ID on ++ * success, -EPERM on failure (nesting count too high). ++ * ++ * asm volatile and "memory" clobber prevent the compiler from moving ++ * instructions out of the ring buffer nesting count. This is required to ensure ++ * that probe side-effects which can cause recursion (e.g. unforeseen traps, ++ * divisions by 0, ...) are triggered within the incremented nesting count ++ * section. ++ */ ++static inline ++int lib_ring_buffer_get_cpu(const struct lib_ring_buffer_config *config) ++{ ++ int cpu, nesting; ++ ++ rcu_read_lock_sched_notrace(); ++ cpu = smp_processor_id(); ++ nesting = ++per_cpu(lib_ring_buffer_nesting, cpu); ++ barrier(); ++ ++ if (unlikely(nesting > 4)) { ++ WARN_ON_ONCE(1); ++ per_cpu(lib_ring_buffer_nesting, cpu)--; ++ rcu_read_unlock_sched_notrace(); ++ return -EPERM; ++ } else ++ return cpu; ++} ++ ++/** ++ * lib_ring_buffer_put_cpu - Follows ring buffer reserve/commit. ++ */ ++static inline ++void lib_ring_buffer_put_cpu(const struct lib_ring_buffer_config *config) ++{ ++ barrier(); ++ __get_cpu_var(lib_ring_buffer_nesting)--; ++ rcu_read_unlock_sched_notrace(); ++} ++ ++/* ++ * lib_ring_buffer_try_reserve is called by lib_ring_buffer_reserve(). It is not ++ * part of the API per se. ++ * ++ * returns 0 if reserve ok, or 1 if the slow path must be taken. ++ */ ++static inline ++int lib_ring_buffer_try_reserve(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_ctx *ctx, ++ unsigned long *o_begin, unsigned long *o_end, ++ unsigned long *o_old, size_t *before_hdr_pad) ++{ ++ struct channel *chan = ctx->chan; ++ struct lib_ring_buffer *buf = ctx->buf; ++ *o_begin = v_read(config, &buf->offset); ++ *o_old = *o_begin; ++ ++ ctx->tsc = lib_ring_buffer_clock_read(chan); ++ if ((int64_t) ctx->tsc == -EIO) ++ return 1; ++ ++ /* ++ * Prefetch cacheline for read because we have to read the previous ++ * commit counter to increment it and commit seq value to compare it to ++ * the commit counter. ++ */ ++ prefetch(&buf->commit_hot[subbuf_index(*o_begin, chan)]); ++ ++ if (last_tsc_overflow(config, buf, ctx->tsc)) ++ ctx->rflags |= RING_BUFFER_RFLAG_FULL_TSC; ++ ++ if (unlikely(subbuf_offset(*o_begin, chan) == 0)) ++ return 1; ++ ++ ctx->slot_size = record_header_size(config, chan, *o_begin, ++ before_hdr_pad, ctx); ++ ctx->slot_size += ++ lib_ring_buffer_align(*o_begin + ctx->slot_size, ++ ctx->largest_align) + ctx->data_size; ++ if (unlikely((subbuf_offset(*o_begin, chan) + ctx->slot_size) ++ > chan->backend.subbuf_size)) ++ return 1; ++ ++ /* ++ * Record fits in the current buffer and we are not on a switch ++ * boundary. It's safe to write. ++ */ ++ *o_end = *o_begin + ctx->slot_size; ++ ++ if (unlikely((subbuf_offset(*o_end, chan)) == 0)) ++ /* ++ * The offset_end will fall at the very beginning of the next ++ * subbuffer. ++ */ ++ return 1; ++ ++ return 0; ++} ++ ++/** ++ * lib_ring_buffer_reserve - Reserve space in a ring buffer. ++ * @config: ring buffer instance configuration. ++ * @ctx: ring buffer context. (input and output) Must be already initialized. ++ * ++ * Atomic wait-free slot reservation. The reserved space starts at the context ++ * "pre_offset". Its length is "slot_size". The associated time-stamp is "tsc". ++ * ++ * Return : ++ * 0 on success. ++ * -EAGAIN if channel is disabled. ++ * -ENOSPC if event size is too large for packet. ++ * -ENOBUFS if there is currently not enough space in buffer for the event. ++ * -EIO if data cannot be written into the buffer for any other reason. ++ */ ++ ++static inline ++int lib_ring_buffer_reserve(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_ctx *ctx) ++{ ++ struct channel *chan = ctx->chan; ++ struct lib_ring_buffer *buf; ++ unsigned long o_begin, o_end, o_old; ++ size_t before_hdr_pad = 0; ++ ++ if (atomic_read(&chan->record_disabled)) ++ return -EAGAIN; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ buf = per_cpu_ptr(chan->backend.buf, ctx->cpu); ++ else ++ buf = chan->backend.buf; ++ if (atomic_read(&buf->record_disabled)) ++ return -EAGAIN; ++ ctx->buf = buf; ++ ++ /* ++ * Perform retryable operations. ++ */ ++ if (unlikely(lib_ring_buffer_try_reserve(config, ctx, &o_begin, ++ &o_end, &o_old, &before_hdr_pad))) ++ goto slow_path; ++ ++ if (unlikely(v_cmpxchg(config, &ctx->buf->offset, o_old, o_end) ++ != o_old)) ++ goto slow_path; ++ ++ /* ++ * Atomically update last_tsc. This update races against concurrent ++ * atomic updates, but the race will always cause supplementary full TSC ++ * record headers, never the opposite (missing a full TSC record header ++ * when it would be needed). ++ */ ++ save_last_tsc(config, ctx->buf, ctx->tsc); ++ ++ /* ++ * Push the reader if necessary ++ */ ++ lib_ring_buffer_reserve_push_reader(ctx->buf, chan, o_end - 1); ++ ++ /* ++ * Clear noref flag for this subbuffer. ++ */ ++ lib_ring_buffer_clear_noref(config, &ctx->buf->backend, ++ subbuf_index(o_end - 1, chan)); ++ ++ ctx->pre_offset = o_begin; ++ ctx->buf_offset = o_begin + before_hdr_pad; ++ return 0; ++slow_path: ++ return lib_ring_buffer_reserve_slow(ctx); ++} ++ ++/** ++ * lib_ring_buffer_switch - Perform a sub-buffer switch for a per-cpu buffer. ++ * @config: ring buffer instance configuration. ++ * @buf: buffer ++ * @mode: buffer switch mode (SWITCH_ACTIVE or SWITCH_FLUSH) ++ * ++ * This operation is completely reentrant : can be called while tracing is ++ * active with absolutely no lock held. ++ * ++ * Note, however, that as a v_cmpxchg is used for some atomic operations and ++ * requires to be executed locally for per-CPU buffers, this function must be ++ * called from the CPU which owns the buffer for a ACTIVE flush, with preemption ++ * disabled, for RING_BUFFER_SYNC_PER_CPU configuration. ++ */ ++static inline ++void lib_ring_buffer_switch(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, enum switch_mode mode) ++{ ++ lib_ring_buffer_switch_slow(buf, mode); ++} ++ ++/* See ring_buffer_frontend_api.h for lib_ring_buffer_reserve(). */ ++ ++/** ++ * lib_ring_buffer_commit - Commit an record. ++ * @config: ring buffer instance configuration. ++ * @ctx: ring buffer context. (input arguments only) ++ * ++ * Atomic unordered slot commit. Increments the commit count in the ++ * specified sub-buffer, and delivers it if necessary. ++ */ ++static inline ++void lib_ring_buffer_commit(const struct lib_ring_buffer_config *config, ++ const struct lib_ring_buffer_ctx *ctx) ++{ ++ struct channel *chan = ctx->chan; ++ struct lib_ring_buffer *buf = ctx->buf; ++ unsigned long offset_end = ctx->buf_offset; ++ unsigned long endidx = subbuf_index(offset_end - 1, chan); ++ unsigned long commit_count; ++ ++ /* ++ * Must count record before incrementing the commit count. ++ */ ++ subbuffer_count_record(config, &buf->backend, endidx); ++ ++ /* ++ * Order all writes to buffer before the commit count update that will ++ * determine that the subbuffer is full. ++ */ ++ if (config->ipi == RING_BUFFER_IPI_BARRIER) { ++ /* ++ * Must write slot data before incrementing commit count. This ++ * compiler barrier is upgraded into a smp_mb() by the IPI sent ++ * by get_subbuf(). ++ */ ++ barrier(); ++ } else ++ smp_wmb(); ++ ++ v_add(config, ctx->slot_size, &buf->commit_hot[endidx].cc); ++ ++ /* ++ * commit count read can race with concurrent OOO commit count updates. ++ * This is only needed for lib_ring_buffer_check_deliver (for ++ * non-polling delivery only) and for ++ * lib_ring_buffer_write_commit_counter. The race can only cause the ++ * counter to be read with the same value more than once, which could ++ * cause : ++ * - Multiple delivery for the same sub-buffer (which is handled ++ * gracefully by the reader code) if the value is for a full ++ * sub-buffer. It's important that we can never miss a sub-buffer ++ * delivery. Re-reading the value after the v_add ensures this. ++ * - Reading a commit_count with a higher value that what was actually ++ * added to it for the lib_ring_buffer_write_commit_counter call ++ * (again caused by a concurrent committer). It does not matter, ++ * because this function is interested in the fact that the commit ++ * count reaches back the reserve offset for a specific sub-buffer, ++ * which is completely independent of the order. ++ */ ++ commit_count = v_read(config, &buf->commit_hot[endidx].cc); ++ ++ lib_ring_buffer_check_deliver(config, buf, chan, offset_end - 1, ++ commit_count, endidx); ++ /* ++ * Update used size at each commit. It's needed only for extracting ++ * ring_buffer buffers from vmcore, after crash. ++ */ ++ lib_ring_buffer_write_commit_counter(config, buf, chan, endidx, ++ ctx->buf_offset, commit_count, ++ ctx->slot_size); ++} ++ ++/** ++ * lib_ring_buffer_try_discard_reserve - Try discarding a record. ++ * @config: ring buffer instance configuration. ++ * @ctx: ring buffer context. (input arguments only) ++ * ++ * Only succeeds if no other record has been written after the record to ++ * discard. If discard fails, the record must be committed to the buffer. ++ * ++ * Returns 0 upon success, -EPERM if the record cannot be discarded. ++ */ ++static inline ++int lib_ring_buffer_try_discard_reserve(const struct lib_ring_buffer_config *config, ++ const struct lib_ring_buffer_ctx *ctx) ++{ ++ struct lib_ring_buffer *buf = ctx->buf; ++ unsigned long end_offset = ctx->pre_offset + ctx->slot_size; ++ ++ /* ++ * We need to ensure that if the cmpxchg succeeds and discards the ++ * record, the next record will record a full TSC, because it cannot ++ * rely on the last_tsc associated with the discarded record to detect ++ * overflows. The only way to ensure this is to set the last_tsc to 0 ++ * (assuming no 64-bit TSC overflow), which forces to write a 64-bit ++ * timestamp in the next record. ++ * ++ * Note: if discard fails, we must leave the TSC in the record header. ++ * It is needed to keep track of TSC overflows for the following ++ * records. ++ */ ++ save_last_tsc(config, buf, 0ULL); ++ ++ if (likely(v_cmpxchg(config, &buf->offset, end_offset, ctx->pre_offset) ++ != end_offset)) ++ return -EPERM; ++ else ++ return 0; ++} ++ ++static inline ++void channel_record_disable(const struct lib_ring_buffer_config *config, ++ struct channel *chan) ++{ ++ atomic_inc(&chan->record_disabled); ++} ++ ++static inline ++void channel_record_enable(const struct lib_ring_buffer_config *config, ++ struct channel *chan) ++{ ++ atomic_dec(&chan->record_disabled); ++} ++ ++static inline ++void lib_ring_buffer_record_disable(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ atomic_inc(&buf->record_disabled); ++} ++ ++static inline ++void lib_ring_buffer_record_enable(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf) ++{ ++ atomic_dec(&buf->record_disabled); ++} ++ ++#endif /* _LINUX_RING_BUFFER_FRONTEND_API_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/frontend_internal.h b/drivers/staging/lttng/lib/ringbuffer/frontend_internal.h +new file mode 100644 +index 0000000..3bd5721 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/frontend_internal.h +@@ -0,0 +1,424 @@ ++#ifndef _LINUX_RING_BUFFER_FRONTEND_INTERNAL_H ++#define _LINUX_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). ++ * ++ * 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" ++#include "../../wrapper/ringbuffer/backend_types.h" ++#include "../../wrapper/ringbuffer/frontend_types.h" ++#include "../../lib/prio_heap/lttng_prio_heap.h" /* For per-CPU read-side iterator */ ++ ++/* Buffer offset macros */ ++ ++/* buf_trunc mask selects only the buffer number. */ ++static inline ++unsigned long buf_trunc(unsigned long offset, struct channel *chan) ++{ ++ return offset & ~(chan->backend.buf_size - 1); ++ ++} ++ ++/* Select the buffer number value (counter). */ ++static inline ++unsigned long buf_trunc_val(unsigned long offset, struct channel *chan) ++{ ++ return buf_trunc(offset, chan) >> chan->backend.buf_size_order; ++} ++ ++/* buf_offset mask selects only the offset within the current buffer. */ ++static inline ++unsigned long buf_offset(unsigned long offset, struct channel *chan) ++{ ++ return offset & (chan->backend.buf_size - 1); ++} ++ ++/* subbuf_offset mask selects the offset within the current subbuffer. */ ++static inline ++unsigned long subbuf_offset(unsigned long offset, struct channel *chan) ++{ ++ return offset & (chan->backend.subbuf_size - 1); ++} ++ ++/* subbuf_trunc mask selects the subbuffer number. */ ++static inline ++unsigned long subbuf_trunc(unsigned long offset, struct channel *chan) ++{ ++ return offset & ~(chan->backend.subbuf_size - 1); ++} ++ ++/* subbuf_align aligns the offset to the next subbuffer. */ ++static inline ++unsigned long subbuf_align(unsigned long offset, struct channel *chan) ++{ ++ return (offset + chan->backend.subbuf_size) ++ & ~(chan->backend.subbuf_size - 1); ++} ++ ++/* subbuf_index returns the index of the current subbuffer within the buffer. */ ++static inline ++unsigned long subbuf_index(unsigned long offset, struct channel *chan) ++{ ++ return buf_offset(offset, chan) >> chan->backend.subbuf_size_order; ++} ++ ++/* ++ * Last TSC comparison functions. Check if the current TSC overflows tsc_bits ++ * bits from the last TSC read. When overflows are detected, the full 64-bit ++ * timestamp counter should be written in the record header. Reads and writes ++ * last_tsc atomically. ++ */ ++ ++#if (BITS_PER_LONG == 32) ++static inline ++void save_last_tsc(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, u64 tsc) ++{ ++ if (config->tsc_bits == 0 || config->tsc_bits == 64) ++ return; ++ ++ /* ++ * Ensure the compiler performs this update in a single instruction. ++ */ ++ v_set(config, &buf->last_tsc, (unsigned long)(tsc >> config->tsc_bits)); ++} ++ ++static inline ++int last_tsc_overflow(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, u64 tsc) ++{ ++ unsigned long tsc_shifted; ++ ++ if (config->tsc_bits == 0 || config->tsc_bits == 64) ++ return 0; ++ ++ tsc_shifted = (unsigned long)(tsc >> config->tsc_bits); ++ if (unlikely(tsc_shifted ++ - (unsigned long)v_read(config, &buf->last_tsc))) ++ return 1; ++ else ++ return 0; ++} ++#else ++static inline ++void save_last_tsc(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, u64 tsc) ++{ ++ if (config->tsc_bits == 0 || config->tsc_bits == 64) ++ return; ++ ++ v_set(config, &buf->last_tsc, (unsigned long)tsc); ++} ++ ++static inline ++int last_tsc_overflow(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, u64 tsc) ++{ ++ if (config->tsc_bits == 0 || config->tsc_bits == 64) ++ return 0; ++ ++ if (unlikely((tsc - v_read(config, &buf->last_tsc)) ++ >> config->tsc_bits)) ++ return 1; ++ else ++ return 0; ++} ++#endif ++ ++extern ++int lib_ring_buffer_reserve_slow(struct lib_ring_buffer_ctx *ctx); ++ ++extern ++void lib_ring_buffer_switch_slow(struct lib_ring_buffer *buf, ++ enum switch_mode mode); ++ ++/* Buffer write helpers */ ++ ++static inline ++void lib_ring_buffer_reserve_push_reader(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ unsigned long offset) ++{ ++ unsigned long consumed_old, consumed_new; ++ ++ do { ++ consumed_old = atomic_long_read(&buf->consumed); ++ /* ++ * If buffer is in overwrite mode, push the reader consumed ++ * count if the write position has reached it and we are not ++ * at the first iteration (don't push the reader farther than ++ * the writer). This operation can be done concurrently by many ++ * writers in the same buffer, the writer being at the farthest ++ * write position sub-buffer index in the buffer being the one ++ * which will win this loop. ++ */ ++ if (unlikely(subbuf_trunc(offset, chan) ++ - subbuf_trunc(consumed_old, chan) ++ >= chan->backend.buf_size)) ++ consumed_new = subbuf_align(consumed_old, chan); ++ else ++ return; ++ } while (unlikely(atomic_long_cmpxchg(&buf->consumed, consumed_old, ++ consumed_new) != consumed_old)); ++} ++ ++static inline ++void lib_ring_buffer_vmcore_check_deliver(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, ++ unsigned long commit_count, ++ unsigned long idx) ++{ ++ if (config->oops == RING_BUFFER_OOPS_CONSISTENCY) ++ v_set(config, &buf->commit_hot[idx].seq, commit_count); ++} ++ ++static inline ++int lib_ring_buffer_poll_deliver(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, ++ struct channel *chan) ++{ ++ unsigned long consumed_old, consumed_idx, commit_count, write_offset; ++ ++ consumed_old = atomic_long_read(&buf->consumed); ++ consumed_idx = subbuf_index(consumed_old, chan); ++ commit_count = v_read(config, &buf->commit_cold[consumed_idx].cc_sb); ++ /* ++ * No memory barrier here, since we are only interested ++ * in a statistically correct polling result. The next poll will ++ * get the data is we are racing. The mb() that ensures correct ++ * memory order is in get_subbuf. ++ */ ++ write_offset = v_read(config, &buf->offset); ++ ++ /* ++ * Check that the subbuffer we are trying to consume has been ++ * already fully committed. ++ */ ++ ++ if (((commit_count - chan->backend.subbuf_size) ++ & chan->commit_count_mask) ++ - (buf_trunc(consumed_old, chan) ++ >> chan->backend.num_subbuf_order) ++ != 0) ++ return 0; ++ ++ /* ++ * Check that we are not about to read the same subbuffer in ++ * which the writer head is. ++ */ ++ if (subbuf_trunc(write_offset, chan) - subbuf_trunc(consumed_old, chan) ++ == 0) ++ return 0; ++ ++ return 1; ++ ++} ++ ++static inline ++int lib_ring_buffer_pending_data(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, ++ struct channel *chan) ++{ ++ return !!subbuf_offset(v_read(config, &buf->offset), chan); ++} ++ ++static inline ++unsigned long lib_ring_buffer_get_data_size(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, ++ unsigned long idx) ++{ ++ return subbuffer_get_data_size(config, &buf->backend, idx); ++} ++ ++/* ++ * Check if all space reservation in a buffer have been committed. This helps ++ * knowing if an execution context is nested (for per-cpu buffers only). ++ * This is a very specific ftrace use-case, so we keep this as "internal" API. ++ */ ++static inline ++int lib_ring_buffer_reserve_committed(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, ++ struct channel *chan) ++{ ++ unsigned long offset, idx, commit_count; ++ ++ CHAN_WARN_ON(chan, config->alloc != RING_BUFFER_ALLOC_PER_CPU); ++ CHAN_WARN_ON(chan, config->sync != RING_BUFFER_SYNC_PER_CPU); ++ ++ /* ++ * Read offset and commit count in a loop so they are both read ++ * atomically wrt interrupts. By deal with interrupt concurrency by ++ * restarting both reads if the offset has been pushed. Note that given ++ * we only have to deal with interrupt concurrency here, an interrupt ++ * modifying the commit count will also modify "offset", so it is safe ++ * to only check for offset modifications. ++ */ ++ do { ++ offset = v_read(config, &buf->offset); ++ idx = subbuf_index(offset, chan); ++ commit_count = v_read(config, &buf->commit_hot[idx].cc); ++ } while (offset != v_read(config, &buf->offset)); ++ ++ return ((buf_trunc(offset, chan) >> chan->backend.num_subbuf_order) ++ - (commit_count & chan->commit_count_mask) == 0); ++} ++ ++static inline ++void lib_ring_buffer_check_deliver(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, ++ struct channel *chan, ++ unsigned long offset, ++ unsigned long commit_count, ++ unsigned long idx) ++{ ++ unsigned long old_commit_count = commit_count ++ - chan->backend.subbuf_size; ++ u64 tsc; ++ ++ /* Check if all commits have been done */ ++ if (unlikely((buf_trunc(offset, chan) >> chan->backend.num_subbuf_order) ++ - (old_commit_count & chan->commit_count_mask) == 0)) { ++ /* ++ * If we succeeded at updating cc_sb below, we are the subbuffer ++ * writer delivering the subbuffer. Deals with concurrent ++ * updates of the "cc" value without adding a add_return atomic ++ * operation to the fast path. ++ * ++ * We are doing the delivery in two steps: ++ * - First, we cmpxchg() cc_sb to the new value ++ * old_commit_count + 1. This ensures that we are the only ++ * subbuffer user successfully filling the subbuffer, but we ++ * do _not_ set the cc_sb value to "commit_count" yet. ++ * Therefore, other writers that would wrap around the ring ++ * buffer and try to start writing to our subbuffer would ++ * have to drop records, because it would appear as ++ * non-filled. ++ * We therefore have exclusive access to the subbuffer control ++ * structures. This mutual exclusion with other writers is ++ * crucially important to perform record overruns count in ++ * flight recorder mode locklessly. ++ * - When we are ready to release the subbuffer (either for ++ * reading or for overrun by other writers), we simply set the ++ * cc_sb value to "commit_count" and perform delivery. ++ * ++ * The subbuffer size is least 2 bytes (minimum size: 1 page). ++ * This guarantees that old_commit_count + 1 != commit_count. ++ */ ++ if (likely(v_cmpxchg(config, &buf->commit_cold[idx].cc_sb, ++ old_commit_count, old_commit_count + 1) ++ == old_commit_count)) { ++ /* ++ * Start of exclusive subbuffer access. We are ++ * guaranteed to be the last writer in this subbuffer ++ * and any other writer trying to access this subbuffer ++ * in this state is required to drop records. ++ */ ++ tsc = config->cb.ring_buffer_clock_read(chan); ++ v_add(config, ++ subbuffer_get_records_count(config, ++ &buf->backend, idx), ++ &buf->records_count); ++ v_add(config, ++ subbuffer_count_records_overrun(config, ++ &buf->backend, ++ idx), ++ &buf->records_overrun); ++ config->cb.buffer_end(buf, tsc, idx, ++ lib_ring_buffer_get_data_size(config, ++ buf, ++ idx)); ++ ++ /* ++ * Set noref flag and offset for this subbuffer id. ++ * Contains a memory barrier that ensures counter stores ++ * are ordered before set noref and offset. ++ */ ++ lib_ring_buffer_set_noref_offset(config, &buf->backend, idx, ++ buf_trunc_val(offset, chan)); ++ ++ /* ++ * Order set_noref and record counter updates before the ++ * end of subbuffer exclusive access. Orders with ++ * respect to writers coming into the subbuffer after ++ * wrap around, and also order wrt concurrent readers. ++ */ ++ smp_mb(); ++ /* End of exclusive subbuffer access */ ++ v_set(config, &buf->commit_cold[idx].cc_sb, ++ commit_count); ++ lib_ring_buffer_vmcore_check_deliver(config, buf, ++ commit_count, idx); ++ ++ /* ++ * RING_BUFFER_WAKEUP_BY_WRITER wakeup is not lock-free. ++ */ ++ if (config->wakeup == RING_BUFFER_WAKEUP_BY_WRITER ++ && atomic_long_read(&buf->active_readers) ++ && lib_ring_buffer_poll_deliver(config, buf, chan)) { ++ wake_up_interruptible(&buf->read_wait); ++ wake_up_interruptible(&chan->read_wait); ++ } ++ ++ } ++ } ++} ++ ++/* ++ * lib_ring_buffer_write_commit_counter ++ * ++ * For flight recording. must be called after commit. ++ * This function increments the subbuffer's commit_seq counter each time the ++ * commit count reaches back the reserve offset (modulo subbuffer size). It is ++ * useful for crash dump. ++ */ ++static inline ++void lib_ring_buffer_write_commit_counter(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer *buf, ++ struct channel *chan, ++ unsigned long idx, ++ unsigned long buf_offset, ++ unsigned long commit_count, ++ size_t slot_size) ++{ ++ unsigned long offset, commit_seq_old; ++ ++ if (config->oops != RING_BUFFER_OOPS_CONSISTENCY) ++ return; ++ ++ offset = buf_offset + slot_size; ++ ++ /* ++ * subbuf_offset includes commit_count_mask. We can simply ++ * compare the offsets within the subbuffer without caring about ++ * buffer full/empty mismatch because offset is never zero here ++ * (subbuffer header and record headers have non-zero length). ++ */ ++ if (unlikely(subbuf_offset(offset - commit_count, chan))) ++ return; ++ ++ commit_seq_old = v_read(config, &buf->commit_hot[idx].seq); ++ while ((long) (commit_seq_old - commit_count) < 0) ++ commit_seq_old = v_cmpxchg(config, &buf->commit_hot[idx].seq, ++ commit_seq_old, commit_count); ++} ++ ++extern int lib_ring_buffer_create(struct lib_ring_buffer *buf, ++ struct channel_backend *chanb, int cpu); ++extern void lib_ring_buffer_free(struct lib_ring_buffer *buf); ++ ++/* 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 */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/frontend_types.h b/drivers/staging/lttng/lib/ringbuffer/frontend_types.h +new file mode 100644 +index 0000000..5c7437f +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/frontend_types.h +@@ -0,0 +1,176 @@ ++#ifndef _LINUX_RING_BUFFER_FRONTEND_TYPES_H ++#define _LINUX_RING_BUFFER_FRONTEND_TYPES_H ++ ++/* ++ * linux/ringbuffer/frontend_types.h ++ * ++ * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring Buffer Library Synchronization Header (types). ++ * ++ * 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> ++#include "../../wrapper/ringbuffer/config.h" ++#include "../../wrapper/ringbuffer/backend_types.h" ++#include "../../wrapper/spinlock.h" ++#include "../../lib/prio_heap/lttng_prio_heap.h" /* For per-CPU read-side iterator */ ++ ++/* ++ * A switch is done during tracing or as a final flush after tracing (so it ++ * won't write in the new sub-buffer). ++ */ ++enum switch_mode { SWITCH_ACTIVE, SWITCH_FLUSH }; ++ ++/* channel-level read-side iterator */ ++struct channel_iter { ++ /* Prio heap of buffers. Lowest timestamps at the top. */ ++ struct lttng_ptr_heap heap; /* Heap of struct lib_ring_buffer ptrs */ ++ struct list_head empty_head; /* Empty buffers linked-list head */ ++ int read_open; /* Opened for reading ? */ ++ u64 last_qs; /* Last quiescent state timestamp */ ++ u64 last_timestamp; /* Last timestamp (for WARN_ON) */ ++ int last_cpu; /* Last timestamp cpu */ ++ /* ++ * read() file operation state. ++ */ ++ unsigned long len_left; ++}; ++ ++/* channel: collection of per-cpu ring buffers. */ ++struct channel { ++ atomic_t record_disabled; ++ unsigned long commit_count_mask; /* ++ * Commit count mask, removing ++ * the MSBs corresponding to ++ * bits used to represent the ++ * subbuffer index. ++ */ ++ ++ struct channel_backend backend; /* Associated backend */ ++ ++ unsigned long switch_timer_interval; /* Buffer flush (jiffies) */ ++ unsigned long read_timer_interval; /* Reader wakeup (jiffies) */ ++ struct notifier_block cpu_hp_notifier; /* CPU hotplug notifier */ ++ struct notifier_block tick_nohz_notifier; /* CPU nohz notifier */ ++ struct notifier_block hp_iter_notifier; /* hotplug iterator notifier */ ++ int cpu_hp_enable:1; /* Enable CPU hotplug notif. */ ++ int hp_iter_enable:1; /* Enable hp iter notif. */ ++ wait_queue_head_t read_wait; /* reader wait queue */ ++ wait_queue_head_t hp_wait; /* CPU hotplug wait queue */ ++ int finalized; /* Has channel been finalized */ ++ struct channel_iter iter; /* Channel read-side iterator */ ++ struct kref ref; /* Reference count */ ++}; ++ ++/* Per-subbuffer commit counters used on the hot path */ ++struct commit_counters_hot { ++ union v_atomic cc; /* Commit counter */ ++ union v_atomic seq; /* Consecutive commits */ ++}; ++ ++/* Per-subbuffer commit counters used only on cold paths */ ++struct commit_counters_cold { ++ union v_atomic cc_sb; /* Incremented _once_ at sb switch */ ++}; ++ ++/* Per-buffer read iterator */ ++struct lib_ring_buffer_iter { ++ u64 timestamp; /* Current record timestamp */ ++ size_t header_len; /* Current record header length */ ++ size_t payload_len; /* Current record payload length */ ++ ++ struct list_head empty_node; /* Linked list of empty buffers */ ++ unsigned long consumed, read_offset, data_size; ++ enum { ++ ITER_GET_SUBBUF = 0, ++ ITER_TEST_RECORD, ++ ITER_NEXT_RECORD, ++ ITER_PUT_SUBBUF, ++ } state; ++ int allocated:1; ++ int read_open:1; /* Opened for reading ? */ ++}; ++ ++/* ring buffer state */ ++struct lib_ring_buffer { ++ /* First 32 bytes cache-hot cacheline */ ++ union v_atomic offset; /* Current offset in the buffer */ ++ struct commit_counters_hot *commit_hot; ++ /* Commit count per sub-buffer */ ++ atomic_long_t consumed; /* ++ * Current offset in the buffer ++ * standard atomic access (shared) ++ */ ++ atomic_t record_disabled; ++ /* End of first 32 bytes cacheline */ ++ union v_atomic last_tsc; /* ++ * Last timestamp written in the buffer. ++ */ ++ ++ struct lib_ring_buffer_backend backend; /* Associated backend */ ++ ++ struct commit_counters_cold *commit_cold; ++ /* Commit count per sub-buffer */ ++ atomic_long_t active_readers; /* ++ * Active readers count ++ * standard atomic access (shared) ++ */ ++ /* Dropped records */ ++ union v_atomic records_lost_full; /* Buffer full */ ++ union v_atomic records_lost_wrap; /* Nested wrap-around */ ++ union v_atomic records_lost_big; /* Events too big */ ++ union v_atomic records_count; /* Number of records written */ ++ union v_atomic records_overrun; /* Number of overwritten records */ ++ wait_queue_head_t read_wait; /* reader buffer-level wait queue */ ++ wait_queue_head_t write_wait; /* writer buffer-level wait queue (for metadata only) */ ++ int finalized; /* buffer has been finalized */ ++ struct timer_list switch_timer; /* timer for periodical switch */ ++ struct timer_list read_timer; /* timer for read poll */ ++ raw_spinlock_t raw_tick_nohz_spinlock; /* nohz entry lock/trylock */ ++ struct lib_ring_buffer_iter iter; /* read-side iterator */ ++ unsigned long get_subbuf_consumed; /* Read-side consumed */ ++ unsigned long prod_snapshot; /* Producer count snapshot */ ++ unsigned long cons_snapshot; /* Consumer count snapshot */ ++ int get_subbuf:1; /* Sub-buffer being held by reader */ ++ int switch_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ ++ int read_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ ++}; ++ ++static inline ++void *channel_get_private(struct channel *chan) ++{ ++ return chan->backend.priv; ++} ++ ++/* ++ * Issue warnings and disable channels upon internal error. ++ * Can receive struct lib_ring_buffer or struct lib_ring_buffer_backend ++ * parameters. ++ */ ++#define CHAN_WARN_ON(c, cond) \ ++ ({ \ ++ struct channel *__chan; \ ++ int _____ret = unlikely(cond); \ ++ if (_____ret) { \ ++ if (__same_type(*(c), struct channel_backend)) \ ++ __chan = container_of((void *) (c), \ ++ struct channel, \ ++ backend); \ ++ else if (__same_type(*(c), struct channel)) \ ++ __chan = (void *) (c); \ ++ else \ ++ BUG_ON(1); \ ++ atomic_inc(&__chan->record_disabled); \ ++ WARN_ON(1); \ ++ } \ ++ _____ret; \ ++ }) ++ ++#endif /* _LINUX_RING_BUFFER_FRONTEND_TYPES_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/iterator.h b/drivers/staging/lttng/lib/ringbuffer/iterator.h +new file mode 100644 +index 0000000..f2bd50d +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/iterator.h +@@ -0,0 +1,70 @@ ++#ifndef _LINUX_RING_BUFFER_ITERATOR_H ++#define _LINUX_RING_BUFFER_ITERATOR_H ++ ++/* ++ * linux/ringbuffer/iterator.h ++ * ++ * (C) Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring buffer and channel iterators. ++ * ++ * Author: ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include "../../wrapper/ringbuffer/backend.h" ++#include "../../wrapper/ringbuffer/frontend.h" ++ ++/* ++ * lib_ring_buffer_get_next_record advances the buffer read position to the next ++ * record. It returns either the size of the next record, -EAGAIN if there is ++ * currently no data available, or -ENODATA if no data is available and buffer ++ * is finalized. ++ */ ++extern ssize_t lib_ring_buffer_get_next_record(struct channel *chan, ++ struct lib_ring_buffer *buf); ++ ++/* ++ * channel_get_next_record advances the buffer read position to the next record. ++ * It returns either the size of the next record, -EAGAIN if there is currently ++ * no data available, or -ENODATA if no data is available and buffer is ++ * finalized. ++ * Returns the current buffer in ret_buf. ++ */ ++extern ssize_t channel_get_next_record(struct channel *chan, ++ struct lib_ring_buffer **ret_buf); ++ ++/** ++ * read_current_record - copy the buffer current record into dest. ++ * @buf: ring buffer ++ * @dest: destination where the record should be copied ++ * ++ * dest should be large enough to contain the record. Returns the number of ++ * bytes copied. ++ */ ++static inline size_t read_current_record(struct lib_ring_buffer *buf, void *dest) ++{ ++ return lib_ring_buffer_read(&buf->backend, buf->iter.read_offset, ++ dest, buf->iter.payload_len); ++} ++ ++extern int lib_ring_buffer_iterator_open(struct lib_ring_buffer *buf); ++extern void lib_ring_buffer_iterator_release(struct lib_ring_buffer *buf); ++extern int channel_iterator_open(struct channel *chan); ++extern void channel_iterator_release(struct channel *chan); ++ ++extern const struct file_operations channel_payload_file_operations; ++extern const struct file_operations lib_ring_buffer_payload_file_operations; ++ ++/* ++ * Used internally. ++ */ ++int channel_iterator_init(struct channel *chan); ++void channel_iterator_unregister_notifiers(struct channel *chan); ++void channel_iterator_free(struct channel *chan); ++void channel_iterator_reset(struct channel *chan); ++void lib_ring_buffer_iterator_reset(struct lib_ring_buffer *buf); ++ ++#endif /* _LINUX_RING_BUFFER_ITERATOR_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/nohz.h b/drivers/staging/lttng/lib/ringbuffer/nohz.h +new file mode 100644 +index 0000000..3c31072 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/nohz.h +@@ -0,0 +1,30 @@ ++#ifndef _LINUX_RING_BUFFER_NOHZ_H ++#define _LINUX_RING_BUFFER_NOHZ_H ++ ++/* ++ * ringbuffer/nohz.h ++ * ++ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#ifdef CONFIG_LIB_RING_BUFFER ++void lib_ring_buffer_tick_nohz_flush(void); ++void lib_ring_buffer_tick_nohz_stop(void); ++void lib_ring_buffer_tick_nohz_restart(void); ++#else ++static inline void lib_ring_buffer_tick_nohz_flush(void) ++{ ++} ++ ++static inline void lib_ring_buffer_tick_nohz_stop(void) ++{ ++} ++ ++static inline void lib_ring_buffer_tick_nohz_restart(void) ++{ ++} ++#endif ++ ++#endif /* _LINUX_RING_BUFFER_NOHZ_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_backend.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_backend.c +new file mode 100644 +index 0000000..d1b5b8c +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_backend.c +@@ -0,0 +1,854 @@ ++/* ++ * ring_buffer_backend.c ++ * ++ * Copyright (C) 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/stddef.h> ++#include <linux/module.h> ++#include <linux/string.h> ++#include <linux/bitops.h> ++#include <linux/delay.h> ++#include <linux/errno.h> ++#include <linux/slab.h> ++#include <linux/cpu.h> ++#include <linux/mm.h> ++ ++#include "../../wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ ++#include "../../wrapper/ringbuffer/config.h" ++#include "../../wrapper/ringbuffer/backend.h" ++#include "../../wrapper/ringbuffer/frontend.h" ++ ++/** ++ * lib_ring_buffer_backend_allocate - allocate a channel buffer ++ * @config: ring buffer instance configuration ++ * @buf: the buffer struct ++ * @size: total size of the buffer ++ * @num_subbuf: number of subbuffers ++ * @extra_reader_sb: need extra subbuffer for reader ++ */ ++static ++int lib_ring_buffer_backend_allocate(const struct lib_ring_buffer_config *config, ++ struct lib_ring_buffer_backend *bufb, ++ size_t size, size_t num_subbuf, ++ int extra_reader_sb) ++{ ++ struct channel_backend *chanb = &bufb->chan->backend; ++ unsigned long j, num_pages, num_pages_per_subbuf, page_idx = 0; ++ unsigned long subbuf_size, mmap_offset = 0; ++ unsigned long num_subbuf_alloc; ++ struct page **pages; ++ void **virt; ++ unsigned long i; ++ ++ num_pages = size >> PAGE_SHIFT; ++ num_pages_per_subbuf = num_pages >> get_count_order(num_subbuf); ++ subbuf_size = chanb->subbuf_size; ++ num_subbuf_alloc = num_subbuf; ++ ++ if (extra_reader_sb) { ++ num_pages += num_pages_per_subbuf; /* Add pages for reader */ ++ num_subbuf_alloc++; ++ } ++ ++ pages = kmalloc_node(ALIGN(sizeof(*pages) * num_pages, ++ 1 << INTERNODE_CACHE_SHIFT), ++ GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); ++ if (unlikely(!pages)) ++ goto pages_error; ++ ++ virt = kmalloc_node(ALIGN(sizeof(*virt) * num_pages, ++ 1 << INTERNODE_CACHE_SHIFT), ++ GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); ++ if (unlikely(!virt)) ++ goto virt_error; ++ ++ bufb->array = kmalloc_node(ALIGN(sizeof(*bufb->array) ++ * num_subbuf_alloc, ++ 1 << INTERNODE_CACHE_SHIFT), ++ GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); ++ if (unlikely(!bufb->array)) ++ goto array_error; ++ ++ for (i = 0; i < num_pages; i++) { ++ pages[i] = alloc_pages_node(cpu_to_node(max(bufb->cpu, 0)), ++ GFP_KERNEL | __GFP_ZERO, 0); ++ if (unlikely(!pages[i])) ++ goto depopulate; ++ virt[i] = page_address(pages[i]); ++ } ++ bufb->num_pages_per_subbuf = num_pages_per_subbuf; ++ ++ /* Allocate backend pages array elements */ ++ for (i = 0; i < num_subbuf_alloc; i++) { ++ bufb->array[i] = ++ kzalloc_node(ALIGN( ++ sizeof(struct lib_ring_buffer_backend_pages) + ++ sizeof(struct lib_ring_buffer_backend_page) ++ * num_pages_per_subbuf, ++ 1 << INTERNODE_CACHE_SHIFT), ++ GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); ++ if (!bufb->array[i]) ++ goto free_array; ++ } ++ ++ /* Allocate write-side subbuffer table */ ++ bufb->buf_wsb = kzalloc_node(ALIGN( ++ sizeof(struct lib_ring_buffer_backend_subbuffer) ++ * num_subbuf, ++ 1 << INTERNODE_CACHE_SHIFT), ++ GFP_KERNEL, cpu_to_node(max(bufb->cpu, 0))); ++ if (unlikely(!bufb->buf_wsb)) ++ goto free_array; ++ ++ for (i = 0; i < num_subbuf; i++) ++ bufb->buf_wsb[i].id = subbuffer_id(config, 0, 1, i); ++ ++ /* Assign read-side subbuffer table */ ++ if (extra_reader_sb) ++ bufb->buf_rsb.id = subbuffer_id(config, 0, 1, ++ num_subbuf_alloc - 1); ++ else ++ bufb->buf_rsb.id = subbuffer_id(config, 0, 1, 0); ++ ++ /* Assign pages to page index */ ++ for (i = 0; i < num_subbuf_alloc; i++) { ++ for (j = 0; j < num_pages_per_subbuf; j++) { ++ CHAN_WARN_ON(chanb, page_idx > num_pages); ++ bufb->array[i]->p[j].virt = virt[page_idx]; ++ bufb->array[i]->p[j].page = pages[page_idx]; ++ page_idx++; ++ } ++ if (config->output == RING_BUFFER_MMAP) { ++ bufb->array[i]->mmap_offset = mmap_offset; ++ mmap_offset += subbuf_size; ++ } ++ } ++ ++ /* ++ * If kmalloc ever uses vmalloc underneath, make sure the buffer pages ++ * will not fault. ++ */ ++ wrapper_vmalloc_sync_all(); ++ kfree(virt); ++ kfree(pages); ++ return 0; ++ ++free_array: ++ for (i = 0; (i < num_subbuf_alloc && bufb->array[i]); i++) ++ kfree(bufb->array[i]); ++depopulate: ++ /* Free all allocated pages */ ++ for (i = 0; (i < num_pages && pages[i]); i++) ++ __free_page(pages[i]); ++ kfree(bufb->array); ++array_error: ++ kfree(virt); ++virt_error: ++ kfree(pages); ++pages_error: ++ return -ENOMEM; ++} ++ ++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; ++ ++ bufb->chan = container_of(chanb, struct channel, backend); ++ bufb->cpu = cpu; ++ ++ return lib_ring_buffer_backend_allocate(config, bufb, chanb->buf_size, ++ chanb->num_subbuf, ++ chanb->extra_reader_sb); ++} ++ ++void lib_ring_buffer_backend_free(struct lib_ring_buffer_backend *bufb) ++{ ++ struct channel_backend *chanb = &bufb->chan->backend; ++ unsigned long i, j, num_subbuf_alloc; ++ ++ num_subbuf_alloc = chanb->num_subbuf; ++ if (chanb->extra_reader_sb) ++ num_subbuf_alloc++; ++ ++ kfree(bufb->buf_wsb); ++ for (i = 0; i < num_subbuf_alloc; i++) { ++ for (j = 0; j < bufb->num_pages_per_subbuf; j++) ++ __free_page(bufb->array[i]->p[j].page); ++ kfree(bufb->array[i]); ++ } ++ kfree(bufb->array); ++ bufb->allocated = 0; ++} ++ ++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; ++ unsigned long num_subbuf_alloc; ++ unsigned int i; ++ ++ num_subbuf_alloc = chanb->num_subbuf; ++ if (chanb->extra_reader_sb) ++ num_subbuf_alloc++; ++ ++ for (i = 0; i < chanb->num_subbuf; i++) ++ bufb->buf_wsb[i].id = subbuffer_id(config, 0, 1, i); ++ if (chanb->extra_reader_sb) ++ bufb->buf_rsb.id = subbuffer_id(config, 0, 1, ++ num_subbuf_alloc - 1); ++ else ++ bufb->buf_rsb.id = subbuffer_id(config, 0, 1, 0); ++ ++ for (i = 0; i < num_subbuf_alloc; i++) { ++ /* Don't reset mmap_offset */ ++ v_set(config, &bufb->array[i]->records_commit, 0); ++ v_set(config, &bufb->array[i]->records_unread, 0); ++ bufb->array[i]->data_size = 0; ++ /* Don't reset backend page and virt addresses */ ++ } ++ /* Don't reset num_pages_per_subbuf, cpu, allocated */ ++ v_set(config, &bufb->records_read, 0); ++} ++ ++/* ++ * The frontend is responsible for also calling ring_buffer_backend_reset for ++ * each buffer when calling channel_backend_reset. ++ */ ++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; ++ ++ /* ++ * Don't reset buf_size, subbuf_size, subbuf_size_order, ++ * num_subbuf_order, buf_size_order, extra_reader_sb, num_subbuf, ++ * priv, notifiers, config, cpumask and name. ++ */ ++ chanb->start_tsc = config->cb.ring_buffer_clock_read(chan); ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++/** ++ * lib_ring_buffer_cpu_hp_callback - CPU hotplug callback ++ * @nb: notifier block ++ * @action: hotplug action to take ++ * @hcpu: CPU number ++ * ++ * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD) ++ */ ++static ++int __cpuinit lib_ring_buffer_cpu_hp_callback(struct notifier_block *nb, ++ unsigned long action, ++ void *hcpu) ++{ ++ 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; ++ struct lib_ring_buffer *buf; ++ int ret; ++ ++ CHAN_WARN_ON(chanb, config->alloc == RING_BUFFER_ALLOC_GLOBAL); ++ ++ switch (action) { ++ case CPU_UP_PREPARE: ++ case CPU_UP_PREPARE_FROZEN: ++ buf = per_cpu_ptr(chanb->buf, cpu); ++ ret = lib_ring_buffer_create(buf, chanb, cpu); ++ if (ret) { ++ printk(KERN_ERR ++ "ring_buffer_cpu_hp_callback: cpu %d " ++ "buffer creation failed\n", cpu); ++ return NOTIFY_BAD; ++ } ++ break; ++ case CPU_DEAD: ++ case CPU_DEAD_FROZEN: ++ /* No need to do a buffer switch here, because it will happen ++ * when tracing is stopped, or will be done by switch timer CPU ++ * DEAD callback. */ ++ break; ++ } ++ return NOTIFY_OK; ++} ++#endif ++ ++/** ++ * channel_backend_init - initialize a channel backend ++ * @chanb: channel backend ++ * @name: channel name ++ * @config: client ring buffer configuration ++ * @priv: client private data ++ * @parent: dentry of parent directory, %NULL for root directory ++ * @subbuf_size: size of sub-buffers (> PAGE_SIZE, power of 2) ++ * @num_subbuf: number of sub-buffers (power of 2) ++ * ++ * Returns channel pointer if successful, %NULL otherwise. ++ * ++ * Creates per-cpu channel buffers using the sizes and attributes ++ * specified. The created channel buffer files will be named ++ * name_0...name_N-1. File permissions will be %S_IRUSR. ++ * ++ * Called with CPU hotplug disabled. ++ */ ++int channel_backend_init(struct channel_backend *chanb, ++ const char *name, ++ const struct lib_ring_buffer_config *config, ++ void *priv, size_t subbuf_size, size_t num_subbuf) ++{ ++ struct channel *chan = container_of(chanb, struct channel, backend); ++ unsigned int i; ++ int ret; ++ ++ 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. ++ */ ++ CHAN_WARN_ON(chanb, hweight32(subbuf_size) != 1); ++ CHAN_WARN_ON(chanb, hweight32(num_subbuf) != 1); ++ ++ ret = subbuffer_id_check_index(config, num_subbuf); ++ if (ret) ++ return ret; ++ ++ chanb->priv = priv; ++ chanb->buf_size = num_subbuf * subbuf_size; ++ chanb->subbuf_size = subbuf_size; ++ chanb->buf_size_order = get_count_order(chanb->buf_size); ++ chanb->subbuf_size_order = get_count_order(subbuf_size); ++ chanb->num_subbuf_order = get_count_order(num_subbuf); ++ chanb->extra_reader_sb = ++ (config->mode == RING_BUFFER_OVERWRITE) ? 1 : 0; ++ chanb->num_subbuf = num_subbuf; ++ strlcpy(chanb->name, name, NAME_MAX); ++ chanb->config = config; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ if (!zalloc_cpumask_var(&chanb->cpumask, GFP_KERNEL)) ++ return -ENOMEM; ++ } ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ /* Allocating the buffer per-cpu structures */ ++ chanb->buf = alloc_percpu(struct lib_ring_buffer); ++ if (!chanb->buf) ++ goto free_cpumask; ++ ++ /* ++ * In case of non-hotplug cpu, if the ring-buffer is allocated ++ * in early initcall, it will not be notified of secondary cpus. ++ * In that off case, we need to allocate for all possible cpus. ++ */ ++#ifdef CONFIG_HOTPLUG_CPU ++ /* ++ * buf->backend.allocated test takes care of concurrent CPU ++ * hotplug. ++ * Priority higher than frontend, so we create the ring buffer ++ * before we start the timer. ++ */ ++ chanb->cpu_hp_notifier.notifier_call = ++ lib_ring_buffer_cpu_hp_callback; ++ chanb->cpu_hp_notifier.priority = 5; ++ register_hotcpu_notifier(&chanb->cpu_hp_notifier); ++ ++ get_online_cpus(); ++ for_each_online_cpu(i) { ++ ret = lib_ring_buffer_create(per_cpu_ptr(chanb->buf, i), ++ chanb, i); ++ if (ret) ++ goto free_bufs; /* cpu hotplug locked */ ++ } ++ put_online_cpus(); ++#else ++ for_each_possible_cpu(i) { ++ ret = lib_ring_buffer_create(per_cpu_ptr(chanb->buf, i), ++ chanb, i); ++ if (ret) ++ goto free_bufs; /* cpu hotplug locked */ ++ } ++#endif ++ } else { ++ chanb->buf = kzalloc(sizeof(struct lib_ring_buffer), GFP_KERNEL); ++ if (!chanb->buf) ++ goto free_cpumask; ++ ret = lib_ring_buffer_create(chanb->buf, chanb, -1); ++ if (ret) ++ goto free_bufs; ++ } ++ chanb->start_tsc = config->cb.ring_buffer_clock_read(chan); ++ ++ return 0; ++ ++free_bufs: ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ for_each_possible_cpu(i) { ++ struct lib_ring_buffer *buf = per_cpu_ptr(chanb->buf, i); ++ ++ if (!buf->backend.allocated) ++ continue; ++ lib_ring_buffer_free(buf); ++ } ++#ifdef CONFIG_HOTPLUG_CPU ++ put_online_cpus(); ++#endif ++ free_percpu(chanb->buf); ++ } else ++ kfree(chanb->buf); ++free_cpumask: ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ free_cpumask_var(chanb->cpumask); ++ return -ENOMEM; ++} ++ ++/** ++ * channel_backend_unregister_notifiers - unregister notifiers ++ * @chan: the channel ++ * ++ * Holds CPU hotplug. ++ */ ++void channel_backend_unregister_notifiers(struct channel_backend *chanb) ++{ ++ const struct lib_ring_buffer_config *config = chanb->config; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ unregister_hotcpu_notifier(&chanb->cpu_hp_notifier); ++} ++ ++/** ++ * channel_backend_free - destroy the channel ++ * @chan: the channel ++ * ++ * Destroy all channel buffers and frees the channel. ++ */ ++void channel_backend_free(struct channel_backend *chanb) ++{ ++ const struct lib_ring_buffer_config *config = chanb->config; ++ unsigned int i; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ for_each_possible_cpu(i) { ++ struct lib_ring_buffer *buf = per_cpu_ptr(chanb->buf, i); ++ ++ if (!buf->backend.allocated) ++ continue; ++ lib_ring_buffer_free(buf); ++ } ++ free_cpumask_var(chanb->cpumask); ++ free_percpu(chanb->buf); ++ } else { ++ struct lib_ring_buffer *buf = chanb->buf; ++ ++ CHAN_WARN_ON(chanb, !buf->backend.allocated); ++ lib_ring_buffer_free(buf); ++ kfree(buf); ++ } ++} ++ ++/** ++ * lib_ring_buffer_write - write data to a ring_buffer buffer. ++ * @bufb : buffer backend ++ * @offset : offset within the buffer ++ * @src : source address ++ * @len : length to write ++ * @pagecpy : page size copied so far ++ */ ++void _lib_ring_buffer_write(struct lib_ring_buffer_backend *bufb, size_t offset, ++ 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; ++ size_t sbidx, index; ++ struct lib_ring_buffer_backend_pages *rpages; ++ unsigned long sb_bindex, id; ++ ++ do { ++ len -= pagecpy; ++ src += pagecpy; ++ offset += pagecpy; ++ sbidx = offset >> chanb->subbuf_size_order; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ ++ /* ++ * Underlying layer should never ask for writes across ++ * subbuffers. ++ */ ++ CHAN_WARN_ON(chanb, offset >= chanb->buf_size); ++ ++ pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); ++ id = bufb->buf_wsb[sbidx].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ lib_ring_buffer_do_copy(config, ++ rpages->p[index].virt ++ + (offset & ~PAGE_MASK), ++ src, pagecpy); ++ } while (unlikely(len != pagecpy)); ++} ++EXPORT_SYMBOL_GPL(_lib_ring_buffer_write); ++ ++ ++/** ++ * lib_ring_buffer_memset - write len bytes of c to a ring_buffer buffer. ++ * @bufb : buffer backend ++ * @offset : offset within the buffer ++ * @c : the byte to write ++ * @len : length to write ++ * @pagecpy : page size copied so far ++ */ ++void _lib_ring_buffer_memset(struct lib_ring_buffer_backend *bufb, ++ size_t offset, ++ int c, size_t len, ssize_t pagecpy) ++{ ++ struct channel_backend *chanb = &bufb->chan->backend; ++ 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; ++ ++ do { ++ len -= pagecpy; ++ offset += pagecpy; ++ sbidx = offset >> chanb->subbuf_size_order; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ ++ /* ++ * Underlying layer should never ask for writes across ++ * subbuffers. ++ */ ++ CHAN_WARN_ON(chanb, offset >= chanb->buf_size); ++ ++ pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); ++ id = bufb->buf_wsb[sbidx].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ lib_ring_buffer_do_memset(rpages->p[index].virt ++ + (offset & ~PAGE_MASK), ++ c, pagecpy); ++ } while (unlikely(len != pagecpy)); ++} ++EXPORT_SYMBOL_GPL(_lib_ring_buffer_memset); ++ ++ ++/** ++ * lib_ring_buffer_copy_from_user - write user data to a ring_buffer buffer. ++ * @bufb : buffer backend ++ * @offset : offset within the buffer ++ * @src : source address ++ * @len : length to write ++ * @pagecpy : page size copied so far ++ * ++ * This function deals with userspace pointers, it should never be called ++ * directly without having the src pointer checked with access_ok() ++ * previously. ++ */ ++void _lib_ring_buffer_copy_from_user(struct lib_ring_buffer_backend *bufb, ++ size_t offset, ++ const void __user *src, size_t len, ++ ssize_t pagecpy) ++{ ++ struct channel_backend *chanb = &bufb->chan->backend; ++ 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; ++ int ret; ++ ++ do { ++ len -= pagecpy; ++ src += pagecpy; ++ offset += pagecpy; ++ sbidx = offset >> chanb->subbuf_size_order; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ ++ /* ++ * Underlying layer should never ask for writes across ++ * subbuffers. ++ */ ++ CHAN_WARN_ON(chanb, offset >= chanb->buf_size); ++ ++ pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); ++ id = bufb->buf_wsb[sbidx].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ ret = lib_ring_buffer_do_copy_from_user(rpages->p[index].virt ++ + (offset & ~PAGE_MASK), ++ src, pagecpy) != 0; ++ if (ret > 0) { ++ offset += (pagecpy - ret); ++ len -= (pagecpy - ret); ++ _lib_ring_buffer_memset(bufb, offset, 0, len, 0); ++ break; /* stop copy */ ++ } ++ } while (unlikely(len != pagecpy)); ++} ++EXPORT_SYMBOL_GPL(_lib_ring_buffer_copy_from_user); ++ ++/** ++ * lib_ring_buffer_read - read data from ring_buffer_buffer. ++ * @bufb : buffer backend ++ * @offset : offset within the buffer ++ * @dest : destination address ++ * @len : length to copy to destination ++ * ++ * Should be protected by get_subbuf/put_subbuf. ++ * Returns the length copied. ++ */ ++size_t lib_ring_buffer_read(struct lib_ring_buffer_backend *bufb, size_t offset, ++ void *dest, size_t len) ++{ ++ struct channel_backend *chanb = &bufb->chan->backend; ++ const struct lib_ring_buffer_config *config = chanb->config; ++ size_t index; ++ ssize_t pagecpy, orig_len; ++ struct lib_ring_buffer_backend_pages *rpages; ++ unsigned long sb_bindex, id; ++ ++ orig_len = len; ++ offset &= chanb->buf_size - 1; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ if (unlikely(!len)) ++ return 0; ++ for (;;) { ++ pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); ++ id = bufb->buf_rsb.id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ memcpy(dest, rpages->p[index].virt + (offset & ~PAGE_MASK), ++ pagecpy); ++ len -= pagecpy; ++ if (likely(!len)) ++ break; ++ dest += pagecpy; ++ offset += pagecpy; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ /* ++ * Underlying layer should never ask for reads across ++ * subbuffers. ++ */ ++ CHAN_WARN_ON(chanb, offset >= chanb->buf_size); ++ } ++ return orig_len; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_read); ++ ++/** ++ * __lib_ring_buffer_copy_to_user - read data from ring_buffer to userspace ++ * @bufb : buffer backend ++ * @offset : offset within the buffer ++ * @dest : destination userspace address ++ * @len : length to copy to destination ++ * ++ * Should be protected by get_subbuf/put_subbuf. ++ * access_ok() must have been performed on dest addresses prior to call this ++ * function. ++ * Returns -EFAULT on error, 0 if ok. ++ */ ++int __lib_ring_buffer_copy_to_user(struct lib_ring_buffer_backend *bufb, ++ 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; ++ size_t index; ++ ssize_t pagecpy; ++ struct lib_ring_buffer_backend_pages *rpages; ++ unsigned long sb_bindex, id; ++ ++ offset &= chanb->buf_size - 1; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ if (unlikely(!len)) ++ return 0; ++ for (;;) { ++ pagecpy = min_t(size_t, len, PAGE_SIZE - (offset & ~PAGE_MASK)); ++ id = bufb->buf_rsb.id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ if (__copy_to_user(dest, ++ rpages->p[index].virt + (offset & ~PAGE_MASK), ++ pagecpy)) ++ return -EFAULT; ++ len -= pagecpy; ++ if (likely(!len)) ++ break; ++ dest += pagecpy; ++ offset += pagecpy; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ /* ++ * Underlying layer should never ask for reads across ++ * subbuffers. ++ */ ++ CHAN_WARN_ON(chanb, offset >= chanb->buf_size); ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(__lib_ring_buffer_copy_to_user); ++ ++/** ++ * lib_ring_buffer_read_cstr - read a C-style string from ring_buffer. ++ * @bufb : buffer backend ++ * @offset : offset within the buffer ++ * @dest : destination address ++ * @len : destination's length ++ * ++ * return string's length ++ * Should be protected by get_subbuf/put_subbuf. ++ */ ++int lib_ring_buffer_read_cstr(struct lib_ring_buffer_backend *bufb, size_t offset, ++ void *dest, size_t len) ++{ ++ struct channel_backend *chanb = &bufb->chan->backend; ++ const struct lib_ring_buffer_config *config = chanb->config; ++ size_t index; ++ ssize_t pagecpy, pagelen, strpagelen, orig_offset; ++ char *str; ++ struct lib_ring_buffer_backend_pages *rpages; ++ unsigned long sb_bindex, id; ++ ++ offset &= chanb->buf_size - 1; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ orig_offset = offset; ++ for (;;) { ++ id = bufb->buf_rsb.id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ str = (char *)rpages->p[index].virt + (offset & ~PAGE_MASK); ++ pagelen = PAGE_SIZE - (offset & ~PAGE_MASK); ++ strpagelen = strnlen(str, pagelen); ++ if (len) { ++ pagecpy = min_t(size_t, len, strpagelen); ++ if (dest) { ++ memcpy(dest, str, pagecpy); ++ dest += pagecpy; ++ } ++ len -= pagecpy; ++ } ++ offset += strpagelen; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ if (strpagelen < pagelen) ++ break; ++ /* ++ * Underlying layer should never ask for reads across ++ * subbuffers. ++ */ ++ CHAN_WARN_ON(chanb, offset >= chanb->buf_size); ++ } ++ if (dest && len) ++ ((char *)dest)[0] = 0; ++ return offset - orig_offset; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_read_cstr); ++ ++/** ++ * lib_ring_buffer_read_get_page - Get a whole page to read from ++ * @bufb : buffer backend ++ * @offset : offset within the buffer ++ * @virt : pointer to page address (output) ++ * ++ * Should be protected by get_subbuf/put_subbuf. ++ * Returns the pointer to the page struct pointer. ++ */ ++struct page **lib_ring_buffer_read_get_page(struct lib_ring_buffer_backend *bufb, ++ size_t offset, void ***virt) ++{ ++ 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; ++ unsigned long sb_bindex, id; ++ ++ offset &= chanb->buf_size - 1; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ id = bufb->buf_rsb.id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ *virt = &rpages->p[index].virt; ++ return &rpages->p[index].page; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_read_get_page); ++ ++/** ++ * lib_ring_buffer_read_offset_address - get address of a buffer location ++ * @bufb : buffer backend ++ * @offset : offset within the buffer. ++ * ++ * Return the address where a given offset is located (for read). ++ * Should be used to get the current subbuffer header pointer. Given we know ++ * it's never on a page boundary, it's safe to write directly to this address, ++ * as long as the write is never bigger than a page size. ++ */ ++void *lib_ring_buffer_read_offset_address(struct lib_ring_buffer_backend *bufb, ++ size_t offset) ++{ ++ 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; ++ unsigned long sb_bindex, id; ++ ++ offset &= chanb->buf_size - 1; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ id = bufb->buf_rsb.id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ return rpages->p[index].virt + (offset & ~PAGE_MASK); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_read_offset_address); ++ ++/** ++ * lib_ring_buffer_offset_address - get address of a location within the buffer ++ * @bufb : buffer backend ++ * @offset : offset within the buffer. ++ * ++ * Return the address where a given offset is located. ++ * Should be used to get the current subbuffer header pointer. Given we know ++ * it's always at the beginning of a page, it's safe to write directly to this ++ * address, as long as the write is never bigger than a page size. ++ */ ++void *lib_ring_buffer_offset_address(struct lib_ring_buffer_backend *bufb, ++ size_t offset) ++{ ++ 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; ++ unsigned long sb_bindex, id; ++ ++ offset &= chanb->buf_size - 1; ++ sbidx = offset >> chanb->subbuf_size_order; ++ index = (offset & (chanb->subbuf_size - 1)) >> PAGE_SHIFT; ++ id = bufb->buf_wsb[sbidx].id; ++ sb_bindex = subbuffer_id_get_index(config, id); ++ rpages = bufb->array[sb_bindex]; ++ CHAN_WARN_ON(chanb, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, id)); ++ return rpages->p[index].virt + (offset & ~PAGE_MASK); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_offset_address); +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +new file mode 100644 +index 0000000..802f5cd +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +@@ -0,0 +1,1721 @@ ++/* ++ * ring_buffer_frontend.c ++ * ++ * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Ring buffer wait-free buffer synchronization. Producer-consumer and flight ++ * recorder (overwrite) modes. See thesis: ++ * ++ * Desnoyers, Mathieu (2009), "Low-Impact Operating System Tracing", Ph.D. ++ * dissertation, Ecole Polytechnique de Montreal. ++ * http://www.lttng.org/pub/thesis/desnoyers-dissertation-2009-12.pdf ++ * ++ * - Algorithm presentation in Chapter 5: ++ * "Lockless Multi-Core High-Throughput Buffering". ++ * - Algorithm formal verification in Section 8.6: ++ * "Formal verification of LTTng" ++ * ++ * Author: ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Inspired from LTT and RelayFS: ++ * Karim Yaghmour <karim@opersys.com> ++ * Tom Zanussi <zanussi@us.ibm.com> ++ * Bob Wisniewski <bob@watson.ibm.com> ++ * And from K42 : ++ * Bob Wisniewski <bob@watson.ibm.com> ++ * ++ * Buffer reader semantic : ++ * ++ * - get_subbuf_size ++ * while buffer is not finalized and empty ++ * - get_subbuf ++ * - if return value != 0, continue ++ * - 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> ++#include <linux/module.h> ++#include <linux/percpu.h> ++ ++#include "../../wrapper/ringbuffer/config.h" ++#include "../../wrapper/ringbuffer/backend.h" ++#include "../../wrapper/ringbuffer/frontend.h" ++#include "../../wrapper/ringbuffer/iterator.h" ++#include "../../wrapper/ringbuffer/nohz.h" ++ ++/* ++ * Internal structure representing offsets to use at a sub-buffer switch. ++ */ ++struct switch_offsets { ++ unsigned long begin, end, old; ++ size_t pre_header_padding, size; ++ unsigned int switch_new_start:1, switch_new_end:1, switch_old_start:1, ++ switch_old_end:1; ++}; ++ ++#ifdef CONFIG_NO_HZ ++enum tick_nohz_val { ++ TICK_NOHZ_STOP, ++ TICK_NOHZ_FLUSH, ++ TICK_NOHZ_RESTART, ++}; ++ ++static ATOMIC_NOTIFIER_HEAD(tick_nohz_notifier); ++#endif /* CONFIG_NO_HZ */ ++ ++static DEFINE_PER_CPU(spinlock_t, ring_buffer_nohz_lock); ++ ++DEFINE_PER_CPU(unsigned int, lib_ring_buffer_nesting); ++EXPORT_PER_CPU_SYMBOL(lib_ring_buffer_nesting); ++ ++static ++void lib_ring_buffer_print_errors(struct channel *chan, ++ struct lib_ring_buffer *buf, int cpu); ++ ++/* ++ * Must be called under cpu hotplug protection. ++ */ ++void lib_ring_buffer_free(struct lib_ring_buffer *buf) ++{ ++ struct channel *chan = buf->backend.chan; ++ ++ lib_ring_buffer_print_errors(chan, buf, buf->backend.cpu); ++ kfree(buf->commit_hot); ++ kfree(buf->commit_cold); ++ ++ lib_ring_buffer_backend_free(&buf->backend); ++} ++ ++/** ++ * lib_ring_buffer_reset - Reset ring buffer to initial values. ++ * @buf: Ring buffer. ++ * ++ * Effectively empty the ring buffer. Should be called when the buffer is not ++ * used for writing. The ring buffer can be opened for reading, but the reader ++ * should not be using the iterator concurrently with reset. The previous ++ * current iterator record is reset. ++ */ ++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; ++ unsigned int i; ++ ++ /* ++ * Reset iterator first. It will put the subbuffer if it currently holds ++ * it. ++ */ ++ lib_ring_buffer_iterator_reset(buf); ++ v_set(config, &buf->offset, 0); ++ for (i = 0; i < chan->backend.num_subbuf; i++) { ++ v_set(config, &buf->commit_hot[i].cc, 0); ++ v_set(config, &buf->commit_hot[i].seq, 0); ++ v_set(config, &buf->commit_cold[i].cc_sb, 0); ++ } ++ atomic_long_set(&buf->consumed, 0); ++ atomic_set(&buf->record_disabled, 0); ++ v_set(config, &buf->last_tsc, 0); ++ lib_ring_buffer_backend_reset(&buf->backend); ++ /* Don't reset number of active readers */ ++ v_set(config, &buf->records_lost_full, 0); ++ v_set(config, &buf->records_lost_wrap, 0); ++ v_set(config, &buf->records_lost_big, 0); ++ v_set(config, &buf->records_count, 0); ++ v_set(config, &buf->records_overrun, 0); ++ buf->finalized = 0; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_reset); ++ ++/** ++ * channel_reset - Reset channel to initial values. ++ * @chan: Channel. ++ * ++ * Effectively empty the channel. Should be called when the channel is not used ++ * for writing. The channel can be opened for reading, but the reader should not ++ * be using the iterator concurrently with reset. The previous current iterator ++ * record is reset. ++ */ ++void channel_reset(struct channel *chan) ++{ ++ /* ++ * Reset iterators first. Will put the subbuffer if held for reading. ++ */ ++ channel_iterator_reset(chan); ++ atomic_set(&chan->record_disabled, 0); ++ /* Don't reset commit_count_mask, still valid */ ++ channel_backend_reset(&chan->backend); ++ /* Don't reset switch/read timer interval */ ++ /* Don't reset notifiers and notifier enable bits */ ++ /* Don't reset reader reference count */ ++} ++EXPORT_SYMBOL_GPL(channel_reset); ++ ++/* ++ * Must be called under cpu hotplug protection. ++ */ ++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; ++ struct channel *chan = container_of(chanb, struct channel, backend); ++ void *priv = chanb->priv; ++ size_t subbuf_header_size; ++ u64 tsc; ++ int ret; ++ ++ /* Test for cpu hotplug */ ++ if (buf->backend.allocated) ++ return 0; ++ ++ /* ++ * Paranoia: per cpu dynamic allocation is not officially documented as ++ * zeroing the memory, so let's do it here too, just in case. ++ */ ++ memset(buf, 0, sizeof(*buf)); ++ ++ ret = lib_ring_buffer_backend_create(&buf->backend, &chan->backend, cpu); ++ if (ret) ++ return ret; ++ ++ buf->commit_hot = ++ kzalloc_node(ALIGN(sizeof(*buf->commit_hot) ++ * chan->backend.num_subbuf, ++ 1 << INTERNODE_CACHE_SHIFT), ++ GFP_KERNEL, cpu_to_node(max(cpu, 0))); ++ if (!buf->commit_hot) { ++ ret = -ENOMEM; ++ goto free_chanbuf; ++ } ++ ++ buf->commit_cold = ++ kzalloc_node(ALIGN(sizeof(*buf->commit_cold) ++ * chan->backend.num_subbuf, ++ 1 << INTERNODE_CACHE_SHIFT), ++ GFP_KERNEL, cpu_to_node(max(cpu, 0))); ++ if (!buf->commit_cold) { ++ ret = -ENOMEM; ++ goto free_commit; ++ } ++ ++ init_waitqueue_head(&buf->read_wait); ++ init_waitqueue_head(&buf->write_wait); ++ raw_spin_lock_init(&buf->raw_tick_nohz_spinlock); ++ ++ /* ++ * Write the subbuffer header for first subbuffer so we know the total ++ * duration of data gathering. ++ */ ++ subbuf_header_size = config->cb.subbuffer_header_size(); ++ v_set(config, &buf->offset, subbuf_header_size); ++ subbuffer_id_clear_noref(config, &buf->backend.buf_wsb[0].id); ++ tsc = config->cb.ring_buffer_clock_read(buf->backend.chan); ++ config->cb.buffer_begin(buf, tsc, 0); ++ v_add(config, subbuf_header_size, &buf->commit_hot[0].cc); ++ ++ if (config->cb.buffer_create) { ++ ret = config->cb.buffer_create(buf, priv, cpu, chanb->name); ++ if (ret) ++ goto free_init; ++ } ++ ++ /* ++ * Ensure the buffer is ready before setting it to allocated and setting ++ * the cpumask. ++ * Used for cpu hotplug vs cpumask iteration. ++ */ ++ smp_wmb(); ++ buf->backend.allocated = 1; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ CHAN_WARN_ON(chan, cpumask_test_cpu(cpu, ++ chan->backend.cpumask)); ++ cpumask_set_cpu(cpu, chan->backend.cpumask); ++ } ++ ++ return 0; ++ ++ /* Error handling */ ++free_init: ++ kfree(buf->commit_cold); ++free_commit: ++ kfree(buf->commit_hot); ++free_chanbuf: ++ lib_ring_buffer_backend_free(&buf->backend); ++ return ret; ++} ++ ++static void switch_buffer_timer(unsigned long data) ++{ ++ 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; ++ ++ /* ++ * Only flush buffers periodically if readers are active. ++ */ ++ if (atomic_long_read(&buf->active_readers)) ++ lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE); ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ mod_timer_pinned(&buf->switch_timer, ++ jiffies + chan->switch_timer_interval); ++ else ++ mod_timer(&buf->switch_timer, ++ jiffies + chan->switch_timer_interval); ++} ++ ++/* ++ * Called with ring_buffer_nohz_lock held for per-cpu buffers. ++ */ ++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; ++ ++ if (!chan->switch_timer_interval || buf->switch_timer_enabled) ++ return; ++ init_timer(&buf->switch_timer); ++ buf->switch_timer.function = switch_buffer_timer; ++ buf->switch_timer.expires = jiffies + chan->switch_timer_interval; ++ buf->switch_timer.data = (unsigned long)buf; ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ add_timer_on(&buf->switch_timer, buf->backend.cpu); ++ else ++ add_timer(&buf->switch_timer); ++ buf->switch_timer_enabled = 1; ++} ++ ++/* ++ * Called with ring_buffer_nohz_lock held for per-cpu buffers. ++ */ ++static void lib_ring_buffer_stop_switch_timer(struct lib_ring_buffer *buf) ++{ ++ struct channel *chan = buf->backend.chan; ++ ++ if (!chan->switch_timer_interval || !buf->switch_timer_enabled) ++ return; ++ ++ del_timer_sync(&buf->switch_timer); ++ buf->switch_timer_enabled = 0; ++} ++ ++/* ++ * Polling timer to check the channels for data. ++ */ ++static void read_buffer_timer(unsigned long data) ++{ ++ 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; ++ ++ CHAN_WARN_ON(chan, !buf->backend.allocated); ++ ++ if (atomic_long_read(&buf->active_readers) ++ && lib_ring_buffer_poll_deliver(config, buf, chan)) { ++ wake_up_interruptible(&buf->read_wait); ++ wake_up_interruptible(&chan->read_wait); ++ } ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ mod_timer_pinned(&buf->read_timer, ++ jiffies + chan->read_timer_interval); ++ else ++ mod_timer(&buf->read_timer, ++ jiffies + chan->read_timer_interval); ++} ++ ++/* ++ * Called with ring_buffer_nohz_lock held for per-cpu buffers. ++ */ ++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; ++ ++ if (config->wakeup != RING_BUFFER_WAKEUP_BY_TIMER ++ || !chan->read_timer_interval ++ || buf->read_timer_enabled) ++ return; ++ ++ init_timer(&buf->read_timer); ++ buf->read_timer.function = read_buffer_timer; ++ buf->read_timer.expires = jiffies + chan->read_timer_interval; ++ buf->read_timer.data = (unsigned long)buf; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ add_timer_on(&buf->read_timer, buf->backend.cpu); ++ else ++ add_timer(&buf->read_timer); ++ buf->read_timer_enabled = 1; ++} ++ ++/* ++ * Called with ring_buffer_nohz_lock held for per-cpu buffers. ++ */ ++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; ++ ++ if (config->wakeup != RING_BUFFER_WAKEUP_BY_TIMER ++ || !chan->read_timer_interval ++ || !buf->read_timer_enabled) ++ return; ++ ++ del_timer_sync(&buf->read_timer); ++ /* ++ * do one more check to catch data that has been written in the last ++ * timer period. ++ */ ++ if (lib_ring_buffer_poll_deliver(config, buf, chan)) { ++ wake_up_interruptible(&buf->read_wait); ++ wake_up_interruptible(&chan->read_wait); ++ } ++ buf->read_timer_enabled = 0; ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++/** ++ * lib_ring_buffer_cpu_hp_callback - CPU hotplug callback ++ * @nb: notifier block ++ * @action: hotplug action to take ++ * @hcpu: CPU number ++ * ++ * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD) ++ */ ++static ++int __cpuinit lib_ring_buffer_cpu_hp_callback(struct notifier_block *nb, ++ unsigned long action, ++ void *hcpu) ++{ ++ unsigned int cpu = (unsigned long)hcpu; ++ 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; ++ ++ if (!chan->cpu_hp_enable) ++ return NOTIFY_DONE; ++ ++ CHAN_WARN_ON(chan, config->alloc == RING_BUFFER_ALLOC_GLOBAL); ++ ++ switch (action) { ++ case CPU_DOWN_FAILED: ++ case CPU_DOWN_FAILED_FROZEN: ++ case CPU_ONLINE: ++ case CPU_ONLINE_FROZEN: ++ wake_up_interruptible(&chan->hp_wait); ++ lib_ring_buffer_start_switch_timer(buf); ++ lib_ring_buffer_start_read_timer(buf); ++ return NOTIFY_OK; ++ ++ case CPU_DOWN_PREPARE: ++ case CPU_DOWN_PREPARE_FROZEN: ++ lib_ring_buffer_stop_switch_timer(buf); ++ lib_ring_buffer_stop_read_timer(buf); ++ return NOTIFY_OK; ++ ++ case CPU_DEAD: ++ case CPU_DEAD_FROZEN: ++ /* ++ * Performing a buffer switch on a remote CPU. Performed by ++ * the CPU responsible for doing the hotunplug after the target ++ * CPU stopped running completely. Ensures that all data ++ * from that remote CPU is flushed. ++ */ ++ lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE); ++ return NOTIFY_OK; ++ ++ default: ++ return NOTIFY_DONE; ++ } ++} ++#endif ++ ++#if defined(CONFIG_NO_HZ) && defined(CONFIG_LIB_RING_BUFFER) ++/* ++ * For per-cpu buffers, call the reader wakeups before switching the buffer, so ++ * that wake-up-tracing generated events are flushed before going idle (in ++ * tick_nohz). We test if the spinlock is locked to deal with the race where ++ * readers try to sample the ring buffer before we perform the switch. We let ++ * the readers retry in that case. If there is data in the buffer, the wake up ++ * is going to forbid the CPU running the reader thread from going idle. ++ */ ++static int notrace ring_buffer_tick_nohz_callback(struct notifier_block *nb, ++ unsigned long val, ++ void *data) ++{ ++ struct channel *chan = container_of(nb, struct channel, ++ tick_nohz_notifier); ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ struct lib_ring_buffer *buf; ++ int cpu = smp_processor_id(); ++ ++ if (config->alloc != RING_BUFFER_ALLOC_PER_CPU) { ++ /* ++ * We don't support keeping the system idle with global buffers ++ * and streaming active. In order to do so, we would need to ++ * sample a non-nohz-cpumask racelessly with the nohz updates ++ * without adding synchronization overhead to nohz. Leave this ++ * use-case out for now. ++ */ ++ return 0; ++ } ++ ++ buf = channel_get_ring_buffer(config, chan, cpu); ++ switch (val) { ++ case TICK_NOHZ_FLUSH: ++ raw_spin_lock(&buf->raw_tick_nohz_spinlock); ++ if (config->wakeup == RING_BUFFER_WAKEUP_BY_TIMER ++ && chan->read_timer_interval ++ && atomic_long_read(&buf->active_readers) ++ && (lib_ring_buffer_poll_deliver(config, buf, chan) ++ || lib_ring_buffer_pending_data(config, buf, chan))) { ++ wake_up_interruptible(&buf->read_wait); ++ wake_up_interruptible(&chan->read_wait); ++ } ++ if (chan->switch_timer_interval) ++ lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE); ++ raw_spin_unlock(&buf->raw_tick_nohz_spinlock); ++ break; ++ case TICK_NOHZ_STOP: ++ spin_lock(&__get_cpu_var(ring_buffer_nohz_lock)); ++ lib_ring_buffer_stop_switch_timer(buf); ++ lib_ring_buffer_stop_read_timer(buf); ++ spin_unlock(&__get_cpu_var(ring_buffer_nohz_lock)); ++ break; ++ case TICK_NOHZ_RESTART: ++ spin_lock(&__get_cpu_var(ring_buffer_nohz_lock)); ++ lib_ring_buffer_start_read_timer(buf); ++ lib_ring_buffer_start_switch_timer(buf); ++ spin_unlock(&__get_cpu_var(ring_buffer_nohz_lock)); ++ break; ++ } ++ ++ return 0; ++} ++ ++void notrace lib_ring_buffer_tick_nohz_flush(void) ++{ ++ atomic_notifier_call_chain(&tick_nohz_notifier, TICK_NOHZ_FLUSH, ++ NULL); ++} ++ ++void notrace lib_ring_buffer_tick_nohz_stop(void) ++{ ++ atomic_notifier_call_chain(&tick_nohz_notifier, TICK_NOHZ_STOP, ++ NULL); ++} ++ ++void notrace lib_ring_buffer_tick_nohz_restart(void) ++{ ++ atomic_notifier_call_chain(&tick_nohz_notifier, TICK_NOHZ_RESTART, ++ NULL); ++} ++#endif /* defined(CONFIG_NO_HZ) && defined(CONFIG_LIB_RING_BUFFER) */ ++ ++/* ++ * Holds CPU hotplug. ++ */ ++static void channel_unregister_notifiers(struct channel *chan) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ int cpu; ++ ++ channel_iterator_unregister_notifiers(chan); ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++#ifdef CONFIG_NO_HZ ++ /* ++ * Remove the nohz notifier first, so we are certain we stop ++ * the timers. ++ */ ++ atomic_notifier_chain_unregister(&tick_nohz_notifier, ++ &chan->tick_nohz_notifier); ++ /* ++ * ring_buffer_nohz_lock will not be needed below, because ++ * we just removed the notifiers, which were the only source of ++ * concurrency. ++ */ ++#endif /* CONFIG_NO_HZ */ ++#ifdef CONFIG_HOTPLUG_CPU ++ get_online_cpus(); ++ chan->cpu_hp_enable = 0; ++ for_each_online_cpu(cpu) { ++ struct lib_ring_buffer *buf = per_cpu_ptr(chan->backend.buf, ++ cpu); ++ lib_ring_buffer_stop_switch_timer(buf); ++ lib_ring_buffer_stop_read_timer(buf); ++ } ++ put_online_cpus(); ++ unregister_cpu_notifier(&chan->cpu_hp_notifier); ++#else ++ for_each_possible_cpu(cpu) { ++ struct lib_ring_buffer *buf = per_cpu_ptr(chan->backend.buf, ++ cpu); ++ lib_ring_buffer_stop_switch_timer(buf); ++ lib_ring_buffer_stop_read_timer(buf); ++ } ++#endif ++ } else { ++ struct lib_ring_buffer *buf = chan->backend.buf; ++ ++ lib_ring_buffer_stop_switch_timer(buf); ++ lib_ring_buffer_stop_read_timer(buf); ++ } ++ channel_backend_unregister_notifiers(&chan->backend); ++} ++ ++static void channel_free(struct channel *chan) ++{ ++ channel_iterator_free(chan); ++ channel_backend_free(&chan->backend); ++ kfree(chan); ++} ++ ++/** ++ * channel_create - Create channel. ++ * @config: ring buffer instance configuration ++ * @name: name of the channel ++ * @priv: ring buffer client private data ++ * @buf_addr: pointer the the beginning of the preallocated buffer contiguous ++ * address mapping. It is used only by RING_BUFFER_STATIC ++ * configuration. It can be set to NULL for other backends. ++ * @subbuf_size: subbuffer size ++ * @num_subbuf: number of subbuffers ++ * @switch_timer_interval: Time interval (in us) to fill sub-buffers with ++ * padding to let readers get those sub-buffers. ++ * Used for live streaming. ++ * @read_timer_interval: Time interval (in us) to wake up pending readers. ++ * ++ * Holds cpu hotplug. ++ * Returns NULL on failure. ++ */ ++struct channel *channel_create(const struct lib_ring_buffer_config *config, ++ const char *name, void *priv, void *buf_addr, ++ size_t subbuf_size, ++ size_t num_subbuf, unsigned int switch_timer_interval, ++ unsigned int read_timer_interval) ++{ ++ int ret, cpu; ++ struct channel *chan; ++ ++ if (lib_ring_buffer_check_config(config, switch_timer_interval, ++ read_timer_interval)) ++ return NULL; ++ ++ chan = kzalloc(sizeof(struct channel), GFP_KERNEL); ++ if (!chan) ++ return NULL; ++ ++ ret = channel_backend_init(&chan->backend, name, config, priv, ++ subbuf_size, num_subbuf); ++ if (ret) ++ goto error; ++ ++ ret = channel_iterator_init(chan); ++ if (ret) ++ goto error_free_backend; ++ ++ chan->commit_count_mask = (~0UL >> chan->backend.num_subbuf_order); ++ chan->switch_timer_interval = usecs_to_jiffies(switch_timer_interval); ++ chan->read_timer_interval = usecs_to_jiffies(read_timer_interval); ++ kref_init(&chan->ref); ++ init_waitqueue_head(&chan->read_wait); ++ init_waitqueue_head(&chan->hp_wait); ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++#if defined(CONFIG_NO_HZ) && defined(CONFIG_LIB_RING_BUFFER) ++ /* Only benefit from NO_HZ idle with per-cpu buffers for now. */ ++ chan->tick_nohz_notifier.notifier_call = ++ ring_buffer_tick_nohz_callback; ++ chan->tick_nohz_notifier.priority = ~0U; ++ atomic_notifier_chain_register(&tick_nohz_notifier, ++ &chan->tick_nohz_notifier); ++#endif /* defined(CONFIG_NO_HZ) && defined(CONFIG_LIB_RING_BUFFER) */ ++ ++ /* ++ * In case of non-hotplug cpu, if the ring-buffer is allocated ++ * in early initcall, it will not be notified of secondary cpus. ++ * In that off case, we need to allocate for all possible cpus. ++ */ ++#ifdef CONFIG_HOTPLUG_CPU ++ chan->cpu_hp_notifier.notifier_call = ++ lib_ring_buffer_cpu_hp_callback; ++ chan->cpu_hp_notifier.priority = 6; ++ register_cpu_notifier(&chan->cpu_hp_notifier); ++ ++ get_online_cpus(); ++ for_each_online_cpu(cpu) { ++ struct lib_ring_buffer *buf = per_cpu_ptr(chan->backend.buf, ++ cpu); ++ spin_lock(&per_cpu(ring_buffer_nohz_lock, cpu)); ++ lib_ring_buffer_start_switch_timer(buf); ++ lib_ring_buffer_start_read_timer(buf); ++ spin_unlock(&per_cpu(ring_buffer_nohz_lock, cpu)); ++ } ++ chan->cpu_hp_enable = 1; ++ put_online_cpus(); ++#else ++ for_each_possible_cpu(cpu) { ++ struct lib_ring_buffer *buf = per_cpu_ptr(chan->backend.buf, ++ cpu); ++ spin_lock(&per_cpu(ring_buffer_nohz_lock, cpu)); ++ lib_ring_buffer_start_switch_timer(buf); ++ lib_ring_buffer_start_read_timer(buf); ++ spin_unlock(&per_cpu(ring_buffer_nohz_lock, cpu)); ++ } ++#endif ++ } else { ++ struct lib_ring_buffer *buf = chan->backend.buf; ++ ++ lib_ring_buffer_start_switch_timer(buf); ++ lib_ring_buffer_start_read_timer(buf); ++ } ++ ++ return chan; ++ ++error_free_backend: ++ channel_backend_free(&chan->backend); ++error: ++ kfree(chan); ++ return NULL; ++} ++EXPORT_SYMBOL_GPL(channel_create); ++ ++static ++void channel_release(struct kref *kref) ++{ ++ struct channel *chan = container_of(kref, struct channel, ref); ++ channel_free(chan); ++} ++ ++/** ++ * channel_destroy - Finalize, wait for q.s. and destroy channel. ++ * @chan: channel to destroy ++ * ++ * Holds cpu hotplug. ++ * Call "destroy" callback, finalize channels, and then decrement the ++ * channel reference count. Note that when readers have completed data ++ * consumption of finalized channels, get_subbuf() will return -ENODATA. ++ * They should release their handle at that point. Returns the private ++ * data pointer. ++ */ ++void *channel_destroy(struct channel *chan) ++{ ++ int cpu; ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ void *priv; ++ ++ channel_unregister_notifiers(chan); ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ /* ++ * No need to hold cpu hotplug, because all notifiers have been ++ * unregistered. ++ */ ++ for_each_channel_cpu(cpu, chan) { ++ struct lib_ring_buffer *buf = per_cpu_ptr(chan->backend.buf, ++ cpu); ++ ++ if (config->cb.buffer_finalize) ++ config->cb.buffer_finalize(buf, ++ chan->backend.priv, ++ cpu); ++ if (buf->backend.allocated) ++ lib_ring_buffer_switch_slow(buf, SWITCH_FLUSH); ++ /* ++ * Perform flush before writing to finalized. ++ */ ++ smp_wmb(); ++ ACCESS_ONCE(buf->finalized) = 1; ++ wake_up_interruptible(&buf->read_wait); ++ } ++ } else { ++ struct lib_ring_buffer *buf = chan->backend.buf; ++ ++ if (config->cb.buffer_finalize) ++ config->cb.buffer_finalize(buf, chan->backend.priv, -1); ++ if (buf->backend.allocated) ++ lib_ring_buffer_switch_slow(buf, SWITCH_FLUSH); ++ /* ++ * Perform flush before writing to finalized. ++ */ ++ smp_wmb(); ++ ACCESS_ONCE(buf->finalized) = 1; ++ wake_up_interruptible(&buf->read_wait); ++ } ++ ACCESS_ONCE(chan->finalized) = 1; ++ wake_up_interruptible(&chan->hp_wait); ++ wake_up_interruptible(&chan->read_wait); ++ priv = chan->backend.priv; ++ kref_put(&chan->ref, channel_release); ++ return priv; ++} ++EXPORT_SYMBOL_GPL(channel_destroy); ++ ++struct lib_ring_buffer *channel_get_ring_buffer( ++ const struct lib_ring_buffer_config *config, ++ struct channel *chan, int cpu) ++{ ++ if (config->alloc == RING_BUFFER_ALLOC_GLOBAL) ++ return chan->backend.buf; ++ else ++ return per_cpu_ptr(chan->backend.buf, cpu); ++} ++EXPORT_SYMBOL_GPL(channel_get_ring_buffer); ++ ++int lib_ring_buffer_open_read(struct lib_ring_buffer *buf) ++{ ++ struct channel *chan = buf->backend.chan; ++ ++ if (!atomic_long_add_unless(&buf->active_readers, 1, 1)) ++ return -EBUSY; ++ kref_get(&chan->ref); ++ smp_mb__after_atomic_inc(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_open_read); ++ ++void lib_ring_buffer_release_read(struct lib_ring_buffer *buf) ++{ ++ struct channel *chan = buf->backend.chan; ++ ++ CHAN_WARN_ON(chan, atomic_long_read(&buf->active_readers) != 1); ++ smp_mb__before_atomic_dec(); ++ atomic_long_dec(&buf->active_readers); ++ kref_put(&chan->ref, channel_release); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_release_read); ++ ++/* ++ * Promote compiler barrier to a smp_mb(). ++ * For the specific ring buffer case, this IPI call should be removed if the ++ * architecture does not reorder writes. This should eventually be provided by ++ * a separate architecture-specific infrastructure. ++ */ ++static void remote_mb(void *info) ++{ ++ smp_mb(); ++} ++ ++/** ++ * lib_ring_buffer_snapshot - save subbuffer position snapshot (for read) ++ * @buf: ring buffer ++ * @consumed: consumed count indicating the position where to read ++ * @produced: produced count, indicates position when to stop reading ++ * ++ * Returns -ENODATA if buffer is finalized, -EAGAIN if there is currently no ++ * data to read at consumed position, or 0 if the get operation succeeds. ++ * Busy-loop trying to get data if the tick_nohz sequence lock is held. ++ */ ++ ++int lib_ring_buffer_snapshot(struct lib_ring_buffer *buf, ++ unsigned long *consumed, unsigned long *produced) ++{ ++ struct channel *chan = buf->backend.chan; ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ unsigned long consumed_cur, write_offset; ++ int finalized; ++ ++retry: ++ finalized = ACCESS_ONCE(buf->finalized); ++ /* ++ * Read finalized before counters. ++ */ ++ smp_rmb(); ++ consumed_cur = atomic_long_read(&buf->consumed); ++ /* ++ * No need to issue a memory barrier between consumed count read and ++ * write offset read, because consumed count can only change ++ * concurrently in overwrite mode, and we keep a sequence counter ++ * identifier derived from the write offset to check we are getting ++ * the same sub-buffer we are expecting (the sub-buffers are atomically ++ * "tagged" upon writes, tags are checked upon read). ++ */ ++ write_offset = v_read(config, &buf->offset); ++ ++ /* ++ * Check that we are not about to read the same subbuffer in ++ * which the writer head is. ++ */ ++ if (subbuf_trunc(write_offset, chan) - subbuf_trunc(consumed_cur, chan) ++ == 0) ++ goto nodata; ++ ++ *consumed = consumed_cur; ++ *produced = subbuf_trunc(write_offset, chan); ++ ++ return 0; ++ ++nodata: ++ /* ++ * The memory barriers __wait_event()/wake_up_interruptible() take care ++ * of "raw_spin_is_locked" memory ordering. ++ */ ++ if (finalized) ++ return -ENODATA; ++ else if (raw_spin_is_locked(&buf->raw_tick_nohz_spinlock)) ++ goto retry; ++ else ++ return -EAGAIN; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_snapshot); ++ ++/** ++ * lib_ring_buffer_put_snapshot - move consumed counter forward ++ * ++ * Should only be called from consumer context. ++ * @buf: ring buffer ++ * @consumed_new: new consumed count value ++ */ ++void lib_ring_buffer_move_consumer(struct lib_ring_buffer *buf, ++ unsigned long consumed_new) ++{ ++ struct lib_ring_buffer_backend *bufb = &buf->backend; ++ struct channel *chan = bufb->chan; ++ unsigned long consumed; ++ ++ CHAN_WARN_ON(chan, atomic_long_read(&buf->active_readers) != 1); ++ ++ /* ++ * Only push the consumed value forward. ++ * If the consumed cmpxchg fails, this is because we have been pushed by ++ * the writer in flight recorder mode. ++ */ ++ consumed = atomic_long_read(&buf->consumed); ++ while ((long) consumed - (long) consumed_new < 0) ++ consumed = atomic_long_cmpxchg(&buf->consumed, consumed, ++ consumed_new); ++ /* Wake-up the metadata producer */ ++ wake_up_interruptible(&buf->write_wait); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_move_consumer); ++ ++/** ++ * lib_ring_buffer_get_subbuf - get exclusive access to subbuffer for reading ++ * @buf: ring buffer ++ * @consumed: consumed count indicating the position where to read ++ * ++ * Returns -ENODATA if buffer is finalized, -EAGAIN if there is currently no ++ * data to read at consumed position, or 0 if the get operation succeeds. ++ * Busy-loop trying to get data if the tick_nohz sequence lock is held. ++ */ ++int lib_ring_buffer_get_subbuf(struct lib_ring_buffer *buf, ++ unsigned long consumed) ++{ ++ struct channel *chan = buf->backend.chan; ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ unsigned long consumed_cur, consumed_idx, commit_count, write_offset; ++ int ret; ++ int finalized; ++ ++retry: ++ finalized = ACCESS_ONCE(buf->finalized); ++ /* ++ * Read finalized before counters. ++ */ ++ smp_rmb(); ++ consumed_cur = atomic_long_read(&buf->consumed); ++ consumed_idx = subbuf_index(consumed, chan); ++ commit_count = v_read(config, &buf->commit_cold[consumed_idx].cc_sb); ++ /* ++ * Make sure we read the commit count before reading the buffer ++ * data and the write offset. Correct consumed offset ordering ++ * wrt commit count is insured by the use of cmpxchg to update ++ * the consumed offset. ++ * smp_call_function_single can fail if the remote CPU is offline, ++ * this is OK because then there is no wmb to execute there. ++ * If our thread is executing on the same CPU as the on the buffers ++ * belongs to, we don't have to synchronize it at all. If we are ++ * migrated, the scheduler will take care of the memory barriers. ++ * Normally, smp_call_function_single() should ensure program order when ++ * executing the remote function, which implies that it surrounds the ++ * function execution with : ++ * smp_mb() ++ * send IPI ++ * csd_lock_wait ++ * recv IPI ++ * smp_mb() ++ * exec. function ++ * smp_mb() ++ * csd unlock ++ * smp_mb() ++ * ++ * However, smp_call_function_single() does not seem to clearly execute ++ * such barriers. It depends on spinlock semantic to provide the barrier ++ * before executing the IPI and, when busy-looping, csd_lock_wait only ++ * executes smp_mb() when it has to wait for the other CPU. ++ * ++ * I don't trust this code. Therefore, let's add the smp_mb() sequence ++ * required ourself, even if duplicated. It has no performance impact ++ * anyway. ++ * ++ * smp_mb() is needed because smp_rmb() and smp_wmb() only order read vs ++ * read and write vs write. They do not ensure core synchronization. We ++ * really have to ensure total order between the 3 barriers running on ++ * the 2 CPUs. ++ */ ++ if (config->ipi == RING_BUFFER_IPI_BARRIER) { ++ if (config->sync == RING_BUFFER_SYNC_PER_CPU ++ && config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ if (raw_smp_processor_id() != buf->backend.cpu) { ++ /* Total order with IPI handler smp_mb() */ ++ smp_mb(); ++ smp_call_function_single(buf->backend.cpu, ++ remote_mb, NULL, 1); ++ /* Total order with IPI handler smp_mb() */ ++ smp_mb(); ++ } ++ } else { ++ /* Total order with IPI handler smp_mb() */ ++ smp_mb(); ++ smp_call_function(remote_mb, NULL, 1); ++ /* Total order with IPI handler smp_mb() */ ++ smp_mb(); ++ } ++ } else { ++ /* ++ * Local rmb to match the remote wmb to read the commit count ++ * before the buffer data and the write offset. ++ */ ++ smp_rmb(); ++ } ++ ++ write_offset = v_read(config, &buf->offset); ++ ++ /* ++ * Check that the buffer we are getting is after or at consumed_cur ++ * position. ++ */ ++ if ((long) subbuf_trunc(consumed, chan) ++ - (long) subbuf_trunc(consumed_cur, chan) < 0) ++ goto nodata; ++ ++ /* ++ * Check that the subbuffer we are trying to consume has been ++ * already fully committed. ++ */ ++ if (((commit_count - chan->backend.subbuf_size) ++ & chan->commit_count_mask) ++ - (buf_trunc(consumed_cur, chan) ++ >> chan->backend.num_subbuf_order) ++ != 0) ++ goto nodata; ++ ++ /* ++ * Check that we are not about to read the same subbuffer in ++ * which the writer head is. ++ */ ++ if (subbuf_trunc(write_offset, chan) - subbuf_trunc(consumed_cur, chan) ++ == 0) ++ goto nodata; ++ ++ /* ++ * Failure to get the subbuffer causes a busy-loop retry without going ++ * to a wait queue. These are caused by short-lived race windows where ++ * the writer is getting access to a subbuffer we were trying to get ++ * access to. Also checks that the "consumed" buffer count we are ++ * looking for matches the one contained in the subbuffer id. ++ */ ++ ret = update_read_sb_index(config, &buf->backend, &chan->backend, ++ consumed_idx, buf_trunc_val(consumed, chan)); ++ if (ret) ++ goto retry; ++ subbuffer_id_clear_noref(config, &buf->backend.buf_rsb.id); ++ ++ buf->get_subbuf_consumed = consumed; ++ buf->get_subbuf = 1; ++ ++ return 0; ++ ++nodata: ++ /* ++ * The memory barriers __wait_event()/wake_up_interruptible() take care ++ * of "raw_spin_is_locked" memory ordering. ++ */ ++ if (finalized) ++ return -ENODATA; ++ else if (raw_spin_is_locked(&buf->raw_tick_nohz_spinlock)) ++ goto retry; ++ else ++ return -EAGAIN; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_get_subbuf); ++ ++/** ++ * lib_ring_buffer_put_subbuf - release exclusive subbuffer access ++ * @buf: ring buffer ++ */ ++void lib_ring_buffer_put_subbuf(struct lib_ring_buffer *buf) ++{ ++ struct lib_ring_buffer_backend *bufb = &buf->backend; ++ struct channel *chan = bufb->chan; ++ 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); ++ ++ if (!buf->get_subbuf) { ++ /* ++ * Reader puts a subbuffer it did not get. ++ */ ++ CHAN_WARN_ON(chan, 1); ++ return; ++ } ++ consumed = buf->get_subbuf_consumed; ++ buf->get_subbuf = 0; ++ ++ /* ++ * Clear the records_unread counter. (overruns counter) ++ * Can still be non-zero if a file reader simply grabbed the data ++ * without using iterators. ++ * Can be below zero if an iterator is used on a snapshot more than ++ * once. ++ */ ++ read_sb_bindex = subbuffer_id_get_index(config, bufb->buf_rsb.id); ++ v_add(config, v_read(config, ++ &bufb->array[read_sb_bindex]->records_unread), ++ &bufb->records_read); ++ v_set(config, &bufb->array[read_sb_bindex]->records_unread, 0); ++ CHAN_WARN_ON(chan, config->mode == RING_BUFFER_OVERWRITE ++ && subbuffer_id_is_noref(config, bufb->buf_rsb.id)); ++ subbuffer_id_set_noref(config, &bufb->buf_rsb.id); ++ ++ /* ++ * Exchange the reader subbuffer with the one we put in its place in the ++ * writer subbuffer table. Expect the original consumed count. If ++ * update_read_sb_index fails, this is because the writer updated the ++ * subbuffer concurrently. We should therefore keep the subbuffer we ++ * currently have: it has become invalid to try reading this sub-buffer ++ * consumed count value anyway. ++ */ ++ consumed_idx = subbuf_index(consumed, chan); ++ update_read_sb_index(config, &buf->backend, &chan->backend, ++ consumed_idx, buf_trunc_val(consumed, chan)); ++ /* ++ * update_read_sb_index return value ignored. Don't exchange sub-buffer ++ * if the writer concurrently updated it. ++ */ ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_put_subbuf); ++ ++/* ++ * cons_offset is an iterator on all subbuffer offsets between the reader ++ * position and the writer position. (inclusive) ++ */ ++static ++void lib_ring_buffer_print_subbuffer_errors(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ unsigned long cons_offset, ++ int cpu) ++{ ++ 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); ++ commit_count = v_read(config, &buf->commit_hot[cons_idx].cc); ++ commit_count_sb = v_read(config, &buf->commit_cold[cons_idx].cc_sb); ++ ++ if (subbuf_offset(commit_count, chan) != 0) ++ printk(KERN_WARNING ++ "ring buffer %s, cpu %d: " ++ "commit count in subbuffer %lu,\n" ++ "expecting multiples of %lu bytes\n" ++ " [ %lu bytes committed, %lu bytes reader-visible ]\n", ++ chan->backend.name, cpu, cons_idx, ++ chan->backend.subbuf_size, ++ commit_count, commit_count_sb); ++ ++ printk(KERN_DEBUG "ring buffer: %s, cpu %d: %lu bytes committed\n", ++ chan->backend.name, cpu, commit_count); ++} ++ ++static ++void lib_ring_buffer_print_buffer_errors(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ void *priv, int cpu) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ unsigned long write_offset, cons_offset; ++ ++ /* ++ * Can be called in the error path of allocation when ++ * trans_channel_data is not yet set. ++ */ ++ if (!chan) ++ return; ++ /* ++ * No need to order commit_count, write_offset and cons_offset reads ++ * because we execute at teardown when no more writer nor reader ++ * references are left. ++ */ ++ write_offset = v_read(config, &buf->offset); ++ cons_offset = atomic_long_read(&buf->consumed); ++ if (write_offset != cons_offset) ++ printk(KERN_DEBUG ++ "ring buffer %s, cpu %d: " ++ "non-consumed data\n" ++ " [ %lu bytes written, %lu bytes read ]\n", ++ chan->backend.name, cpu, write_offset, cons_offset); ++ ++ for (cons_offset = atomic_long_read(&buf->consumed); ++ (long) (subbuf_trunc((unsigned long) v_read(config, &buf->offset), ++ chan) ++ - cons_offset) > 0; ++ cons_offset = subbuf_align(cons_offset, chan)) ++ lib_ring_buffer_print_subbuffer_errors(buf, chan, cons_offset, ++ cpu); ++} ++ ++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; ++ 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)); ++ ++ lib_ring_buffer_print_buffer_errors(buf, chan, priv, cpu); ++} ++ ++/* ++ * lib_ring_buffer_switch_old_start: Populate old subbuffer header. ++ * ++ * Only executed when the buffer is finalized, in SWITCH_FLUSH. ++ */ ++static ++void lib_ring_buffer_switch_old_start(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ struct switch_offsets *offsets, ++ u64 tsc) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ unsigned long oldidx = subbuf_index(offsets->old, chan); ++ unsigned long commit_count; ++ ++ config->cb.buffer_begin(buf, tsc, oldidx); ++ ++ /* ++ * Order all writes to buffer before the commit count update that will ++ * determine that the subbuffer is full. ++ */ ++ if (config->ipi == RING_BUFFER_IPI_BARRIER) { ++ /* ++ * Must write slot data before incrementing commit count. This ++ * compiler barrier is upgraded into a smp_mb() by the IPI sent ++ * by get_subbuf(). ++ */ ++ barrier(); ++ } else ++ smp_wmb(); ++ v_add(config, config->cb.subbuffer_header_size(), ++ &buf->commit_hot[oldidx].cc); ++ commit_count = v_read(config, &buf->commit_hot[oldidx].cc); ++ /* Check if the written buffer has to be delivered */ ++ lib_ring_buffer_check_deliver(config, buf, chan, offsets->old, ++ commit_count, oldidx); ++ lib_ring_buffer_write_commit_counter(config, buf, chan, oldidx, ++ offsets->old, commit_count, ++ config->cb.subbuffer_header_size()); ++} ++ ++/* ++ * lib_ring_buffer_switch_old_end: switch old subbuffer ++ * ++ * Note : offset_old should never be 0 here. It is ok, because we never perform ++ * buffer switch on an empty subbuffer in SWITCH_ACTIVE mode. The caller ++ * increments the offset_old value when doing a SWITCH_FLUSH on an empty ++ * subbuffer. ++ */ ++static ++void lib_ring_buffer_switch_old_end(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ struct switch_offsets *offsets, ++ u64 tsc) ++{ ++ 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; ++ ++ data_size = subbuf_offset(offsets->old - 1, chan) + 1; ++ padding_size = chan->backend.subbuf_size - data_size; ++ subbuffer_set_data_size(config, &buf->backend, oldidx, data_size); ++ ++ /* ++ * Order all writes to buffer before the commit count update that will ++ * determine that the subbuffer is full. ++ */ ++ if (config->ipi == RING_BUFFER_IPI_BARRIER) { ++ /* ++ * Must write slot data before incrementing commit count. This ++ * compiler barrier is upgraded into a smp_mb() by the IPI sent ++ * by get_subbuf(). ++ */ ++ barrier(); ++ } else ++ smp_wmb(); ++ v_add(config, padding_size, &buf->commit_hot[oldidx].cc); ++ commit_count = v_read(config, &buf->commit_hot[oldidx].cc); ++ lib_ring_buffer_check_deliver(config, buf, chan, offsets->old - 1, ++ commit_count, oldidx); ++ lib_ring_buffer_write_commit_counter(config, buf, chan, oldidx, ++ offsets->old, commit_count, ++ padding_size); ++} ++ ++/* ++ * lib_ring_buffer_switch_new_start: Populate new subbuffer. ++ * ++ * This code can be executed unordered : writers may already have written to the ++ * sub-buffer before this code gets executed, caution. The commit makes sure ++ * that this code is executed before the deliver of this sub-buffer. ++ */ ++static ++void lib_ring_buffer_switch_new_start(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ struct switch_offsets *offsets, ++ u64 tsc) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ unsigned long beginidx = subbuf_index(offsets->begin, chan); ++ unsigned long commit_count; ++ ++ config->cb.buffer_begin(buf, tsc, beginidx); ++ ++ /* ++ * Order all writes to buffer before the commit count update that will ++ * determine that the subbuffer is full. ++ */ ++ if (config->ipi == RING_BUFFER_IPI_BARRIER) { ++ /* ++ * Must write slot data before incrementing commit count. This ++ * compiler barrier is upgraded into a smp_mb() by the IPI sent ++ * by get_subbuf(). ++ */ ++ barrier(); ++ } else ++ smp_wmb(); ++ v_add(config, config->cb.subbuffer_header_size(), ++ &buf->commit_hot[beginidx].cc); ++ commit_count = v_read(config, &buf->commit_hot[beginidx].cc); ++ /* Check if the written buffer has to be delivered */ ++ lib_ring_buffer_check_deliver(config, buf, chan, offsets->begin, ++ commit_count, beginidx); ++ lib_ring_buffer_write_commit_counter(config, buf, chan, beginidx, ++ offsets->begin, commit_count, ++ config->cb.subbuffer_header_size()); ++} ++ ++/* ++ * lib_ring_buffer_switch_new_end: finish switching current subbuffer ++ * ++ * The only remaining threads could be the ones with pending commits. They will ++ * have to do the deliver themselves. ++ */ ++static ++void lib_ring_buffer_switch_new_end(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ struct switch_offsets *offsets, ++ u64 tsc) ++{ ++ 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; ++ ++ data_size = subbuf_offset(offsets->end - 1, chan) + 1; ++ padding_size = chan->backend.subbuf_size - data_size; ++ subbuffer_set_data_size(config, &buf->backend, endidx, data_size); ++ ++ /* ++ * Order all writes to buffer before the commit count update that will ++ * determine that the subbuffer is full. ++ */ ++ if (config->ipi == RING_BUFFER_IPI_BARRIER) { ++ /* ++ * Must write slot data before incrementing commit count. This ++ * compiler barrier is upgraded into a smp_mb() by the IPI sent ++ * by get_subbuf(). ++ */ ++ barrier(); ++ } else ++ smp_wmb(); ++ v_add(config, padding_size, &buf->commit_hot[endidx].cc); ++ commit_count = v_read(config, &buf->commit_hot[endidx].cc); ++ lib_ring_buffer_check_deliver(config, buf, chan, offsets->end - 1, ++ commit_count, endidx); ++ lib_ring_buffer_write_commit_counter(config, buf, chan, endidx, ++ offsets->end, commit_count, ++ padding_size); ++} ++ ++/* ++ * Returns : ++ * 0 if ok ++ * !0 if execution must be aborted. ++ */ ++static ++int lib_ring_buffer_try_switch_slow(enum switch_mode mode, ++ struct lib_ring_buffer *buf, ++ struct channel *chan, ++ struct switch_offsets *offsets, ++ u64 *tsc) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ unsigned long off; ++ ++ offsets->begin = v_read(config, &buf->offset); ++ offsets->old = offsets->begin; ++ offsets->switch_old_start = 0; ++ off = subbuf_offset(offsets->begin, chan); ++ ++ *tsc = config->cb.ring_buffer_clock_read(chan); ++ ++ /* ++ * Ensure we flush the header of an empty subbuffer when doing the ++ * finalize (SWITCH_FLUSH). This ensures that we end up knowing the ++ * total data gathering duration even if there were no records saved ++ * after the last buffer switch. ++ * In SWITCH_ACTIVE mode, switch the buffer when it contains events. ++ * SWITCH_ACTIVE only flushes the current subbuffer, dealing with end of ++ * subbuffer header as appropriate. ++ * The next record that reserves space will be responsible for ++ * populating the following subbuffer header. We choose not to populate ++ * the next subbuffer header here because we want to be able to use ++ * SWITCH_ACTIVE for periodical buffer flush and CPU tick_nohz stop ++ * buffer flush, which must guarantee that all the buffer content ++ * (records and header timestamps) are visible to the reader. This is ++ * required for quiescence guarantees for the fusion merge. ++ */ ++ if (mode == SWITCH_FLUSH || off > 0) { ++ if (unlikely(off == 0)) { ++ /* ++ * The client does not save any header information. ++ * Don't switch empty subbuffer on finalize, because it ++ * is invalid to deliver a completely empty subbuffer. ++ */ ++ if (!config->cb.subbuffer_header_size()) ++ return -1; ++ /* ++ * Need to write the subbuffer start header on finalize. ++ */ ++ offsets->switch_old_start = 1; ++ } ++ offsets->begin = subbuf_align(offsets->begin, chan); ++ } else ++ return -1; /* we do not have to switch : buffer is empty */ ++ /* Note: old points to the next subbuf at offset 0 */ ++ offsets->end = offsets->begin; ++ return 0; ++} ++ ++/* ++ * Force a sub-buffer switch. This operation is completely reentrant : can be ++ * called while tracing is active with absolutely no lock held. ++ * ++ * Note, however, that as a v_cmpxchg is used for some atomic ++ * operations, this function must be called from the CPU which owns the buffer ++ * for a ACTIVE flush. ++ */ ++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; ++ struct switch_offsets offsets; ++ unsigned long oldidx; ++ u64 tsc; ++ ++ offsets.size = 0; ++ ++ /* ++ * Perform retryable operations. ++ */ ++ do { ++ if (lib_ring_buffer_try_switch_slow(mode, buf, chan, &offsets, ++ &tsc)) ++ return; /* Switch not needed */ ++ } while (v_cmpxchg(config, &buf->offset, offsets.old, offsets.end) ++ != offsets.old); ++ ++ /* ++ * Atomically update last_tsc. This update races against concurrent ++ * atomic updates, but the race will always cause supplementary full TSC ++ * records, never the opposite (missing a full TSC record when it would ++ * be needed). ++ */ ++ save_last_tsc(config, buf, tsc); ++ ++ /* ++ * Push the reader if necessary ++ */ ++ lib_ring_buffer_reserve_push_reader(buf, chan, offsets.old); ++ ++ oldidx = subbuf_index(offsets.old, chan); ++ lib_ring_buffer_clear_noref(config, &buf->backend, oldidx); ++ ++ /* ++ * May need to populate header start on SWITCH_FLUSH. ++ */ ++ if (offsets.switch_old_start) { ++ lib_ring_buffer_switch_old_start(buf, chan, &offsets, tsc); ++ offsets.old += config->cb.subbuffer_header_size(); ++ } ++ ++ /* ++ * Switch old subbuffer. ++ */ ++ lib_ring_buffer_switch_old_end(buf, chan, &offsets, tsc); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_switch_slow); ++ ++/* ++ * Returns : ++ * 0 if ok ++ * -ENOSPC if event size is too large for packet. ++ * -ENOBUFS if there is currently not enough space in buffer for the event. ++ * -EIO if data cannot be written into the buffer for any other reason. ++ */ ++static ++int lib_ring_buffer_try_reserve_slow(struct lib_ring_buffer *buf, ++ struct channel *chan, ++ struct switch_offsets *offsets, ++ struct lib_ring_buffer_ctx *ctx) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ unsigned long reserve_commit_diff; ++ ++ offsets->begin = v_read(config, &buf->offset); ++ offsets->old = offsets->begin; ++ offsets->switch_new_start = 0; ++ offsets->switch_new_end = 0; ++ offsets->switch_old_end = 0; ++ offsets->pre_header_padding = 0; ++ ++ ctx->tsc = config->cb.ring_buffer_clock_read(chan); ++ if ((int64_t) ctx->tsc == -EIO) ++ return -EIO; ++ ++ if (last_tsc_overflow(config, buf, ctx->tsc)) ++ ctx->rflags |= RING_BUFFER_RFLAG_FULL_TSC; ++ ++ if (unlikely(subbuf_offset(offsets->begin, ctx->chan) == 0)) { ++ offsets->switch_new_start = 1; /* For offsets->begin */ ++ } else { ++ offsets->size = config->cb.record_header_size(config, chan, ++ offsets->begin, ++ &offsets->pre_header_padding, ++ ctx); ++ offsets->size += ++ lib_ring_buffer_align(offsets->begin + offsets->size, ++ ctx->largest_align) ++ + ctx->data_size; ++ if (unlikely(subbuf_offset(offsets->begin, chan) + ++ offsets->size > chan->backend.subbuf_size)) { ++ offsets->switch_old_end = 1; /* For offsets->old */ ++ offsets->switch_new_start = 1; /* For offsets->begin */ ++ } ++ } ++ if (unlikely(offsets->switch_new_start)) { ++ unsigned long sb_index; ++ ++ /* ++ * We are typically not filling the previous buffer completely. ++ */ ++ if (likely(offsets->switch_old_end)) ++ offsets->begin = subbuf_align(offsets->begin, chan); ++ offsets->begin = offsets->begin ++ + config->cb.subbuffer_header_size(); ++ /* Test new buffer integrity */ ++ sb_index = subbuf_index(offsets->begin, chan); ++ reserve_commit_diff = ++ (buf_trunc(offsets->begin, chan) ++ >> chan->backend.num_subbuf_order) ++ - ((unsigned long) v_read(config, ++ &buf->commit_cold[sb_index].cc_sb) ++ & chan->commit_count_mask); ++ if (likely(reserve_commit_diff == 0)) { ++ /* Next subbuffer not being written to. */ ++ if (unlikely(config->mode != RING_BUFFER_OVERWRITE && ++ subbuf_trunc(offsets->begin, chan) ++ - subbuf_trunc((unsigned long) ++ atomic_long_read(&buf->consumed), chan) ++ >= chan->backend.buf_size)) { ++ /* ++ * We do not overwrite non consumed buffers ++ * and we are full : record is lost. ++ */ ++ v_inc(config, &buf->records_lost_full); ++ return -ENOBUFS; ++ } else { ++ /* ++ * Next subbuffer not being written to, and we ++ * are either in overwrite mode or the buffer is ++ * not full. It's safe to write in this new ++ * subbuffer. ++ */ ++ } ++ } else { ++ /* ++ * Next subbuffer reserve offset does not match the ++ * commit offset. Drop record in producer-consumer and ++ * overwrite mode. Caused by either a writer OOPS or too ++ * many nested writes over a reserve/commit pair. ++ */ ++ v_inc(config, &buf->records_lost_wrap); ++ return -EIO; ++ } ++ offsets->size = ++ config->cb.record_header_size(config, chan, ++ offsets->begin, ++ &offsets->pre_header_padding, ++ ctx); ++ offsets->size += ++ lib_ring_buffer_align(offsets->begin + offsets->size, ++ ctx->largest_align) ++ + ctx->data_size; ++ if (unlikely(subbuf_offset(offsets->begin, chan) ++ + offsets->size > chan->backend.subbuf_size)) { ++ /* ++ * Record too big for subbuffers, report error, don't ++ * complete the sub-buffer switch. ++ */ ++ v_inc(config, &buf->records_lost_big); ++ return -ENOSPC; ++ } else { ++ /* ++ * We just made a successful buffer switch and the ++ * record fits in the new subbuffer. Let's write. ++ */ ++ } ++ } else { ++ /* ++ * Record fits in the current buffer and we are not on a switch ++ * boundary. It's safe to write. ++ */ ++ } ++ offsets->end = offsets->begin + offsets->size; ++ ++ if (unlikely(subbuf_offset(offsets->end, chan) == 0)) { ++ /* ++ * The offset_end will fall at the very beginning of the next ++ * subbuffer. ++ */ ++ offsets->switch_new_end = 1; /* For offsets->begin */ ++ } ++ return 0; ++} ++ ++/** ++ * lib_ring_buffer_reserve_slow - Atomic slot reservation in a buffer. ++ * @ctx: ring buffer context. ++ * ++ * Return : -NOBUFS if not enough space, -ENOSPC if event size too large, ++ * -EIO for other errors, else returns 0. ++ * It will take care of sub-buffer switching. ++ */ ++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; ++ struct lib_ring_buffer *buf; ++ struct switch_offsets offsets; ++ int ret; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ buf = per_cpu_ptr(chan->backend.buf, ctx->cpu); ++ else ++ buf = chan->backend.buf; ++ ctx->buf = buf; ++ ++ offsets.size = 0; ++ ++ do { ++ ret = lib_ring_buffer_try_reserve_slow(buf, chan, &offsets, ++ ctx); ++ if (unlikely(ret)) ++ return ret; ++ } while (unlikely(v_cmpxchg(config, &buf->offset, offsets.old, ++ offsets.end) ++ != offsets.old)); ++ ++ /* ++ * Atomically update last_tsc. This update races against concurrent ++ * atomic updates, but the race will always cause supplementary full TSC ++ * records, never the opposite (missing a full TSC record when it would ++ * be needed). ++ */ ++ save_last_tsc(config, buf, ctx->tsc); ++ ++ /* ++ * Push the reader if necessary ++ */ ++ lib_ring_buffer_reserve_push_reader(buf, chan, offsets.end - 1); ++ ++ /* ++ * Clear noref flag for this subbuffer. ++ */ ++ lib_ring_buffer_clear_noref(config, &buf->backend, ++ subbuf_index(offsets.end - 1, chan)); ++ ++ /* ++ * Switch old subbuffer if needed. ++ */ ++ if (unlikely(offsets.switch_old_end)) { ++ lib_ring_buffer_clear_noref(config, &buf->backend, ++ subbuf_index(offsets.old - 1, chan)); ++ lib_ring_buffer_switch_old_end(buf, chan, &offsets, ctx->tsc); ++ } ++ ++ /* ++ * Populate new subbuffer. ++ */ ++ if (unlikely(offsets.switch_new_start)) ++ lib_ring_buffer_switch_new_start(buf, chan, &offsets, ctx->tsc); ++ ++ if (unlikely(offsets.switch_new_end)) ++ lib_ring_buffer_switch_new_end(buf, chan, &offsets, ctx->tsc); ++ ++ ctx->slot_size = offsets.size; ++ ctx->pre_offset = offsets.begin; ++ ctx->buf_offset = offsets.begin + offsets.pre_header_padding; ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_reserve_slow); ++ ++int __init init_lib_ring_buffer_frontend(void) ++{ ++ int cpu; ++ ++ for_each_possible_cpu(cpu) ++ spin_lock_init(&per_cpu(ring_buffer_nohz_lock, cpu)); ++ return 0; ++} ++ ++module_init(init_lib_ring_buffer_frontend); ++ ++void __exit exit_lib_ring_buffer_frontend(void) ++{ ++} ++ ++module_exit(exit_lib_ring_buffer_frontend); +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_iterator.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_iterator.c +new file mode 100644 +index 0000000..1321b5f +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_iterator.c +@@ -0,0 +1,798 @@ ++/* ++ * 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. ++ * ++ * Author: ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include "../../wrapper/ringbuffer/iterator.h" ++#include <linux/jiffies.h> ++#include <linux/delay.h> ++#include <linux/module.h> ++ ++/* ++ * Safety factor taking into account internal kernel interrupt latency. ++ * Assuming 250ms worse-case latency. ++ */ ++#define MAX_SYSTEM_LATENCY 250 ++ ++/* ++ * Maximum delta expected between trace clocks. At most 1 jiffy delta. ++ */ ++#define MAX_CLOCK_DELTA (jiffies_to_usecs(1) * 1000) ++ ++/** ++ * lib_ring_buffer_get_next_record - Get the next record in a buffer. ++ * @chan: channel ++ * @buf: buffer ++ * ++ * Returns the size of the event read, -EAGAIN if buffer is empty, -ENODATA if ++ * buffer is empty and finalized. The buffer must already be opened for reading. ++ */ ++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; ++ struct lib_ring_buffer_iter *iter = &buf->iter; ++ int ret; ++ ++restart: ++ switch (iter->state) { ++ case ITER_GET_SUBBUF: ++ ret = lib_ring_buffer_get_next_subbuf(buf); ++ if (ret && !ACCESS_ONCE(buf->finalized) ++ && config->alloc == RING_BUFFER_ALLOC_GLOBAL) { ++ /* ++ * Use "pull" scheme for global buffers. The reader ++ * itself flushes the buffer to "pull" data not visible ++ * to readers yet. Flush current subbuffer and re-try. ++ * ++ * Per-CPU buffers rather use a "push" scheme because ++ * the IPI needed to flush all CPU's buffers is too ++ * costly. In the "push" scheme, the reader waits for ++ * the writer periodic deferrable timer to flush the ++ * buffers (keeping track of a quiescent state ++ * timestamp). Therefore, the writer "pushes" data out ++ * of the buffers rather than letting the reader "pull" ++ * data from the buffer. ++ */ ++ lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE); ++ ret = lib_ring_buffer_get_next_subbuf(buf); ++ } ++ if (ret) ++ return ret; ++ iter->consumed = buf->cons_snapshot; ++ iter->data_size = lib_ring_buffer_get_read_data_size(config, buf); ++ iter->read_offset = iter->consumed; ++ /* skip header */ ++ iter->read_offset += config->cb.subbuffer_header_size(); ++ iter->state = ITER_TEST_RECORD; ++ goto restart; ++ case ITER_TEST_RECORD: ++ if (iter->read_offset - iter->consumed >= iter->data_size) { ++ iter->state = ITER_PUT_SUBBUF; ++ } else { ++ CHAN_WARN_ON(chan, !config->cb.record_get); ++ config->cb.record_get(config, chan, buf, ++ iter->read_offset, ++ &iter->header_len, ++ &iter->payload_len, ++ &iter->timestamp); ++ iter->read_offset += iter->header_len; ++ subbuffer_consume_record(config, &buf->backend); ++ iter->state = ITER_NEXT_RECORD; ++ return iter->payload_len; ++ } ++ goto restart; ++ case ITER_NEXT_RECORD: ++ iter->read_offset += iter->payload_len; ++ iter->state = ITER_TEST_RECORD; ++ goto restart; ++ case ITER_PUT_SUBBUF: ++ lib_ring_buffer_put_next_subbuf(buf); ++ iter->state = ITER_GET_SUBBUF; ++ goto restart; ++ default: ++ CHAN_WARN_ON(chan, 1); /* Should not happen */ ++ return -EPERM; ++ } ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_get_next_record); ++ ++static int buf_is_higher(void *a, void *b) ++{ ++ struct lib_ring_buffer *bufa = a; ++ struct lib_ring_buffer *bufb = b; ++ ++ /* Consider lowest timestamps to be at the top of the heap */ ++ return (bufa->iter.timestamp < bufb->iter.timestamp); ++} ++ ++static ++void lib_ring_buffer_get_empty_buf_records(const struct lib_ring_buffer_config *config, ++ struct channel *chan) ++{ ++ struct lttng_ptr_heap *heap = &chan->iter.heap; ++ struct lib_ring_buffer *buf, *tmp; ++ ssize_t len; ++ ++ list_for_each_entry_safe(buf, tmp, &chan->iter.empty_head, ++ iter.empty_node) { ++ len = lib_ring_buffer_get_next_record(chan, buf); ++ ++ /* ++ * Deal with -EAGAIN and -ENODATA. ++ * len >= 0 means record contains data. ++ * -EBUSY should never happen, because we support only one ++ * reader. ++ */ ++ switch (len) { ++ case -EAGAIN: ++ /* Keep node in empty list */ ++ break; ++ case -ENODATA: ++ /* ++ * Buffer is finalized. Don't add to list of empty ++ * buffer, because it has no more data to provide, ever. ++ */ ++ list_del(&buf->iter.empty_node); ++ break; ++ case -EBUSY: ++ CHAN_WARN_ON(chan, 1); ++ break; ++ default: ++ /* ++ * Insert buffer into the heap, remove from empty buffer ++ * list. ++ */ ++ CHAN_WARN_ON(chan, len < 0); ++ list_del(&buf->iter.empty_node); ++ CHAN_WARN_ON(chan, lttng_heap_insert(heap, buf)); ++ } ++ } ++} ++ ++static ++void lib_ring_buffer_wait_for_qs(const struct lib_ring_buffer_config *config, ++ struct channel *chan) ++{ ++ u64 timestamp_qs; ++ unsigned long wait_msecs; ++ ++ /* ++ * No need to wait if no empty buffers are present. ++ */ ++ if (list_empty(&chan->iter.empty_head)) ++ return; ++ ++ timestamp_qs = config->cb.ring_buffer_clock_read(chan); ++ /* ++ * We need to consider previously empty buffers. ++ * Do a get next buf record on each of them. Add them to ++ * the heap if they have data. If at least one of them ++ * don't have data, we need to wait for ++ * switch_timer_interval + MAX_SYSTEM_LATENCY (so we are sure the ++ * buffers have been switched either by the timer or idle entry) and ++ * check them again, adding them if they have data. ++ */ ++ lib_ring_buffer_get_empty_buf_records(config, chan); ++ ++ /* ++ * No need to wait if no empty buffers are present. ++ */ ++ if (list_empty(&chan->iter.empty_head)) ++ return; ++ ++ /* ++ * We need to wait for the buffer switch timer to run. If the ++ * CPU is idle, idle entry performed the switch. ++ * TODO: we could optimize further by skipping the sleep if all ++ * empty buffers belong to idle or offline cpus. ++ */ ++ wait_msecs = jiffies_to_msecs(chan->switch_timer_interval); ++ wait_msecs += MAX_SYSTEM_LATENCY; ++ msleep(wait_msecs); ++ lib_ring_buffer_get_empty_buf_records(config, chan); ++ /* ++ * Any buffer still in the empty list here cannot possibly ++ * contain an event with a timestamp prior to "timestamp_qs". ++ * The new quiescent state timestamp is the one we grabbed ++ * before waiting for buffer data. It is therefore safe to ++ * ignore empty buffers up to last_qs timestamp for fusion ++ * merge. ++ */ ++ chan->iter.last_qs = timestamp_qs; ++} ++ ++/** ++ * channel_get_next_record - Get the next record in a channel. ++ * @chan: channel ++ * @ret_buf: the buffer in which the event is located (output) ++ * ++ * Returns the size of new current event, -EAGAIN if all buffers are empty, ++ * -ENODATA if all buffers are empty and finalized. The channel must already be ++ * opened for reading. ++ */ ++ ++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; ++ struct lib_ring_buffer *buf; ++ struct lttng_ptr_heap *heap; ++ ssize_t len; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_GLOBAL) { ++ *ret_buf = channel_get_ring_buffer(config, chan, 0); ++ return lib_ring_buffer_get_next_record(chan, *ret_buf); ++ } ++ ++ heap = &chan->iter.heap; ++ ++ /* ++ * get next record for topmost buffer. ++ */ ++ buf = lttng_heap_maximum(heap); ++ if (buf) { ++ len = lib_ring_buffer_get_next_record(chan, buf); ++ /* ++ * Deal with -EAGAIN and -ENODATA. ++ * len >= 0 means record contains data. ++ */ ++ switch (len) { ++ case -EAGAIN: ++ buf->iter.timestamp = 0; ++ list_add(&buf->iter.empty_node, &chan->iter.empty_head); ++ /* Remove topmost buffer from the heap */ ++ CHAN_WARN_ON(chan, lttng_heap_remove(heap) != buf); ++ break; ++ case -ENODATA: ++ /* ++ * Buffer is finalized. Remove buffer from heap and ++ * don't add to list of empty buffer, because it has no ++ * more data to provide, ever. ++ */ ++ CHAN_WARN_ON(chan, lttng_heap_remove(heap) != buf); ++ break; ++ case -EBUSY: ++ CHAN_WARN_ON(chan, 1); ++ break; ++ default: ++ /* ++ * Reinsert buffer into the heap. Note that heap can be ++ * partially empty, so we need to use ++ * lttng_heap_replace_max(). ++ */ ++ CHAN_WARN_ON(chan, len < 0); ++ CHAN_WARN_ON(chan, lttng_heap_replace_max(heap, buf) != buf); ++ break; ++ } ++ } ++ ++ buf = lttng_heap_maximum(heap); ++ if (!buf || buf->iter.timestamp > chan->iter.last_qs) { ++ /* ++ * Deal with buffers previously showing no data. ++ * Add buffers containing data to the heap, update ++ * last_qs. ++ */ ++ lib_ring_buffer_wait_for_qs(config, chan); ++ } ++ ++ *ret_buf = buf = lttng_heap_maximum(heap); ++ if (buf) { ++ /* ++ * If this warning triggers, you probably need to check your ++ * system interrupt latency. Typical causes: too many printk() ++ * output going to a serial console with interrupts off. ++ * Allow for MAX_CLOCK_DELTA ns timestamp delta going backward. ++ * Observed on SMP KVM setups with trace_clock(). ++ */ ++ if (chan->iter.last_timestamp ++ > (buf->iter.timestamp + MAX_CLOCK_DELTA)) { ++ printk(KERN_WARNING "ring_buffer: timestamps going " ++ "backward. Last time %llu ns, cpu %d, " ++ "current time %llu ns, cpu %d, " ++ "delta %llu ns.\n", ++ chan->iter.last_timestamp, chan->iter.last_cpu, ++ buf->iter.timestamp, buf->backend.cpu, ++ chan->iter.last_timestamp - buf->iter.timestamp); ++ CHAN_WARN_ON(chan, 1); ++ } ++ chan->iter.last_timestamp = buf->iter.timestamp; ++ chan->iter.last_cpu = buf->backend.cpu; ++ return buf->iter.payload_len; ++ } else { ++ /* Heap is empty */ ++ if (list_empty(&chan->iter.empty_head)) ++ return -ENODATA; /* All buffers finalized */ ++ else ++ return -EAGAIN; /* Temporarily empty */ ++ } ++} ++EXPORT_SYMBOL_GPL(channel_get_next_record); ++ ++static ++void lib_ring_buffer_iterator_init(struct channel *chan, struct lib_ring_buffer *buf) ++{ ++ if (buf->iter.allocated) ++ return; ++ ++ buf->iter.allocated = 1; ++ if (chan->iter.read_open && !buf->iter.read_open) { ++ CHAN_WARN_ON(chan, lib_ring_buffer_open_read(buf) != 0); ++ buf->iter.read_open = 1; ++ } ++ ++ /* Add to list of buffers without any current record */ ++ if (chan->backend.config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ list_add(&buf->iter.empty_node, &chan->iter.empty_head); ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++static ++int __cpuinit channel_iterator_cpu_hotplug(struct notifier_block *nb, ++ unsigned long action, ++ void *hcpu) ++{ ++ unsigned int cpu = (unsigned long)hcpu; ++ 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; ++ ++ if (!chan->hp_iter_enable) ++ return NOTIFY_DONE; ++ ++ CHAN_WARN_ON(chan, config->alloc == RING_BUFFER_ALLOC_GLOBAL); ++ ++ switch (action) { ++ case CPU_DOWN_FAILED: ++ case CPU_DOWN_FAILED_FROZEN: ++ case CPU_ONLINE: ++ case CPU_ONLINE_FROZEN: ++ lib_ring_buffer_iterator_init(chan, buf); ++ return NOTIFY_OK; ++ default: ++ return NOTIFY_DONE; ++ } ++} ++#endif ++ ++int channel_iterator_init(struct channel *chan) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ struct lib_ring_buffer *buf; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ int cpu, ret; ++ ++ INIT_LIST_HEAD(&chan->iter.empty_head); ++ ret = lttng_heap_init(&chan->iter.heap, ++ num_possible_cpus(), ++ GFP_KERNEL, buf_is_higher); ++ if (ret) ++ return ret; ++ /* ++ * In case of non-hotplug cpu, if the ring-buffer is allocated ++ * in early initcall, it will not be notified of secondary cpus. ++ * In that off case, we need to allocate for all possible cpus. ++ */ ++#ifdef CONFIG_HOTPLUG_CPU ++ chan->hp_iter_notifier.notifier_call = ++ channel_iterator_cpu_hotplug; ++ chan->hp_iter_notifier.priority = 10; ++ register_cpu_notifier(&chan->hp_iter_notifier); ++ get_online_cpus(); ++ for_each_online_cpu(cpu) { ++ buf = per_cpu_ptr(chan->backend.buf, cpu); ++ lib_ring_buffer_iterator_init(chan, buf); ++ } ++ chan->hp_iter_enable = 1; ++ put_online_cpus(); ++#else ++ for_each_possible_cpu(cpu) { ++ buf = per_cpu_ptr(chan->backend.buf, cpu); ++ lib_ring_buffer_iterator_init(chan, buf); ++ } ++#endif ++ } else { ++ buf = channel_get_ring_buffer(config, chan, 0); ++ lib_ring_buffer_iterator_init(chan, buf); ++ } ++ return 0; ++} ++ ++void channel_iterator_unregister_notifiers(struct channel *chan) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ chan->hp_iter_enable = 0; ++ unregister_cpu_notifier(&chan->hp_iter_notifier); ++ } ++} ++ ++void channel_iterator_free(struct channel *chan) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) ++ lttng_heap_free(&chan->iter.heap); ++} ++ ++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; ++ CHAN_WARN_ON(chan, config->output != RING_BUFFER_ITERATOR); ++ return lib_ring_buffer_open_read(buf); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_iterator_open); ++ ++/* ++ * Note: Iterators must not be mixed with other types of outputs, because an ++ * iterator can leave the buffer in "GET" state, which is not consistent with ++ * other types of output (mmap, splice, raw data read). ++ */ ++void lib_ring_buffer_iterator_release(struct lib_ring_buffer *buf) ++{ ++ lib_ring_buffer_release_read(buf); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_iterator_release); ++ ++int channel_iterator_open(struct channel *chan) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ struct lib_ring_buffer *buf; ++ int ret = 0, cpu; ++ ++ CHAN_WARN_ON(chan, config->output != RING_BUFFER_ITERATOR); ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ get_online_cpus(); ++ /* Allow CPU hotplug to keep track of opened reader */ ++ chan->iter.read_open = 1; ++ for_each_channel_cpu(cpu, chan) { ++ buf = channel_get_ring_buffer(config, chan, cpu); ++ ret = lib_ring_buffer_iterator_open(buf); ++ if (ret) ++ goto error; ++ buf->iter.read_open = 1; ++ } ++ put_online_cpus(); ++ } else { ++ buf = channel_get_ring_buffer(config, chan, 0); ++ ret = lib_ring_buffer_iterator_open(buf); ++ } ++ return ret; ++error: ++ /* Error should always happen on CPU 0, hence no close is required. */ ++ CHAN_WARN_ON(chan, cpu != 0); ++ put_online_cpus(); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(channel_iterator_open); ++ ++void channel_iterator_release(struct channel *chan) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ struct lib_ring_buffer *buf; ++ int cpu; ++ ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU) { ++ get_online_cpus(); ++ for_each_channel_cpu(cpu, chan) { ++ buf = channel_get_ring_buffer(config, chan, cpu); ++ if (buf->iter.read_open) { ++ lib_ring_buffer_iterator_release(buf); ++ buf->iter.read_open = 0; ++ } ++ } ++ chan->iter.read_open = 0; ++ put_online_cpus(); ++ } else { ++ buf = channel_get_ring_buffer(config, chan, 0); ++ lib_ring_buffer_iterator_release(buf); ++ } ++} ++EXPORT_SYMBOL_GPL(channel_iterator_release); ++ ++void lib_ring_buffer_iterator_reset(struct lib_ring_buffer *buf) ++{ ++ struct channel *chan = buf->backend.chan; ++ ++ if (buf->iter.state != ITER_GET_SUBBUF) ++ lib_ring_buffer_put_next_subbuf(buf); ++ buf->iter.state = ITER_GET_SUBBUF; ++ /* Remove from heap (if present). */ ++ if (lttng_heap_cherrypick(&chan->iter.heap, buf)) ++ list_add(&buf->iter.empty_node, &chan->iter.empty_head); ++ buf->iter.timestamp = 0; ++ buf->iter.header_len = 0; ++ buf->iter.payload_len = 0; ++ buf->iter.consumed = 0; ++ buf->iter.read_offset = 0; ++ buf->iter.data_size = 0; ++ /* Don't reset allocated and read_open */ ++} ++ ++void channel_iterator_reset(struct channel *chan) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ struct lib_ring_buffer *buf; ++ int cpu; ++ ++ /* Empty heap, put into empty_head */ ++ while ((buf = lttng_heap_remove(&chan->iter.heap)) != NULL) ++ list_add(&buf->iter.empty_node, &chan->iter.empty_head); ++ ++ for_each_channel_cpu(cpu, chan) { ++ buf = channel_get_ring_buffer(config, chan, cpu); ++ lib_ring_buffer_iterator_reset(buf); ++ } ++ /* Don't reset read_open */ ++ chan->iter.last_qs = 0; ++ chan->iter.last_timestamp = 0; ++ chan->iter.last_cpu = 0; ++ chan->iter.len_left = 0; ++} ++ ++/* ++ * Ring buffer payload extraction read() implementation. ++ */ ++static ++ssize_t channel_ring_buffer_file_read(struct file *filp, ++ char __user *user_buf, ++ size_t count, ++ loff_t *ppos, ++ struct channel *chan, ++ struct lib_ring_buffer *buf, ++ int fusionmerge) ++{ ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ size_t read_count = 0, read_offset; ++ ssize_t len; ++ ++ might_sleep(); ++ if (!access_ok(VERIFY_WRITE, user_buf, count)) ++ return -EFAULT; ++ ++ /* Finish copy of previous record */ ++ if (*ppos != 0) { ++ if (read_count < count) { ++ len = chan->iter.len_left; ++ read_offset = *ppos; ++ if (config->alloc == RING_BUFFER_ALLOC_PER_CPU ++ && fusionmerge) ++ buf = lttng_heap_maximum(&chan->iter.heap); ++ CHAN_WARN_ON(chan, !buf); ++ goto skip_get_next; ++ } ++ } ++ ++ while (read_count < count) { ++ size_t copy_len, space_left; ++ ++ if (fusionmerge) ++ len = channel_get_next_record(chan, &buf); ++ else ++ len = lib_ring_buffer_get_next_record(chan, buf); ++len_test: ++ if (len < 0) { ++ /* ++ * Check if buffer is finalized (end of file). ++ */ ++ if (len == -ENODATA) { ++ /* A 0 read_count will tell about end of file */ ++ goto nodata; ++ } ++ if (filp->f_flags & O_NONBLOCK) { ++ if (!read_count) ++ read_count = -EAGAIN; ++ goto nodata; ++ } else { ++ int error; ++ ++ /* ++ * No data available at the moment, return what ++ * we got. ++ */ ++ if (read_count) ++ goto nodata; ++ ++ /* ++ * Wait for returned len to be >= 0 or -ENODATA. ++ */ ++ if (fusionmerge) ++ error = wait_event_interruptible( ++ chan->read_wait, ++ ((len = channel_get_next_record(chan, ++ &buf)), len != -EAGAIN)); ++ else ++ error = wait_event_interruptible( ++ buf->read_wait, ++ ((len = lib_ring_buffer_get_next_record( ++ chan, buf)), len != -EAGAIN)); ++ CHAN_WARN_ON(chan, len == -EBUSY); ++ if (error) { ++ read_count = error; ++ goto nodata; ++ } ++ CHAN_WARN_ON(chan, len < 0 && len != -ENODATA); ++ goto len_test; ++ } ++ } ++ read_offset = buf->iter.read_offset; ++skip_get_next: ++ space_left = count - read_count; ++ if (len <= space_left) { ++ copy_len = len; ++ chan->iter.len_left = 0; ++ *ppos = 0; ++ } else { ++ copy_len = space_left; ++ chan->iter.len_left = len - copy_len; ++ *ppos = read_offset + copy_len; ++ } ++ if (__lib_ring_buffer_copy_to_user(&buf->backend, read_offset, ++ &user_buf[read_count], ++ copy_len)) { ++ /* ++ * Leave the len_left and ppos values at their current ++ * state, as we currently have a valid event to read. ++ */ ++ return -EFAULT; ++ } ++ read_count += copy_len; ++ }; ++ return read_count; ++ ++nodata: ++ *ppos = 0; ++ chan->iter.len_left = 0; ++ return read_count; ++} ++ ++/** ++ * lib_ring_buffer_file_read - Read buffer record payload. ++ * @filp: file structure pointer. ++ * @buffer: user buffer to read data into. ++ * @count: number of bytes to read. ++ * @ppos: file read position. ++ * ++ * Returns a negative value on error, or the number of bytes read on success. ++ * ppos is used to save the position _within the current record_ between calls ++ * to read(). ++ */ ++static ++ssize_t lib_ring_buffer_file_read(struct file *filp, ++ char __user *user_buf, ++ size_t count, ++ loff_t *ppos) ++{ ++ struct inode *inode = filp->f_dentry->d_inode; ++ struct lib_ring_buffer *buf = inode->i_private; ++ struct channel *chan = buf->backend.chan; ++ ++ return channel_ring_buffer_file_read(filp, user_buf, count, ppos, ++ chan, buf, 0); ++} ++ ++/** ++ * channel_file_read - Read channel record payload. ++ * @filp: file structure pointer. ++ * @buffer: user buffer to read data into. ++ * @count: number of bytes to read. ++ * @ppos: file read position. ++ * ++ * Returns a negative value on error, or the number of bytes read on success. ++ * ppos is used to save the position _within the current record_ between calls ++ * to read(). ++ */ ++static ++ssize_t channel_file_read(struct file *filp, ++ char __user *user_buf, ++ size_t count, ++ loff_t *ppos) ++{ ++ struct inode *inode = filp->f_dentry->d_inode; ++ struct channel *chan = inode->i_private; ++ 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, ++ ppos, chan, NULL, 1); ++ else { ++ struct lib_ring_buffer *buf = ++ channel_get_ring_buffer(config, chan, 0); ++ return channel_ring_buffer_file_read(filp, user_buf, count, ++ ppos, chan, buf, 0); ++ } ++} ++ ++static ++int lib_ring_buffer_file_open(struct inode *inode, struct file *file) ++{ ++ struct lib_ring_buffer *buf = inode->i_private; ++ int ret; ++ ++ ret = lib_ring_buffer_iterator_open(buf); ++ if (ret) ++ return ret; ++ ++ file->private_data = buf; ++ ret = nonseekable_open(inode, file); ++ if (ret) ++ goto release_iter; ++ return 0; ++ ++release_iter: ++ lib_ring_buffer_iterator_release(buf); ++ return ret; ++} ++ ++static ++int lib_ring_buffer_file_release(struct inode *inode, struct file *file) ++{ ++ struct lib_ring_buffer *buf = inode->i_private; ++ ++ lib_ring_buffer_iterator_release(buf); ++ return 0; ++} ++ ++static ++int channel_file_open(struct inode *inode, struct file *file) ++{ ++ struct channel *chan = inode->i_private; ++ int ret; ++ ++ ret = channel_iterator_open(chan); ++ if (ret) ++ return ret; ++ ++ file->private_data = chan; ++ ret = nonseekable_open(inode, file); ++ if (ret) ++ goto release_iter; ++ return 0; ++ ++release_iter: ++ channel_iterator_release(chan); ++ return ret; ++} ++ ++static ++int channel_file_release(struct inode *inode, struct file *file) ++{ ++ struct channel *chan = inode->i_private; ++ ++ channel_iterator_release(chan); ++ return 0; ++} ++ ++const struct file_operations channel_payload_file_operations = { ++ .owner = THIS_MODULE, ++ .open = channel_file_open, ++ .release = channel_file_release, ++ .read = channel_file_read, ++ .llseek = lib_ring_buffer_no_llseek, ++}; ++EXPORT_SYMBOL_GPL(channel_payload_file_operations); ++ ++const struct file_operations lib_ring_buffer_payload_file_operations = { ++ .owner = THIS_MODULE, ++ .open = lib_ring_buffer_file_open, ++ .release = lib_ring_buffer_file_release, ++ .read = lib_ring_buffer_file_read, ++ .llseek = lib_ring_buffer_no_llseek, ++}; ++EXPORT_SYMBOL_GPL(lib_ring_buffer_payload_file_operations); +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +new file mode 100644 +index 0000000..68221ee +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +@@ -0,0 +1,115 @@ ++/* ++ * ring_buffer_mmap.c ++ * ++ * 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> ++ * ++ * Re-using content from kernel/relay.c. ++ * ++ * This file is released under the GPL v2. ++ */ ++ ++#include <linux/module.h> ++#include <linux/mm.h> ++ ++#include "../../wrapper/ringbuffer/backend.h" ++#include "../../wrapper/ringbuffer/frontend.h" ++#include "../../wrapper/ringbuffer/vfs.h" ++ ++/* ++ * fault() vm_op implementation for ring buffer file mapping. ++ */ ++static int lib_ring_buffer_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ++{ ++ 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; ++ 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. ++ */ ++ offset = pgoff << PAGE_SHIFT; ++ sb_bindex = subbuffer_id_get_index(config, buf->backend.buf_rsb.id); ++ if (!(offset >= buf->backend.array[sb_bindex]->mmap_offset ++ && offset < buf->backend.array[sb_bindex]->mmap_offset + ++ buf->backend.chan->backend.subbuf_size)) ++ return VM_FAULT_SIGBUS; ++ /* ++ * ring_buffer_read_get_page() gets the page in the current reader's ++ * pages. ++ */ ++ page = lib_ring_buffer_read_get_page(&buf->backend, offset, &virt); ++ if (!*page) ++ return VM_FAULT_SIGBUS; ++ get_page(*page); ++ vmf->page = *page; ++ ++ return 0; ++} ++ ++/* ++ * vm_ops for ring buffer file mappings. ++ */ ++static const struct vm_operations_struct lib_ring_buffer_mmap_ops = { ++ .fault = lib_ring_buffer_fault, ++}; ++ ++/** ++ * lib_ring_buffer_mmap_buf: - mmap channel buffer to process address space ++ * @buf: ring buffer to map ++ * @vma: vm_area_struct describing memory to be mapped ++ * ++ * Returns 0 if ok, negative on error ++ * ++ * Caller should already have grabbed mmap_sem. ++ */ ++static int lib_ring_buffer_mmap_buf(struct lib_ring_buffer *buf, ++ struct vm_area_struct *vma) ++{ ++ 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; ++ 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; ++ ++ if (length != mmap_buf_len) ++ return -EINVAL; ++ ++ vma->vm_ops = &lib_ring_buffer_mmap_ops; ++ vma->vm_flags |= VM_DONTEXPAND; ++ vma->vm_private_data = buf; ++ ++ return 0; ++} ++ ++/** ++ * lib_ring_buffer_mmap - mmap file op ++ * @filp: the file ++ * @vma: the vma describing what to map ++ * ++ * Calls upon lib_ring_buffer_mmap_buf() to map the file into user space. ++ */ ++int lib_ring_buffer_mmap(struct file *filp, struct vm_area_struct *vma) ++{ ++ struct lib_ring_buffer *buf = filp->private_data; ++ return lib_ring_buffer_mmap_buf(buf, vma); ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_mmap); +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_splice.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_splice.c +new file mode 100644 +index 0000000..ded18ba +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_splice.c +@@ -0,0 +1,202 @@ ++/* ++ * ring_buffer_splice.c ++ * ++ * 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> ++ * ++ * Re-using content from kernel/relay.c. ++ * ++ * This file is released under the GPL v2. ++ */ ++ ++#include <linux/module.h> ++#include <linux/fs.h> ++ ++#include "../../wrapper/splice.h" ++#include "../../wrapper/ringbuffer/backend.h" ++#include "../../wrapper/ringbuffer/frontend.h" ++#include "../../wrapper/ringbuffer/vfs.h" ++ ++#if 0 ++#define printk_dbg(fmt, args...) printk(fmt, args) ++#else ++#define printk_dbg(fmt, args...) ++#endif ++ ++loff_t lib_ring_buffer_no_llseek(struct file *file, loff_t offset, int origin) ++{ ++ return -ESPIPE; ++} ++ ++/* ++ * Release pages from the buffer so splice pipe_to_file can move them. ++ * Called after the pipe has been populated with buffer pages. ++ */ ++static void lib_ring_buffer_pipe_buf_release(struct pipe_inode_info *pipe, ++ struct pipe_buffer *pbuf) ++{ ++ __free_page(pbuf->page); ++} ++ ++static const struct pipe_buf_operations ring_buffer_pipe_buf_ops = { ++ .can_merge = 0, ++ .map = generic_pipe_buf_map, ++ .unmap = generic_pipe_buf_unmap, ++ .confirm = generic_pipe_buf_confirm, ++ .release = lib_ring_buffer_pipe_buf_release, ++ .steal = generic_pipe_buf_steal, ++ .get = generic_pipe_buf_get, ++}; ++ ++/* ++ * Page release operation after splice pipe_to_file ends. ++ */ ++static void lib_ring_buffer_page_release(struct splice_pipe_desc *spd, ++ unsigned int i) ++{ ++ __free_page(spd->pages[i]); ++} ++ ++/* ++ * subbuf_splice_actor - splice up to one subbuf's worth of data ++ */ ++static int subbuf_splice_actor(struct file *in, ++ loff_t *ppos, ++ struct pipe_inode_info *pipe, ++ size_t len, ++ unsigned int flags) ++{ ++ struct lib_ring_buffer *buf = in->private_data; ++ struct channel *chan = buf->backend.chan; ++ 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]; ++ struct splice_pipe_desc spd = { ++ .pages = pages, ++ .nr_pages = 0, ++ .partial = partial, ++ .flags = flags, ++ .ops = &ring_buffer_pipe_buf_ops, ++ .spd_release = lib_ring_buffer_page_release, ++ }; ++ unsigned long consumed_old, roffset; ++ unsigned long bytes_avail; ++ ++ /* ++ * Check that a GET_SUBBUF ioctl has been done before. ++ */ ++ WARN_ON(atomic_long_read(&buf->active_readers) != 1); ++ consumed_old = lib_ring_buffer_get_consumed(config, buf); ++ consumed_old += *ppos; ++ ++ /* ++ * Adjust read len, if longer than what is available. ++ * Max read size is 1 subbuffer due to get_subbuf/put_subbuf for ++ * protection. ++ */ ++ bytes_avail = chan->backend.subbuf_size; ++ WARN_ON(bytes_avail > chan->backend.buf_size); ++ len = min_t(size_t, len, bytes_avail); ++ subbuf_pages = bytes_avail >> PAGE_SHIFT; ++ nr_pages = min_t(unsigned int, subbuf_pages, PIPE_DEF_BUFFERS); ++ roffset = consumed_old & PAGE_MASK; ++ poff = consumed_old & ~PAGE_MASK; ++ printk_dbg(KERN_DEBUG "SPLICE actor len %zu pos %zd write_pos %ld\n", ++ len, (ssize_t)*ppos, lib_ring_buffer_get_offset(config, buf)); ++ ++ for (; spd.nr_pages < nr_pages; spd.nr_pages++) { ++ unsigned int this_len; ++ struct page **page, *new_page; ++ void **virt; ++ ++ if (!len) ++ break; ++ printk_dbg(KERN_DEBUG "SPLICE actor loop len %zu roffset %ld\n", ++ len, roffset); ++ ++ /* ++ * We have to replace the page we are moving into the splice ++ * pipe. ++ */ ++ new_page = alloc_pages_node(cpu_to_node(max(buf->backend.cpu, ++ 0)), ++ GFP_KERNEL | __GFP_ZERO, 0); ++ if (!new_page) ++ break; ++ ++ this_len = PAGE_SIZE - poff; ++ page = lib_ring_buffer_read_get_page(&buf->backend, roffset, &virt); ++ spd.pages[spd.nr_pages] = *page; ++ *page = new_page; ++ *virt = page_address(new_page); ++ spd.partial[spd.nr_pages].offset = poff; ++ spd.partial[spd.nr_pages].len = this_len; ++ ++ poff = 0; ++ roffset += PAGE_SIZE; ++ len -= this_len; ++ } ++ ++ if (!spd.nr_pages) ++ return 0; ++ ++ return wrapper_splice_to_pipe(pipe, &spd); ++} ++ ++ssize_t lib_ring_buffer_splice_read(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags) ++{ ++ struct lib_ring_buffer *buf = in->private_data; ++ struct channel *chan = buf->backend.chan; ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ ssize_t spliced; ++ int ret; ++ ++ if (config->output != RING_BUFFER_SPLICE) ++ return -EINVAL; ++ ++ /* ++ * We require ppos and length to be page-aligned for performance reasons ++ * (no page copy). Size is known using the ioctl ++ * RING_BUFFER_GET_PADDED_SUBBUF_SIZE, which is page-size padded. ++ * We fail when the ppos or len passed is not page-sized, because splice ++ * is not allowed to copy more than the length passed as parameter (so ++ * the ABI does not let us silently copy more than requested to include ++ * padding). ++ */ ++ if (*ppos != PAGE_ALIGN(*ppos) || len != PAGE_ALIGN(len)) ++ return -EINVAL; ++ ++ ret = 0; ++ spliced = 0; ++ ++ printk_dbg(KERN_DEBUG "SPLICE read len %zu pos %zd\n", len, ++ (ssize_t)*ppos); ++ while (len && !spliced) { ++ ret = subbuf_splice_actor(in, ppos, pipe, len, flags); ++ printk_dbg(KERN_DEBUG "SPLICE read loop ret %d\n", ret); ++ if (ret < 0) ++ break; ++ else if (!ret) { ++ if (flags & SPLICE_F_NONBLOCK) ++ ret = -EAGAIN; ++ break; ++ } ++ ++ *ppos += ret; ++ if (ret > len) ++ len = 0; ++ else ++ len -= ret; ++ spliced += ret; ++ } ++ ++ if (spliced) ++ return spliced; ++ ++ return ret; ++} ++EXPORT_SYMBOL_GPL(lib_ring_buffer_splice_read); +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c +new file mode 100644 +index 0000000..1708ffd +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c +@@ -0,0 +1,387 @@ ++/* ++ * 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. ++ */ ++ ++#include <linux/module.h> ++#include <linux/fs.h> ++#include <linux/compat.h> ++ ++#include "../../wrapper/ringbuffer/backend.h" ++#include "../../wrapper/ringbuffer/frontend.h" ++#include "../../wrapper/ringbuffer/vfs.h" ++#include "../../wrapper/poll.h" ++ ++static int put_ulong(unsigned long val, unsigned long arg) ++{ ++ return put_user(val, (unsigned long __user *)arg); ++} ++ ++#ifdef CONFIG_COMPAT ++static int compat_put_ulong(compat_ulong_t val, unsigned long arg) ++{ ++ return put_user(val, (compat_ulong_t __user *)compat_ptr(arg)); ++} ++#endif ++ ++/** ++ * lib_ring_buffer_open - ring buffer open file operation ++ * @inode: opened inode ++ * @file: opened file ++ * ++ * Open implementation. Makes sure only one open instance of a buffer is ++ * done at a given moment. ++ */ ++int lib_ring_buffer_open(struct inode *inode, struct file *file) ++{ ++ struct lib_ring_buffer *buf = inode->i_private; ++ int ret; ++ ++ ret = lib_ring_buffer_open_read(buf); ++ if (ret) ++ return ret; ++ ++ file->private_data = buf; ++ ret = nonseekable_open(inode, file); ++ if (ret) ++ goto release_read; ++ return 0; ++ ++release_read: ++ lib_ring_buffer_release_read(buf); ++ return ret; ++} ++ ++/** ++ * lib_ring_buffer_release - ring buffer release file operation ++ * @inode: opened inode ++ * @file: opened file ++ * ++ * Release implementation. ++ */ ++int lib_ring_buffer_release(struct inode *inode, struct file *file) ++{ ++ struct lib_ring_buffer *buf = file->private_data; ++ ++ lib_ring_buffer_release_read(buf); ++ ++ return 0; ++} ++ ++/** ++ * lib_ring_buffer_poll - ring buffer poll file operation ++ * @filp: the file ++ * @wait: poll table ++ * ++ * Poll implementation. ++ */ ++unsigned int lib_ring_buffer_poll(struct file *filp, poll_table *wait) ++{ ++ 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; ++ int finalized, disabled; ++ ++ if (filp->f_mode & FMODE_READ) { ++ poll_wait_set_exclusive(wait); ++ poll_wait(filp, &buf->read_wait, wait); ++ ++ finalized = lib_ring_buffer_is_finalized(config, buf); ++ disabled = lib_ring_buffer_channel_is_disabled(chan); ++ ++ /* ++ * lib_ring_buffer_is_finalized() contains a smp_rmb() ordering ++ * finalized load before offsets loads. ++ */ ++ WARN_ON(atomic_long_read(&buf->active_readers) != 1); ++retry: ++ if (disabled) ++ return POLLERR; ++ ++ if (subbuf_trunc(lib_ring_buffer_get_offset(config, buf), chan) ++ - subbuf_trunc(lib_ring_buffer_get_consumed(config, buf), chan) ++ == 0) { ++ if (finalized) ++ return POLLHUP; ++ else { ++ /* ++ * The memory barriers ++ * __wait_event()/wake_up_interruptible() take ++ * care of "raw_spin_is_locked" memory ordering. ++ */ ++ if (raw_spin_is_locked(&buf->raw_tick_nohz_spinlock)) ++ goto retry; ++ else ++ return 0; ++ } ++ } else { ++ if (subbuf_trunc(lib_ring_buffer_get_offset(config, buf), ++ chan) ++ - subbuf_trunc(lib_ring_buffer_get_consumed(config, buf), ++ chan) ++ >= chan->backend.buf_size) ++ return POLLPRI | POLLRDBAND; ++ else ++ return POLLIN | POLLRDNORM; ++ } ++ } ++ return mask; ++} ++ ++/** ++ * lib_ring_buffer_ioctl - control ring buffer reader synchronization ++ * ++ * @filp: the file ++ * @cmd: the command ++ * @arg: command arg ++ * ++ * This ioctl implements commands necessary for producer/consumer ++ * and flight recorder reader interaction : ++ * RING_BUFFER_GET_NEXT_SUBBUF ++ * Get the next sub-buffer that can be read. It never blocks. ++ * RING_BUFFER_PUT_NEXT_SUBBUF ++ * Release the currently read sub-buffer. ++ * RING_BUFFER_GET_SUBBUF_SIZE ++ * returns the size of the current sub-buffer. ++ * RING_BUFFER_GET_MAX_SUBBUF_SIZE ++ * returns the maximum size for sub-buffers. ++ * RING_BUFFER_GET_NUM_SUBBUF ++ * returns the number of reader-visible sub-buffers in the per cpu ++ * channel (for mmap). ++ * RING_BUFFER_GET_MMAP_READ_OFFSET ++ * returns the offset of the subbuffer belonging to the reader. ++ * Should only be used for mmap clients. ++ */ ++long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) ++{ ++ struct lib_ring_buffer *buf = filp->private_data; ++ struct channel *chan = buf->backend.chan; ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ ++ if (lib_ring_buffer_channel_is_disabled(chan)) ++ return -EIO; ++ ++ switch (cmd) { ++ case RING_BUFFER_SNAPSHOT: ++ return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot, ++ &buf->prod_snapshot); ++ case RING_BUFFER_SNAPSHOT_GET_CONSUMED: ++ return put_ulong(buf->cons_snapshot, arg); ++ case RING_BUFFER_SNAPSHOT_GET_PRODUCED: ++ return put_ulong(buf->prod_snapshot, arg); ++ case RING_BUFFER_GET_SUBBUF: ++ { ++ unsigned long uconsume; ++ long ret; ++ ++ ret = get_user(uconsume, (unsigned long __user *) arg); ++ if (ret) ++ return ret; /* will return -EFAULT */ ++ ret = lib_ring_buffer_get_subbuf(buf, uconsume); ++ if (!ret) { ++ /* Set file position to zero at each successful "get" */ ++ filp->f_pos = 0; ++ } ++ return ret; ++ } ++ case RING_BUFFER_PUT_SUBBUF: ++ lib_ring_buffer_put_subbuf(buf); ++ return 0; ++ ++ case RING_BUFFER_GET_NEXT_SUBBUF: ++ { ++ long ret; ++ ++ ret = lib_ring_buffer_get_next_subbuf(buf); ++ if (!ret) { ++ /* Set file position to zero at each successful "get" */ ++ filp->f_pos = 0; ++ } ++ return ret; ++ } ++ case RING_BUFFER_PUT_NEXT_SUBBUF: ++ lib_ring_buffer_put_next_subbuf(buf); ++ return 0; ++ case RING_BUFFER_GET_SUBBUF_SIZE: ++ return put_ulong(lib_ring_buffer_get_read_data_size(config, buf), ++ arg); ++ case RING_BUFFER_GET_PADDED_SUBBUF_SIZE: ++ { ++ unsigned long size; ++ ++ size = lib_ring_buffer_get_read_data_size(config, buf); ++ size = PAGE_ALIGN(size); ++ return put_ulong(size, arg); ++ } ++ case RING_BUFFER_GET_MAX_SUBBUF_SIZE: ++ return put_ulong(chan->backend.subbuf_size, arg); ++ case RING_BUFFER_GET_MMAP_LEN: ++ { ++ unsigned long mmap_buf_len; ++ ++ if (config->output != RING_BUFFER_MMAP) ++ return -EINVAL; ++ mmap_buf_len = chan->backend.buf_size; ++ if (chan->backend.extra_reader_sb) ++ mmap_buf_len += chan->backend.subbuf_size; ++ if (mmap_buf_len > INT_MAX) ++ return -EFBIG; ++ return put_ulong(mmap_buf_len, arg); ++ } ++ case RING_BUFFER_GET_MMAP_READ_OFFSET: ++ { ++ unsigned long sb_bindex; ++ ++ if (config->output != RING_BUFFER_MMAP) ++ return -EINVAL; ++ sb_bindex = subbuffer_id_get_index(config, ++ buf->backend.buf_rsb.id); ++ return put_ulong(buf->backend.array[sb_bindex]->mmap_offset, ++ arg); ++ } ++ case RING_BUFFER_FLUSH: ++ lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE); ++ return 0; ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++ ++#ifdef CONFIG_COMPAT ++long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg) ++{ ++ struct lib_ring_buffer *buf = filp->private_data; ++ struct channel *chan = buf->backend.chan; ++ const struct lib_ring_buffer_config *config = chan->backend.config; ++ ++ if (lib_ring_buffer_channel_is_disabled(chan)) ++ return -EIO; ++ ++ switch (cmd) { ++ case RING_BUFFER_SNAPSHOT: ++ return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot, ++ &buf->prod_snapshot); ++ case RING_BUFFER_SNAPSHOT_GET_CONSUMED: ++ return compat_put_ulong(buf->cons_snapshot, arg); ++ case RING_BUFFER_SNAPSHOT_GET_PRODUCED: ++ return compat_put_ulong(buf->prod_snapshot, arg); ++ case RING_BUFFER_GET_SUBBUF: ++ { ++ __u32 uconsume; ++ unsigned long consume; ++ long ret; ++ ++ ret = get_user(uconsume, (__u32 __user *) arg); ++ if (ret) ++ return ret; /* will return -EFAULT */ ++ consume = buf->cons_snapshot; ++ consume &= ~0xFFFFFFFFL; ++ consume |= uconsume; ++ ret = lib_ring_buffer_get_subbuf(buf, consume); ++ if (!ret) { ++ /* Set file position to zero at each successful "get" */ ++ filp->f_pos = 0; ++ } ++ return ret; ++ } ++ case RING_BUFFER_PUT_SUBBUF: ++ lib_ring_buffer_put_subbuf(buf); ++ return 0; ++ ++ case RING_BUFFER_GET_NEXT_SUBBUF: ++ { ++ long ret; ++ ++ ret = lib_ring_buffer_get_next_subbuf(buf); ++ if (!ret) { ++ /* Set file position to zero at each successful "get" */ ++ filp->f_pos = 0; ++ } ++ return ret; ++ } ++ case RING_BUFFER_PUT_NEXT_SUBBUF: ++ lib_ring_buffer_put_next_subbuf(buf); ++ return 0; ++ case RING_BUFFER_GET_SUBBUF_SIZE: ++ { ++ unsigned long data_size; ++ ++ data_size = lib_ring_buffer_get_read_data_size(config, buf); ++ if (data_size > UINT_MAX) ++ return -EFBIG; ++ return put_ulong(data_size, arg); ++ } ++ case RING_BUFFER_GET_PADDED_SUBBUF_SIZE: ++ { ++ unsigned long size; ++ ++ size = lib_ring_buffer_get_read_data_size(config, buf); ++ size = PAGE_ALIGN(size); ++ if (size > UINT_MAX) ++ return -EFBIG; ++ return put_ulong(size, arg); ++ } ++ case RING_BUFFER_GET_MAX_SUBBUF_SIZE: ++ if (chan->backend.subbuf_size > UINT_MAX) ++ return -EFBIG; ++ return put_ulong(chan->backend.subbuf_size, arg); ++ case RING_BUFFER_GET_MMAP_LEN: ++ { ++ unsigned long mmap_buf_len; ++ ++ if (config->output != RING_BUFFER_MMAP) ++ return -EINVAL; ++ mmap_buf_len = chan->backend.buf_size; ++ if (chan->backend.extra_reader_sb) ++ mmap_buf_len += chan->backend.subbuf_size; ++ if (mmap_buf_len > UINT_MAX) ++ return -EFBIG; ++ return put_ulong(mmap_buf_len, arg); ++ } ++ case RING_BUFFER_GET_MMAP_READ_OFFSET: ++ { ++ unsigned long sb_bindex, read_offset; ++ ++ if (config->output != RING_BUFFER_MMAP) ++ return -EINVAL; ++ sb_bindex = subbuffer_id_get_index(config, ++ buf->backend.buf_rsb.id); ++ read_offset = buf->backend.array[sb_bindex]->mmap_offset; ++ if (read_offset > UINT_MAX) ++ return -EINVAL; ++ return put_ulong(read_offset, arg); ++ } ++ case RING_BUFFER_FLUSH: ++ lib_ring_buffer_switch_slow(buf, SWITCH_ACTIVE); ++ return 0; ++ default: ++ return -ENOIOCTLCMD; ++ } ++} ++#endif ++ ++const struct file_operations lib_ring_buffer_file_operations = { ++ .owner = THIS_MODULE, ++ .open = lib_ring_buffer_open, ++ .release = lib_ring_buffer_release, ++ .poll = lib_ring_buffer_poll, ++ .splice_read = lib_ring_buffer_splice_read, ++ .mmap = lib_ring_buffer_mmap, ++ .unlocked_ioctl = lib_ring_buffer_ioctl, ++ .llseek = lib_ring_buffer_no_llseek, ++#ifdef CONFIG_COMPAT ++ .compat_ioctl = lib_ring_buffer_compat_ioctl, ++#endif ++}; ++EXPORT_SYMBOL_GPL(lib_ring_buffer_file_operations); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Ring Buffer Library VFS"); +diff --git a/drivers/staging/lttng/lib/ringbuffer/vatomic.h b/drivers/staging/lttng/lib/ringbuffer/vatomic.h +new file mode 100644 +index 0000000..b944dd6 +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/vatomic.h +@@ -0,0 +1,85 @@ ++#ifndef _LINUX_RING_BUFFER_VATOMIC_H ++#define _LINUX_RING_BUFFER_VATOMIC_H ++ ++/* ++ * linux/ringbuffer/vatomic.h ++ * ++ * Copyright (C) 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <asm/atomic.h> ++#include <asm/local.h> ++ ++/* ++ * Same data type (long) accessed differently depending on configuration. ++ * v field is for non-atomic access (protected by mutual exclusion). ++ * In the fast-path, the ring_buffer_config structure is constant, so the ++ * compiler can statically select the appropriate branch. ++ * local_t is used for per-cpu and per-thread buffers. ++ * atomic_long_t is used for globally shared buffers. ++ */ ++union v_atomic { ++ local_t l; ++ atomic_long_t a; ++ long v; ++}; ++ ++static inline ++long v_read(const struct lib_ring_buffer_config *config, union v_atomic *v_a) ++{ ++ if (config->sync == RING_BUFFER_SYNC_PER_CPU) ++ return local_read(&v_a->l); ++ else ++ return atomic_long_read(&v_a->a); ++} ++ ++static inline ++void v_set(const struct lib_ring_buffer_config *config, union v_atomic *v_a, ++ long v) ++{ ++ if (config->sync == RING_BUFFER_SYNC_PER_CPU) ++ local_set(&v_a->l, v); ++ else ++ atomic_long_set(&v_a->a, v); ++} ++ ++static inline ++void v_add(const struct lib_ring_buffer_config *config, long v, union v_atomic *v_a) ++{ ++ if (config->sync == RING_BUFFER_SYNC_PER_CPU) ++ local_add(v, &v_a->l); ++ else ++ atomic_long_add(v, &v_a->a); ++} ++ ++static inline ++void v_inc(const struct lib_ring_buffer_config *config, union v_atomic *v_a) ++{ ++ if (config->sync == RING_BUFFER_SYNC_PER_CPU) ++ local_inc(&v_a->l); ++ else ++ atomic_long_inc(&v_a->a); ++} ++ ++/* ++ * Non-atomic decrement. Only used by reader, apply to reader-owned subbuffer. ++ */ ++static inline ++void _v_dec(const struct lib_ring_buffer_config *config, union v_atomic *v_a) ++{ ++ --v_a->v; ++} ++ ++static inline ++long v_cmpxchg(const struct lib_ring_buffer_config *config, union v_atomic *v_a, ++ long old, long _new) ++{ ++ if (config->sync == RING_BUFFER_SYNC_PER_CPU) ++ return local_cmpxchg(&v_a->l, old, _new); ++ else ++ return atomic_long_cmpxchg(&v_a->a, old, _new); ++} ++ ++#endif /* _LINUX_RING_BUFFER_VATOMIC_H */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/vfs.h b/drivers/staging/lttng/lib/ringbuffer/vfs.h +new file mode 100644 +index 0000000..d073e4c +--- /dev/null ++++ b/drivers/staging/lttng/lib/ringbuffer/vfs.h +@@ -0,0 +1,89 @@ ++#ifndef _LINUX_RING_BUFFER_VFS_H ++#define _LINUX_RING_BUFFER_VFS_H ++ ++/* ++ * linux/ringbuffer/vfs.h ++ * ++ * (C) Copyright 2005-2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Wait-free ring buffer VFS file operations. ++ * ++ * Author: ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/fs.h> ++#include <linux/poll.h> ++ ++/* VFS API */ ++ ++extern const struct file_operations lib_ring_buffer_file_operations; ++ ++/* ++ * Internal file operations. ++ */ ++ ++int lib_ring_buffer_open(struct inode *inode, struct file *file); ++int lib_ring_buffer_release(struct inode *inode, struct file *file); ++unsigned int lib_ring_buffer_poll(struct file *filp, poll_table *wait); ++ssize_t lib_ring_buffer_splice_read(struct file *in, loff_t *ppos, ++ struct pipe_inode_info *pipe, size_t len, ++ unsigned int flags); ++int lib_ring_buffer_mmap(struct file *filp, struct vm_area_struct *vma); ++ ++/* Ring Buffer ioctl() and ioctl numbers */ ++long lib_ring_buffer_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); ++#ifdef CONFIG_COMPAT ++long lib_ring_buffer_compat_ioctl(struct file *filp, unsigned int cmd, ++ unsigned long arg); ++#endif ++ ++/* ++ * Use RING_BUFFER_GET_NEXT_SUBBUF / RING_BUFFER_PUT_NEXT_SUBBUF to read and ++ * consume sub-buffers sequentially. ++ * ++ * Reading sub-buffers without consuming them can be performed with: ++ * ++ * RING_BUFFER_SNAPSHOT ++ * RING_BUFFER_SNAPSHOT_GET_CONSUMED ++ * RING_BUFFER_SNAPSHOT_GET_PRODUCED ++ * ++ * to get the offset range to consume, and then by passing each sub-buffer ++ * offset to RING_BUFFER_GET_SUBBUF, read the sub-buffer, and then release it ++ * with RING_BUFFER_PUT_SUBBUF. ++ * ++ * Note that the "snapshot" API can be used to read the sub-buffer in reverse ++ * order, which is useful for flight recorder snapshots. ++ */ ++ ++/* Get a snapshot of the current ring buffer producer and consumer positions */ ++#define RING_BUFFER_SNAPSHOT _IO(0xF6, 0x00) ++/* Get the consumer position (iteration start) */ ++#define RING_BUFFER_SNAPSHOT_GET_CONSUMED _IOR(0xF6, 0x01, unsigned long) ++/* Get the producer position (iteration end) */ ++#define RING_BUFFER_SNAPSHOT_GET_PRODUCED _IOR(0xF6, 0x02, unsigned long) ++/* Get exclusive read access to the specified sub-buffer position */ ++#define RING_BUFFER_GET_SUBBUF _IOW(0xF6, 0x03, unsigned long) ++/* Release exclusive sub-buffer access */ ++#define RING_BUFFER_PUT_SUBBUF _IO(0xF6, 0x04) ++ ++/* Get exclusive read access to the next sub-buffer that can be read. */ ++#define RING_BUFFER_GET_NEXT_SUBBUF _IO(0xF6, 0x05) ++/* Release exclusive sub-buffer access, move consumer forward. */ ++#define RING_BUFFER_PUT_NEXT_SUBBUF _IO(0xF6, 0x06) ++/* returns the size of the current sub-buffer, without padding (for mmap). */ ++#define RING_BUFFER_GET_SUBBUF_SIZE _IOR(0xF6, 0x07, unsigned long) ++/* returns the size of the current sub-buffer, with padding (for splice). */ ++#define RING_BUFFER_GET_PADDED_SUBBUF_SIZE _IOR(0xF6, 0x08, unsigned long) ++/* returns the maximum size for sub-buffers. */ ++#define RING_BUFFER_GET_MAX_SUBBUF_SIZE _IOR(0xF6, 0x09, unsigned long) ++/* returns the length to mmap. */ ++#define RING_BUFFER_GET_MMAP_LEN _IOR(0xF6, 0x0A, unsigned long) ++/* returns the offset of the subbuffer belonging to the mmap reader. */ ++#define RING_BUFFER_GET_MMAP_READ_OFFSET _IOR(0xF6, 0x0B, unsigned long) ++/* flush the current sub-buffer */ ++#define RING_BUFFER_FLUSH _IO(0xF6, 0x0C) ++ ++#endif /* _LINUX_RING_BUFFER_VFS_H */ +-- +1.7.9 + diff --git a/patches.lttng/0002-lttng-lib-portable-bitfield-read-write-header.patch b/patches.lttng/0002-lttng-lib-portable-bitfield-read-write-header.patch new file mode 100644 index 0000000000000..1bca3f78fe694 --- /dev/null +++ b/patches.lttng/0002-lttng-lib-portable-bitfield-read-write-header.patch @@ -0,0 +1,421 @@ +From 7430010ec58a189e2ef81d504417299779f47663 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:10 -0500 +Subject: lttng lib: portable bitfield read/write header + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/lib/bitfield.h | 400 ++++++++++++++++++++++++++++++++++ + 1 files changed, 400 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/lib/bitfield.h + +diff --git a/drivers/staging/lttng/lib/bitfield.h b/drivers/staging/lttng/lib/bitfield.h +new file mode 100644 +index 0000000..861e6dc +--- /dev/null ++++ b/drivers/staging/lttng/lib/bitfield.h +@@ -0,0 +1,400 @@ ++#ifndef _BABELTRACE_BITFIELD_H ++#define _BABELTRACE_BITFIELD_H ++ ++/* ++ * BabelTrace ++ * ++ * Bitfields read/write functions. ++ * ++ * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ */ ++ ++#include "../ltt-endian.h" ++ ++#ifndef CHAR_BIT ++#define CHAR_BIT 8 ++#endif ++ ++/* We can't shift a int from 32 bit, >> 32 and << 32 on int is undefined */ ++#define _bt_piecewise_rshift(_v, _shift) \ ++({ \ ++ typeof(_v) ___v = (_v); \ ++ typeof(_shift) ___shift = (_shift); \ ++ unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \ ++ unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \ ++ \ ++ for (; sb; sb--) \ ++ ___v >>= sizeof(___v) * CHAR_BIT - 1; \ ++ ___v >>= final; \ ++}) ++ ++#define _bt_piecewise_lshift(_v, _shift) \ ++({ \ ++ typeof(_v) ___v = (_v); \ ++ typeof(_shift) ___shift = (_shift); \ ++ unsigned long sb = (___shift) / (sizeof(___v) * CHAR_BIT - 1); \ ++ unsigned long final = (___shift) % (sizeof(___v) * CHAR_BIT - 1); \ ++ \ ++ for (; sb; sb--) \ ++ ___v <<= sizeof(___v) * CHAR_BIT - 1; \ ++ ___v <<= final; \ ++}) ++ ++#define _bt_is_signed_type(type) (((type)(-1)) < 0) ++ ++#define _bt_unsigned_cast(type, v) \ ++({ \ ++ (sizeof(v) < sizeof(type)) ? \ ++ ((type) (v)) & (~(~(type) 0 << (sizeof(v) * CHAR_BIT))) : \ ++ (type) (v); \ ++}) ++ ++/* ++ * bt_bitfield_write - write integer to a bitfield in native endianness ++ * ++ * Save integer to the bitfield, which starts at the "start" bit, has "len" ++ * bits. ++ * The inside of a bitfield is from high bits to low bits. ++ * Uses native endianness. ++ * For unsigned "v", pad MSB with 0 if bitfield is larger than v. ++ * For signed "v", sign-extend v if bitfield is larger than v. ++ * ++ * On little endian, bytes are placed from the less significant to the most ++ * significant. Also, consecutive bitfields are placed from lower bits to higher ++ * bits. ++ * ++ * On big endian, bytes are places from most significant to less significant. ++ * Also, consecutive bitfields are placed from higher to lower bits. ++ */ ++ ++#define _bt_bitfield_write_le(_ptr, type, _start, _length, _v) \ ++do { \ ++ typeof(_v) __v = (_v); \ ++ type *__ptr = (void *) (_ptr); \ ++ unsigned long __start = (_start), __length = (_length); \ ++ type mask, cmask; \ ++ unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ ++ unsigned long start_unit, end_unit, this_unit; \ ++ unsigned long end, cshift; /* cshift is "complement shift" */ \ ++ \ ++ if (!__length) \ ++ break; \ ++ \ ++ end = __start + __length; \ ++ start_unit = __start / ts; \ ++ end_unit = (end + (ts - 1)) / ts; \ ++ \ ++ /* Trim v high bits */ \ ++ if (__length < sizeof(__v) * CHAR_BIT) \ ++ __v &= ~((~(typeof(__v)) 0) << __length); \ ++ \ ++ /* We can now append v with a simple "or", shift it piece-wise */ \ ++ this_unit = start_unit; \ ++ if (start_unit == end_unit - 1) { \ ++ mask = ~((~(type) 0) << (__start % ts)); \ ++ if (end % ts) \ ++ mask |= (~(type) 0) << (end % ts); \ ++ cmask = (type) __v << (__start % ts); \ ++ cmask &= ~mask; \ ++ __ptr[this_unit] &= mask; \ ++ __ptr[this_unit] |= cmask; \ ++ break; \ ++ } \ ++ if (__start % ts) { \ ++ cshift = __start % ts; \ ++ mask = ~((~(type) 0) << cshift); \ ++ cmask = (type) __v << cshift; \ ++ cmask &= ~mask; \ ++ __ptr[this_unit] &= mask; \ ++ __ptr[this_unit] |= cmask; \ ++ __v = _bt_piecewise_rshift(__v, ts - cshift); \ ++ __start += ts - cshift; \ ++ this_unit++; \ ++ } \ ++ for (; this_unit < end_unit - 1; this_unit++) { \ ++ __ptr[this_unit] = (type) __v; \ ++ __v = _bt_piecewise_rshift(__v, ts); \ ++ __start += ts; \ ++ } \ ++ if (end % ts) { \ ++ mask = (~(type) 0) << (end % ts); \ ++ cmask = (type) __v; \ ++ cmask &= ~mask; \ ++ __ptr[this_unit] &= mask; \ ++ __ptr[this_unit] |= cmask; \ ++ } else \ ++ __ptr[this_unit] = (type) __v; \ ++} while (0) ++ ++#define _bt_bitfield_write_be(_ptr, type, _start, _length, _v) \ ++do { \ ++ typeof(_v) __v = (_v); \ ++ type *__ptr = (void *) (_ptr); \ ++ unsigned long __start = (_start), __length = (_length); \ ++ type mask, cmask; \ ++ unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ ++ unsigned long start_unit, end_unit, this_unit; \ ++ unsigned long end, cshift; /* cshift is "complement shift" */ \ ++ \ ++ if (!__length) \ ++ break; \ ++ \ ++ end = __start + __length; \ ++ start_unit = __start / ts; \ ++ end_unit = (end + (ts - 1)) / ts; \ ++ \ ++ /* Trim v high bits */ \ ++ if (__length < sizeof(__v) * CHAR_BIT) \ ++ __v &= ~((~(typeof(__v)) 0) << __length); \ ++ \ ++ /* We can now append v with a simple "or", shift it piece-wise */ \ ++ this_unit = end_unit - 1; \ ++ if (start_unit == end_unit - 1) { \ ++ mask = ~((~(type) 0) << ((ts - (end % ts)) % ts)); \ ++ if (__start % ts) \ ++ mask |= (~((type) 0)) << (ts - (__start % ts)); \ ++ cmask = (type) __v << ((ts - (end % ts)) % ts); \ ++ cmask &= ~mask; \ ++ __ptr[this_unit] &= mask; \ ++ __ptr[this_unit] |= cmask; \ ++ break; \ ++ } \ ++ if (end % ts) { \ ++ cshift = end % ts; \ ++ mask = ~((~(type) 0) << (ts - cshift)); \ ++ cmask = (type) __v << (ts - cshift); \ ++ cmask &= ~mask; \ ++ __ptr[this_unit] &= mask; \ ++ __ptr[this_unit] |= cmask; \ ++ __v = _bt_piecewise_rshift(__v, cshift); \ ++ end -= cshift; \ ++ this_unit--; \ ++ } \ ++ for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \ ++ __ptr[this_unit] = (type) __v; \ ++ __v = _bt_piecewise_rshift(__v, ts); \ ++ end -= ts; \ ++ } \ ++ if (__start % ts) { \ ++ mask = (~(type) 0) << (ts - (__start % ts)); \ ++ cmask = (type) __v; \ ++ cmask &= ~mask; \ ++ __ptr[this_unit] &= mask; \ ++ __ptr[this_unit] |= cmask; \ ++ } else \ ++ __ptr[this_unit] = (type) __v; \ ++} while (0) ++ ++/* ++ * bt_bitfield_write - write integer to a bitfield in native endianness ++ * bt_bitfield_write_le - write integer to a bitfield in little endian ++ * bt_bitfield_write_be - write integer to a bitfield in big endian ++ */ ++ ++#if (__BYTE_ORDER == __LITTLE_ENDIAN) ++ ++#define bt_bitfield_write(ptr, type, _start, _length, _v) \ ++ _bt_bitfield_write_le(ptr, type, _start, _length, _v) ++ ++#define bt_bitfield_write_le(ptr, type, _start, _length, _v) \ ++ _bt_bitfield_write_le(ptr, type, _start, _length, _v) ++ ++#define bt_bitfield_write_be(ptr, type, _start, _length, _v) \ ++ _bt_bitfield_write_be(ptr, unsigned char, _start, _length, _v) ++ ++#elif (__BYTE_ORDER == __BIG_ENDIAN) ++ ++#define bt_bitfield_write(ptr, type, _start, _length, _v) \ ++ _bt_bitfield_write_be(ptr, type, _start, _length, _v) ++ ++#define bt_bitfield_write_le(ptr, type, _start, _length, _v) \ ++ _bt_bitfield_write_le(ptr, unsigned char, _start, _length, _v) ++ ++#define bt_bitfield_write_be(ptr, type, _start, _length, _v) \ ++ _bt_bitfield_write_be(ptr, type, _start, _length, _v) ++ ++#else /* (BYTE_ORDER == PDP_ENDIAN) */ ++ ++#error "Byte order not supported" ++ ++#endif ++ ++#define _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ ++do { \ ++ typeof(*(_vptr)) *__vptr = (_vptr); \ ++ typeof(*__vptr) __v; \ ++ type *__ptr = (void *) (_ptr); \ ++ unsigned long __start = (_start), __length = (_length); \ ++ type mask, cmask; \ ++ unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ ++ unsigned long start_unit, end_unit, this_unit; \ ++ unsigned long end, cshift; /* cshift is "complement shift" */ \ ++ \ ++ if (!__length) { \ ++ *__vptr = 0; \ ++ break; \ ++ } \ ++ \ ++ end = __start + __length; \ ++ start_unit = __start / ts; \ ++ end_unit = (end + (ts - 1)) / ts; \ ++ \ ++ this_unit = end_unit - 1; \ ++ if (_bt_is_signed_type(typeof(__v)) \ ++ && (__ptr[this_unit] & ((type) 1 << ((end % ts ? : ts) - 1)))) \ ++ __v = ~(typeof(__v)) 0; \ ++ else \ ++ __v = 0; \ ++ if (start_unit == end_unit - 1) { \ ++ cmask = __ptr[this_unit]; \ ++ cmask >>= (__start % ts); \ ++ if ((end - __start) % ts) { \ ++ mask = ~((~(type) 0) << (end - __start)); \ ++ cmask &= mask; \ ++ } \ ++ __v = _bt_piecewise_lshift(__v, end - __start); \ ++ __v |= _bt_unsigned_cast(typeof(__v), cmask); \ ++ *__vptr = __v; \ ++ break; \ ++ } \ ++ if (end % ts) { \ ++ cshift = end % ts; \ ++ mask = ~((~(type) 0) << cshift); \ ++ cmask = __ptr[this_unit]; \ ++ cmask &= mask; \ ++ __v = _bt_piecewise_lshift(__v, cshift); \ ++ __v |= _bt_unsigned_cast(typeof(__v), cmask); \ ++ end -= cshift; \ ++ this_unit--; \ ++ } \ ++ for (; (long) this_unit >= (long) start_unit + 1; this_unit--) { \ ++ __v = _bt_piecewise_lshift(__v, ts); \ ++ __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ ++ end -= ts; \ ++ } \ ++ if (__start % ts) { \ ++ mask = ~((~(type) 0) << (ts - (__start % ts))); \ ++ cmask = __ptr[this_unit]; \ ++ cmask >>= (__start % ts); \ ++ cmask &= mask; \ ++ __v = _bt_piecewise_lshift(__v, ts - (__start % ts)); \ ++ __v |= _bt_unsigned_cast(typeof(__v), cmask); \ ++ } else { \ ++ __v = _bt_piecewise_lshift(__v, ts); \ ++ __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ ++ } \ ++ *__vptr = __v; \ ++} while (0) ++ ++#define _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ ++do { \ ++ typeof(*(_vptr)) *__vptr = (_vptr); \ ++ typeof(*__vptr) __v; \ ++ type *__ptr = (void *) (_ptr); \ ++ unsigned long __start = (_start), __length = (_length); \ ++ type mask, cmask; \ ++ unsigned long ts = sizeof(type) * CHAR_BIT; /* type size */ \ ++ unsigned long start_unit, end_unit, this_unit; \ ++ unsigned long end, cshift; /* cshift is "complement shift" */ \ ++ \ ++ if (!__length) { \ ++ *__vptr = 0; \ ++ break; \ ++ } \ ++ \ ++ end = __start + __length; \ ++ start_unit = __start / ts; \ ++ end_unit = (end + (ts - 1)) / ts; \ ++ \ ++ this_unit = start_unit; \ ++ if (_bt_is_signed_type(typeof(__v)) \ ++ && (__ptr[this_unit] & ((type) 1 << (ts - (__start % ts) - 1)))) \ ++ __v = ~(typeof(__v)) 0; \ ++ else \ ++ __v = 0; \ ++ if (start_unit == end_unit - 1) { \ ++ cmask = __ptr[this_unit]; \ ++ cmask >>= (ts - (end % ts)) % ts; \ ++ if ((end - __start) % ts) { \ ++ mask = ~((~(type) 0) << (end - __start)); \ ++ cmask &= mask; \ ++ } \ ++ __v = _bt_piecewise_lshift(__v, end - __start); \ ++ __v |= _bt_unsigned_cast(typeof(__v), cmask); \ ++ *__vptr = __v; \ ++ break; \ ++ } \ ++ if (__start % ts) { \ ++ cshift = __start % ts; \ ++ mask = ~((~(type) 0) << (ts - cshift)); \ ++ cmask = __ptr[this_unit]; \ ++ cmask &= mask; \ ++ __v = _bt_piecewise_lshift(__v, ts - cshift); \ ++ __v |= _bt_unsigned_cast(typeof(__v), cmask); \ ++ __start += ts - cshift; \ ++ this_unit++; \ ++ } \ ++ for (; this_unit < end_unit - 1; this_unit++) { \ ++ __v = _bt_piecewise_lshift(__v, ts); \ ++ __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ ++ __start += ts; \ ++ } \ ++ if (end % ts) { \ ++ mask = ~((~(type) 0) << (end % ts)); \ ++ cmask = __ptr[this_unit]; \ ++ cmask >>= ts - (end % ts); \ ++ cmask &= mask; \ ++ __v = _bt_piecewise_lshift(__v, end % ts); \ ++ __v |= _bt_unsigned_cast(typeof(__v), cmask); \ ++ } else { \ ++ __v = _bt_piecewise_lshift(__v, ts); \ ++ __v |= _bt_unsigned_cast(typeof(__v), __ptr[this_unit]);\ ++ } \ ++ *__vptr = __v; \ ++} while (0) ++ ++/* ++ * bt_bitfield_read - read integer from a bitfield in native endianness ++ * bt_bitfield_read_le - read integer from a bitfield in little endian ++ * bt_bitfield_read_be - read integer from a bitfield in big endian ++ */ ++ ++#if (__BYTE_ORDER == __LITTLE_ENDIAN) ++ ++#define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \ ++ _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) ++ ++#define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ ++ _bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) ++ ++#define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ ++ _bt_bitfield_read_be(_ptr, unsigned char, _start, _length, _vptr) ++ ++#elif (__BYTE_ORDER == __BIG_ENDIAN) ++ ++#define bt_bitfield_read(_ptr, type, _start, _length, _vptr) \ ++ _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) ++ ++#define bt_bitfield_read_le(_ptr, type, _start, _length, _vptr) \ ++ _bt_bitfield_read_le(_ptr, unsigned char, _start, _length, _vptr) ++ ++#define bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) \ ++ _bt_bitfield_read_be(_ptr, type, _start, _length, _vptr) ++ ++#else /* (__BYTE_ORDER == __PDP_ENDIAN) */ ++ ++#error "Byte order not supported" ++ ++#endif ++ ++#endif /* _BABELTRACE_BITFIELD_H */ +-- +1.7.9 + diff --git a/patches.lttng/0003-lttng-BUILD_RUNTIME_BUG_ON.patch b/patches.lttng/0003-lttng-BUILD_RUNTIME_BUG_ON.patch new file mode 100644 index 0000000000000..a94b2ea072151 --- /dev/null +++ b/patches.lttng/0003-lttng-BUILD_RUNTIME_BUG_ON.patch @@ -0,0 +1,50 @@ +From a643061cb861ebb18e0292b7510dd9879b598ae0 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:11 -0500 +Subject: lttng: BUILD_RUNTIME_BUG_ON + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/lib/bug.h | 29 +++++++++++++++++++++++++++++ + 1 files changed, 29 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/lib/bug.h + +diff --git a/drivers/staging/lttng/lib/bug.h b/drivers/staging/lttng/lib/bug.h +new file mode 100644 +index 0000000..8243cc9 +--- /dev/null ++++ b/drivers/staging/lttng/lib/bug.h +@@ -0,0 +1,29 @@ ++#ifndef _LTTNG_BUG_H ++#define _LTTNG_BUG_H ++ ++/* ++ * lib/bug.h ++ * ++ * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++/** ++ * BUILD_RUNTIME_BUG_ON - check condition at build (if constant) or runtime ++ * @condition: the condition which should be false. ++ * ++ * If the condition is a constant and true, the compiler will generate a build ++ * error. If the condition is not constant, a BUG will be triggered at runtime ++ * if the condition is ever true. If the condition is constant and false, no ++ * code is emitted. ++ */ ++#define BUILD_RUNTIME_BUG_ON(condition) \ ++ do { \ ++ if (__builtin_constant_p(condition)) \ ++ BUILD_BUG_ON(condition); \ ++ else \ ++ BUG_ON(condition); \ ++ } while (0) ++ ++#endif +-- +1.7.9 + diff --git a/patches.lttng/0004-lttng-offset-alignment-header.patch b/patches.lttng/0004-lttng-offset-alignment-header.patch new file mode 100644 index 0000000000000..4ddd02356b96e --- /dev/null +++ b/patches.lttng/0004-lttng-offset-alignment-header.patch @@ -0,0 +1,82 @@ +From 2d31597d37ec8842b9575005190fde2898764628 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:12 -0500 +Subject: lttng: offset alignment header + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/lib/align.h | 61 +++++++++++++++++++++++++++++++++++++ + 1 files changed, 61 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/lib/align.h + +diff --git a/drivers/staging/lttng/lib/align.h b/drivers/staging/lttng/lib/align.h +new file mode 100644 +index 0000000..0b86100 +--- /dev/null ++++ b/drivers/staging/lttng/lib/align.h +@@ -0,0 +1,61 @@ ++#ifndef _LTTNG_ALIGN_H ++#define _LTTNG_ALIGN_H ++ ++/* ++ * lib/align.h ++ * ++ * (C) Copyright 2010-2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#ifdef __KERNEL__ ++ ++#include <linux/types.h> ++#include "bug.h" ++ ++#define ALIGN_FLOOR(x, a) __ALIGN_FLOOR_MASK(x, (typeof(x)) (a) - 1) ++#define __ALIGN_FLOOR_MASK(x, mask) ((x) & ~(mask)) ++#define PTR_ALIGN_FLOOR(p, a) \ ++ ((typeof(p)) ALIGN_FLOOR((unsigned long) (p), a)) ++ ++/* ++ * Align pointer on natural object alignment. ++ */ ++#define object_align(obj) PTR_ALIGN(obj, __alignof__(*(obj))) ++#define object_align_floor(obj) PTR_ALIGN_FLOOR(obj, __alignof__(*(obj))) ++ ++/** ++ * offset_align - Calculate the offset needed to align an object on its natural ++ * alignment towards higher addresses. ++ * @align_drift: object offset from an "alignment"-aligned address. ++ * @alignment: natural object alignment. Must be non-zero, power of 2. ++ * ++ * Returns the offset that must be added to align towards higher ++ * addresses. ++ */ ++#define offset_align(align_drift, alignment) \ ++ ({ \ ++ BUILD_RUNTIME_BUG_ON((alignment) == 0 \ ++ || ((alignment) & ((alignment) - 1))); \ ++ (((alignment) - (align_drift)) & ((alignment) - 1)); \ ++ }) ++ ++/** ++ * offset_align_floor - Calculate the offset needed to align an object ++ * on its natural alignment towards lower addresses. ++ * @align_drift: object offset from an "alignment"-aligned address. ++ * @alignment: natural object alignment. Must be non-zero, power of 2. ++ * ++ * Returns the offset that must be substracted to align towards lower addresses. ++ */ ++#define offset_align_floor(align_drift, alignment) \ ++ ({ \ ++ BUILD_RUNTIME_BUG_ON((alignment) == 0 \ ++ || ((alignment) & ((alignment) - 1))); \ ++ (((align_drift) - (alignment)) & ((alignment) - 1); \ ++ }) ++ ++#endif /* __KERNEL__ */ ++ ++#endif +-- +1.7.9 + diff --git a/patches.lttng/0005-lttng-libs-add-Makefile.patch b/patches.lttng/0005-lttng-libs-add-Makefile.patch new file mode 100644 index 0000000000000..2c2b608ab14e9 --- /dev/null +++ b/patches.lttng/0005-lttng-libs-add-Makefile.patch @@ -0,0 +1,32 @@ +From 848afbd72ed02db1ed20ae7917c241983df7b314 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:13 -0500 +Subject: lttng libs: add Makefile + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/lib/Makefile | 11 +++++++++++ + 1 files changed, 11 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/lib/Makefile + +diff --git a/drivers/staging/lttng/lib/Makefile b/drivers/staging/lttng/lib/Makefile +new file mode 100644 +index 0000000..e5735ec +--- /dev/null ++++ b/drivers/staging/lttng/lib/Makefile +@@ -0,0 +1,11 @@ ++obj-m += lib-ring-buffer.o ++ ++lib-ring-buffer-objs := \ ++ ringbuffer/ring_buffer_backend.o \ ++ ringbuffer/ring_buffer_frontend.o \ ++ ringbuffer/ring_buffer_iterator.o \ ++ ringbuffer/ring_buffer_vfs.o \ ++ ringbuffer/ring_buffer_splice.o \ ++ ringbuffer/ring_buffer_mmap.o \ ++ prio_heap/lttng_prio_heap.o \ ++ ../wrapper/splice.o +-- +1.7.9 + diff --git a/patches.lttng/0006-lttng-wrappers.patch b/patches.lttng/0006-lttng-wrappers.patch new file mode 100644 index 0000000000000..f31856354014a --- /dev/null +++ b/patches.lttng/0006-lttng-wrappers.patch @@ -0,0 +1,625 @@ +From 69e1242eaab021eb6a4110a671af1e443fbf704d Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:14 -0500 +Subject: lttng wrappers + +Implement wrappers for compatibility with older kernel versions and +kernels with had the libringbuffer (old) patchset applied. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/wrapper/ftrace.h | 70 ++++++++++++++++++ + drivers/staging/lttng/wrapper/inline_memcpy.h | 11 +++ + drivers/staging/lttng/wrapper/kallsyms.h | 28 +++++++ + drivers/staging/lttng/wrapper/perf.h | 32 ++++++++ + drivers/staging/lttng/wrapper/poll.h | 14 ++++ + drivers/staging/lttng/wrapper/ringbuffer/api.h | 1 + + drivers/staging/lttng/wrapper/ringbuffer/backend.h | 1 + + .../lttng/wrapper/ringbuffer/backend_internal.h | 2 + + .../lttng/wrapper/ringbuffer/backend_types.h | 1 + + drivers/staging/lttng/wrapper/ringbuffer/config.h | 1 + + .../staging/lttng/wrapper/ringbuffer/frontend.h | 1 + + .../lttng/wrapper/ringbuffer/frontend_api.h | 1 + + .../lttng/wrapper/ringbuffer/frontend_internal.h | 1 + + .../lttng/wrapper/ringbuffer/frontend_types.h | 1 + + .../staging/lttng/wrapper/ringbuffer/iterator.h | 1 + + drivers/staging/lttng/wrapper/ringbuffer/nohz.h | 1 + + drivers/staging/lttng/wrapper/ringbuffer/vatomic.h | 1 + + drivers/staging/lttng/wrapper/ringbuffer/vfs.h | 1 + + drivers/staging/lttng/wrapper/spinlock.h | 26 +++++++ + drivers/staging/lttng/wrapper/splice.c | 46 ++++++++++++ + drivers/staging/lttng/wrapper/splice.h | 23 ++++++ + drivers/staging/lttng/wrapper/trace-clock.h | 75 ++++++++++++++++++++ + drivers/staging/lttng/wrapper/uuid.h | 29 ++++++++ + drivers/staging/lttng/wrapper/vmalloc.h | 49 +++++++++++++ + 24 files changed, 417 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/wrapper/ftrace.h + create mode 100644 drivers/staging/lttng/wrapper/inline_memcpy.h + create mode 100644 drivers/staging/lttng/wrapper/kallsyms.h + create mode 100644 drivers/staging/lttng/wrapper/perf.h + create mode 100644 drivers/staging/lttng/wrapper/poll.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/api.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/backend.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/backend_internal.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/backend_types.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/config.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/frontend.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/frontend_api.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/frontend_internal.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/frontend_types.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/iterator.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/nohz.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/vatomic.h + create mode 100644 drivers/staging/lttng/wrapper/ringbuffer/vfs.h + create mode 100644 drivers/staging/lttng/wrapper/spinlock.h + create mode 100644 drivers/staging/lttng/wrapper/splice.c + create mode 100644 drivers/staging/lttng/wrapper/splice.h + create mode 100644 drivers/staging/lttng/wrapper/trace-clock.h + create mode 100644 drivers/staging/lttng/wrapper/uuid.h + create mode 100644 drivers/staging/lttng/wrapper/vmalloc.h + +diff --git a/drivers/staging/lttng/wrapper/ftrace.h b/drivers/staging/lttng/wrapper/ftrace.h +new file mode 100644 +index 0000000..ace33c5 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ftrace.h +@@ -0,0 +1,70 @@ ++#ifndef _LTT_WRAPPER_FTRACE_H ++#define _LTT_WRAPPER_FTRACE_H ++ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * 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. ++ */ ++ ++#include <linux/ftrace.h> ++ ++#ifdef CONFIG_KALLSYMS ++ ++#include <linux/kallsyms.h> ++#include "kallsyms.h" ++ ++static inline ++int wrapper_register_ftrace_function_probe(char *glob, ++ struct ftrace_probe_ops *ops, void *data) ++{ ++ int (*register_ftrace_function_probe_sym)(char *glob, ++ struct ftrace_probe_ops *ops, void *data); ++ ++ register_ftrace_function_probe_sym = (void *) kallsyms_lookup_funcptr("register_ftrace_function_probe"); ++ if (register_ftrace_function_probe_sym) { ++ return register_ftrace_function_probe_sym(glob, ops, data); ++ } else { ++ printk(KERN_WARNING "LTTng: register_ftrace_function_probe symbol lookup failed.\n"); ++ return -EINVAL; ++ } ++} ++ ++static inline ++void wrapper_unregister_ftrace_function_probe(char *glob, ++ struct ftrace_probe_ops *ops, void *data) ++{ ++ void (*unregister_ftrace_function_probe_sym)(char *glob, ++ struct ftrace_probe_ops *ops, void *data); ++ ++ unregister_ftrace_function_probe_sym = (void *) kallsyms_lookup_funcptr("unregister_ftrace_function_probe"); ++ if (unregister_ftrace_function_probe_sym) { ++ unregister_ftrace_function_probe_sym(glob, ops, data); ++ } else { ++ printk(KERN_WARNING "LTTng: unregister_ftrace_function_probe symbol lookup failed.\n"); ++ WARN_ON(1); ++ } ++} ++ ++#else ++ ++static inline ++int wrapper_register_ftrace_function_probe(char *glob, ++ struct ftrace_probe_ops *ops, void *data) ++{ ++ return register_ftrace_function_probe(glob, ops, data); ++} ++ ++static inline ++void wrapper_unregister_ftrace_function_probe(char *glob, ++ struct ftrace_probe_ops *ops, void *data) ++{ ++ return unregister_ftrace_function_probe(glob, ops, data); ++} ++#endif ++ ++#endif /* _LTT_WRAPPER_FTRACE_H */ +diff --git a/drivers/staging/lttng/wrapper/inline_memcpy.h b/drivers/staging/lttng/wrapper/inline_memcpy.h +new file mode 100644 +index 0000000..33150cd +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/inline_memcpy.h +@@ -0,0 +1,11 @@ ++/* ++ * wrapper/inline_memcpy.h ++ * ++ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#if !defined(__HAVE_ARCH_INLINE_MEMCPY) && !defined(inline_memcpy) ++#define inline_memcpy memcpy ++#endif +diff --git a/drivers/staging/lttng/wrapper/kallsyms.h b/drivers/staging/lttng/wrapper/kallsyms.h +new file mode 100644 +index 0000000..bb45f38 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/kallsyms.h +@@ -0,0 +1,28 @@ ++#ifndef _LTT_WRAPPER_KALLSYMS_H ++#define _LTT_WRAPPER_KALLSYMS_H ++ ++/* ++ * Copyright (C) 2011 Avik Sil (avik.sil@linaro.org) ++ * ++ * 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. ++ */ ++ ++static inline ++unsigned long kallsyms_lookup_funcptr(const char *name) ++{ ++ unsigned long addr; ++ ++ addr = kallsyms_lookup_name(name); ++#ifdef CONFIG_ARM ++#ifdef CONFIG_THUMB2_KERNEL ++ if (addr) ++ addr |= 1; /* set bit 0 in address for thumb mode */ ++#endif ++#endif ++ return addr; ++} ++#endif /* _LTT_WRAPPER_KALLSYMS_H */ +diff --git a/drivers/staging/lttng/wrapper/perf.h b/drivers/staging/lttng/wrapper/perf.h +new file mode 100644 +index 0000000..9a6dbfc +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/perf.h +@@ -0,0 +1,32 @@ ++#ifndef _LTT_WRAPPER_PERF_H ++#define _LTT_WRAPPER_PERF_H ++ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/perf_event.h> ++ ++#if defined(CONFIG_PERF_EVENTS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,99)) ++static inline struct perf_event * ++wrapper_perf_event_create_kernel_counter(struct perf_event_attr *attr, ++ int cpu, ++ struct task_struct *task, ++ perf_overflow_handler_t callback) ++{ ++ return perf_event_create_kernel_counter(attr, cpu, task, callback, NULL); ++} ++#else ++static inline struct perf_event * ++wrapper_perf_event_create_kernel_counter(struct perf_event_attr *attr, ++ int cpu, ++ struct task_struct *task, ++ perf_overflow_handler_t callback) ++{ ++ return perf_event_create_kernel_counter(attr, cpu, task, callback); ++} ++#endif ++ ++#endif /* _LTT_WRAPPER_PERF_H */ +diff --git a/drivers/staging/lttng/wrapper/poll.h b/drivers/staging/lttng/wrapper/poll.h +new file mode 100644 +index 0000000..9c2d18f +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/poll.h +@@ -0,0 +1,14 @@ ++#ifndef _LTTNG_WRAPPER_POLL_H ++#define _LTTNG_WRAPPER_POLL_H ++ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/poll.h> ++ ++#define poll_wait_set_exclusive(poll_table) ++ ++#endif /* _LTTNG_WRAPPER_POLL_H */ +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/api.h b/drivers/staging/lttng/wrapper/ringbuffer/api.h +new file mode 100644 +index 0000000..182bee2 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/api.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/api.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/backend.h b/drivers/staging/lttng/wrapper/ringbuffer/backend.h +new file mode 100644 +index 0000000..bfdd39d +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/backend.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/backend.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/backend_internal.h b/drivers/staging/lttng/wrapper/ringbuffer/backend_internal.h +new file mode 100644 +index 0000000..00d45e4 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/backend_internal.h +@@ -0,0 +1,2 @@ ++#include "../../wrapper/inline_memcpy.h" ++#include "../../lib/ringbuffer/backend_internal.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/backend_types.h b/drivers/staging/lttng/wrapper/ringbuffer/backend_types.h +new file mode 100644 +index 0000000..c59effd +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/backend_types.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/backend_types.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/config.h b/drivers/staging/lttng/wrapper/ringbuffer/config.h +new file mode 100644 +index 0000000..0ce7a9d +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/config.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/config.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/frontend.h b/drivers/staging/lttng/wrapper/ringbuffer/frontend.h +new file mode 100644 +index 0000000..7c6c070 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/frontend.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/frontend.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/frontend_api.h b/drivers/staging/lttng/wrapper/ringbuffer/frontend_api.h +new file mode 100644 +index 0000000..b03c501 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/frontend_api.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/frontend_api.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/frontend_internal.h b/drivers/staging/lttng/wrapper/ringbuffer/frontend_internal.h +new file mode 100644 +index 0000000..1899101 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/frontend_internal.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/frontend_internal.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/frontend_types.h b/drivers/staging/lttng/wrapper/ringbuffer/frontend_types.h +new file mode 100644 +index 0000000..0c23244 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/frontend_types.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/frontend_types.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/iterator.h b/drivers/staging/lttng/wrapper/ringbuffer/iterator.h +new file mode 100644 +index 0000000..76e9edb +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/iterator.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/iterator.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/nohz.h b/drivers/staging/lttng/wrapper/ringbuffer/nohz.h +new file mode 100644 +index 0000000..9fbb84d +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/nohz.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/nohz.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/vatomic.h b/drivers/staging/lttng/wrapper/ringbuffer/vatomic.h +new file mode 100644 +index 0000000..d578445 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/vatomic.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/vatomic.h" +diff --git a/drivers/staging/lttng/wrapper/ringbuffer/vfs.h b/drivers/staging/lttng/wrapper/ringbuffer/vfs.h +new file mode 100644 +index 0000000..f8e9ed9 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/ringbuffer/vfs.h +@@ -0,0 +1 @@ ++#include "../../lib/ringbuffer/vfs.h" +diff --git a/drivers/staging/lttng/wrapper/spinlock.h b/drivers/staging/lttng/wrapper/spinlock.h +new file mode 100644 +index 0000000..8b1ad99 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/spinlock.h +@@ -0,0 +1,26 @@ ++#ifndef _LTT_WRAPPER_SPINLOCK_H ++#define _LTT_WRAPPER_SPINLOCK_H ++ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/version.h> ++ ++#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)) ++ ++#include <linux/string.h> ++ ++#define raw_spin_lock_init(lock) \ ++ do { \ ++ raw_spinlock_t __lock = __RAW_SPIN_LOCK_UNLOCKED; \ ++ memcpy(lock, &__lock, sizeof(lock)); \ ++ } while (0) ++ ++#define raw_spin_is_locked(lock) __raw_spin_is_locked(lock) ++ ++ ++#endif ++#endif /* _LTT_WRAPPER_SPINLOCK_H */ +diff --git a/drivers/staging/lttng/wrapper/splice.c b/drivers/staging/lttng/wrapper/splice.c +new file mode 100644 +index 0000000..ba224ee +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/splice.c +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * 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. ++ */ ++ ++#ifdef CONFIG_KALLSYMS ++ ++#include <linux/kallsyms.h> ++#include <linux/fs.h> ++#include <linux/splice.h> ++#include "kallsyms.h" ++ ++static ++ssize_t (*splice_to_pipe_sym)(struct pipe_inode_info *pipe, ++ struct splice_pipe_desc *spd); ++ ++ssize_t wrapper_splice_to_pipe(struct pipe_inode_info *pipe, ++ struct splice_pipe_desc *spd) ++{ ++ if (!splice_to_pipe_sym) ++ splice_to_pipe_sym = (void *) kallsyms_lookup_funcptr("splice_to_pipe"); ++ if (splice_to_pipe_sym) { ++ return splice_to_pipe_sym(pipe, spd); ++ } else { ++ printk(KERN_WARNING "LTTng: splice_to_pipe symbol lookup failed.\n"); ++ return -ENOSYS; ++ } ++} ++ ++#else ++ ++#include <linux/fs.h> ++#include <linux/splice.h> ++ ++ssize_t wrapper_splice_to_pipe(struct pipe_inode_info *pipe, ++ struct splice_pipe_desc *spd) ++{ ++ return splice_to_pipe(pipe, spd); ++} ++ ++#endif +diff --git a/drivers/staging/lttng/wrapper/splice.h b/drivers/staging/lttng/wrapper/splice.h +new file mode 100644 +index 0000000..f75309a +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/splice.h +@@ -0,0 +1,23 @@ ++#ifndef _LTT_WRAPPER_SPLICE_H ++#define _LTT_WRAPPER_SPLICE_H ++ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * 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. ++ */ ++ ++#include <linux/splice.h> ++ ++ssize_t wrapper_splice_to_pipe(struct pipe_inode_info *pipe, ++ struct splice_pipe_desc *spd); ++ ++#ifndef PIPE_DEF_BUFFERS ++#define PIPE_DEF_BUFFERS 16 ++#endif ++ ++#endif /* _LTT_WRAPPER_SPLICE_H */ +diff --git a/drivers/staging/lttng/wrapper/trace-clock.h b/drivers/staging/lttng/wrapper/trace-clock.h +new file mode 100644 +index 0000000..8b77428 +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/trace-clock.h +@@ -0,0 +1,75 @@ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * 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. ++ */ ++ ++#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 */ ++ ++#include <linux/hardirq.h> ++#include <linux/ktime.h> ++#include <linux/time.h> ++#include <linux/hrtimer.h> ++ ++static inline u64 trace_clock_monotonic_wrapper(void) ++{ ++ ktime_t ktime; ++ ++ /* ++ * Refuse to trace from NMIs with this wrapper, because an NMI could ++ * nest over the xtime write seqlock and deadlock. ++ */ ++ if (in_nmi()) ++ return (u64) -EIO; ++ ++ ktime = ktime_get(); ++ return (u64) ktime.tv64; ++} ++ ++static inline u32 trace_clock_read32(void) ++{ ++ return (u32) trace_clock_monotonic_wrapper(); ++} ++ ++static inline u64 trace_clock_read64(void) ++{ ++ return (u64) trace_clock_monotonic_wrapper(); ++} ++ ++static inline u64 trace_clock_frequency(void) ++{ ++ return (u64)NSEC_PER_SEC; ++} ++ ++static inline u32 trace_clock_freq_scale(void) ++{ ++ return 1; ++} ++ ++static inline int get_trace_clock(void) ++{ ++ 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"); ++ printk(KERN_WARNING " LTTng trace clocks.\n"); ++ printk(KERN_WARNING "Integration of the LTTng 0.x trace clocks into LTTng 2.0 is planned\n"); ++ printk(KERN_WARNING "in a near future.\n"); ++ ++ return 0; ++} ++ ++static inline void put_trace_clock(void) ++{ ++} ++ ++#endif /* CONFIG_HAVE_TRACE_CLOCK */ ++ ++#endif /* _LTT_TRACE_CLOCK_H */ +diff --git a/drivers/staging/lttng/wrapper/uuid.h b/drivers/staging/lttng/wrapper/uuid.h +new file mode 100644 +index 0000000..bfa67ff +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/uuid.h +@@ -0,0 +1,29 @@ ++#ifndef _LTT_WRAPPER_UUID_H ++#define _LTT_WRAPPER_UUID_H ++ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/version.h> ++ ++#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)) ++#include <linux/uuid.h> ++#else ++ ++#include <linux/random.h> ++ ++typedef struct { ++ __u8 b[16]; ++} uuid_le; ++ ++static inline ++void uuid_le_gen(uuid_le *u) ++{ ++ generate_random_uuid(u->b); ++} ++ ++#endif ++#endif /* _LTT_WRAPPER_UUID_H */ +diff --git a/drivers/staging/lttng/wrapper/vmalloc.h b/drivers/staging/lttng/wrapper/vmalloc.h +new file mode 100644 +index 0000000..765f2ad +--- /dev/null ++++ b/drivers/staging/lttng/wrapper/vmalloc.h +@@ -0,0 +1,49 @@ ++#ifndef _LTT_WRAPPER_VMALLOC_H ++#define _LTT_WRAPPER_VMALLOC_H ++ ++/* ++ * Copyright (C) 2011 Mathieu Desnoyers (mathieu.desnoyers@efficios.com) ++ * ++ * 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. ++ */ ++ ++#ifdef CONFIG_KALLSYMS ++ ++#include <linux/kallsyms.h> ++#include "kallsyms.h" ++ ++static inline ++void wrapper_vmalloc_sync_all(void) ++{ ++ void (*vmalloc_sync_all_sym)(void); ++ ++ vmalloc_sync_all_sym = (void *) kallsyms_lookup_funcptr("vmalloc_sync_all"); ++ if (vmalloc_sync_all_sym) { ++ vmalloc_sync_all_sym(); ++ } else { ++#ifdef CONFIG_X86 ++ /* ++ * Only x86 needs vmalloc_sync_all to make sure LTTng does not ++ * trigger recursive page faults. ++ */ ++ printk(KERN_WARNING "LTTng: vmalloc_sync_all symbol lookup failed.\n"); ++ printk(KERN_WARNING "Page fault handler and NMI tracing might trigger faults.\n"); ++#endif ++ } ++} ++#else ++ ++#include <linux/vmalloc.h> ++ ++static inline ++void wrapper_vmalloc_sync_all(void) ++{ ++ return vmalloc_sync_all(); ++} ++#endif ++ ++#endif /* _LTT_WRAPPER_VMALLOC_H */ +-- +1.7.9 + diff --git a/patches.lttng/0007-lttng-instrumentation-tracepoint-events.patch b/patches.lttng/0007-lttng-instrumentation-tracepoint-events.patch new file mode 100644 index 0000000000000..2aa7da85ea9ea --- /dev/null +++ b/patches.lttng/0007-lttng-instrumentation-tracepoint-events.patch @@ -0,0 +1,3227 @@ +From 763be8c0a919015a3c1e205005176d4aacec22e3 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:15 -0500 +Subject: lttng instrumentation: tracepoint events + +Modifications to the in-kernel TRACE_EVENT are needed to generate the +compact event descriptions and the probe code LTTng generates. These +changes could apply to upstream TRACE_EVENT, but requires changing the +in-kernel API. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + .../staging/lttng/instrumentation/events/README | 7 + + .../instrumentation/events/lttng-module/block.h | 626 ++++++++++++++++++++ + .../instrumentation/events/lttng-module/irq.h | 155 +++++ + .../instrumentation/events/lttng-module/kvm.h | 312 ++++++++++ + .../instrumentation/events/lttng-module/lttng.h | 34 ++ + .../instrumentation/events/lttng-module/sched.h | 400 +++++++++++++ + .../instrumentation/events/lttng-module/syscalls.h | 76 +++ + .../lttng/instrumentation/events/mainline/block.h | 569 ++++++++++++++++++ + .../lttng/instrumentation/events/mainline/irq.h | 150 +++++ + .../lttng/instrumentation/events/mainline/kvm.h | 312 ++++++++++ + .../lttng/instrumentation/events/mainline/sched.h | 397 +++++++++++++ + .../instrumentation/events/mainline/syscalls.h | 75 +++ + 12 files changed, 3113 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/instrumentation/events/README + create mode 100644 drivers/staging/lttng/instrumentation/events/lttng-module/block.h + create mode 100644 drivers/staging/lttng/instrumentation/events/lttng-module/irq.h + create mode 100644 drivers/staging/lttng/instrumentation/events/lttng-module/kvm.h + create mode 100644 drivers/staging/lttng/instrumentation/events/lttng-module/lttng.h + create mode 100644 drivers/staging/lttng/instrumentation/events/lttng-module/sched.h + create mode 100644 drivers/staging/lttng/instrumentation/events/lttng-module/syscalls.h + create mode 100644 drivers/staging/lttng/instrumentation/events/mainline/block.h + create mode 100644 drivers/staging/lttng/instrumentation/events/mainline/irq.h + create mode 100644 drivers/staging/lttng/instrumentation/events/mainline/kvm.h + create mode 100644 drivers/staging/lttng/instrumentation/events/mainline/sched.h + create mode 100644 drivers/staging/lttng/instrumentation/events/mainline/syscalls.h + +diff --git a/drivers/staging/lttng/instrumentation/events/README b/drivers/staging/lttng/instrumentation/events/README +new file mode 100644 +index 0000000..dad2cbb +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/README +@@ -0,0 +1,7 @@ ++The workflow for updating patches from newer kernel: ++ ++Diff mainline/ and lttng-module/ directories. ++ ++Pull the new headers from mainline kernel to mainline/. ++Copy them into lttng-modules. ++Apply diff. Fix conflicts. +diff --git a/drivers/staging/lttng/instrumentation/events/lttng-module/block.h b/drivers/staging/lttng/instrumentation/events/lttng-module/block.h +new file mode 100644 +index 0000000..42184f3 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/lttng-module/block.h +@@ -0,0 +1,626 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM block ++ ++#if !defined(_TRACE_BLOCK_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_BLOCK_H ++ ++#include <linux/blktrace_api.h> ++#include <linux/blkdev.h> ++#include <linux/tracepoint.h> ++#include <linux/trace_seq.h> ++ ++#ifndef _TRACE_BLOCK_DEF_ ++#define _TRACE_BLOCK_DEF_ ++ ++#define __blk_dump_cmd(cmd, len) "<unknown>" ++ ++enum { ++ RWBS_FLAG_WRITE = (1 << 0), ++ RWBS_FLAG_DISCARD = (1 << 1), ++ RWBS_FLAG_READ = (1 << 2), ++ RWBS_FLAG_RAHEAD = (1 << 3), ++ RWBS_FLAG_SYNC = (1 << 4), ++ RWBS_FLAG_META = (1 << 5), ++ RWBS_FLAG_SECURE = (1 << 6), ++}; ++ ++#endif /* _TRACE_BLOCK_DEF_ */ ++ ++#define __print_rwbs_flags(rwbs) \ ++ __print_flags(rwbs, "", \ ++ { RWBS_FLAG_WRITE, "W" }, \ ++ { RWBS_FLAG_DISCARD, "D" }, \ ++ { RWBS_FLAG_READ, "R" }, \ ++ { RWBS_FLAG_RAHEAD, "A" }, \ ++ { RWBS_FLAG_SYNC, "S" }, \ ++ { RWBS_FLAG_META, "M" }, \ ++ { RWBS_FLAG_SECURE, "E" }) ++ ++#define blk_fill_rwbs(rwbs, rw, bytes) \ ++ tp_assign(rwbs, ((rw) & WRITE ? RWBS_FLAG_WRITE : \ ++ ( (rw) & REQ_DISCARD ? RWBS_FLAG_DISCARD : \ ++ ( (bytes) ? RWBS_FLAG_READ : \ ++ ( 0 )))) \ ++ | ((rw) & REQ_RAHEAD ? RWBS_FLAG_RAHEAD : 0) \ ++ | ((rw) & REQ_SYNC ? RWBS_FLAG_SYNC : 0) \ ++ | ((rw) & REQ_META ? RWBS_FLAG_META : 0) \ ++ | ((rw) & REQ_SECURE ? RWBS_FLAG_SECURE : 0)) ++ ++DECLARE_EVENT_CLASS(block_rq_with_error, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( int, errors ) ++ __field( unsigned int, rwbs ) ++ __dynamic_array_hex( unsigned char, cmd, ++ (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ rq->cmd_len : 0) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, rq->rq_disk ? disk_devt(rq->rq_disk) : 0) ++ tp_assign(sector, (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_pos(rq)) ++ tp_assign(nr_sector, (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_sectors(rq)) ++ tp_assign(errors, rq->errors) ++ blk_fill_rwbs(rwbs, rq->cmd_flags, blk_rq_bytes(rq)) ++ tp_memcpy_dyn(cmd, (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ rq->cmd : NULL); ++ ), ++ ++ TP_printk("%d,%d %s (%s) %llu + %u [%d]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ __blk_dump_cmd(__get_dynamic_array(cmd), ++ __get_dynamic_array_len(cmd)), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->errors) ++) ++ ++/** ++ * block_rq_abort - abort block operation request ++ * @q: queue containing the block operation request ++ * @rq: block IO operation request ++ * ++ * Called immediately after pending block IO operation request @rq in ++ * queue @q is aborted. The fields in the operation request @rq ++ * can be examined to determine which device and sectors the pending ++ * operation would access. ++ */ ++DEFINE_EVENT(block_rq_with_error, block_rq_abort, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++) ++ ++/** ++ * block_rq_requeue - place block IO request back on a queue ++ * @q: queue holding operation ++ * @rq: block IO operation request ++ * ++ * The block operation request @rq is being placed back into queue ++ * @q. For some reason the request was not completed and needs to be ++ * put back in the queue. ++ */ ++DEFINE_EVENT(block_rq_with_error, block_rq_requeue, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++) ++ ++/** ++ * block_rq_complete - block IO operation completed by device driver ++ * @q: queue containing the block operation request ++ * @rq: block operations request ++ * ++ * The block_rq_complete tracepoint event indicates that some portion ++ * of operation request has been completed by the device driver. If ++ * the @rq->bio is %NULL, then there is absolutely no additional work to ++ * do for the request. If @rq->bio is non-NULL then there is ++ * additional work required to complete the request. ++ */ ++DEFINE_EVENT(block_rq_with_error, block_rq_complete, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++) ++ ++DECLARE_EVENT_CLASS(block_rq, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( unsigned int, bytes ) ++ __field( unsigned int, rwbs ) ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __dynamic_array_hex( unsigned char, cmd, ++ (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ rq->cmd_len : 0) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, rq->rq_disk ? disk_devt(rq->rq_disk) : 0) ++ tp_assign(sector, (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_pos(rq)) ++ tp_assign(nr_sector, (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_sectors(rq)) ++ tp_assign(bytes, (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ blk_rq_bytes(rq) : 0) ++ blk_fill_rwbs(rwbs, rq->cmd_flags, blk_rq_bytes(rq)) ++ tp_memcpy_dyn(cmd, (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ rq->cmd : NULL); ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ ), ++ ++ TP_printk("%d,%d %s %u (%s) %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ __entry->bytes, ++ __blk_dump_cmd(__get_dynamic_array(cmd), ++ __get_dynamic_array_len(cmd)), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++) ++ ++/** ++ * block_rq_insert - insert block operation request into queue ++ * @q: target queue ++ * @rq: block IO operation request ++ * ++ * Called immediately before block operation request @rq is inserted ++ * into queue @q. The fields in the operation request @rq struct can ++ * be examined to determine which device and sectors the pending ++ * operation would access. ++ */ ++DEFINE_EVENT(block_rq, block_rq_insert, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++) ++ ++/** ++ * block_rq_issue - issue pending block IO request operation to device driver ++ * @q: queue holding operation ++ * @rq: block IO operation operation request ++ * ++ * Called when block operation request @rq from queue @q is sent to a ++ * device driver for processing. ++ */ ++DEFINE_EVENT(block_rq, block_rq_issue, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++) ++ ++/** ++ * block_bio_bounce - used bounce buffer when processing block operation ++ * @q: queue holding the block operation ++ * @bio: block operation ++ * ++ * A bounce buffer was used to handle the block operation @bio in @q. ++ * This occurs when hardware limitations prevent a direct transfer of ++ * data between the @bio data memory area and the IO device. Use of a ++ * bounce buffer requires extra copying of data and decreases ++ * performance. ++ */ ++TRACE_EVENT(block_bio_bounce, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( unsigned int, rwbs ) ++ __array_text( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, bio->bi_bdev ? ++ bio->bi_bdev->bd_dev : 0) ++ tp_assign(sector, bio->bi_sector) ++ tp_assign(nr_sector, bio->bi_size >> 9) ++ blk_fill_rwbs(rwbs, bio->bi_rw, bio->bi_size) ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++) ++ ++/** ++ * block_bio_complete - completed all work on the block operation ++ * @q: queue holding the block operation ++ * @bio: block operation completed ++ * @error: io error value ++ * ++ * This tracepoint indicates there is no further work to do on this ++ * block IO operation @bio. ++ */ ++TRACE_EVENT(block_bio_complete, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int error), ++ ++ TP_ARGS(q, bio, error), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned, nr_sector ) ++ __field( int, error ) ++ __field( unsigned int, rwbs ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, bio->bi_bdev->bd_dev) ++ tp_assign(sector, bio->bi_sector) ++ tp_assign(nr_sector, bio->bi_size >> 9) ++ tp_assign(error, error) ++ blk_fill_rwbs(rwbs, bio->bi_rw, bio->bi_size) ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%d]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->error) ++) ++ ++DECLARE_EVENT_CLASS(block_bio, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( unsigned int, rwbs ) ++ __array_text( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, bio->bi_bdev->bd_dev) ++ tp_assign(sector, bio->bi_sector) ++ tp_assign(nr_sector, bio->bi_size >> 9) ++ blk_fill_rwbs(rwbs, bio->bi_rw, bio->bi_size) ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++) ++ ++/** ++ * block_bio_backmerge - merging block operation to the end of an existing operation ++ * @q: queue holding operation ++ * @bio: new block operation to merge ++ * ++ * Merging block request @bio to the end of an existing block request ++ * in queue @q. ++ */ ++DEFINE_EVENT(block_bio, block_bio_backmerge, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio) ++) ++ ++/** ++ * block_bio_frontmerge - merging block operation to the beginning of an existing operation ++ * @q: queue holding operation ++ * @bio: new block operation to merge ++ * ++ * Merging block IO operation @bio to the beginning of an existing block ++ * operation in queue @q. ++ */ ++DEFINE_EVENT(block_bio, block_bio_frontmerge, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio) ++) ++ ++/** ++ * block_bio_queue - putting new block IO operation in queue ++ * @q: queue holding operation ++ * @bio: new block operation ++ * ++ * About to place the block IO operation @bio into queue @q. ++ */ ++DEFINE_EVENT(block_bio, block_bio_queue, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio) ++) ++ ++DECLARE_EVENT_CLASS(block_get_rq, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int rw), ++ ++ TP_ARGS(q, bio, rw), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( unsigned int, rwbs ) ++ __array_text( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, bio ? bio->bi_bdev->bd_dev : 0) ++ tp_assign(sector, bio ? bio->bi_sector : 0) ++ tp_assign(nr_sector, bio ? bio->bi_size >> 9 : 0) ++ blk_fill_rwbs(rwbs, bio ? bio->bi_rw : 0, ++ bio ? bio->bi_size >> 9 : 0) ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++) ++ ++/** ++ * block_getrq - get a free request entry in queue for block IO operations ++ * @q: queue for operations ++ * @bio: pending block IO operation ++ * @rw: low bit indicates a read (%0) or a write (%1) ++ * ++ * A request struct for queue @q has been allocated to handle the ++ * block IO operation @bio. ++ */ ++DEFINE_EVENT(block_get_rq, block_getrq, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int rw), ++ ++ TP_ARGS(q, bio, rw) ++) ++ ++/** ++ * block_sleeprq - waiting to get a free request entry in queue for block IO operation ++ * @q: queue for operation ++ * @bio: pending block IO operation ++ * @rw: low bit indicates a read (%0) or a write (%1) ++ * ++ * In the case where a request struct cannot be provided for queue @q ++ * the process needs to wait for an request struct to become ++ * available. This tracepoint event is generated each time the ++ * process goes to sleep waiting for request struct become available. ++ */ ++DEFINE_EVENT(block_get_rq, block_sleeprq, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int rw), ++ ++ TP_ARGS(q, bio, rw) ++) ++ ++/** ++ * block_plug - keep operations requests in request queue ++ * @q: request queue to plug ++ * ++ * Plug the request queue @q. Do not allow block operation requests ++ * to be sent to the device driver. Instead, accumulate requests in ++ * the queue to improve throughput performance of the block device. ++ */ ++TRACE_EVENT(block_plug, ++ ++ TP_PROTO(struct request_queue *q), ++ ++ TP_ARGS(q), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ ), ++ ++ TP_printk("[%s]", __entry->comm) ++) ++ ++DECLARE_EVENT_CLASS(block_unplug, ++ ++ TP_PROTO(struct request_queue *q, unsigned int depth, bool explicit), ++ ++ TP_ARGS(q, depth, explicit), ++ ++ TP_STRUCT__entry( ++ __field( int, nr_rq ) ++ __array_text( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(nr_rq, depth) ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ ), ++ ++ TP_printk("[%s] %d", __entry->comm, __entry->nr_rq) ++) ++ ++/** ++ * block_unplug - release of operations requests in request queue ++ * @q: request queue to unplug ++ * @depth: number of requests just added to the queue ++ * @explicit: whether this was an explicit unplug, or one from schedule() ++ * ++ * Unplug request queue @q because device driver is scheduled to work ++ * on elements in the request queue. ++ */ ++DEFINE_EVENT(block_unplug, block_unplug, ++ ++ TP_PROTO(struct request_queue *q, unsigned int depth, bool explicit), ++ ++ TP_ARGS(q, depth, explicit) ++) ++ ++/** ++ * block_split - split a single bio struct into two bio structs ++ * @q: queue containing the bio ++ * @bio: block operation being split ++ * @new_sector: The starting sector for the new bio ++ * ++ * The bio request @bio in request queue @q needs to be split into two ++ * bio requests. The newly created @bio request starts at ++ * @new_sector. This split may be required due to hardware limitation ++ * such as operation crossing device boundaries in a RAID system. ++ */ ++TRACE_EVENT(block_split, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, ++ unsigned int new_sector), ++ ++ TP_ARGS(q, bio, new_sector), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( sector_t, new_sector ) ++ __field( unsigned int, rwbs ) ++ __array_text( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, bio->bi_bdev->bd_dev) ++ tp_assign(sector, bio->bi_sector) ++ tp_assign(new_sector, new_sector) ++ blk_fill_rwbs(rwbs, bio->bi_rw, bio->bi_size) ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ ), ++ ++ TP_printk("%d,%d %s %llu / %llu [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ (unsigned long long)__entry->sector, ++ (unsigned long long)__entry->new_sector, ++ __entry->comm) ++) ++ ++/** ++ * block_bio_remap - map request for a logical device to the raw device ++ * @q: queue holding the operation ++ * @bio: revised operation ++ * @dev: device for the operation ++ * @from: original sector for the operation ++ * ++ * An operation for a logical device has been mapped to the ++ * raw block device. ++ */ ++TRACE_EVENT(block_bio_remap, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, dev_t dev, ++ sector_t from), ++ ++ TP_ARGS(q, bio, dev, from), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( dev_t, old_dev ) ++ __field( sector_t, old_sector ) ++ __field( unsigned int, rwbs ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, bio->bi_bdev->bd_dev) ++ tp_assign(sector, bio->bi_sector) ++ tp_assign(nr_sector, bio->bi_size >> 9) ++ tp_assign(old_dev, dev) ++ tp_assign(old_sector, from) ++ blk_fill_rwbs(rwbs, bio->bi_rw, bio->bi_size) ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, ++ MAJOR(__entry->old_dev), MINOR(__entry->old_dev), ++ (unsigned long long)__entry->old_sector) ++) ++ ++/** ++ * block_rq_remap - map request for a block operation request ++ * @q: queue holding the operation ++ * @rq: block IO operation request ++ * @dev: device for the operation ++ * @from: original sector for the operation ++ * ++ * The block operation request @rq in @q has been remapped. The block ++ * operation request @rq holds the current information and @from hold ++ * the original sector. ++ */ ++TRACE_EVENT(block_rq_remap, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq, dev_t dev, ++ sector_t from), ++ ++ TP_ARGS(q, rq, dev, from), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( dev_t, old_dev ) ++ __field( sector_t, old_sector ) ++ __field( unsigned int, rwbs ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(dev, disk_devt(rq->rq_disk)) ++ tp_assign(sector, blk_rq_pos(rq)) ++ tp_assign(nr_sector, blk_rq_sectors(rq)) ++ tp_assign(old_dev, dev) ++ tp_assign(old_sector, from) ++ blk_fill_rwbs(rwbs, rq->cmd_flags, blk_rq_bytes(rq)) ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __print_rwbs_flags(__entry->rwbs), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, ++ MAJOR(__entry->old_dev), MINOR(__entry->old_dev), ++ (unsigned long long)__entry->old_sector) ++) ++ ++#undef __print_rwbs_flags ++#undef blk_fill_rwbs ++ ++#endif /* _TRACE_BLOCK_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" ++ +diff --git a/drivers/staging/lttng/instrumentation/events/lttng-module/irq.h b/drivers/staging/lttng/instrumentation/events/lttng-module/irq.h +new file mode 100644 +index 0000000..344015d +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/lttng-module/irq.h +@@ -0,0 +1,155 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM irq ++ ++#if !defined(_TRACE_IRQ_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_IRQ_H ++ ++#include <linux/tracepoint.h> ++ ++#ifndef _TRACE_IRQ_DEF_ ++#define _TRACE_IRQ_DEF_ ++ ++struct irqaction; ++struct softirq_action; ++ ++#define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq } ++#define show_softirq_name(val) \ ++ __print_symbolic(val, \ ++ softirq_name(HI), \ ++ softirq_name(TIMER), \ ++ softirq_name(NET_TX), \ ++ softirq_name(NET_RX), \ ++ softirq_name(BLOCK), \ ++ softirq_name(BLOCK_IOPOLL), \ ++ softirq_name(TASKLET), \ ++ softirq_name(SCHED), \ ++ softirq_name(HRTIMER), \ ++ softirq_name(RCU)) ++ ++#endif /* _TRACE_IRQ_DEF_ */ ++ ++/** ++ * irq_handler_entry - called immediately before the irq action handler ++ * @irq: irq number ++ * @action: pointer to struct irqaction ++ * ++ * The struct irqaction pointed to by @action contains various ++ * information about the handler, including the device name, ++ * @action->name, and the device id, @action->dev_id. When used in ++ * conjunction with the irq_handler_exit tracepoint, we can figure ++ * out irq handler latencies. ++ */ ++TRACE_EVENT(irq_handler_entry, ++ ++ TP_PROTO(int irq, struct irqaction *action), ++ ++ TP_ARGS(irq, action), ++ ++ TP_STRUCT__entry( ++ __field( int, irq ) ++ __string( name, action->name ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(irq, irq) ++ tp_strcpy(name, action->name) ++ ), ++ ++ TP_printk("irq=%d name=%s", __entry->irq, __get_str(name)) ++) ++ ++/** ++ * irq_handler_exit - called immediately after the irq action handler returns ++ * @irq: irq number ++ * @action: pointer to struct irqaction ++ * @ret: return value ++ * ++ * If the @ret value is set to IRQ_HANDLED, then we know that the corresponding ++ * @action->handler scuccessully handled this irq. Otherwise, the irq might be ++ * a shared irq line, or the irq was not handled successfully. Can be used in ++ * conjunction with the irq_handler_entry to understand irq handler latencies. ++ */ ++TRACE_EVENT(irq_handler_exit, ++ ++ TP_PROTO(int irq, struct irqaction *action, int ret), ++ ++ TP_ARGS(irq, action, ret), ++ ++ TP_STRUCT__entry( ++ __field( int, irq ) ++ __field( int, ret ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(irq, irq) ++ tp_assign(ret, ret) ++ ), ++ ++ TP_printk("irq=%d ret=%s", ++ __entry->irq, __entry->ret ? "handled" : "unhandled") ++) ++ ++DECLARE_EVENT_CLASS(softirq, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr), ++ ++ TP_STRUCT__entry( ++ __field( unsigned int, vec ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(vec, vec_nr) ++ ), ++ ++ TP_printk("vec=%u [action=%s]", __entry->vec, ++ show_softirq_name(__entry->vec)) ++) ++ ++/** ++ * softirq_entry - called immediately before the softirq handler ++ * @vec_nr: softirq vector number ++ * ++ * When used in combination with the softirq_exit tracepoint ++ * we can determine the softirq handler runtine. ++ */ ++DEFINE_EVENT(softirq, softirq_entry, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr) ++) ++ ++/** ++ * softirq_exit - called immediately after the softirq handler returns ++ * @vec_nr: softirq vector number ++ * ++ * When used in combination with the softirq_entry tracepoint ++ * we can determine the softirq handler runtine. ++ */ ++DEFINE_EVENT(softirq, softirq_exit, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr) ++) ++ ++/** ++ * softirq_raise - called immediately when a softirq is raised ++ * @vec_nr: softirq vector number ++ * ++ * When used in combination with the softirq_entry tracepoint ++ * we can determine the softirq raise to run latency. ++ */ ++DEFINE_EVENT(softirq, softirq_raise, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr) ++) ++ ++#endif /* _TRACE_IRQ_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" +diff --git a/drivers/staging/lttng/instrumentation/events/lttng-module/kvm.h b/drivers/staging/lttng/instrumentation/events/lttng-module/kvm.h +new file mode 100644 +index 0000000..e10455b +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/lttng-module/kvm.h +@@ -0,0 +1,312 @@ ++#if !defined(_TRACE_KVM_MAIN_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_KVM_MAIN_H ++ ++#include <linux/tracepoint.h> ++ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM kvm ++ ++#define ERSN(x) { KVM_EXIT_##x, "KVM_EXIT_" #x } ++ ++#define kvm_trace_exit_reason \ ++ ERSN(UNKNOWN), ERSN(EXCEPTION), ERSN(IO), ERSN(HYPERCALL), \ ++ ERSN(DEBUG), ERSN(HLT), ERSN(MMIO), ERSN(IRQ_WINDOW_OPEN), \ ++ ERSN(SHUTDOWN), ERSN(FAIL_ENTRY), ERSN(INTR), ERSN(SET_TPR), \ ++ ERSN(TPR_ACCESS), ERSN(S390_SIEIC), ERSN(S390_RESET), ERSN(DCR),\ ++ ERSN(NMI), ERSN(INTERNAL_ERROR), ERSN(OSI) ++ ++TRACE_EVENT(kvm_userspace_exit, ++ TP_PROTO(__u32 reason, int errno), ++ TP_ARGS(reason, errno), ++ ++ TP_STRUCT__entry( ++ __field( __u32, reason ) ++ __field( int, errno ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(reason, reason) ++ tp_assign(errno, errno) ++ ), ++ ++ TP_printk("reason %s (%d)", ++ __entry->errno < 0 ? ++ (__entry->errno == -EINTR ? "restart" : "error") : ++ __print_symbolic(__entry->reason, kvm_trace_exit_reason), ++ __entry->errno < 0 ? -__entry->errno : __entry->reason) ++) ++ ++#if defined(__KVM_HAVE_IOAPIC) ++TRACE_EVENT(kvm_set_irq, ++ TP_PROTO(unsigned int gsi, int level, int irq_source_id), ++ TP_ARGS(gsi, level, irq_source_id), ++ ++ TP_STRUCT__entry( ++ __field( unsigned int, gsi ) ++ __field( int, level ) ++ __field( int, irq_source_id ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(gsi, gsi) ++ tp_assign(level, level) ++ tp_assign(irq_source_id, irq_source_id) ++ ), ++ ++ TP_printk("gsi %u level %d source %d", ++ __entry->gsi, __entry->level, __entry->irq_source_id) ++) ++ ++#define kvm_deliver_mode \ ++ {0x0, "Fixed"}, \ ++ {0x1, "LowPrio"}, \ ++ {0x2, "SMI"}, \ ++ {0x3, "Res3"}, \ ++ {0x4, "NMI"}, \ ++ {0x5, "INIT"}, \ ++ {0x6, "SIPI"}, \ ++ {0x7, "ExtINT"} ++ ++TRACE_EVENT(kvm_ioapic_set_irq, ++ TP_PROTO(__u64 e, int pin, bool coalesced), ++ TP_ARGS(e, pin, coalesced), ++ ++ TP_STRUCT__entry( ++ __field( __u64, e ) ++ __field( int, pin ) ++ __field( bool, coalesced ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(e, e) ++ tp_assign(pin, pin) ++ tp_assign(coalesced, coalesced) ++ ), ++ ++ TP_printk("pin %u dst %x vec=%u (%s|%s|%s%s)%s", ++ __entry->pin, (u8)(__entry->e >> 56), (u8)__entry->e, ++ __print_symbolic((__entry->e >> 8 & 0x7), kvm_deliver_mode), ++ (__entry->e & (1<<11)) ? "logical" : "physical", ++ (__entry->e & (1<<15)) ? "level" : "edge", ++ (__entry->e & (1<<16)) ? "|masked" : "", ++ __entry->coalesced ? " (coalesced)" : "") ++) ++ ++TRACE_EVENT(kvm_msi_set_irq, ++ TP_PROTO(__u64 address, __u64 data), ++ TP_ARGS(address, data), ++ ++ TP_STRUCT__entry( ++ __field( __u64, address ) ++ __field( __u64, data ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(address, address) ++ tp_assign(data, data) ++ ), ++ ++ TP_printk("dst %u vec %x (%s|%s|%s%s)", ++ (u8)(__entry->address >> 12), (u8)__entry->data, ++ __print_symbolic((__entry->data >> 8 & 0x7), kvm_deliver_mode), ++ (__entry->address & (1<<2)) ? "logical" : "physical", ++ (__entry->data & (1<<15)) ? "level" : "edge", ++ (__entry->address & (1<<3)) ? "|rh" : "") ++) ++ ++#define kvm_irqchips \ ++ {KVM_IRQCHIP_PIC_MASTER, "PIC master"}, \ ++ {KVM_IRQCHIP_PIC_SLAVE, "PIC slave"}, \ ++ {KVM_IRQCHIP_IOAPIC, "IOAPIC"} ++ ++TRACE_EVENT(kvm_ack_irq, ++ TP_PROTO(unsigned int irqchip, unsigned int pin), ++ TP_ARGS(irqchip, pin), ++ ++ TP_STRUCT__entry( ++ __field( unsigned int, irqchip ) ++ __field( unsigned int, pin ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(irqchip, irqchip) ++ tp_assign(pin, pin) ++ ), ++ ++ TP_printk("irqchip %s pin %u", ++ __print_symbolic(__entry->irqchip, kvm_irqchips), ++ __entry->pin) ++) ++ ++ ++ ++#endif /* defined(__KVM_HAVE_IOAPIC) */ ++ ++#define KVM_TRACE_MMIO_READ_UNSATISFIED 0 ++#define KVM_TRACE_MMIO_READ 1 ++#define KVM_TRACE_MMIO_WRITE 2 ++ ++#define kvm_trace_symbol_mmio \ ++ { KVM_TRACE_MMIO_READ_UNSATISFIED, "unsatisfied-read" }, \ ++ { KVM_TRACE_MMIO_READ, "read" }, \ ++ { KVM_TRACE_MMIO_WRITE, "write" } ++ ++TRACE_EVENT(kvm_mmio, ++ TP_PROTO(int type, int len, u64 gpa, u64 val), ++ TP_ARGS(type, len, gpa, val), ++ ++ TP_STRUCT__entry( ++ __field( u32, type ) ++ __field( u32, len ) ++ __field( u64, gpa ) ++ __field( u64, val ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(type, type) ++ tp_assign(len, len) ++ tp_assign(gpa, gpa) ++ tp_assign(val, val) ++ ), ++ ++ TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx", ++ __print_symbolic(__entry->type, kvm_trace_symbol_mmio), ++ __entry->len, __entry->gpa, __entry->val) ++) ++ ++#define kvm_fpu_load_symbol \ ++ {0, "unload"}, \ ++ {1, "load"} ++ ++TRACE_EVENT(kvm_fpu, ++ TP_PROTO(int load), ++ TP_ARGS(load), ++ ++ TP_STRUCT__entry( ++ __field( u32, load ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(load, load) ++ ), ++ ++ TP_printk("%s", __print_symbolic(__entry->load, kvm_fpu_load_symbol)) ++) ++ ++TRACE_EVENT(kvm_age_page, ++ TP_PROTO(ulong hva, struct kvm_memory_slot *slot, int ref), ++ TP_ARGS(hva, slot, ref), ++ ++ TP_STRUCT__entry( ++ __field( u64, hva ) ++ __field( u64, gfn ) ++ __field( u8, referenced ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(hva, hva) ++ tp_assign(gfn, ++ slot->base_gfn + ((hva - slot->userspace_addr) >> PAGE_SHIFT)) ++ tp_assign(referenced, ref) ++ ), ++ ++ TP_printk("hva %llx gfn %llx %s", ++ __entry->hva, __entry->gfn, ++ __entry->referenced ? "YOUNG" : "OLD") ++) ++ ++#ifdef CONFIG_KVM_ASYNC_PF ++DECLARE_EVENT_CLASS(kvm_async_get_page_class, ++ ++ TP_PROTO(u64 gva, u64 gfn), ++ ++ TP_ARGS(gva, gfn), ++ ++ TP_STRUCT__entry( ++ __field(__u64, gva) ++ __field(u64, gfn) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(gva, gva) ++ tp_assign(gfn, gfn) ++ ), ++ ++ TP_printk("gva = %#llx, gfn = %#llx", __entry->gva, __entry->gfn) ++) ++ ++DEFINE_EVENT(kvm_async_get_page_class, kvm_try_async_get_page, ++ ++ TP_PROTO(u64 gva, u64 gfn), ++ ++ TP_ARGS(gva, gfn) ++) ++ ++DEFINE_EVENT(kvm_async_get_page_class, kvm_async_pf_doublefault, ++ ++ TP_PROTO(u64 gva, u64 gfn), ++ ++ TP_ARGS(gva, gfn) ++) ++ ++DECLARE_EVENT_CLASS(kvm_async_pf_nopresent_ready, ++ ++ TP_PROTO(u64 token, u64 gva), ++ ++ TP_ARGS(token, gva), ++ ++ TP_STRUCT__entry( ++ __field(__u64, token) ++ __field(__u64, gva) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(token, token) ++ tp_assign(gva, gva) ++ ), ++ ++ TP_printk("token %#llx gva %#llx", __entry->token, __entry->gva) ++ ++) ++ ++DEFINE_EVENT(kvm_async_pf_nopresent_ready, kvm_async_pf_not_present, ++ ++ TP_PROTO(u64 token, u64 gva), ++ ++ TP_ARGS(token, gva) ++) ++ ++DEFINE_EVENT(kvm_async_pf_nopresent_ready, kvm_async_pf_ready, ++ ++ TP_PROTO(u64 token, u64 gva), ++ ++ TP_ARGS(token, gva) ++) ++ ++TRACE_EVENT( ++ kvm_async_pf_completed, ++ TP_PROTO(unsigned long address, struct page *page, u64 gva), ++ TP_ARGS(address, page, gva), ++ ++ TP_STRUCT__entry( ++ __field(unsigned long, address) ++ __field(pfn_t, pfn) ++ __field(u64, gva) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(address, address) ++ tp_assign(pfn, page ? page_to_pfn(page) : 0) ++ tp_assign(gva, gva) ++ ), ++ ++ TP_printk("gva %#llx address %#lx pfn %#llx", __entry->gva, ++ __entry->address, __entry->pfn) ++) ++ ++#endif ++ ++#endif /* _TRACE_KVM_MAIN_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" +diff --git a/drivers/staging/lttng/instrumentation/events/lttng-module/lttng.h b/drivers/staging/lttng/instrumentation/events/lttng-module/lttng.h +new file mode 100644 +index 0000000..6f3d6d1 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/lttng-module/lttng.h +@@ -0,0 +1,34 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM lttng ++ ++#if !defined(_TRACE_LTTNG_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_LTTNG_H ++ ++#include <linux/tracepoint.h> ++ ++TRACE_EVENT(lttng_metadata, ++ ++ TP_PROTO(const char *str), ++ ++ TP_ARGS(str), ++ ++ /* ++ * Not exactly a string: more a sequence of bytes (dynamic ++ * array) without the length. This is a dummy anyway: we only ++ * use this declaration to generate an event metadata entry. ++ */ ++ TP_STRUCT__entry( ++ __string( str, str ) ++ ), ++ ++ TP_fast_assign( ++ tp_strcpy(str, str) ++ ), ++ ++ TP_printk("") ++) ++ ++#endif /* _TRACE_LTTNG_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" +diff --git a/drivers/staging/lttng/instrumentation/events/lttng-module/sched.h b/drivers/staging/lttng/instrumentation/events/lttng-module/sched.h +new file mode 100644 +index 0000000..33f6921 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/lttng-module/sched.h +@@ -0,0 +1,400 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM sched ++ ++#if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SCHED_H ++ ++#include <linux/sched.h> ++#include <linux/tracepoint.h> ++ ++#ifndef _TRACE_SCHED_DEF_ ++#define _TRACE_SCHED_DEF_ ++ ++static inline long __trace_sched_switch_state(struct task_struct *p) ++{ ++ long state = p->state; ++ ++#ifdef CONFIG_PREEMPT ++ /* ++ * For all intents and purposes a preempted task is a running task. ++ */ ++ if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE) ++ state = TASK_RUNNING; ++#endif ++ ++ return state; ++} ++ ++#endif /* _TRACE_SCHED_DEF_ */ ++ ++/* ++ * Tracepoint for calling kthread_stop, performed to end a kthread: ++ */ ++TRACE_EVENT(sched_kthread_stop, ++ ++ TP_PROTO(struct task_struct *t), ++ ++ TP_ARGS(t), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, t->comm, TASK_COMM_LEN) ++ tp_assign(tid, t->pid) ++ ), ++ ++ TP_printk("comm=%s tid=%d", __entry->comm, __entry->tid) ++) ++ ++/* ++ * Tracepoint for the return value of the kthread stopping: ++ */ ++TRACE_EVENT(sched_kthread_stop_ret, ++ ++ TP_PROTO(int ret), ++ ++ TP_ARGS(ret), ++ ++ TP_STRUCT__entry( ++ __field( int, ret ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(ret, ret) ++ ), ++ ++ TP_printk("ret=%d", __entry->ret) ++) ++ ++/* ++ * Tracepoint for waking up a task: ++ */ ++DECLARE_EVENT_CLASS(sched_wakeup_template, ++ ++ TP_PROTO(struct task_struct *p, int success), ++ ++ TP_ARGS(p, success), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ __field( int, prio ) ++ __field( int, success ) ++ __field( int, target_cpu ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, p->comm, TASK_COMM_LEN) ++ tp_assign(tid, p->pid) ++ tp_assign(prio, p->prio) ++ tp_assign(success, success) ++ tp_assign(target_cpu, task_cpu(p)) ++ ), ++ ++ TP_printk("comm=%s tid=%d prio=%d success=%d target_cpu=%03d", ++ __entry->comm, __entry->tid, __entry->prio, ++ __entry->success, __entry->target_cpu) ++) ++ ++DEFINE_EVENT(sched_wakeup_template, sched_wakeup, ++ TP_PROTO(struct task_struct *p, int success), ++ TP_ARGS(p, success)) ++ ++/* ++ * Tracepoint for waking up a new task: ++ */ ++DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new, ++ TP_PROTO(struct task_struct *p, int success), ++ TP_ARGS(p, success)) ++ ++/* ++ * Tracepoint for task switches, performed by the scheduler: ++ */ ++TRACE_EVENT(sched_switch, ++ ++ TP_PROTO(struct task_struct *prev, ++ struct task_struct *next), ++ ++ TP_ARGS(prev, next), ++ ++ TP_STRUCT__entry( ++ __array_text( char, prev_comm, TASK_COMM_LEN ) ++ __field( pid_t, prev_tid ) ++ __field( int, prev_prio ) ++ __field( long, prev_state ) ++ __array_text( char, next_comm, TASK_COMM_LEN ) ++ __field( pid_t, next_tid ) ++ __field( int, next_prio ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(next_comm, next->comm, TASK_COMM_LEN) ++ tp_assign(prev_tid, prev->pid) ++ tp_assign(prev_prio, prev->prio - MAX_RT_PRIO) ++ tp_assign(prev_state, __trace_sched_switch_state(prev)) ++ tp_memcpy(prev_comm, prev->comm, TASK_COMM_LEN) ++ tp_assign(next_tid, next->pid) ++ tp_assign(next_prio, next->prio - MAX_RT_PRIO) ++ ), ++ ++ TP_printk("prev_comm=%s prev_tid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_tid=%d next_prio=%d", ++ __entry->prev_comm, __entry->prev_tid, __entry->prev_prio, ++ __entry->prev_state ? ++ __print_flags(__entry->prev_state, "|", ++ { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" }, ++ { 16, "Z" }, { 32, "X" }, { 64, "x" }, ++ { 128, "W" }) : "R", ++ __entry->next_comm, __entry->next_tid, __entry->next_prio) ++) ++ ++/* ++ * Tracepoint for a task being migrated: ++ */ ++TRACE_EVENT(sched_migrate_task, ++ ++ TP_PROTO(struct task_struct *p, int dest_cpu), ++ ++ TP_ARGS(p, dest_cpu), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ __field( int, prio ) ++ __field( int, orig_cpu ) ++ __field( int, dest_cpu ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, p->comm, TASK_COMM_LEN) ++ tp_assign(tid, p->pid) ++ tp_assign(prio, p->prio - MAX_RT_PRIO) ++ tp_assign(orig_cpu, task_cpu(p)) ++ tp_assign(dest_cpu, dest_cpu) ++ ), ++ ++ TP_printk("comm=%s tid=%d prio=%d orig_cpu=%d dest_cpu=%d", ++ __entry->comm, __entry->tid, __entry->prio, ++ __entry->orig_cpu, __entry->dest_cpu) ++) ++ ++DECLARE_EVENT_CLASS(sched_process_template, ++ ++ TP_PROTO(struct task_struct *p), ++ ++ TP_ARGS(p), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ __field( int, prio ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, p->comm, TASK_COMM_LEN) ++ tp_assign(tid, p->pid) ++ tp_assign(prio, p->prio - MAX_RT_PRIO) ++ ), ++ ++ TP_printk("comm=%s tid=%d prio=%d", ++ __entry->comm, __entry->tid, __entry->prio) ++) ++ ++/* ++ * Tracepoint for freeing a task: ++ */ ++DEFINE_EVENT(sched_process_template, sched_process_free, ++ TP_PROTO(struct task_struct *p), ++ TP_ARGS(p)) ++ ++ ++/* ++ * Tracepoint for a task exiting: ++ */ ++DEFINE_EVENT(sched_process_template, sched_process_exit, ++ TP_PROTO(struct task_struct *p), ++ TP_ARGS(p)) ++ ++/* ++ * Tracepoint for waiting on task to unschedule: ++ */ ++DEFINE_EVENT(sched_process_template, sched_wait_task, ++ TP_PROTO(struct task_struct *p), ++ TP_ARGS(p)) ++ ++/* ++ * Tracepoint for a waiting task: ++ */ ++TRACE_EVENT(sched_process_wait, ++ ++ TP_PROTO(struct pid *pid), ++ ++ TP_ARGS(pid), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ __field( int, prio ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, current->comm, TASK_COMM_LEN) ++ tp_assign(tid, pid_nr(pid)) ++ tp_assign(prio, current->prio - MAX_RT_PRIO) ++ ), ++ ++ TP_printk("comm=%s tid=%d prio=%d", ++ __entry->comm, __entry->tid, __entry->prio) ++) ++ ++/* ++ * Tracepoint for do_fork: ++ */ ++TRACE_EVENT(sched_process_fork, ++ ++ TP_PROTO(struct task_struct *parent, struct task_struct *child), ++ ++ TP_ARGS(parent, child), ++ ++ TP_STRUCT__entry( ++ __array_text( char, parent_comm, TASK_COMM_LEN ) ++ __field( pid_t, parent_tid ) ++ __array_text( char, child_comm, TASK_COMM_LEN ) ++ __field( pid_t, child_tid ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(parent_comm, parent->comm, TASK_COMM_LEN) ++ tp_assign(parent_tid, parent->pid) ++ tp_memcpy(child_comm, child->comm, TASK_COMM_LEN) ++ tp_assign(child_tid, child->pid) ++ ), ++ ++ TP_printk("comm=%s tid=%d child_comm=%s child_tid=%d", ++ __entry->parent_comm, __entry->parent_tid, ++ __entry->child_comm, __entry->child_tid) ++) ++ ++/* ++ * XXX the below sched_stat tracepoints only apply to SCHED_OTHER/BATCH/IDLE ++ * adding sched_stat support to SCHED_FIFO/RR would be welcome. ++ */ ++DECLARE_EVENT_CLASS(sched_stat_template, ++ ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ ++ TP_ARGS(tsk, delay), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ __field( u64, delay ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, tsk->comm, TASK_COMM_LEN) ++ tp_assign(tid, tsk->pid) ++ tp_assign(delay, delay) ++ ) ++ TP_perf_assign( ++ __perf_count(delay) ++ ), ++ ++ TP_printk("comm=%s tid=%d delay=%Lu [ns]", ++ __entry->comm, __entry->tid, ++ (unsigned long long)__entry->delay) ++) ++ ++ ++/* ++ * Tracepoint for accounting wait time (time the task is runnable ++ * but not actually running due to scheduler contention). ++ */ ++DEFINE_EVENT(sched_stat_template, sched_stat_wait, ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ TP_ARGS(tsk, delay)) ++ ++/* ++ * Tracepoint for accounting sleep time (time the task is not runnable, ++ * including iowait, see below). ++ */ ++DEFINE_EVENT(sched_stat_template, sched_stat_sleep, ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ TP_ARGS(tsk, delay)) ++ ++/* ++ * Tracepoint for accounting iowait time (time the task is not runnable ++ * due to waiting on IO to complete). ++ */ ++DEFINE_EVENT(sched_stat_template, sched_stat_iowait, ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ TP_ARGS(tsk, delay)) ++ ++/* ++ * Tracepoint for accounting runtime (time the task is executing ++ * on a CPU). ++ */ ++TRACE_EVENT(sched_stat_runtime, ++ ++ TP_PROTO(struct task_struct *tsk, u64 runtime, u64 vruntime), ++ ++ TP_ARGS(tsk, runtime, vruntime), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ __field( u64, runtime ) ++ __field( u64, vruntime ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, tsk->comm, TASK_COMM_LEN) ++ tp_assign(tid, tsk->pid) ++ tp_assign(runtime, runtime) ++ tp_assign(vruntime, vruntime) ++ ) ++ TP_perf_assign( ++ __perf_count(runtime) ++ ), ++ ++ TP_printk("comm=%s tid=%d runtime=%Lu [ns] vruntime=%Lu [ns]", ++ __entry->comm, __entry->tid, ++ (unsigned long long)__entry->runtime, ++ (unsigned long long)__entry->vruntime) ++) ++ ++/* ++ * Tracepoint for showing priority inheritance modifying a tasks ++ * priority. ++ */ ++TRACE_EVENT(sched_pi_setprio, ++ ++ TP_PROTO(struct task_struct *tsk, int newprio), ++ ++ TP_ARGS(tsk, newprio), ++ ++ TP_STRUCT__entry( ++ __array_text( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, tid ) ++ __field( int, oldprio ) ++ __field( int, newprio ) ++ ), ++ ++ TP_fast_assign( ++ tp_memcpy(comm, tsk->comm, TASK_COMM_LEN) ++ tp_assign(tid, tsk->pid) ++ tp_assign(oldprio, tsk->prio - MAX_RT_PRIO) ++ tp_assign(newprio, newprio - MAX_RT_PRIO) ++ ), ++ ++ TP_printk("comm=%s tid=%d oldprio=%d newprio=%d", ++ __entry->comm, __entry->tid, ++ __entry->oldprio, __entry->newprio) ++) ++ ++#endif /* _TRACE_SCHED_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" +diff --git a/drivers/staging/lttng/instrumentation/events/lttng-module/syscalls.h b/drivers/staging/lttng/instrumentation/events/lttng-module/syscalls.h +new file mode 100644 +index 0000000..a2bb956 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/lttng-module/syscalls.h +@@ -0,0 +1,76 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM raw_syscalls ++#define TRACE_INCLUDE_FILE syscalls ++ ++#if !defined(_TRACE_EVENTS_SYSCALLS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_EVENTS_SYSCALLS_H ++ ++#include <linux/tracepoint.h> ++ ++#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS ++ ++#ifndef _TRACE_SYSCALLS_DEF_ ++#define _TRACE_SYSCALLS_DEF_ ++ ++#include <asm/ptrace.h> ++#include <asm/syscall.h> ++ ++#endif /* _TRACE_SYSCALLS_DEF_ */ ++ ++TRACE_EVENT(sys_enter, ++ ++ TP_PROTO(struct pt_regs *regs, long id), ++ ++ TP_ARGS(regs, id), ++ ++ TP_STRUCT__entry( ++ __field( long, id ) ++ __array( unsigned long, args, 6 ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(id, id) ++ { ++ tp_memcpy(args, ++ ({ ++ unsigned long args_copy[6]; ++ syscall_get_arguments(current, regs, ++ 0, 6, args_copy); ++ args_copy; ++ }), 6 * sizeof(unsigned long)); ++ } ++ ), ++ ++ TP_printk("NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)", ++ __entry->id, ++ __entry->args[0], __entry->args[1], __entry->args[2], ++ __entry->args[3], __entry->args[4], __entry->args[5]) ++) ++ ++TRACE_EVENT(sys_exit, ++ ++ TP_PROTO(struct pt_regs *regs, long ret), ++ ++ TP_ARGS(regs, ret), ++ ++ TP_STRUCT__entry( ++ __field( long, id ) ++ __field( long, ret ) ++ ), ++ ++ TP_fast_assign( ++ tp_assign(id, syscall_get_nr(current, regs)) ++ tp_assign(ret, ret) ++ ), ++ ++ TP_printk("NR %ld = %ld", ++ __entry->id, __entry->ret) ++) ++ ++#endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */ ++ ++#endif /* _TRACE_EVENTS_SYSCALLS_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" ++ +diff --git a/drivers/staging/lttng/instrumentation/events/mainline/block.h b/drivers/staging/lttng/instrumentation/events/mainline/block.h +new file mode 100644 +index 0000000..bf36654 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/mainline/block.h +@@ -0,0 +1,569 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM block ++ ++#if !defined(_TRACE_BLOCK_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_BLOCK_H ++ ++#include <linux/blktrace_api.h> ++#include <linux/blkdev.h> ++#include <linux/tracepoint.h> ++ ++DECLARE_EVENT_CLASS(block_rq_with_error, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( int, errors ) ++ __array( char, rwbs, 6 ) ++ __dynamic_array( char, cmd, blk_cmd_buf_len(rq) ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0; ++ __entry->sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_pos(rq); ++ __entry->nr_sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_sectors(rq); ++ __entry->errors = rq->errors; ++ ++ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); ++ blk_dump_cmd(__get_str(cmd), rq); ++ ), ++ ++ TP_printk("%d,%d %s (%s) %llu + %u [%d]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __entry->rwbs, __get_str(cmd), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->errors) ++); ++ ++/** ++ * block_rq_abort - abort block operation request ++ * @q: queue containing the block operation request ++ * @rq: block IO operation request ++ * ++ * Called immediately after pending block IO operation request @rq in ++ * queue @q is aborted. The fields in the operation request @rq ++ * can be examined to determine which device and sectors the pending ++ * operation would access. ++ */ ++DEFINE_EVENT(block_rq_with_error, block_rq_abort, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++); ++ ++/** ++ * block_rq_requeue - place block IO request back on a queue ++ * @q: queue holding operation ++ * @rq: block IO operation request ++ * ++ * The block operation request @rq is being placed back into queue ++ * @q. For some reason the request was not completed and needs to be ++ * put back in the queue. ++ */ ++DEFINE_EVENT(block_rq_with_error, block_rq_requeue, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++); ++ ++/** ++ * block_rq_complete - block IO operation completed by device driver ++ * @q: queue containing the block operation request ++ * @rq: block operations request ++ * ++ * The block_rq_complete tracepoint event indicates that some portion ++ * of operation request has been completed by the device driver. If ++ * the @rq->bio is %NULL, then there is absolutely no additional work to ++ * do for the request. If @rq->bio is non-NULL then there is ++ * additional work required to complete the request. ++ */ ++DEFINE_EVENT(block_rq_with_error, block_rq_complete, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++); ++ ++DECLARE_EVENT_CLASS(block_rq, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( unsigned int, bytes ) ++ __array( char, rwbs, 6 ) ++ __array( char, comm, TASK_COMM_LEN ) ++ __dynamic_array( char, cmd, blk_cmd_buf_len(rq) ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = rq->rq_disk ? disk_devt(rq->rq_disk) : 0; ++ __entry->sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_pos(rq); ++ __entry->nr_sector = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ 0 : blk_rq_sectors(rq); ++ __entry->bytes = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? ++ blk_rq_bytes(rq) : 0; ++ ++ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); ++ blk_dump_cmd(__get_str(cmd), rq); ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ ), ++ ++ TP_printk("%d,%d %s %u (%s) %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), ++ __entry->rwbs, __entry->bytes, __get_str(cmd), ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++); ++ ++/** ++ * block_rq_insert - insert block operation request into queue ++ * @q: target queue ++ * @rq: block IO operation request ++ * ++ * Called immediately before block operation request @rq is inserted ++ * into queue @q. The fields in the operation request @rq struct can ++ * be examined to determine which device and sectors the pending ++ * operation would access. ++ */ ++DEFINE_EVENT(block_rq, block_rq_insert, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++); ++ ++/** ++ * block_rq_issue - issue pending block IO request operation to device driver ++ * @q: queue holding operation ++ * @rq: block IO operation operation request ++ * ++ * Called when block operation request @rq from queue @q is sent to a ++ * device driver for processing. ++ */ ++DEFINE_EVENT(block_rq, block_rq_issue, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq), ++ ++ TP_ARGS(q, rq) ++); ++ ++/** ++ * block_bio_bounce - used bounce buffer when processing block operation ++ * @q: queue holding the block operation ++ * @bio: block operation ++ * ++ * A bounce buffer was used to handle the block operation @bio in @q. ++ * This occurs when hardware limitations prevent a direct transfer of ++ * data between the @bio data memory area and the IO device. Use of a ++ * bounce buffer requires extra copying of data and decreases ++ * performance. ++ */ ++TRACE_EVENT(block_bio_bounce, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __array( char, rwbs, 6 ) ++ __array( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = bio->bi_bdev ? ++ bio->bi_bdev->bd_dev : 0; ++ __entry->sector = bio->bi_sector; ++ __entry->nr_sector = bio->bi_size >> 9; ++ blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs, ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++); ++ ++/** ++ * block_bio_complete - completed all work on the block operation ++ * @q: queue holding the block operation ++ * @bio: block operation completed ++ * @error: io error value ++ * ++ * This tracepoint indicates there is no further work to do on this ++ * block IO operation @bio. ++ */ ++TRACE_EVENT(block_bio_complete, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int error), ++ ++ TP_ARGS(q, bio, error), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned, nr_sector ) ++ __field( int, error ) ++ __array( char, rwbs, 6 ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = bio->bi_bdev->bd_dev; ++ __entry->sector = bio->bi_sector; ++ __entry->nr_sector = bio->bi_size >> 9; ++ __entry->error = error; ++ blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%d]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs, ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->error) ++); ++ ++DECLARE_EVENT_CLASS(block_bio, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __array( char, rwbs, 6 ) ++ __array( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = bio->bi_bdev->bd_dev; ++ __entry->sector = bio->bi_sector; ++ __entry->nr_sector = bio->bi_size >> 9; ++ blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs, ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++); ++ ++/** ++ * block_bio_backmerge - merging block operation to the end of an existing operation ++ * @q: queue holding operation ++ * @bio: new block operation to merge ++ * ++ * Merging block request @bio to the end of an existing block request ++ * in queue @q. ++ */ ++DEFINE_EVENT(block_bio, block_bio_backmerge, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio) ++); ++ ++/** ++ * block_bio_frontmerge - merging block operation to the beginning of an existing operation ++ * @q: queue holding operation ++ * @bio: new block operation to merge ++ * ++ * Merging block IO operation @bio to the beginning of an existing block ++ * operation in queue @q. ++ */ ++DEFINE_EVENT(block_bio, block_bio_frontmerge, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio) ++); ++ ++/** ++ * block_bio_queue - putting new block IO operation in queue ++ * @q: queue holding operation ++ * @bio: new block operation ++ * ++ * About to place the block IO operation @bio into queue @q. ++ */ ++DEFINE_EVENT(block_bio, block_bio_queue, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio), ++ ++ TP_ARGS(q, bio) ++); ++ ++DECLARE_EVENT_CLASS(block_get_rq, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int rw), ++ ++ TP_ARGS(q, bio, rw), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __array( char, rwbs, 6 ) ++ __array( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = bio ? bio->bi_bdev->bd_dev : 0; ++ __entry->sector = bio ? bio->bi_sector : 0; ++ __entry->nr_sector = bio ? bio->bi_size >> 9 : 0; ++ blk_fill_rwbs(__entry->rwbs, ++ bio ? bio->bi_rw : 0, __entry->nr_sector); ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs, ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, __entry->comm) ++); ++ ++/** ++ * block_getrq - get a free request entry in queue for block IO operations ++ * @q: queue for operations ++ * @bio: pending block IO operation ++ * @rw: low bit indicates a read (%0) or a write (%1) ++ * ++ * A request struct for queue @q has been allocated to handle the ++ * block IO operation @bio. ++ */ ++DEFINE_EVENT(block_get_rq, block_getrq, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int rw), ++ ++ TP_ARGS(q, bio, rw) ++); ++ ++/** ++ * block_sleeprq - waiting to get a free request entry in queue for block IO operation ++ * @q: queue for operation ++ * @bio: pending block IO operation ++ * @rw: low bit indicates a read (%0) or a write (%1) ++ * ++ * In the case where a request struct cannot be provided for queue @q ++ * the process needs to wait for an request struct to become ++ * available. This tracepoint event is generated each time the ++ * process goes to sleep waiting for request struct become available. ++ */ ++DEFINE_EVENT(block_get_rq, block_sleeprq, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, int rw), ++ ++ TP_ARGS(q, bio, rw) ++); ++ ++/** ++ * block_plug - keep operations requests in request queue ++ * @q: request queue to plug ++ * ++ * Plug the request queue @q. Do not allow block operation requests ++ * to be sent to the device driver. Instead, accumulate requests in ++ * the queue to improve throughput performance of the block device. ++ */ ++TRACE_EVENT(block_plug, ++ ++ TP_PROTO(struct request_queue *q), ++ ++ TP_ARGS(q), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ ), ++ ++ TP_printk("[%s]", __entry->comm) ++); ++ ++DECLARE_EVENT_CLASS(block_unplug, ++ ++ TP_PROTO(struct request_queue *q, unsigned int depth, bool explicit), ++ ++ TP_ARGS(q, depth, explicit), ++ ++ TP_STRUCT__entry( ++ __field( int, nr_rq ) ++ __array( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ __entry->nr_rq = depth; ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ ), ++ ++ TP_printk("[%s] %d", __entry->comm, __entry->nr_rq) ++); ++ ++/** ++ * block_unplug - release of operations requests in request queue ++ * @q: request queue to unplug ++ * @depth: number of requests just added to the queue ++ * @explicit: whether this was an explicit unplug, or one from schedule() ++ * ++ * Unplug request queue @q because device driver is scheduled to work ++ * on elements in the request queue. ++ */ ++DEFINE_EVENT(block_unplug, block_unplug, ++ ++ TP_PROTO(struct request_queue *q, unsigned int depth, bool explicit), ++ ++ TP_ARGS(q, depth, explicit) ++); ++ ++/** ++ * block_split - split a single bio struct into two bio structs ++ * @q: queue containing the bio ++ * @bio: block operation being split ++ * @new_sector: The starting sector for the new bio ++ * ++ * The bio request @bio in request queue @q needs to be split into two ++ * bio requests. The newly created @bio request starts at ++ * @new_sector. This split may be required due to hardware limitation ++ * such as operation crossing device boundaries in a RAID system. ++ */ ++TRACE_EVENT(block_split, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, ++ unsigned int new_sector), ++ ++ TP_ARGS(q, bio, new_sector), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( sector_t, new_sector ) ++ __array( char, rwbs, 6 ) ++ __array( char, comm, TASK_COMM_LEN ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = bio->bi_bdev->bd_dev; ++ __entry->sector = bio->bi_sector; ++ __entry->new_sector = new_sector; ++ blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ ), ++ ++ TP_printk("%d,%d %s %llu / %llu [%s]", ++ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs, ++ (unsigned long long)__entry->sector, ++ (unsigned long long)__entry->new_sector, ++ __entry->comm) ++); ++ ++/** ++ * block_bio_remap - map request for a logical device to the raw device ++ * @q: queue holding the operation ++ * @bio: revised operation ++ * @dev: device for the operation ++ * @from: original sector for the operation ++ * ++ * An operation for a logical device has been mapped to the ++ * raw block device. ++ */ ++TRACE_EVENT(block_bio_remap, ++ ++ TP_PROTO(struct request_queue *q, struct bio *bio, dev_t dev, ++ sector_t from), ++ ++ TP_ARGS(q, bio, dev, from), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( dev_t, old_dev ) ++ __field( sector_t, old_sector ) ++ __array( char, rwbs, 6 ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = bio->bi_bdev->bd_dev; ++ __entry->sector = bio->bi_sector; ++ __entry->nr_sector = bio->bi_size >> 9; ++ __entry->old_dev = dev; ++ __entry->old_sector = from; ++ blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_size); ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu", ++ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs, ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, ++ MAJOR(__entry->old_dev), MINOR(__entry->old_dev), ++ (unsigned long long)__entry->old_sector) ++); ++ ++/** ++ * block_rq_remap - map request for a block operation request ++ * @q: queue holding the operation ++ * @rq: block IO operation request ++ * @dev: device for the operation ++ * @from: original sector for the operation ++ * ++ * The block operation request @rq in @q has been remapped. The block ++ * operation request @rq holds the current information and @from hold ++ * the original sector. ++ */ ++TRACE_EVENT(block_rq_remap, ++ ++ TP_PROTO(struct request_queue *q, struct request *rq, dev_t dev, ++ sector_t from), ++ ++ TP_ARGS(q, rq, dev, from), ++ ++ TP_STRUCT__entry( ++ __field( dev_t, dev ) ++ __field( sector_t, sector ) ++ __field( unsigned int, nr_sector ) ++ __field( dev_t, old_dev ) ++ __field( sector_t, old_sector ) ++ __array( char, rwbs, 6 ) ++ ), ++ ++ TP_fast_assign( ++ __entry->dev = disk_devt(rq->rq_disk); ++ __entry->sector = blk_rq_pos(rq); ++ __entry->nr_sector = blk_rq_sectors(rq); ++ __entry->old_dev = dev; ++ __entry->old_sector = from; ++ blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); ++ ), ++ ++ TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu", ++ MAJOR(__entry->dev), MINOR(__entry->dev), __entry->rwbs, ++ (unsigned long long)__entry->sector, ++ __entry->nr_sector, ++ MAJOR(__entry->old_dev), MINOR(__entry->old_dev), ++ (unsigned long long)__entry->old_sector) ++); ++ ++#endif /* _TRACE_BLOCK_H */ ++ ++/* This part must be outside protection */ ++#include <trace/define_trace.h> ++ +diff --git a/drivers/staging/lttng/instrumentation/events/mainline/irq.h b/drivers/staging/lttng/instrumentation/events/mainline/irq.h +new file mode 100644 +index 0000000..1c09820 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/mainline/irq.h +@@ -0,0 +1,150 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM irq ++ ++#if !defined(_TRACE_IRQ_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_IRQ_H ++ ++#include <linux/tracepoint.h> ++ ++struct irqaction; ++struct softirq_action; ++ ++#define softirq_name(sirq) { sirq##_SOFTIRQ, #sirq } ++#define show_softirq_name(val) \ ++ __print_symbolic(val, \ ++ softirq_name(HI), \ ++ softirq_name(TIMER), \ ++ softirq_name(NET_TX), \ ++ softirq_name(NET_RX), \ ++ softirq_name(BLOCK), \ ++ softirq_name(BLOCK_IOPOLL), \ ++ softirq_name(TASKLET), \ ++ softirq_name(SCHED), \ ++ softirq_name(HRTIMER), \ ++ softirq_name(RCU)) ++ ++/** ++ * irq_handler_entry - called immediately before the irq action handler ++ * @irq: irq number ++ * @action: pointer to struct irqaction ++ * ++ * The struct irqaction pointed to by @action contains various ++ * information about the handler, including the device name, ++ * @action->name, and the device id, @action->dev_id. When used in ++ * conjunction with the irq_handler_exit tracepoint, we can figure ++ * out irq handler latencies. ++ */ ++TRACE_EVENT(irq_handler_entry, ++ ++ TP_PROTO(int irq, struct irqaction *action), ++ ++ TP_ARGS(irq, action), ++ ++ TP_STRUCT__entry( ++ __field( int, irq ) ++ __string( name, action->name ) ++ ), ++ ++ TP_fast_assign( ++ __entry->irq = irq; ++ __assign_str(name, action->name); ++ ), ++ ++ TP_printk("irq=%d name=%s", __entry->irq, __get_str(name)) ++); ++ ++/** ++ * irq_handler_exit - called immediately after the irq action handler returns ++ * @irq: irq number ++ * @action: pointer to struct irqaction ++ * @ret: return value ++ * ++ * If the @ret value is set to IRQ_HANDLED, then we know that the corresponding ++ * @action->handler scuccessully handled this irq. Otherwise, the irq might be ++ * a shared irq line, or the irq was not handled successfully. Can be used in ++ * conjunction with the irq_handler_entry to understand irq handler latencies. ++ */ ++TRACE_EVENT(irq_handler_exit, ++ ++ TP_PROTO(int irq, struct irqaction *action, int ret), ++ ++ TP_ARGS(irq, action, ret), ++ ++ TP_STRUCT__entry( ++ __field( int, irq ) ++ __field( int, ret ) ++ ), ++ ++ TP_fast_assign( ++ __entry->irq = irq; ++ __entry->ret = ret; ++ ), ++ ++ TP_printk("irq=%d ret=%s", ++ __entry->irq, __entry->ret ? "handled" : "unhandled") ++); ++ ++DECLARE_EVENT_CLASS(softirq, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr), ++ ++ TP_STRUCT__entry( ++ __field( unsigned int, vec ) ++ ), ++ ++ TP_fast_assign( ++ __entry->vec = vec_nr; ++ ), ++ ++ TP_printk("vec=%u [action=%s]", __entry->vec, ++ show_softirq_name(__entry->vec)) ++); ++ ++/** ++ * softirq_entry - called immediately before the softirq handler ++ * @vec_nr: softirq vector number ++ * ++ * When used in combination with the softirq_exit tracepoint ++ * we can determine the softirq handler runtine. ++ */ ++DEFINE_EVENT(softirq, softirq_entry, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr) ++); ++ ++/** ++ * softirq_exit - called immediately after the softirq handler returns ++ * @vec_nr: softirq vector number ++ * ++ * When used in combination with the softirq_entry tracepoint ++ * we can determine the softirq handler runtine. ++ */ ++DEFINE_EVENT(softirq, softirq_exit, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr) ++); ++ ++/** ++ * softirq_raise - called immediately when a softirq is raised ++ * @vec_nr: softirq vector number ++ * ++ * When used in combination with the softirq_entry tracepoint ++ * we can determine the softirq raise to run latency. ++ */ ++DEFINE_EVENT(softirq, softirq_raise, ++ ++ TP_PROTO(unsigned int vec_nr), ++ ++ TP_ARGS(vec_nr) ++); ++ ++#endif /* _TRACE_IRQ_H */ ++ ++/* This part must be outside protection */ ++#include <trace/define_trace.h> +diff --git a/drivers/staging/lttng/instrumentation/events/mainline/kvm.h b/drivers/staging/lttng/instrumentation/events/mainline/kvm.h +new file mode 100644 +index 0000000..46e3cd8 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/mainline/kvm.h +@@ -0,0 +1,312 @@ ++#if !defined(_TRACE_KVM_MAIN_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_KVM_MAIN_H ++ ++#include <linux/tracepoint.h> ++ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM kvm ++ ++#define ERSN(x) { KVM_EXIT_##x, "KVM_EXIT_" #x } ++ ++#define kvm_trace_exit_reason \ ++ ERSN(UNKNOWN), ERSN(EXCEPTION), ERSN(IO), ERSN(HYPERCALL), \ ++ ERSN(DEBUG), ERSN(HLT), ERSN(MMIO), ERSN(IRQ_WINDOW_OPEN), \ ++ ERSN(SHUTDOWN), ERSN(FAIL_ENTRY), ERSN(INTR), ERSN(SET_TPR), \ ++ ERSN(TPR_ACCESS), ERSN(S390_SIEIC), ERSN(S390_RESET), ERSN(DCR),\ ++ ERSN(NMI), ERSN(INTERNAL_ERROR), ERSN(OSI) ++ ++TRACE_EVENT(kvm_userspace_exit, ++ TP_PROTO(__u32 reason, int errno), ++ TP_ARGS(reason, errno), ++ ++ TP_STRUCT__entry( ++ __field( __u32, reason ) ++ __field( int, errno ) ++ ), ++ ++ TP_fast_assign( ++ __entry->reason = reason; ++ __entry->errno = errno; ++ ), ++ ++ TP_printk("reason %s (%d)", ++ __entry->errno < 0 ? ++ (__entry->errno == -EINTR ? "restart" : "error") : ++ __print_symbolic(__entry->reason, kvm_trace_exit_reason), ++ __entry->errno < 0 ? -__entry->errno : __entry->reason) ++); ++ ++#if defined(__KVM_HAVE_IOAPIC) ++TRACE_EVENT(kvm_set_irq, ++ TP_PROTO(unsigned int gsi, int level, int irq_source_id), ++ TP_ARGS(gsi, level, irq_source_id), ++ ++ TP_STRUCT__entry( ++ __field( unsigned int, gsi ) ++ __field( int, level ) ++ __field( int, irq_source_id ) ++ ), ++ ++ TP_fast_assign( ++ __entry->gsi = gsi; ++ __entry->level = level; ++ __entry->irq_source_id = irq_source_id; ++ ), ++ ++ TP_printk("gsi %u level %d source %d", ++ __entry->gsi, __entry->level, __entry->irq_source_id) ++); ++ ++#define kvm_deliver_mode \ ++ {0x0, "Fixed"}, \ ++ {0x1, "LowPrio"}, \ ++ {0x2, "SMI"}, \ ++ {0x3, "Res3"}, \ ++ {0x4, "NMI"}, \ ++ {0x5, "INIT"}, \ ++ {0x6, "SIPI"}, \ ++ {0x7, "ExtINT"} ++ ++TRACE_EVENT(kvm_ioapic_set_irq, ++ TP_PROTO(__u64 e, int pin, bool coalesced), ++ TP_ARGS(e, pin, coalesced), ++ ++ TP_STRUCT__entry( ++ __field( __u64, e ) ++ __field( int, pin ) ++ __field( bool, coalesced ) ++ ), ++ ++ TP_fast_assign( ++ __entry->e = e; ++ __entry->pin = pin; ++ __entry->coalesced = coalesced; ++ ), ++ ++ TP_printk("pin %u dst %x vec=%u (%s|%s|%s%s)%s", ++ __entry->pin, (u8)(__entry->e >> 56), (u8)__entry->e, ++ __print_symbolic((__entry->e >> 8 & 0x7), kvm_deliver_mode), ++ (__entry->e & (1<<11)) ? "logical" : "physical", ++ (__entry->e & (1<<15)) ? "level" : "edge", ++ (__entry->e & (1<<16)) ? "|masked" : "", ++ __entry->coalesced ? " (coalesced)" : "") ++); ++ ++TRACE_EVENT(kvm_msi_set_irq, ++ TP_PROTO(__u64 address, __u64 data), ++ TP_ARGS(address, data), ++ ++ TP_STRUCT__entry( ++ __field( __u64, address ) ++ __field( __u64, data ) ++ ), ++ ++ TP_fast_assign( ++ __entry->address = address; ++ __entry->data = data; ++ ), ++ ++ TP_printk("dst %u vec %x (%s|%s|%s%s)", ++ (u8)(__entry->address >> 12), (u8)__entry->data, ++ __print_symbolic((__entry->data >> 8 & 0x7), kvm_deliver_mode), ++ (__entry->address & (1<<2)) ? "logical" : "physical", ++ (__entry->data & (1<<15)) ? "level" : "edge", ++ (__entry->address & (1<<3)) ? "|rh" : "") ++); ++ ++#define kvm_irqchips \ ++ {KVM_IRQCHIP_PIC_MASTER, "PIC master"}, \ ++ {KVM_IRQCHIP_PIC_SLAVE, "PIC slave"}, \ ++ {KVM_IRQCHIP_IOAPIC, "IOAPIC"} ++ ++TRACE_EVENT(kvm_ack_irq, ++ TP_PROTO(unsigned int irqchip, unsigned int pin), ++ TP_ARGS(irqchip, pin), ++ ++ TP_STRUCT__entry( ++ __field( unsigned int, irqchip ) ++ __field( unsigned int, pin ) ++ ), ++ ++ TP_fast_assign( ++ __entry->irqchip = irqchip; ++ __entry->pin = pin; ++ ), ++ ++ TP_printk("irqchip %s pin %u", ++ __print_symbolic(__entry->irqchip, kvm_irqchips), ++ __entry->pin) ++); ++ ++ ++ ++#endif /* defined(__KVM_HAVE_IOAPIC) */ ++ ++#define KVM_TRACE_MMIO_READ_UNSATISFIED 0 ++#define KVM_TRACE_MMIO_READ 1 ++#define KVM_TRACE_MMIO_WRITE 2 ++ ++#define kvm_trace_symbol_mmio \ ++ { KVM_TRACE_MMIO_READ_UNSATISFIED, "unsatisfied-read" }, \ ++ { KVM_TRACE_MMIO_READ, "read" }, \ ++ { KVM_TRACE_MMIO_WRITE, "write" } ++ ++TRACE_EVENT(kvm_mmio, ++ TP_PROTO(int type, int len, u64 gpa, u64 val), ++ TP_ARGS(type, len, gpa, val), ++ ++ TP_STRUCT__entry( ++ __field( u32, type ) ++ __field( u32, len ) ++ __field( u64, gpa ) ++ __field( u64, val ) ++ ), ++ ++ TP_fast_assign( ++ __entry->type = type; ++ __entry->len = len; ++ __entry->gpa = gpa; ++ __entry->val = val; ++ ), ++ ++ TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx", ++ __print_symbolic(__entry->type, kvm_trace_symbol_mmio), ++ __entry->len, __entry->gpa, __entry->val) ++); ++ ++#define kvm_fpu_load_symbol \ ++ {0, "unload"}, \ ++ {1, "load"} ++ ++TRACE_EVENT(kvm_fpu, ++ TP_PROTO(int load), ++ TP_ARGS(load), ++ ++ TP_STRUCT__entry( ++ __field( u32, load ) ++ ), ++ ++ TP_fast_assign( ++ __entry->load = load; ++ ), ++ ++ TP_printk("%s", __print_symbolic(__entry->load, kvm_fpu_load_symbol)) ++); ++ ++TRACE_EVENT(kvm_age_page, ++ TP_PROTO(ulong hva, struct kvm_memory_slot *slot, int ref), ++ TP_ARGS(hva, slot, ref), ++ ++ TP_STRUCT__entry( ++ __field( u64, hva ) ++ __field( u64, gfn ) ++ __field( u8, referenced ) ++ ), ++ ++ TP_fast_assign( ++ __entry->hva = hva; ++ __entry->gfn = ++ slot->base_gfn + ((hva - slot->userspace_addr) >> PAGE_SHIFT); ++ __entry->referenced = ref; ++ ), ++ ++ TP_printk("hva %llx gfn %llx %s", ++ __entry->hva, __entry->gfn, ++ __entry->referenced ? "YOUNG" : "OLD") ++); ++ ++#ifdef CONFIG_KVM_ASYNC_PF ++DECLARE_EVENT_CLASS(kvm_async_get_page_class, ++ ++ TP_PROTO(u64 gva, u64 gfn), ++ ++ TP_ARGS(gva, gfn), ++ ++ TP_STRUCT__entry( ++ __field(__u64, gva) ++ __field(u64, gfn) ++ ), ++ ++ TP_fast_assign( ++ __entry->gva = gva; ++ __entry->gfn = gfn; ++ ), ++ ++ TP_printk("gva = %#llx, gfn = %#llx", __entry->gva, __entry->gfn) ++); ++ ++DEFINE_EVENT(kvm_async_get_page_class, kvm_try_async_get_page, ++ ++ TP_PROTO(u64 gva, u64 gfn), ++ ++ TP_ARGS(gva, gfn) ++); ++ ++DEFINE_EVENT(kvm_async_get_page_class, kvm_async_pf_doublefault, ++ ++ TP_PROTO(u64 gva, u64 gfn), ++ ++ TP_ARGS(gva, gfn) ++); ++ ++DECLARE_EVENT_CLASS(kvm_async_pf_nopresent_ready, ++ ++ TP_PROTO(u64 token, u64 gva), ++ ++ TP_ARGS(token, gva), ++ ++ TP_STRUCT__entry( ++ __field(__u64, token) ++ __field(__u64, gva) ++ ), ++ ++ TP_fast_assign( ++ __entry->token = token; ++ __entry->gva = gva; ++ ), ++ ++ TP_printk("token %#llx gva %#llx", __entry->token, __entry->gva) ++ ++); ++ ++DEFINE_EVENT(kvm_async_pf_nopresent_ready, kvm_async_pf_not_present, ++ ++ TP_PROTO(u64 token, u64 gva), ++ ++ TP_ARGS(token, gva) ++); ++ ++DEFINE_EVENT(kvm_async_pf_nopresent_ready, kvm_async_pf_ready, ++ ++ TP_PROTO(u64 token, u64 gva), ++ ++ TP_ARGS(token, gva) ++); ++ ++TRACE_EVENT( ++ kvm_async_pf_completed, ++ TP_PROTO(unsigned long address, struct page *page, u64 gva), ++ TP_ARGS(address, page, gva), ++ ++ TP_STRUCT__entry( ++ __field(unsigned long, address) ++ __field(pfn_t, pfn) ++ __field(u64, gva) ++ ), ++ ++ TP_fast_assign( ++ __entry->address = address; ++ __entry->pfn = page ? page_to_pfn(page) : 0; ++ __entry->gva = gva; ++ ), ++ ++ TP_printk("gva %#llx address %#lx pfn %#llx", __entry->gva, ++ __entry->address, __entry->pfn) ++); ++ ++#endif ++ ++#endif /* _TRACE_KVM_MAIN_H */ ++ ++/* This part must be outside protection */ ++#include <trace/define_trace.h> +diff --git a/drivers/staging/lttng/instrumentation/events/mainline/sched.h b/drivers/staging/lttng/instrumentation/events/mainline/sched.h +new file mode 100644 +index 0000000..f633478 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/mainline/sched.h +@@ -0,0 +1,397 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM sched ++ ++#if !defined(_TRACE_SCHED_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SCHED_H ++ ++#include <linux/sched.h> ++#include <linux/tracepoint.h> ++ ++/* ++ * Tracepoint for calling kthread_stop, performed to end a kthread: ++ */ ++TRACE_EVENT(sched_kthread_stop, ++ ++ TP_PROTO(struct task_struct *t), ++ ++ TP_ARGS(t), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, t->comm, TASK_COMM_LEN); ++ __entry->pid = t->pid; ++ ), ++ ++ TP_printk("comm=%s pid=%d", __entry->comm, __entry->pid) ++); ++ ++/* ++ * Tracepoint for the return value of the kthread stopping: ++ */ ++TRACE_EVENT(sched_kthread_stop_ret, ++ ++ TP_PROTO(int ret), ++ ++ TP_ARGS(ret), ++ ++ TP_STRUCT__entry( ++ __field( int, ret ) ++ ), ++ ++ TP_fast_assign( ++ __entry->ret = ret; ++ ), ++ ++ TP_printk("ret=%d", __entry->ret) ++); ++ ++/* ++ * Tracepoint for waking up a task: ++ */ ++DECLARE_EVENT_CLASS(sched_wakeup_template, ++ ++ TP_PROTO(struct task_struct *p, int success), ++ ++ TP_ARGS(p, success), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ __field( int, prio ) ++ __field( int, success ) ++ __field( int, target_cpu ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, p->comm, TASK_COMM_LEN); ++ __entry->pid = p->pid; ++ __entry->prio = p->prio; ++ __entry->success = success; ++ __entry->target_cpu = task_cpu(p); ++ ), ++ ++ TP_printk("comm=%s pid=%d prio=%d success=%d target_cpu=%03d", ++ __entry->comm, __entry->pid, __entry->prio, ++ __entry->success, __entry->target_cpu) ++); ++ ++DEFINE_EVENT(sched_wakeup_template, sched_wakeup, ++ TP_PROTO(struct task_struct *p, int success), ++ TP_ARGS(p, success)); ++ ++/* ++ * Tracepoint for waking up a new task: ++ */ ++DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new, ++ TP_PROTO(struct task_struct *p, int success), ++ TP_ARGS(p, success)); ++ ++#ifdef CREATE_TRACE_POINTS ++static inline long __trace_sched_switch_state(struct task_struct *p) ++{ ++ long state = p->state; ++ ++#ifdef CONFIG_PREEMPT ++ /* ++ * For all intents and purposes a preempted task is a running task. ++ */ ++ if (task_thread_info(p)->preempt_count & PREEMPT_ACTIVE) ++ state = TASK_RUNNING; ++#endif ++ ++ return state; ++} ++#endif ++ ++/* ++ * Tracepoint for task switches, performed by the scheduler: ++ */ ++TRACE_EVENT(sched_switch, ++ ++ TP_PROTO(struct task_struct *prev, ++ struct task_struct *next), ++ ++ TP_ARGS(prev, next), ++ ++ TP_STRUCT__entry( ++ __array( char, prev_comm, TASK_COMM_LEN ) ++ __field( pid_t, prev_pid ) ++ __field( int, prev_prio ) ++ __field( long, prev_state ) ++ __array( char, next_comm, TASK_COMM_LEN ) ++ __field( pid_t, next_pid ) ++ __field( int, next_prio ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->next_comm, next->comm, TASK_COMM_LEN); ++ __entry->prev_pid = prev->pid; ++ __entry->prev_prio = prev->prio; ++ __entry->prev_state = __trace_sched_switch_state(prev); ++ memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN); ++ __entry->next_pid = next->pid; ++ __entry->next_prio = next->prio; ++ ), ++ ++ TP_printk("prev_comm=%s prev_pid=%d prev_prio=%d prev_state=%s ==> next_comm=%s next_pid=%d next_prio=%d", ++ __entry->prev_comm, __entry->prev_pid, __entry->prev_prio, ++ __entry->prev_state ? ++ __print_flags(__entry->prev_state, "|", ++ { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" }, ++ { 16, "Z" }, { 32, "X" }, { 64, "x" }, ++ { 128, "W" }) : "R", ++ __entry->next_comm, __entry->next_pid, __entry->next_prio) ++); ++ ++/* ++ * Tracepoint for a task being migrated: ++ */ ++TRACE_EVENT(sched_migrate_task, ++ ++ TP_PROTO(struct task_struct *p, int dest_cpu), ++ ++ TP_ARGS(p, dest_cpu), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ __field( int, prio ) ++ __field( int, orig_cpu ) ++ __field( int, dest_cpu ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, p->comm, TASK_COMM_LEN); ++ __entry->pid = p->pid; ++ __entry->prio = p->prio; ++ __entry->orig_cpu = task_cpu(p); ++ __entry->dest_cpu = dest_cpu; ++ ), ++ ++ TP_printk("comm=%s pid=%d prio=%d orig_cpu=%d dest_cpu=%d", ++ __entry->comm, __entry->pid, __entry->prio, ++ __entry->orig_cpu, __entry->dest_cpu) ++); ++ ++DECLARE_EVENT_CLASS(sched_process_template, ++ ++ TP_PROTO(struct task_struct *p), ++ ++ TP_ARGS(p), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ __field( int, prio ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, p->comm, TASK_COMM_LEN); ++ __entry->pid = p->pid; ++ __entry->prio = p->prio; ++ ), ++ ++ TP_printk("comm=%s pid=%d prio=%d", ++ __entry->comm, __entry->pid, __entry->prio) ++); ++ ++/* ++ * Tracepoint for freeing a task: ++ */ ++DEFINE_EVENT(sched_process_template, sched_process_free, ++ TP_PROTO(struct task_struct *p), ++ TP_ARGS(p)); ++ ++ ++/* ++ * Tracepoint for a task exiting: ++ */ ++DEFINE_EVENT(sched_process_template, sched_process_exit, ++ TP_PROTO(struct task_struct *p), ++ TP_ARGS(p)); ++ ++/* ++ * Tracepoint for waiting on task to unschedule: ++ */ ++DEFINE_EVENT(sched_process_template, sched_wait_task, ++ TP_PROTO(struct task_struct *p), ++ TP_ARGS(p)); ++ ++/* ++ * Tracepoint for a waiting task: ++ */ ++TRACE_EVENT(sched_process_wait, ++ ++ TP_PROTO(struct pid *pid), ++ ++ TP_ARGS(pid), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ __field( int, prio ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ++ __entry->pid = pid_nr(pid); ++ __entry->prio = current->prio; ++ ), ++ ++ TP_printk("comm=%s pid=%d prio=%d", ++ __entry->comm, __entry->pid, __entry->prio) ++); ++ ++/* ++ * Tracepoint for do_fork: ++ */ ++TRACE_EVENT(sched_process_fork, ++ ++ TP_PROTO(struct task_struct *parent, struct task_struct *child), ++ ++ TP_ARGS(parent, child), ++ ++ TP_STRUCT__entry( ++ __array( char, parent_comm, TASK_COMM_LEN ) ++ __field( pid_t, parent_pid ) ++ __array( char, child_comm, TASK_COMM_LEN ) ++ __field( pid_t, child_pid ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->parent_comm, parent->comm, TASK_COMM_LEN); ++ __entry->parent_pid = parent->pid; ++ memcpy(__entry->child_comm, child->comm, TASK_COMM_LEN); ++ __entry->child_pid = child->pid; ++ ), ++ ++ TP_printk("comm=%s pid=%d child_comm=%s child_pid=%d", ++ __entry->parent_comm, __entry->parent_pid, ++ __entry->child_comm, __entry->child_pid) ++); ++ ++/* ++ * XXX the below sched_stat tracepoints only apply to SCHED_OTHER/BATCH/IDLE ++ * adding sched_stat support to SCHED_FIFO/RR would be welcome. ++ */ ++DECLARE_EVENT_CLASS(sched_stat_template, ++ ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ ++ TP_ARGS(tsk, delay), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ __field( u64, delay ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN); ++ __entry->pid = tsk->pid; ++ __entry->delay = delay; ++ ) ++ TP_perf_assign( ++ __perf_count(delay); ++ ), ++ ++ TP_printk("comm=%s pid=%d delay=%Lu [ns]", ++ __entry->comm, __entry->pid, ++ (unsigned long long)__entry->delay) ++); ++ ++ ++/* ++ * Tracepoint for accounting wait time (time the task is runnable ++ * but not actually running due to scheduler contention). ++ */ ++DEFINE_EVENT(sched_stat_template, sched_stat_wait, ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ TP_ARGS(tsk, delay)); ++ ++/* ++ * Tracepoint for accounting sleep time (time the task is not runnable, ++ * including iowait, see below). ++ */ ++DEFINE_EVENT(sched_stat_template, sched_stat_sleep, ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ TP_ARGS(tsk, delay)); ++ ++/* ++ * Tracepoint for accounting iowait time (time the task is not runnable ++ * due to waiting on IO to complete). ++ */ ++DEFINE_EVENT(sched_stat_template, sched_stat_iowait, ++ TP_PROTO(struct task_struct *tsk, u64 delay), ++ TP_ARGS(tsk, delay)); ++ ++/* ++ * Tracepoint for accounting runtime (time the task is executing ++ * on a CPU). ++ */ ++TRACE_EVENT(sched_stat_runtime, ++ ++ TP_PROTO(struct task_struct *tsk, u64 runtime, u64 vruntime), ++ ++ TP_ARGS(tsk, runtime, vruntime), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ __field( u64, runtime ) ++ __field( u64, vruntime ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN); ++ __entry->pid = tsk->pid; ++ __entry->runtime = runtime; ++ __entry->vruntime = vruntime; ++ ) ++ TP_perf_assign( ++ __perf_count(runtime); ++ ), ++ ++ TP_printk("comm=%s pid=%d runtime=%Lu [ns] vruntime=%Lu [ns]", ++ __entry->comm, __entry->pid, ++ (unsigned long long)__entry->runtime, ++ (unsigned long long)__entry->vruntime) ++); ++ ++/* ++ * Tracepoint for showing priority inheritance modifying a tasks ++ * priority. ++ */ ++TRACE_EVENT(sched_pi_setprio, ++ ++ TP_PROTO(struct task_struct *tsk, int newprio), ++ ++ TP_ARGS(tsk, newprio), ++ ++ TP_STRUCT__entry( ++ __array( char, comm, TASK_COMM_LEN ) ++ __field( pid_t, pid ) ++ __field( int, oldprio ) ++ __field( int, newprio ) ++ ), ++ ++ TP_fast_assign( ++ memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN); ++ __entry->pid = tsk->pid; ++ __entry->oldprio = tsk->prio; ++ __entry->newprio = newprio; ++ ), ++ ++ TP_printk("comm=%s pid=%d oldprio=%d newprio=%d", ++ __entry->comm, __entry->pid, ++ __entry->oldprio, __entry->newprio) ++); ++ ++#endif /* _TRACE_SCHED_H */ ++ ++/* This part must be outside protection */ ++#include <trace/define_trace.h> +diff --git a/drivers/staging/lttng/instrumentation/events/mainline/syscalls.h b/drivers/staging/lttng/instrumentation/events/mainline/syscalls.h +new file mode 100644 +index 0000000..5a4c04a +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/events/mainline/syscalls.h +@@ -0,0 +1,75 @@ ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM raw_syscalls ++#define TRACE_INCLUDE_FILE syscalls ++ ++#if !defined(_TRACE_EVENTS_SYSCALLS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_EVENTS_SYSCALLS_H ++ ++#include <linux/tracepoint.h> ++ ++#include <asm/ptrace.h> ++#include <asm/syscall.h> ++ ++ ++#ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS ++ ++extern void syscall_regfunc(void); ++extern void syscall_unregfunc(void); ++ ++TRACE_EVENT_FN(sys_enter, ++ ++ TP_PROTO(struct pt_regs *regs, long id), ++ ++ TP_ARGS(regs, id), ++ ++ TP_STRUCT__entry( ++ __field( long, id ) ++ __array( unsigned long, args, 6 ) ++ ), ++ ++ TP_fast_assign( ++ __entry->id = id; ++ syscall_get_arguments(current, regs, 0, 6, __entry->args); ++ ), ++ ++ TP_printk("NR %ld (%lx, %lx, %lx, %lx, %lx, %lx)", ++ __entry->id, ++ __entry->args[0], __entry->args[1], __entry->args[2], ++ __entry->args[3], __entry->args[4], __entry->args[5]), ++ ++ syscall_regfunc, syscall_unregfunc ++); ++ ++TRACE_EVENT_FLAGS(sys_enter, TRACE_EVENT_FL_CAP_ANY) ++ ++TRACE_EVENT_FN(sys_exit, ++ ++ TP_PROTO(struct pt_regs *regs, long ret), ++ ++ TP_ARGS(regs, ret), ++ ++ TP_STRUCT__entry( ++ __field( long, id ) ++ __field( long, ret ) ++ ), ++ ++ TP_fast_assign( ++ __entry->id = syscall_get_nr(current, regs); ++ __entry->ret = ret; ++ ), ++ ++ TP_printk("NR %ld = %ld", ++ __entry->id, __entry->ret), ++ ++ syscall_regfunc, syscall_unregfunc ++); ++ ++TRACE_EVENT_FLAGS(sys_exit, TRACE_EVENT_FL_CAP_ANY) ++ ++#endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */ ++ ++#endif /* _TRACE_EVENTS_SYSCALLS_H */ ++ ++/* This part must be outside protection */ ++#include <trace/define_trace.h> ++ +-- +1.7.9 + diff --git a/patches.lttng/0008-lttng-syscall-instrumentation.patch b/patches.lttng/0008-lttng-syscall-instrumentation.patch new file mode 100644 index 0000000000000..1ddac7a980728 --- /dev/null +++ b/patches.lttng/0008-lttng-syscall-instrumentation.patch @@ -0,0 +1,7758 @@ +From 54a69e5511f5031d3d14e1418ef7ea2456a73684 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:16 -0500 +Subject: lttng: syscall instrumentation + +x86-32 and x86-64 system call instrumentation, along with the +lttng-syscalls-generate-headers.sh script that generates the headers +from the system call list. See README for details. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + .../syscalls/3.0.4/x86-64-syscalls-3.0.4 | 263 +++ + .../syscalls/3.1.0-rc6/x86-32-syscalls-3.1.0-rc6 | 291 +++ + .../staging/lttng/instrumentation/syscalls/README | 18 + + .../syscalls/headers/compat_syscalls_integers.h | 3 + + .../syscalls/headers/compat_syscalls_pointers.h | 3 + + .../syscalls/headers/syscalls_integers.h | 7 + + .../syscalls/headers/syscalls_integers_override.h | 14 + + .../syscalls/headers/syscalls_pointers.h | 7 + + .../syscalls/headers/syscalls_pointers_override.h | 4 + + .../syscalls/headers/syscalls_unknown.h | 55 + + .../headers/x86-32-syscalls-3.1.0-rc6_integers.h | 1163 ++++++++++ + .../x86-32-syscalls-3.1.0-rc6_integers_override.h | 38 + + .../headers/x86-32-syscalls-3.1.0-rc6_pointers.h | 2232 ++++++++++++++++++++ + .../x86-32-syscalls-3.1.0-rc6_pointers_override.h | 17 + + .../headers/x86-64-syscalls-3.0.4_integers.h | 1013 +++++++++ + .../x86-64-syscalls-3.0.4_integers_override.h | 3 + + .../headers/x86-64-syscalls-3.0.4_pointers.h | 2076 ++++++++++++++++++ + .../x86-64-syscalls-3.0.4_pointers_override.h | 5 + + .../syscalls/lttng-syscalls-extractor/Makefile | 1 + + .../lttng-syscalls-extractor.c | 85 + + .../syscalls/lttng-syscalls-generate-headers.sh | 275 +++ + 21 files changed, 7573 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/3.0.4/x86-64-syscalls-3.0.4 + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/3.1.0-rc6/x86-32-syscalls-3.1.0-rc6 + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/README + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_integers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_pointers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers_override.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers_override.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_unknown.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers_override.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers_override.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers_override.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers_override.h + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/Makefile + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/lttng-syscalls-extractor.c + create mode 100644 drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-generate-headers.sh + +diff --git a/drivers/staging/lttng/instrumentation/syscalls/3.0.4/x86-64-syscalls-3.0.4 b/drivers/staging/lttng/instrumentation/syscalls/3.0.4/x86-64-syscalls-3.0.4 +new file mode 100644 +index 0000000..b229472 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/3.0.4/x86-64-syscalls-3.0.4 +@@ -0,0 +1,263 @@ ++syscall sys_read nr 0 nbargs 3 types: (unsigned int, char *, size_t) args: (fd, buf, count) ++syscall sys_write nr 1 nbargs 3 types: (unsigned int, const char *, size_t) args: (fd, buf, count) ++syscall sys_open nr 2 nbargs 3 types: (const char *, int, int) args: (filename, flags, mode) ++syscall sys_close nr 3 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_newstat nr 4 nbargs 2 types: (const char *, struct stat *) args: (filename, statbuf) ++syscall sys_newfstat nr 5 nbargs 2 types: (unsigned int, struct stat *) args: (fd, statbuf) ++syscall sys_newlstat nr 6 nbargs 2 types: (const char *, struct stat *) args: (filename, statbuf) ++syscall sys_poll nr 7 nbargs 3 types: (struct pollfd *, unsigned int, long) args: (ufds, nfds, timeout_msecs) ++syscall sys_lseek nr 8 nbargs 3 types: (unsigned int, off_t, unsigned int) args: (fd, offset, origin) ++syscall sys_mmap nr 9 nbargs 6 types: (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) args: (addr, len, prot, flags, fd, off) ++syscall sys_mprotect nr 10 nbargs 3 types: (unsigned long, size_t, unsigned long) args: (start, len, prot) ++syscall sys_munmap nr 11 nbargs 2 types: (unsigned long, size_t) args: (addr, len) ++syscall sys_brk nr 12 nbargs 1 types: (unsigned long) args: (brk) ++syscall sys_rt_sigaction nr 13 nbargs 4 types: (int, const struct sigaction *, struct sigaction *, size_t) args: (sig, act, oact, sigsetsize) ++syscall sys_rt_sigprocmask nr 14 nbargs 4 types: (int, sigset_t *, sigset_t *, size_t) args: (how, nset, oset, sigsetsize) ++syscall sys_ioctl nr 16 nbargs 3 types: (unsigned int, unsigned int, unsigned long) args: (fd, cmd, arg) ++syscall sys_readv nr 19 nbargs 3 types: (unsigned long, const struct iovec *, unsigned long) args: (fd, vec, vlen) ++syscall sys_writev nr 20 nbargs 3 types: (unsigned long, const struct iovec *, unsigned long) args: (fd, vec, vlen) ++syscall sys_access nr 21 nbargs 2 types: (const char *, int) args: (filename, mode) ++syscall sys_pipe nr 22 nbargs 1 types: (int *) args: (fildes) ++syscall sys_select nr 23 nbargs 5 types: (int, fd_set *, fd_set *, fd_set *, struct timeval *) args: (n, inp, outp, exp, tvp) ++syscall sys_sched_yield nr 24 nbargs 0 types: () args: () ++syscall sys_mremap nr 25 nbargs 5 types: (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) args: (addr, old_len, new_len, flags, new_addr) ++syscall sys_msync nr 26 nbargs 3 types: (unsigned long, size_t, int) args: (start, len, flags) ++syscall sys_mincore nr 27 nbargs 3 types: (unsigned long, size_t, unsigned char *) args: (start, len, vec) ++syscall sys_madvise nr 28 nbargs 3 types: (unsigned long, size_t, int) args: (start, len_in, behavior) ++syscall sys_shmget nr 29 nbargs 3 types: (key_t, size_t, int) args: (key, size, shmflg) ++syscall sys_shmat nr 30 nbargs 3 types: (int, char *, int) args: (shmid, shmaddr, shmflg) ++syscall sys_shmctl nr 31 nbargs 3 types: (int, int, struct shmid_ds *) args: (shmid, cmd, buf) ++syscall sys_dup nr 32 nbargs 1 types: (unsigned int) args: (fildes) ++syscall sys_dup2 nr 33 nbargs 2 types: (unsigned int, unsigned int) args: (oldfd, newfd) ++syscall sys_pause nr 34 nbargs 0 types: () args: () ++syscall sys_nanosleep nr 35 nbargs 2 types: (struct timespec *, struct timespec *) args: (rqtp, rmtp) ++syscall sys_getitimer nr 36 nbargs 2 types: (int, struct itimerval *) args: (which, value) ++syscall sys_alarm nr 37 nbargs 1 types: (unsigned int) args: (seconds) ++syscall sys_setitimer nr 38 nbargs 3 types: (int, struct itimerval *, struct itimerval *) args: (which, value, ovalue) ++syscall sys_getpid nr 39 nbargs 0 types: () args: () ++syscall sys_sendfile64 nr 40 nbargs 4 types: (int, int, loff_t *, size_t) args: (out_fd, in_fd, offset, count) ++syscall sys_socket nr 41 nbargs 3 types: (int, int, int) args: (family, type, protocol) ++syscall sys_connect nr 42 nbargs 3 types: (int, struct sockaddr *, int) args: (fd, uservaddr, addrlen) ++syscall sys_accept nr 43 nbargs 3 types: (int, struct sockaddr *, int *) args: (fd, upeer_sockaddr, upeer_addrlen) ++syscall sys_sendto nr 44 nbargs 6 types: (int, void *, size_t, unsigned, struct sockaddr *, int) args: (fd, buff, len, flags, addr, addr_len) ++syscall sys_recvfrom nr 45 nbargs 6 types: (int, void *, size_t, unsigned, struct sockaddr *, int *) args: (fd, ubuf, size, flags, addr, addr_len) ++syscall sys_sendmsg nr 46 nbargs 3 types: (int, struct msghdr *, unsigned) args: (fd, msg, flags) ++syscall sys_recvmsg nr 47 nbargs 3 types: (int, struct msghdr *, unsigned int) args: (fd, msg, flags) ++syscall sys_shutdown nr 48 nbargs 2 types: (int, int) args: (fd, how) ++syscall sys_bind nr 49 nbargs 3 types: (int, struct sockaddr *, int) args: (fd, umyaddr, addrlen) ++syscall sys_listen nr 50 nbargs 2 types: (int, int) args: (fd, backlog) ++syscall sys_getsockname nr 51 nbargs 3 types: (int, struct sockaddr *, int *) args: (fd, usockaddr, usockaddr_len) ++syscall sys_getpeername nr 52 nbargs 3 types: (int, struct sockaddr *, int *) args: (fd, usockaddr, usockaddr_len) ++syscall sys_socketpair nr 53 nbargs 4 types: (int, int, int, int *) args: (family, type, protocol, usockvec) ++syscall sys_setsockopt nr 54 nbargs 5 types: (int, int, int, char *, int) args: (fd, level, optname, optval, optlen) ++syscall sys_getsockopt nr 55 nbargs 5 types: (int, int, int, char *, int *) args: (fd, level, optname, optval, optlen) ++syscall sys_exit nr 60 nbargs 1 types: (int) args: (error_code) ++syscall sys_wait4 nr 61 nbargs 4 types: (pid_t, int *, int, struct rusage *) args: (upid, stat_addr, options, ru) ++syscall sys_kill nr 62 nbargs 2 types: (pid_t, int) args: (pid, sig) ++syscall sys_newuname nr 63 nbargs 1 types: (struct new_utsname *) args: (name) ++syscall sys_semget nr 64 nbargs 3 types: (key_t, int, int) args: (key, nsems, semflg) ++syscall sys_semop nr 65 nbargs 3 types: (int, struct sembuf *, unsigned) args: (semid, tsops, nsops) ++syscall sys_shmdt nr 67 nbargs 1 types: (char *) args: (shmaddr) ++syscall sys_msgget nr 68 nbargs 2 types: (key_t, int) args: (key, msgflg) ++syscall sys_msgsnd nr 69 nbargs 4 types: (int, struct msgbuf *, size_t, int) args: (msqid, msgp, msgsz, msgflg) ++syscall sys_msgrcv nr 70 nbargs 5 types: (int, struct msgbuf *, size_t, long, int) args: (msqid, msgp, msgsz, msgtyp, msgflg) ++syscall sys_msgctl nr 71 nbargs 3 types: (int, int, struct msqid_ds *) args: (msqid, cmd, buf) ++syscall sys_fcntl nr 72 nbargs 3 types: (unsigned int, unsigned int, unsigned long) args: (fd, cmd, arg) ++syscall sys_flock nr 73 nbargs 2 types: (unsigned int, unsigned int) args: (fd, cmd) ++syscall sys_fsync nr 74 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_fdatasync nr 75 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_truncate nr 76 nbargs 2 types: (const char *, long) args: (path, length) ++syscall sys_ftruncate nr 77 nbargs 2 types: (unsigned int, unsigned long) args: (fd, length) ++syscall sys_getdents nr 78 nbargs 3 types: (unsigned int, struct linux_dirent *, unsigned int) args: (fd, dirent, count) ++syscall sys_getcwd nr 79 nbargs 2 types: (char *, unsigned long) args: (buf, size) ++syscall sys_chdir nr 80 nbargs 1 types: (const char *) args: (filename) ++syscall sys_fchdir nr 81 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_rename nr 82 nbargs 2 types: (const char *, const char *) args: (oldname, newname) ++syscall sys_mkdir nr 83 nbargs 2 types: (const char *, int) args: (pathname, mode) ++syscall sys_rmdir nr 84 nbargs 1 types: (const char *) args: (pathname) ++syscall sys_creat nr 85 nbargs 2 types: (const char *, int) args: (pathname, mode) ++syscall sys_link nr 86 nbargs 2 types: (const char *, const char *) args: (oldname, newname) ++syscall sys_unlink nr 87 nbargs 1 types: (const char *) args: (pathname) ++syscall sys_symlink nr 88 nbargs 2 types: (const char *, const char *) args: (oldname, newname) ++syscall sys_readlink nr 89 nbargs 3 types: (const char *, char *, int) args: (path, buf, bufsiz) ++syscall sys_chmod nr 90 nbargs 2 types: (const char *, mode_t) args: (filename, mode) ++syscall sys_fchmod nr 91 nbargs 2 types: (unsigned int, mode_t) args: (fd, mode) ++syscall sys_chown nr 92 nbargs 3 types: (const char *, uid_t, gid_t) args: (filename, user, group) ++syscall sys_fchown nr 93 nbargs 3 types: (unsigned int, uid_t, gid_t) args: (fd, user, group) ++syscall sys_lchown nr 94 nbargs 3 types: (const char *, uid_t, gid_t) args: (filename, user, group) ++syscall sys_umask nr 95 nbargs 1 types: (int) args: (mask) ++syscall sys_gettimeofday nr 96 nbargs 2 types: (struct timeval *, struct timezone *) args: (tv, tz) ++syscall sys_getrlimit nr 97 nbargs 2 types: (unsigned int, struct rlimit *) args: (resource, rlim) ++syscall sys_getrusage nr 98 nbargs 2 types: (int, struct rusage *) args: (who, ru) ++syscall sys_sysinfo nr 99 nbargs 1 types: (struct sysinfo *) args: (info) ++syscall sys_times nr 100 nbargs 1 types: (struct tms *) args: (tbuf) ++syscall sys_ptrace nr 101 nbargs 4 types: (long, long, unsigned long, unsigned long) args: (request, pid, addr, data) ++syscall sys_getuid nr 102 nbargs 0 types: () args: () ++syscall sys_syslog nr 103 nbargs 3 types: (int, char *, int) args: (type, buf, len) ++syscall sys_getgid nr 104 nbargs 0 types: () args: () ++syscall sys_setuid nr 105 nbargs 1 types: (uid_t) args: (uid) ++syscall sys_setgid nr 106 nbargs 1 types: (gid_t) args: (gid) ++syscall sys_geteuid nr 107 nbargs 0 types: () args: () ++syscall sys_getegid nr 108 nbargs 0 types: () args: () ++syscall sys_setpgid nr 109 nbargs 2 types: (pid_t, pid_t) args: (pid, pgid) ++syscall sys_getppid nr 110 nbargs 0 types: () args: () ++syscall sys_getpgrp nr 111 nbargs 0 types: () args: () ++syscall sys_setsid nr 112 nbargs 0 types: () args: () ++syscall sys_setreuid nr 113 nbargs 2 types: (uid_t, uid_t) args: (ruid, euid) ++syscall sys_setregid nr 114 nbargs 2 types: (gid_t, gid_t) args: (rgid, egid) ++syscall sys_getgroups nr 115 nbargs 2 types: (int, gid_t *) args: (gidsetsize, grouplist) ++syscall sys_setgroups nr 116 nbargs 2 types: (int, gid_t *) args: (gidsetsize, grouplist) ++syscall sys_setresuid nr 117 nbargs 3 types: (uid_t, uid_t, uid_t) args: (ruid, euid, suid) ++syscall sys_getresuid nr 118 nbargs 3 types: (uid_t *, uid_t *, uid_t *) args: (ruid, euid, suid) ++syscall sys_setresgid nr 119 nbargs 3 types: (gid_t, gid_t, gid_t) args: (rgid, egid, sgid) ++syscall sys_getresgid nr 120 nbargs 3 types: (gid_t *, gid_t *, gid_t *) args: (rgid, egid, sgid) ++syscall sys_getpgid nr 121 nbargs 1 types: (pid_t) args: (pid) ++syscall sys_setfsuid nr 122 nbargs 1 types: (uid_t) args: (uid) ++syscall sys_setfsgid nr 123 nbargs 1 types: (gid_t) args: (gid) ++syscall sys_getsid nr 124 nbargs 1 types: (pid_t) args: (pid) ++syscall sys_capget nr 125 nbargs 2 types: (cap_user_header_t, cap_user_data_t) args: (header, dataptr) ++syscall sys_capset nr 126 nbargs 2 types: (cap_user_header_t, const cap_user_data_t) args: (header, data) ++syscall sys_rt_sigpending nr 127 nbargs 2 types: (sigset_t *, size_t) args: (set, sigsetsize) ++syscall sys_rt_sigtimedwait nr 128 nbargs 4 types: (const sigset_t *, siginfo_t *, const struct timespec *, size_t) args: (uthese, uinfo, uts, sigsetsize) ++syscall sys_rt_sigqueueinfo nr 129 nbargs 3 types: (pid_t, int, siginfo_t *) args: (pid, sig, uinfo) ++syscall sys_rt_sigsuspend nr 130 nbargs 2 types: (sigset_t *, size_t) args: (unewset, sigsetsize) ++syscall sys_utime nr 132 nbargs 2 types: (char *, struct utimbuf *) args: (filename, times) ++syscall sys_mknod nr 133 nbargs 3 types: (const char *, int, unsigned) args: (filename, mode, dev) ++syscall sys_personality nr 135 nbargs 1 types: (unsigned int) args: (personality) ++syscall sys_ustat nr 136 nbargs 2 types: (unsigned, struct ustat *) args: (dev, ubuf) ++syscall sys_statfs nr 137 nbargs 2 types: (const char *, struct statfs *) args: (pathname, buf) ++syscall sys_fstatfs nr 138 nbargs 2 types: (unsigned int, struct statfs *) args: (fd, buf) ++syscall sys_sysfs nr 139 nbargs 3 types: (int, unsigned long, unsigned long) args: (option, arg1, arg2) ++syscall sys_getpriority nr 140 nbargs 2 types: (int, int) args: (which, who) ++syscall sys_setpriority nr 141 nbargs 3 types: (int, int, int) args: (which, who, niceval) ++syscall sys_sched_setparam nr 142 nbargs 2 types: (pid_t, struct sched_param *) args: (pid, param) ++syscall sys_sched_getparam nr 143 nbargs 2 types: (pid_t, struct sched_param *) args: (pid, param) ++syscall sys_sched_setscheduler nr 144 nbargs 3 types: (pid_t, int, struct sched_param *) args: (pid, policy, param) ++syscall sys_sched_getscheduler nr 145 nbargs 1 types: (pid_t) args: (pid) ++syscall sys_sched_get_priority_max nr 146 nbargs 1 types: (int) args: (policy) ++syscall sys_sched_get_priority_min nr 147 nbargs 1 types: (int) args: (policy) ++syscall sys_sched_rr_get_interval nr 148 nbargs 2 types: (pid_t, struct timespec *) args: (pid, interval) ++syscall sys_mlock nr 149 nbargs 2 types: (unsigned long, size_t) args: (start, len) ++syscall sys_munlock nr 150 nbargs 2 types: (unsigned long, size_t) args: (start, len) ++syscall sys_mlockall nr 151 nbargs 1 types: (int) args: (flags) ++syscall sys_munlockall nr 152 nbargs 0 types: () args: () ++syscall sys_vhangup nr 153 nbargs 0 types: () args: () ++syscall sys_pivot_root nr 155 nbargs 2 types: (const char *, const char *) args: (new_root, put_old) ++syscall sys_sysctl nr 156 nbargs 1 types: (struct __sysctl_args *) args: (args) ++syscall sys_prctl nr 157 nbargs 5 types: (int, unsigned long, unsigned long, unsigned long, unsigned long) args: (option, arg2, arg3, arg4, arg5) ++syscall sys_adjtimex nr 159 nbargs 1 types: (struct timex *) args: (txc_p) ++syscall sys_setrlimit nr 160 nbargs 2 types: (unsigned int, struct rlimit *) args: (resource, rlim) ++syscall sys_chroot nr 161 nbargs 1 types: (const char *) args: (filename) ++syscall sys_sync nr 162 nbargs 0 types: () args: () ++syscall sys_settimeofday nr 164 nbargs 2 types: (struct timeval *, struct timezone *) args: (tv, tz) ++syscall sys_mount nr 165 nbargs 5 types: (char *, char *, char *, unsigned long, void *) args: (dev_name, dir_name, type, flags, data) ++syscall sys_umount nr 166 nbargs 2 types: (char *, int) args: (name, flags) ++syscall sys_swapon nr 167 nbargs 2 types: (const char *, int) args: (specialfile, swap_flags) ++syscall sys_swapoff nr 168 nbargs 1 types: (const char *) args: (specialfile) ++syscall sys_reboot nr 169 nbargs 4 types: (int, int, unsigned int, void *) args: (magic1, magic2, cmd, arg) ++syscall sys_sethostname nr 170 nbargs 2 types: (char *, int) args: (name, len) ++syscall sys_setdomainname nr 171 nbargs 2 types: (char *, int) args: (name, len) ++syscall sys_init_module nr 175 nbargs 3 types: (void *, unsigned long, const char *) args: (umod, len, uargs) ++syscall sys_delete_module nr 176 nbargs 2 types: (const char *, unsigned int) args: (name_user, flags) ++syscall sys_nfsservctl nr 180 nbargs 3 types: (int, struct nfsctl_arg *, void *) args: (cmd, arg, res) ++syscall sys_gettid nr 186 nbargs 0 types: () args: () ++syscall sys_setxattr nr 188 nbargs 5 types: (const char *, const char *, const void *, size_t, int) args: (pathname, name, value, size, flags) ++syscall sys_lsetxattr nr 189 nbargs 5 types: (const char *, const char *, const void *, size_t, int) args: (pathname, name, value, size, flags) ++syscall sys_fsetxattr nr 190 nbargs 5 types: (int, const char *, const void *, size_t, int) args: (fd, name, value, size, flags) ++syscall sys_getxattr nr 191 nbargs 4 types: (const char *, const char *, void *, size_t) args: (pathname, name, value, size) ++syscall sys_lgetxattr nr 192 nbargs 4 types: (const char *, const char *, void *, size_t) args: (pathname, name, value, size) ++syscall sys_fgetxattr nr 193 nbargs 4 types: (int, const char *, void *, size_t) args: (fd, name, value, size) ++syscall sys_listxattr nr 194 nbargs 3 types: (const char *, char *, size_t) args: (pathname, list, size) ++syscall sys_llistxattr nr 195 nbargs 3 types: (const char *, char *, size_t) args: (pathname, list, size) ++syscall sys_flistxattr nr 196 nbargs 3 types: (int, char *, size_t) args: (fd, list, size) ++syscall sys_removexattr nr 197 nbargs 2 types: (const char *, const char *) args: (pathname, name) ++syscall sys_lremovexattr nr 198 nbargs 2 types: (const char *, const char *) args: (pathname, name) ++syscall sys_fremovexattr nr 199 nbargs 2 types: (int, const char *) args: (fd, name) ++syscall sys_tkill nr 200 nbargs 2 types: (pid_t, int) args: (pid, sig) ++syscall sys_time nr 201 nbargs 1 types: (time_t *) args: (tloc) ++syscall sys_futex nr 202 nbargs 6 types: (u32 *, int, u32, struct timespec *, u32 *, u32) args: (uaddr, op, val, utime, uaddr2, val3) ++syscall sys_sched_setaffinity nr 203 nbargs 3 types: (pid_t, unsigned int, unsigned long *) args: (pid, len, user_mask_ptr) ++syscall sys_sched_getaffinity nr 204 nbargs 3 types: (pid_t, unsigned int, unsigned long *) args: (pid, len, user_mask_ptr) ++syscall sys_io_setup nr 206 nbargs 2 types: (unsigned, aio_context_t *) args: (nr_events, ctxp) ++syscall sys_io_destroy nr 207 nbargs 1 types: (aio_context_t) args: (ctx) ++syscall sys_io_getevents nr 208 nbargs 5 types: (aio_context_t, long, long, struct io_event *, struct timespec *) args: (ctx_id, min_nr, nr, events, timeout) ++syscall sys_io_submit nr 209 nbargs 3 types: (aio_context_t, long, struct iocb * *) args: (ctx_id, nr, iocbpp) ++syscall sys_io_cancel nr 210 nbargs 3 types: (aio_context_t, struct iocb *, struct io_event *) args: (ctx_id, iocb, result) ++syscall sys_epoll_create nr 213 nbargs 1 types: (int) args: (size) ++syscall sys_remap_file_pages nr 216 nbargs 5 types: (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) args: (start, size, prot, pgoff, flags) ++syscall sys_getdents64 nr 217 nbargs 3 types: (unsigned int, struct linux_dirent64 *, unsigned int) args: (fd, dirent, count) ++syscall sys_set_tid_address nr 218 nbargs 1 types: (int *) args: (tidptr) ++syscall sys_restart_syscall nr 219 nbargs 0 types: () args: () ++syscall sys_semtimedop nr 220 nbargs 4 types: (int, struct sembuf *, unsigned, const struct timespec *) args: (semid, tsops, nsops, timeout) ++syscall sys_timer_create nr 222 nbargs 3 types: (const clockid_t, struct sigevent *, timer_t *) args: (which_clock, timer_event_spec, created_timer_id) ++syscall sys_timer_settime nr 223 nbargs 4 types: (timer_t, int, const struct itimerspec *, struct itimerspec *) args: (timer_id, flags, new_setting, old_setting) ++syscall sys_timer_gettime nr 224 nbargs 2 types: (timer_t, struct itimerspec *) args: (timer_id, setting) ++syscall sys_timer_getoverrun nr 225 nbargs 1 types: (timer_t) args: (timer_id) ++syscall sys_timer_delete nr 226 nbargs 1 types: (timer_t) args: (timer_id) ++syscall sys_clock_settime nr 227 nbargs 2 types: (const clockid_t, const struct timespec *) args: (which_clock, tp) ++syscall sys_clock_gettime nr 228 nbargs 2 types: (const clockid_t, struct timespec *) args: (which_clock, tp) ++syscall sys_clock_getres nr 229 nbargs 2 types: (const clockid_t, struct timespec *) args: (which_clock, tp) ++syscall sys_clock_nanosleep nr 230 nbargs 4 types: (const clockid_t, int, const struct timespec *, struct timespec *) args: (which_clock, flags, rqtp, rmtp) ++syscall sys_exit_group nr 231 nbargs 1 types: (int) args: (error_code) ++syscall sys_epoll_wait nr 232 nbargs 4 types: (int, struct epoll_event *, int, int) args: (epfd, events, maxevents, timeout) ++syscall sys_epoll_ctl nr 233 nbargs 4 types: (int, int, int, struct epoll_event *) args: (epfd, op, fd, event) ++syscall sys_tgkill nr 234 nbargs 3 types: (pid_t, pid_t, int) args: (tgid, pid, sig) ++syscall sys_utimes nr 235 nbargs 2 types: (char *, struct timeval *) args: (filename, utimes) ++syscall sys_mq_open nr 240 nbargs 4 types: (const char *, int, mode_t, struct mq_attr *) args: (u_name, oflag, mode, u_attr) ++syscall sys_mq_unlink nr 241 nbargs 1 types: (const char *) args: (u_name) ++syscall sys_mq_timedsend nr 242 nbargs 5 types: (mqd_t, const char *, size_t, unsigned int, const struct timespec *) args: (mqdes, u_msg_ptr, msg_len, msg_prio, u_abs_timeout) ++syscall sys_mq_timedreceive nr 243 nbargs 5 types: (mqd_t, char *, size_t, unsigned int *, const struct timespec *) args: (mqdes, u_msg_ptr, msg_len, u_msg_prio, u_abs_timeout) ++syscall sys_mq_notify nr 244 nbargs 2 types: (mqd_t, const struct sigevent *) args: (mqdes, u_notification) ++syscall sys_mq_getsetattr nr 245 nbargs 3 types: (mqd_t, const struct mq_attr *, struct mq_attr *) args: (mqdes, u_mqstat, u_omqstat) ++syscall sys_kexec_load nr 246 nbargs 4 types: (unsigned long, unsigned long, struct kexec_segment *, unsigned long) args: (entry, nr_segments, segments, flags) ++syscall sys_waitid nr 247 nbargs 5 types: (int, pid_t, struct siginfo *, int, struct rusage *) args: (which, upid, infop, options, ru) ++syscall sys_ioprio_set nr 251 nbargs 3 types: (int, int, int) args: (which, who, ioprio) ++syscall sys_ioprio_get nr 252 nbargs 2 types: (int, int) args: (which, who) ++syscall sys_inotify_init nr 253 nbargs 0 types: () args: () ++syscall sys_inotify_add_watch nr 254 nbargs 3 types: (int, const char *, u32) args: (fd, pathname, mask) ++syscall sys_inotify_rm_watch nr 255 nbargs 2 types: (int, __s32) args: (fd, wd) ++syscall sys_openat nr 257 nbargs 4 types: (int, const char *, int, int) args: (dfd, filename, flags, mode) ++syscall sys_mkdirat nr 258 nbargs 3 types: (int, const char *, int) args: (dfd, pathname, mode) ++syscall sys_mknodat nr 259 nbargs 4 types: (int, const char *, int, unsigned) args: (dfd, filename, mode, dev) ++syscall sys_fchownat nr 260 nbargs 5 types: (int, const char *, uid_t, gid_t, int) args: (dfd, filename, user, group, flag) ++syscall sys_futimesat nr 261 nbargs 3 types: (int, const char *, struct timeval *) args: (dfd, filename, utimes) ++syscall sys_newfstatat nr 262 nbargs 4 types: (int, const char *, struct stat *, int) args: (dfd, filename, statbuf, flag) ++syscall sys_unlinkat nr 263 nbargs 3 types: (int, const char *, int) args: (dfd, pathname, flag) ++syscall sys_renameat nr 264 nbargs 4 types: (int, const char *, int, const char *) args: (olddfd, oldname, newdfd, newname) ++syscall sys_linkat nr 265 nbargs 5 types: (int, const char *, int, const char *, int) args: (olddfd, oldname, newdfd, newname, flags) ++syscall sys_symlinkat nr 266 nbargs 3 types: (const char *, int, const char *) args: (oldname, newdfd, newname) ++syscall sys_readlinkat nr 267 nbargs 4 types: (int, const char *, char *, int) args: (dfd, pathname, buf, bufsiz) ++syscall sys_fchmodat nr 268 nbargs 3 types: (int, const char *, mode_t) args: (dfd, filename, mode) ++syscall sys_faccessat nr 269 nbargs 3 types: (int, const char *, int) args: (dfd, filename, mode) ++syscall sys_pselect6 nr 270 nbargs 6 types: (int, fd_set *, fd_set *, fd_set *, struct timespec *, void *) args: (n, inp, outp, exp, tsp, sig) ++syscall sys_ppoll nr 271 nbargs 5 types: (struct pollfd *, unsigned int, struct timespec *, const sigset_t *, size_t) args: (ufds, nfds, tsp, sigmask, sigsetsize) ++syscall sys_unshare nr 272 nbargs 1 types: (unsigned long) args: (unshare_flags) ++syscall sys_set_robust_list nr 273 nbargs 2 types: (struct robust_list_head *, size_t) args: (head, len) ++syscall sys_get_robust_list nr 274 nbargs 3 types: (int, struct robust_list_head * *, size_t *) args: (pid, head_ptr, len_ptr) ++syscall sys_splice nr 275 nbargs 6 types: (int, loff_t *, int, loff_t *, size_t, unsigned int) args: (fd_in, off_in, fd_out, off_out, len, flags) ++syscall sys_tee nr 276 nbargs 4 types: (int, int, size_t, unsigned int) args: (fdin, fdout, len, flags) ++syscall sys_vmsplice nr 278 nbargs 4 types: (int, const struct iovec *, unsigned long, unsigned int) args: (fd, iov, nr_segs, flags) ++syscall sys_utimensat nr 280 nbargs 4 types: (int, const char *, struct timespec *, int) args: (dfd, filename, utimes, flags) ++syscall sys_epoll_pwait nr 281 nbargs 6 types: (int, struct epoll_event *, int, int, const sigset_t *, size_t) args: (epfd, events, maxevents, timeout, sigmask, sigsetsize) ++syscall sys_signalfd nr 282 nbargs 3 types: (int, sigset_t *, size_t) args: (ufd, user_mask, sizemask) ++syscall sys_timerfd_create nr 283 nbargs 2 types: (int, int) args: (clockid, flags) ++syscall sys_eventfd nr 284 nbargs 1 types: (unsigned int) args: (count) ++syscall sys_timerfd_settime nr 286 nbargs 4 types: (int, int, const struct itimerspec *, struct itimerspec *) args: (ufd, flags, utmr, otmr) ++syscall sys_timerfd_gettime nr 287 nbargs 2 types: (int, struct itimerspec *) args: (ufd, otmr) ++syscall sys_accept4 nr 288 nbargs 4 types: (int, struct sockaddr *, int *, int) args: (fd, upeer_sockaddr, upeer_addrlen, flags) ++syscall sys_signalfd4 nr 289 nbargs 4 types: (int, sigset_t *, size_t, int) args: (ufd, user_mask, sizemask, flags) ++syscall sys_eventfd2 nr 290 nbargs 2 types: (unsigned int, int) args: (count, flags) ++syscall sys_epoll_create1 nr 291 nbargs 1 types: (int) args: (flags) ++syscall sys_dup3 nr 292 nbargs 3 types: (unsigned int, unsigned int, int) args: (oldfd, newfd, flags) ++syscall sys_pipe2 nr 293 nbargs 2 types: (int *, int) args: (fildes, flags) ++syscall sys_inotify_init1 nr 294 nbargs 1 types: (int) args: (flags) ++syscall sys_preadv nr 295 nbargs 5 types: (unsigned long, const struct iovec *, unsigned long, unsigned long, unsigned long) args: (fd, vec, vlen, pos_l, pos_h) ++syscall sys_pwritev nr 296 nbargs 5 types: (unsigned long, const struct iovec *, unsigned long, unsigned long, unsigned long) args: (fd, vec, vlen, pos_l, pos_h) ++syscall sys_rt_tgsigqueueinfo nr 297 nbargs 4 types: (pid_t, pid_t, int, siginfo_t *) args: (tgid, pid, sig, uinfo) ++syscall sys_perf_event_open nr 298 nbargs 5 types: (struct perf_event_attr *, pid_t, int, int, unsigned long) args: (attr_uptr, pid, cpu, group_fd, flags) ++syscall sys_recvmmsg nr 299 nbargs 5 types: (int, struct mmsghdr *, unsigned int, unsigned int, struct timespec *) args: (fd, mmsg, vlen, flags, timeout) ++syscall sys_prlimit64 nr 302 nbargs 4 types: (pid_t, unsigned int, const struct rlimit64 *, struct rlimit64 *) args: (pid, resource, new_rlim, old_rlim) ++syscall sys_clock_adjtime nr 305 nbargs 2 types: (const clockid_t, struct timex *) args: (which_clock, utx) ++syscall sys_syncfs nr 306 nbargs 1 types: (int) args: (fd) ++syscall sys_sendmmsg nr 307 nbargs 4 types: (int, struct mmsghdr *, unsigned int, unsigned int) args: (fd, mmsg, vlen, flags) ++syscall sys_setns nr 308 nbargs 2 types: (int, int) args: (fd, nstype) +diff --git a/drivers/staging/lttng/instrumentation/syscalls/3.1.0-rc6/x86-32-syscalls-3.1.0-rc6 b/drivers/staging/lttng/instrumentation/syscalls/3.1.0-rc6/x86-32-syscalls-3.1.0-rc6 +new file mode 100644 +index 0000000..130c1e3 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/3.1.0-rc6/x86-32-syscalls-3.1.0-rc6 +@@ -0,0 +1,291 @@ ++syscall sys_restart_syscall nr 0 nbargs 0 types: () args: () ++syscall sys_exit nr 1 nbargs 1 types: (int) args: (error_code) ++syscall sys_read nr 3 nbargs 3 types: (unsigned int, char *, size_t) args: (fd, buf, count) ++syscall sys_write nr 4 nbargs 3 types: (unsigned int, const char *, size_t) args: (fd, buf, count) ++syscall sys_open nr 5 nbargs 3 types: (const char *, int, int) args: (filename, flags, mode) ++syscall sys_close nr 6 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_waitpid nr 7 nbargs 3 types: (pid_t, int *, int) args: (pid, stat_addr, options) ++syscall sys_creat nr 8 nbargs 2 types: (const char *, int) args: (pathname, mode) ++syscall sys_link nr 9 nbargs 2 types: (const char *, const char *) args: (oldname, newname) ++syscall sys_unlink nr 10 nbargs 1 types: (const char *) args: (pathname) ++syscall sys_chdir nr 12 nbargs 1 types: (const char *) args: (filename) ++syscall sys_time nr 13 nbargs 1 types: (time_t *) args: (tloc) ++syscall sys_mknod nr 14 nbargs 3 types: (const char *, int, unsigned) args: (filename, mode, dev) ++syscall sys_chmod nr 15 nbargs 2 types: (const char *, mode_t) args: (filename, mode) ++syscall sys_lchown16 nr 16 nbargs 3 types: (const char *, old_uid_t, old_gid_t) args: (filename, user, group) ++syscall sys_stat nr 18 nbargs 2 types: (const char *, struct __old_kernel_stat *) args: (filename, statbuf) ++syscall sys_lseek nr 19 nbargs 3 types: (unsigned int, off_t, unsigned int) args: (fd, offset, origin) ++syscall sys_getpid nr 20 nbargs 0 types: () args: () ++syscall sys_mount nr 21 nbargs 5 types: (char *, char *, char *, unsigned long, void *) args: (dev_name, dir_name, type, flags, data) ++syscall sys_oldumount nr 22 nbargs 1 types: (char *) args: (name) ++syscall sys_setuid16 nr 23 nbargs 1 types: (old_uid_t) args: (uid) ++syscall sys_getuid16 nr 24 nbargs 0 types: () args: () ++syscall sys_stime nr 25 nbargs 1 types: (time_t *) args: (tptr) ++syscall sys_ptrace nr 26 nbargs 4 types: (long, long, unsigned long, unsigned long) args: (request, pid, addr, data) ++syscall sys_alarm nr 27 nbargs 1 types: (unsigned int) args: (seconds) ++syscall sys_fstat nr 28 nbargs 2 types: (unsigned int, struct __old_kernel_stat *) args: (fd, statbuf) ++syscall sys_pause nr 29 nbargs 0 types: () args: () ++syscall sys_utime nr 30 nbargs 2 types: (char *, struct utimbuf *) args: (filename, times) ++syscall sys_access nr 33 nbargs 2 types: (const char *, int) args: (filename, mode) ++syscall sys_nice nr 34 nbargs 1 types: (int) args: (increment) ++syscall sys_sync nr 36 nbargs 0 types: () args: () ++syscall sys_kill nr 37 nbargs 2 types: (pid_t, int) args: (pid, sig) ++syscall sys_rename nr 38 nbargs 2 types: (const char *, const char *) args: (oldname, newname) ++syscall sys_mkdir nr 39 nbargs 2 types: (const char *, int) args: (pathname, mode) ++syscall sys_rmdir nr 40 nbargs 1 types: (const char *) args: (pathname) ++syscall sys_dup nr 41 nbargs 1 types: (unsigned int) args: (fildes) ++syscall sys_pipe nr 42 nbargs 1 types: (int *) args: (fildes) ++syscall sys_times nr 43 nbargs 1 types: (struct tms *) args: (tbuf) ++syscall sys_brk nr 45 nbargs 1 types: (unsigned long) args: (brk) ++syscall sys_setgid16 nr 46 nbargs 1 types: (old_gid_t) args: (gid) ++syscall sys_getgid16 nr 47 nbargs 0 types: () args: () ++syscall sys_signal nr 48 nbargs 2 types: (int, __sighandler_t) args: (sig, handler) ++syscall sys_geteuid16 nr 49 nbargs 0 types: () args: () ++syscall sys_getegid16 nr 50 nbargs 0 types: () args: () ++syscall sys_acct nr 51 nbargs 1 types: (const char *) args: (name) ++syscall sys_umount nr 52 nbargs 2 types: (char *, int) args: (name, flags) ++syscall sys_ioctl nr 54 nbargs 3 types: (unsigned int, unsigned int, unsigned long) args: (fd, cmd, arg) ++syscall sys_fcntl nr 55 nbargs 3 types: (unsigned int, unsigned int, unsigned long) args: (fd, cmd, arg) ++syscall sys_setpgid nr 57 nbargs 2 types: (pid_t, pid_t) args: (pid, pgid) ++syscall sys_olduname nr 59 nbargs 1 types: (struct oldold_utsname *) args: (name) ++syscall sys_umask nr 60 nbargs 1 types: (int) args: (mask) ++syscall sys_chroot nr 61 nbargs 1 types: (const char *) args: (filename) ++syscall sys_ustat nr 62 nbargs 2 types: (unsigned, struct ustat *) args: (dev, ubuf) ++syscall sys_dup2 nr 63 nbargs 2 types: (unsigned int, unsigned int) args: (oldfd, newfd) ++syscall sys_getppid nr 64 nbargs 0 types: () args: () ++syscall sys_getpgrp nr 65 nbargs 0 types: () args: () ++syscall sys_setsid nr 66 nbargs 0 types: () args: () ++syscall sys_sgetmask nr 68 nbargs 0 types: () args: () ++syscall sys_ssetmask nr 69 nbargs 1 types: (int) args: (newmask) ++syscall sys_setreuid16 nr 70 nbargs 2 types: (old_uid_t, old_uid_t) args: (ruid, euid) ++syscall sys_setregid16 nr 71 nbargs 2 types: (old_gid_t, old_gid_t) args: (rgid, egid) ++syscall sys_sigpending nr 73 nbargs 1 types: (old_sigset_t *) args: (set) ++syscall sys_sethostname nr 74 nbargs 2 types: (char *, int) args: (name, len) ++syscall sys_setrlimit nr 75 nbargs 2 types: (unsigned int, struct rlimit *) args: (resource, rlim) ++syscall sys_old_getrlimit nr 76 nbargs 2 types: (unsigned int, struct rlimit *) args: (resource, rlim) ++syscall sys_getrusage nr 77 nbargs 2 types: (int, struct rusage *) args: (who, ru) ++syscall sys_gettimeofday nr 78 nbargs 2 types: (struct timeval *, struct timezone *) args: (tv, tz) ++syscall sys_settimeofday nr 79 nbargs 2 types: (struct timeval *, struct timezone *) args: (tv, tz) ++syscall sys_getgroups16 nr 80 nbargs 2 types: (int, old_gid_t *) args: (gidsetsize, grouplist) ++syscall sys_setgroups16 nr 81 nbargs 2 types: (int, old_gid_t *) args: (gidsetsize, grouplist) ++syscall sys_old_select nr 82 nbargs 1 types: (struct sel_arg_struct *) args: (arg) ++syscall sys_symlink nr 83 nbargs 2 types: (const char *, const char *) args: (oldname, newname) ++syscall sys_lstat nr 84 nbargs 2 types: (const char *, struct __old_kernel_stat *) args: (filename, statbuf) ++syscall sys_readlink nr 85 nbargs 3 types: (const char *, char *, int) args: (path, buf, bufsiz) ++syscall sys_uselib nr 86 nbargs 1 types: (const char *) args: (library) ++syscall sys_swapon nr 87 nbargs 2 types: (const char *, int) args: (specialfile, swap_flags) ++syscall sys_reboot nr 88 nbargs 4 types: (int, int, unsigned int, void *) args: (magic1, magic2, cmd, arg) ++syscall sys_old_readdir nr 89 nbargs 3 types: (unsigned int, struct old_linux_dirent *, unsigned int) args: (fd, dirent, count) ++syscall sys_old_mmap nr 90 nbargs 1 types: (struct mmap_arg_struct *) args: (arg) ++syscall sys_munmap nr 91 nbargs 2 types: (unsigned long, size_t) args: (addr, len) ++syscall sys_truncate nr 92 nbargs 2 types: (const char *, long) args: (path, length) ++syscall sys_ftruncate nr 93 nbargs 2 types: (unsigned int, unsigned long) args: (fd, length) ++syscall sys_fchmod nr 94 nbargs 2 types: (unsigned int, mode_t) args: (fd, mode) ++syscall sys_fchown16 nr 95 nbargs 3 types: (unsigned int, old_uid_t, old_gid_t) args: (fd, user, group) ++syscall sys_getpriority nr 96 nbargs 2 types: (int, int) args: (which, who) ++syscall sys_setpriority nr 97 nbargs 3 types: (int, int, int) args: (which, who, niceval) ++syscall sys_statfs nr 99 nbargs 2 types: (const char *, struct statfs *) args: (pathname, buf) ++syscall sys_fstatfs nr 100 nbargs 2 types: (unsigned int, struct statfs *) args: (fd, buf) ++syscall sys_socketcall nr 102 nbargs 2 types: (int, unsigned long *) args: (call, args) ++syscall sys_syslog nr 103 nbargs 3 types: (int, char *, int) args: (type, buf, len) ++syscall sys_setitimer nr 104 nbargs 3 types: (int, struct itimerval *, struct itimerval *) args: (which, value, ovalue) ++syscall sys_getitimer nr 105 nbargs 2 types: (int, struct itimerval *) args: (which, value) ++syscall sys_newstat nr 106 nbargs 2 types: (const char *, struct stat *) args: (filename, statbuf) ++syscall sys_newlstat nr 107 nbargs 2 types: (const char *, struct stat *) args: (filename, statbuf) ++syscall sys_newfstat nr 108 nbargs 2 types: (unsigned int, struct stat *) args: (fd, statbuf) ++syscall sys_uname nr 109 nbargs 1 types: (struct old_utsname *) args: (name) ++syscall sys_vhangup nr 111 nbargs 0 types: () args: () ++syscall sys_wait4 nr 114 nbargs 4 types: (pid_t, int *, int, struct rusage *) args: (upid, stat_addr, options, ru) ++syscall sys_swapoff nr 115 nbargs 1 types: (const char *) args: (specialfile) ++syscall sys_sysinfo nr 116 nbargs 1 types: (struct sysinfo *) args: (info) ++syscall sys_ipc nr 117 nbargs 6 types: (unsigned int, int, unsigned long, unsigned long, void *, long) args: (call, first, second, third, ptr, fifth) ++syscall sys_fsync nr 118 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_setdomainname nr 121 nbargs 2 types: (char *, int) args: (name, len) ++syscall sys_newuname nr 122 nbargs 1 types: (struct new_utsname *) args: (name) ++syscall sys_adjtimex nr 124 nbargs 1 types: (struct timex *) args: (txc_p) ++syscall sys_mprotect nr 125 nbargs 3 types: (unsigned long, size_t, unsigned long) args: (start, len, prot) ++syscall sys_sigprocmask nr 126 nbargs 3 types: (int, old_sigset_t *, old_sigset_t *) args: (how, nset, oset) ++syscall sys_init_module nr 128 nbargs 3 types: (void *, unsigned long, const char *) args: (umod, len, uargs) ++syscall sys_delete_module nr 129 nbargs 2 types: (const char *, unsigned int) args: (name_user, flags) ++syscall sys_quotactl nr 131 nbargs 4 types: (unsigned int, const char *, qid_t, void *) args: (cmd, special, id, addr) ++syscall sys_getpgid nr 132 nbargs 1 types: (pid_t) args: (pid) ++syscall sys_fchdir nr 133 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_bdflush nr 134 nbargs 2 types: (int, long) args: (func, data) ++syscall sys_sysfs nr 135 nbargs 3 types: (int, unsigned long, unsigned long) args: (option, arg1, arg2) ++syscall sys_personality nr 136 nbargs 1 types: (unsigned int) args: (personality) ++syscall sys_setfsuid16 nr 138 nbargs 1 types: (old_uid_t) args: (uid) ++syscall sys_setfsgid16 nr 139 nbargs 1 types: (old_gid_t) args: (gid) ++syscall sys_llseek nr 140 nbargs 5 types: (unsigned int, unsigned long, unsigned long, loff_t *, unsigned int) args: (fd, offset_high, offset_low, result, origin) ++syscall sys_getdents nr 141 nbargs 3 types: (unsigned int, struct linux_dirent *, unsigned int) args: (fd, dirent, count) ++syscall sys_select nr 142 nbargs 5 types: (int, fd_set *, fd_set *, fd_set *, struct timeval *) args: (n, inp, outp, exp, tvp) ++syscall sys_flock nr 143 nbargs 2 types: (unsigned int, unsigned int) args: (fd, cmd) ++syscall sys_msync nr 144 nbargs 3 types: (unsigned long, size_t, int) args: (start, len, flags) ++syscall sys_readv nr 145 nbargs 3 types: (unsigned long, const struct iovec *, unsigned long) args: (fd, vec, vlen) ++syscall sys_writev nr 146 nbargs 3 types: (unsigned long, const struct iovec *, unsigned long) args: (fd, vec, vlen) ++syscall sys_getsid nr 147 nbargs 1 types: (pid_t) args: (pid) ++syscall sys_fdatasync nr 148 nbargs 1 types: (unsigned int) args: (fd) ++syscall sys_sysctl nr 149 nbargs 1 types: (struct __sysctl_args *) args: (args) ++syscall sys_mlock nr 150 nbargs 2 types: (unsigned long, size_t) args: (start, len) ++syscall sys_munlock nr 151 nbargs 2 types: (unsigned long, size_t) args: (start, len) ++syscall sys_mlockall nr 152 nbargs 1 types: (int) args: (flags) ++syscall sys_munlockall nr 153 nbargs 0 types: () args: () ++syscall sys_sched_setparam nr 154 nbargs 2 types: (pid_t, struct sched_param *) args: (pid, param) ++syscall sys_sched_getparam nr 155 nbargs 2 types: (pid_t, struct sched_param *) args: (pid, param) ++syscall sys_sched_setscheduler nr 156 nbargs 3 types: (pid_t, int, struct sched_param *) args: (pid, policy, param) ++syscall sys_sched_getscheduler nr 157 nbargs 1 types: (pid_t) args: (pid) ++syscall sys_sched_yield nr 158 nbargs 0 types: () args: () ++syscall sys_sched_get_priority_max nr 159 nbargs 1 types: (int) args: (policy) ++syscall sys_sched_get_priority_min nr 160 nbargs 1 types: (int) args: (policy) ++syscall sys_sched_rr_get_interval nr 161 nbargs 2 types: (pid_t, struct timespec *) args: (pid, interval) ++syscall sys_nanosleep nr 162 nbargs 2 types: (struct timespec *, struct timespec *) args: (rqtp, rmtp) ++syscall sys_mremap nr 163 nbargs 5 types: (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) args: (addr, old_len, new_len, flags, new_addr) ++syscall sys_setresuid16 nr 164 nbargs 3 types: (old_uid_t, old_uid_t, old_uid_t) args: (ruid, euid, suid) ++syscall sys_getresuid16 nr 165 nbargs 3 types: (old_uid_t *, old_uid_t *, old_uid_t *) args: (ruid, euid, suid) ++syscall sys_poll nr 168 nbargs 3 types: (struct pollfd *, unsigned int, long) args: (ufds, nfds, timeout_msecs) ++syscall sys_setresgid16 nr 170 nbargs 3 types: (old_gid_t, old_gid_t, old_gid_t) args: (rgid, egid, sgid) ++syscall sys_getresgid16 nr 171 nbargs 3 types: (old_gid_t *, old_gid_t *, old_gid_t *) args: (rgid, egid, sgid) ++syscall sys_prctl nr 172 nbargs 5 types: (int, unsigned long, unsigned long, unsigned long, unsigned long) args: (option, arg2, arg3, arg4, arg5) ++syscall sys_rt_sigaction nr 174 nbargs 4 types: (int, const struct sigaction *, struct sigaction *, size_t) args: (sig, act, oact, sigsetsize) ++syscall sys_rt_sigprocmask nr 175 nbargs 4 types: (int, sigset_t *, sigset_t *, size_t) args: (how, nset, oset, sigsetsize) ++syscall sys_rt_sigpending nr 176 nbargs 2 types: (sigset_t *, size_t) args: (set, sigsetsize) ++syscall sys_rt_sigtimedwait nr 177 nbargs 4 types: (const sigset_t *, siginfo_t *, const struct timespec *, size_t) args: (uthese, uinfo, uts, sigsetsize) ++syscall sys_rt_sigqueueinfo nr 178 nbargs 3 types: (pid_t, int, siginfo_t *) args: (pid, sig, uinfo) ++syscall sys_rt_sigsuspend nr 179 nbargs 2 types: (sigset_t *, size_t) args: (unewset, sigsetsize) ++syscall sys_chown16 nr 182 nbargs 3 types: (const char *, old_uid_t, old_gid_t) args: (filename, user, group) ++syscall sys_getcwd nr 183 nbargs 2 types: (char *, unsigned long) args: (buf, size) ++syscall sys_capget nr 184 nbargs 2 types: (cap_user_header_t, cap_user_data_t) args: (header, dataptr) ++syscall sys_capset nr 185 nbargs 2 types: (cap_user_header_t, const cap_user_data_t) args: (header, data) ++syscall sys_sendfile nr 187 nbargs 4 types: (int, int, off_t *, size_t) args: (out_fd, in_fd, offset, count) ++syscall sys_getrlimit nr 191 nbargs 2 types: (unsigned int, struct rlimit *) args: (resource, rlim) ++syscall sys_mmap_pgoff nr 192 nbargs 6 types: (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) args: (addr, len, prot, flags, fd, pgoff) ++syscall sys_stat64 nr 195 nbargs 2 types: (const char *, struct stat64 *) args: (filename, statbuf) ++syscall sys_lstat64 nr 196 nbargs 2 types: (const char *, struct stat64 *) args: (filename, statbuf) ++syscall sys_fstat64 nr 197 nbargs 2 types: (unsigned long, struct stat64 *) args: (fd, statbuf) ++syscall sys_lchown nr 198 nbargs 3 types: (const char *, uid_t, gid_t) args: (filename, user, group) ++syscall sys_getuid nr 199 nbargs 0 types: () args: () ++syscall sys_getgid nr 200 nbargs 0 types: () args: () ++syscall sys_geteuid nr 201 nbargs 0 types: () args: () ++syscall sys_getegid nr 202 nbargs 0 types: () args: () ++syscall sys_setreuid nr 203 nbargs 2 types: (uid_t, uid_t) args: (ruid, euid) ++syscall sys_setregid nr 204 nbargs 2 types: (gid_t, gid_t) args: (rgid, egid) ++syscall sys_getgroups nr 205 nbargs 2 types: (int, gid_t *) args: (gidsetsize, grouplist) ++syscall sys_setgroups nr 206 nbargs 2 types: (int, gid_t *) args: (gidsetsize, grouplist) ++syscall sys_fchown nr 207 nbargs 3 types: (unsigned int, uid_t, gid_t) args: (fd, user, group) ++syscall sys_setresuid nr 208 nbargs 3 types: (uid_t, uid_t, uid_t) args: (ruid, euid, suid) ++syscall sys_getresuid nr 209 nbargs 3 types: (uid_t *, uid_t *, uid_t *) args: (ruid, euid, suid) ++syscall sys_setresgid nr 210 nbargs 3 types: (gid_t, gid_t, gid_t) args: (rgid, egid, sgid) ++syscall sys_getresgid nr 211 nbargs 3 types: (gid_t *, gid_t *, gid_t *) args: (rgid, egid, sgid) ++syscall sys_chown nr 212 nbargs 3 types: (const char *, uid_t, gid_t) args: (filename, user, group) ++syscall sys_setuid nr 213 nbargs 1 types: (uid_t) args: (uid) ++syscall sys_setgid nr 214 nbargs 1 types: (gid_t) args: (gid) ++syscall sys_setfsuid nr 215 nbargs 1 types: (uid_t) args: (uid) ++syscall sys_setfsgid nr 216 nbargs 1 types: (gid_t) args: (gid) ++syscall sys_pivot_root nr 217 nbargs 2 types: (const char *, const char *) args: (new_root, put_old) ++syscall sys_mincore nr 218 nbargs 3 types: (unsigned long, size_t, unsigned char *) args: (start, len, vec) ++syscall sys_madvise nr 219 nbargs 3 types: (unsigned long, size_t, int) args: (start, len_in, behavior) ++syscall sys_getdents64 nr 220 nbargs 3 types: (unsigned int, struct linux_dirent64 *, unsigned int) args: (fd, dirent, count) ++syscall sys_fcntl64 nr 221 nbargs 3 types: (unsigned int, unsigned int, unsigned long) args: (fd, cmd, arg) ++syscall sys_gettid nr 224 nbargs 0 types: () args: () ++syscall sys_setxattr nr 226 nbargs 5 types: (const char *, const char *, const void *, size_t, int) args: (pathname, name, value, size, flags) ++syscall sys_lsetxattr nr 227 nbargs 5 types: (const char *, const char *, const void *, size_t, int) args: (pathname, name, value, size, flags) ++syscall sys_fsetxattr nr 228 nbargs 5 types: (int, const char *, const void *, size_t, int) args: (fd, name, value, size, flags) ++syscall sys_getxattr nr 229 nbargs 4 types: (const char *, const char *, void *, size_t) args: (pathname, name, value, size) ++syscall sys_lgetxattr nr 230 nbargs 4 types: (const char *, const char *, void *, size_t) args: (pathname, name, value, size) ++syscall sys_fgetxattr nr 231 nbargs 4 types: (int, const char *, void *, size_t) args: (fd, name, value, size) ++syscall sys_listxattr nr 232 nbargs 3 types: (const char *, char *, size_t) args: (pathname, list, size) ++syscall sys_llistxattr nr 233 nbargs 3 types: (const char *, char *, size_t) args: (pathname, list, size) ++syscall sys_flistxattr nr 234 nbargs 3 types: (int, char *, size_t) args: (fd, list, size) ++syscall sys_removexattr nr 235 nbargs 2 types: (const char *, const char *) args: (pathname, name) ++syscall sys_lremovexattr nr 236 nbargs 2 types: (const char *, const char *) args: (pathname, name) ++syscall sys_fremovexattr nr 237 nbargs 2 types: (int, const char *) args: (fd, name) ++syscall sys_tkill nr 238 nbargs 2 types: (pid_t, int) args: (pid, sig) ++syscall sys_sendfile64 nr 239 nbargs 4 types: (int, int, loff_t *, size_t) args: (out_fd, in_fd, offset, count) ++syscall sys_futex nr 240 nbargs 6 types: (u32 *, int, u32, struct timespec *, u32 *, u32) args: (uaddr, op, val, utime, uaddr2, val3) ++syscall sys_sched_setaffinity nr 241 nbargs 3 types: (pid_t, unsigned int, unsigned long *) args: (pid, len, user_mask_ptr) ++syscall sys_sched_getaffinity nr 242 nbargs 3 types: (pid_t, unsigned int, unsigned long *) args: (pid, len, user_mask_ptr) ++syscall sys_io_setup nr 245 nbargs 2 types: (unsigned, aio_context_t *) args: (nr_events, ctxp) ++syscall sys_io_destroy nr 246 nbargs 1 types: (aio_context_t) args: (ctx) ++syscall sys_io_getevents nr 247 nbargs 5 types: (aio_context_t, long, long, struct io_event *, struct timespec *) args: (ctx_id, min_nr, nr, events, timeout) ++syscall sys_io_submit nr 248 nbargs 3 types: (aio_context_t, long, struct iocb * *) args: (ctx_id, nr, iocbpp) ++syscall sys_io_cancel nr 249 nbargs 3 types: (aio_context_t, struct iocb *, struct io_event *) args: (ctx_id, iocb, result) ++syscall sys_exit_group nr 252 nbargs 1 types: (int) args: (error_code) ++syscall sys_epoll_create nr 254 nbargs 1 types: (int) args: (size) ++syscall sys_epoll_ctl nr 255 nbargs 4 types: (int, int, int, struct epoll_event *) args: (epfd, op, fd, event) ++syscall sys_epoll_wait nr 256 nbargs 4 types: (int, struct epoll_event *, int, int) args: (epfd, events, maxevents, timeout) ++syscall sys_remap_file_pages nr 257 nbargs 5 types: (unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) args: (start, size, prot, pgoff, flags) ++syscall sys_set_tid_address nr 258 nbargs 1 types: (int *) args: (tidptr) ++syscall sys_timer_create nr 259 nbargs 3 types: (const clockid_t, struct sigevent *, timer_t *) args: (which_clock, timer_event_spec, created_timer_id) ++syscall sys_timer_settime nr 260 nbargs 4 types: (timer_t, int, const struct itimerspec *, struct itimerspec *) args: (timer_id, flags, new_setting, old_setting) ++syscall sys_timer_gettime nr 261 nbargs 2 types: (timer_t, struct itimerspec *) args: (timer_id, setting) ++syscall sys_timer_getoverrun nr 262 nbargs 1 types: (timer_t) args: (timer_id) ++syscall sys_timer_delete nr 263 nbargs 1 types: (timer_t) args: (timer_id) ++syscall sys_clock_settime nr 264 nbargs 2 types: (const clockid_t, const struct timespec *) args: (which_clock, tp) ++syscall sys_clock_gettime nr 265 nbargs 2 types: (const clockid_t, struct timespec *) args: (which_clock, tp) ++syscall sys_clock_getres nr 266 nbargs 2 types: (const clockid_t, struct timespec *) args: (which_clock, tp) ++syscall sys_clock_nanosleep nr 267 nbargs 4 types: (const clockid_t, int, const struct timespec *, struct timespec *) args: (which_clock, flags, rqtp, rmtp) ++syscall sys_statfs64 nr 268 nbargs 3 types: (const char *, size_t, struct statfs64 *) args: (pathname, sz, buf) ++syscall sys_fstatfs64 nr 269 nbargs 3 types: (unsigned int, size_t, struct statfs64 *) args: (fd, sz, buf) ++syscall sys_tgkill nr 270 nbargs 3 types: (pid_t, pid_t, int) args: (tgid, pid, sig) ++syscall sys_utimes nr 271 nbargs 2 types: (char *, struct timeval *) args: (filename, utimes) ++syscall sys_mq_open nr 277 nbargs 4 types: (const char *, int, mode_t, struct mq_attr *) args: (u_name, oflag, mode, u_attr) ++syscall sys_mq_unlink nr 278 nbargs 1 types: (const char *) args: (u_name) ++syscall sys_mq_timedsend nr 279 nbargs 5 types: (mqd_t, const char *, size_t, unsigned int, const struct timespec *) args: (mqdes, u_msg_ptr, msg_len, msg_prio, u_abs_timeout) ++syscall sys_mq_timedreceive nr 280 nbargs 5 types: (mqd_t, char *, size_t, unsigned int *, const struct timespec *) args: (mqdes, u_msg_ptr, msg_len, u_msg_prio, u_abs_timeout) ++syscall sys_mq_notify nr 281 nbargs 2 types: (mqd_t, const struct sigevent *) args: (mqdes, u_notification) ++syscall sys_mq_getsetattr nr 282 nbargs 3 types: (mqd_t, const struct mq_attr *, struct mq_attr *) args: (mqdes, u_mqstat, u_omqstat) ++syscall sys_kexec_load nr 283 nbargs 4 types: (unsigned long, unsigned long, struct kexec_segment *, unsigned long) args: (entry, nr_segments, segments, flags) ++syscall sys_waitid nr 284 nbargs 5 types: (int, pid_t, struct siginfo *, int, struct rusage *) args: (which, upid, infop, options, ru) ++syscall sys_add_key nr 286 nbargs 5 types: (const char *, const char *, const void *, size_t, key_serial_t) args: (_type, _description, _payload, plen, ringid) ++syscall sys_request_key nr 287 nbargs 4 types: (const char *, const char *, const char *, key_serial_t) args: (_type, _description, _callout_info, destringid) ++syscall sys_keyctl nr 288 nbargs 5 types: (int, unsigned long, unsigned long, unsigned long, unsigned long) args: (option, arg2, arg3, arg4, arg5) ++syscall sys_ioprio_set nr 289 nbargs 3 types: (int, int, int) args: (which, who, ioprio) ++syscall sys_ioprio_get nr 290 nbargs 2 types: (int, int) args: (which, who) ++syscall sys_inotify_init nr 291 nbargs 0 types: () args: () ++syscall sys_inotify_add_watch nr 292 nbargs 3 types: (int, const char *, u32) args: (fd, pathname, mask) ++syscall sys_inotify_rm_watch nr 293 nbargs 2 types: (int, __s32) args: (fd, wd) ++syscall sys_openat nr 295 nbargs 4 types: (int, const char *, int, int) args: (dfd, filename, flags, mode) ++syscall sys_mkdirat nr 296 nbargs 3 types: (int, const char *, int) args: (dfd, pathname, mode) ++syscall sys_mknodat nr 297 nbargs 4 types: (int, const char *, int, unsigned) args: (dfd, filename, mode, dev) ++syscall sys_fchownat nr 298 nbargs 5 types: (int, const char *, uid_t, gid_t, int) args: (dfd, filename, user, group, flag) ++syscall sys_futimesat nr 299 nbargs 3 types: (int, const char *, struct timeval *) args: (dfd, filename, utimes) ++syscall sys_fstatat64 nr 300 nbargs 4 types: (int, const char *, struct stat64 *, int) args: (dfd, filename, statbuf, flag) ++syscall sys_unlinkat nr 301 nbargs 3 types: (int, const char *, int) args: (dfd, pathname, flag) ++syscall sys_renameat nr 302 nbargs 4 types: (int, const char *, int, const char *) args: (olddfd, oldname, newdfd, newname) ++syscall sys_linkat nr 303 nbargs 5 types: (int, const char *, int, const char *, int) args: (olddfd, oldname, newdfd, newname, flags) ++syscall sys_symlinkat nr 304 nbargs 3 types: (const char *, int, const char *) args: (oldname, newdfd, newname) ++syscall sys_readlinkat nr 305 nbargs 4 types: (int, const char *, char *, int) args: (dfd, pathname, buf, bufsiz) ++syscall sys_fchmodat nr 306 nbargs 3 types: (int, const char *, mode_t) args: (dfd, filename, mode) ++syscall sys_faccessat nr 307 nbargs 3 types: (int, const char *, int) args: (dfd, filename, mode) ++syscall sys_pselect6 nr 308 nbargs 6 types: (int, fd_set *, fd_set *, fd_set *, struct timespec *, void *) args: (n, inp, outp, exp, tsp, sig) ++syscall sys_ppoll nr 309 nbargs 5 types: (struct pollfd *, unsigned int, struct timespec *, const sigset_t *, size_t) args: (ufds, nfds, tsp, sigmask, sigsetsize) ++syscall sys_unshare nr 310 nbargs 1 types: (unsigned long) args: (unshare_flags) ++syscall sys_set_robust_list nr 311 nbargs 2 types: (struct robust_list_head *, size_t) args: (head, len) ++syscall sys_get_robust_list nr 312 nbargs 3 types: (int, struct robust_list_head * *, size_t *) args: (pid, head_ptr, len_ptr) ++syscall sys_splice nr 313 nbargs 6 types: (int, loff_t *, int, loff_t *, size_t, unsigned int) args: (fd_in, off_in, fd_out, off_out, len, flags) ++syscall sys_tee nr 315 nbargs 4 types: (int, int, size_t, unsigned int) args: (fdin, fdout, len, flags) ++syscall sys_vmsplice nr 316 nbargs 4 types: (int, const struct iovec *, unsigned long, unsigned int) args: (fd, iov, nr_segs, flags) ++syscall sys_getcpu nr 318 nbargs 3 types: (unsigned *, unsigned *, struct getcpu_cache *) args: (cpup, nodep, unused) ++syscall sys_epoll_pwait nr 319 nbargs 6 types: (int, struct epoll_event *, int, int, const sigset_t *, size_t) args: (epfd, events, maxevents, timeout, sigmask, sigsetsize) ++syscall sys_utimensat nr 320 nbargs 4 types: (int, const char *, struct timespec *, int) args: (dfd, filename, utimes, flags) ++syscall sys_signalfd nr 321 nbargs 3 types: (int, sigset_t *, size_t) args: (ufd, user_mask, sizemask) ++syscall sys_timerfd_create nr 322 nbargs 2 types: (int, int) args: (clockid, flags) ++syscall sys_eventfd nr 323 nbargs 1 types: (unsigned int) args: (count) ++syscall sys_timerfd_settime nr 325 nbargs 4 types: (int, int, const struct itimerspec *, struct itimerspec *) args: (ufd, flags, utmr, otmr) ++syscall sys_timerfd_gettime nr 326 nbargs 2 types: (int, struct itimerspec *) args: (ufd, otmr) ++syscall sys_signalfd4 nr 327 nbargs 4 types: (int, sigset_t *, size_t, int) args: (ufd, user_mask, sizemask, flags) ++syscall sys_eventfd2 nr 328 nbargs 2 types: (unsigned int, int) args: (count, flags) ++syscall sys_epoll_create1 nr 329 nbargs 1 types: (int) args: (flags) ++syscall sys_dup3 nr 330 nbargs 3 types: (unsigned int, unsigned int, int) args: (oldfd, newfd, flags) ++syscall sys_pipe2 nr 331 nbargs 2 types: (int *, int) args: (fildes, flags) ++syscall sys_inotify_init1 nr 332 nbargs 1 types: (int) args: (flags) ++syscall sys_preadv nr 333 nbargs 5 types: (unsigned long, const struct iovec *, unsigned long, unsigned long, unsigned long) args: (fd, vec, vlen, pos_l, pos_h) ++syscall sys_pwritev nr 334 nbargs 5 types: (unsigned long, const struct iovec *, unsigned long, unsigned long, unsigned long) args: (fd, vec, vlen, pos_l, pos_h) ++syscall sys_rt_tgsigqueueinfo nr 335 nbargs 4 types: (pid_t, pid_t, int, siginfo_t *) args: (tgid, pid, sig, uinfo) ++syscall sys_perf_event_open nr 336 nbargs 5 types: (struct perf_event_attr *, pid_t, int, int, unsigned long) args: (attr_uptr, pid, cpu, group_fd, flags) ++syscall sys_recvmmsg nr 337 nbargs 5 types: (int, struct mmsghdr *, unsigned int, unsigned int, struct timespec *) args: (fd, mmsg, vlen, flags, timeout) ++syscall sys_fanotify_init nr 338 nbargs 2 types: (unsigned int, unsigned int) args: (flags, event_f_flags) ++syscall sys_prlimit64 nr 340 nbargs 4 types: (pid_t, unsigned int, const struct rlimit64 *, struct rlimit64 *) args: (pid, resource, new_rlim, old_rlim) ++syscall sys_clock_adjtime nr 343 nbargs 2 types: (const clockid_t, struct timex *) args: (which_clock, utx) ++syscall sys_syncfs nr 344 nbargs 1 types: (int) args: (fd) ++syscall sys_sendmmsg nr 345 nbargs 4 types: (int, struct mmsghdr *, unsigned int, unsigned int) args: (fd, mmsg, vlen, flags) ++syscall sys_setns nr 346 nbargs 2 types: (int, int) args: (fd, nstype) +diff --git a/drivers/staging/lttng/instrumentation/syscalls/README b/drivers/staging/lttng/instrumentation/syscalls/README +new file mode 100644 +index 0000000..6c235e1 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/README +@@ -0,0 +1,18 @@ ++LTTng system call tracing ++ ++1) lttng-syscall-extractor ++ ++You need to build a kernel with CONFIG_FTRACE_SYSCALLS=y and ++CONFIG_KALLSYMS_ALL=y for extraction. Apply the linker patch to get your ++kernel to keep the system call metadata after boot. Then build and load ++the LTTng syscall extractor module. The module will fail to load (this ++is expected). See the dmesg output for system call metadata. ++ ++2) Generate system call TRACE_EVENT(). ++ ++Take the dmesg metadata and feed it to lttng-syscalls-generate-headers.sh, e.g., ++from the instrumentation/syscalls directory. See the script header for ++usage example. ++ ++After these are created, we just need to follow the new system call additions, ++no need to regenerate the whole thing, since system calls are only appended to. +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_integers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_integers.h +new file mode 100644 +index 0000000..dabc4bf +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_integers.h +@@ -0,0 +1,3 @@ ++#ifdef CONFIG_X86_64 ++#include "x86-32-syscalls-3.1.0-rc6_integers.h" ++#endif +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_pointers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_pointers.h +new file mode 100644 +index 0000000..a84423c +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/compat_syscalls_pointers.h +@@ -0,0 +1,3 @@ ++#ifdef CONFIG_X86_64 ++#include "x86-32-syscalls-3.1.0-rc6_pointers.h" ++#endif +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers.h +new file mode 100644 +index 0000000..41db916 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers.h +@@ -0,0 +1,7 @@ ++#ifdef CONFIG_X86_64 ++#include "x86-64-syscalls-3.0.4_integers.h" ++#endif ++ ++#ifdef CONFIG_X86_32 ++#include "x86-32-syscalls-3.1.0-rc6_integers.h" ++#endif +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers_override.h b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers_override.h +new file mode 100644 +index 0000000..276d9a6 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_integers_override.h +@@ -0,0 +1,14 @@ ++#define OVERRIDE_32_sys_mmap ++#define OVERRIDE_64_sys_mmap ++ ++#ifndef CREATE_SYSCALL_TABLE ++ ++SC_TRACE_EVENT(sys_mmap, ++ TP_PROTO(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off), ++ TP_ARGS(addr, len, prot, flags, fd, off), ++ TP_STRUCT__entry(__field_hex(unsigned long, addr) __field(size_t, len) __field(int, prot) __field(int, flags) __field(int, fd) __field(off_t, offset)), ++ TP_fast_assign(tp_assign(addr, addr) tp_assign(len, len) tp_assign(prot, prot) tp_assign(flags, flags) tp_assign(fd, fd) tp_assign(offset, off)), ++ TP_printk() ++) ++ ++#endif /* CREATE_SYSCALL_TABLE */ +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers.h +new file mode 100644 +index 0000000..3223890 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers.h +@@ -0,0 +1,7 @@ ++#ifdef CONFIG_X86_64 ++#include "x86-64-syscalls-3.0.4_pointers.h" ++#endif ++ ++#ifdef CONFIG_X86_32 ++#include "x86-32-syscalls-3.1.0-rc6_pointers.h" ++#endif +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers_override.h b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers_override.h +new file mode 100644 +index 0000000..e464a4e +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_pointers_override.h +@@ -0,0 +1,4 @@ ++/* ++ * This is a place-holder for override defines for system calls with ++ * pointers (all architectures). ++ */ +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_unknown.h b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_unknown.h +new file mode 100644 +index 0000000..4582d03 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/syscalls_unknown.h +@@ -0,0 +1,55 @@ ++#if !defined(_TRACE_SYSCALLS_UNKNOWN_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SYSCALLS_UNKNOWN_H ++ ++#include <linux/tracepoint.h> ++#include <linux/syscalls.h> ++ ++#define UNKNOWN_SYSCALL_NRARGS 6 ++ ++TRACE_EVENT(sys_unknown, ++ TP_PROTO(unsigned int id, unsigned long *args), ++ TP_ARGS(id, args), ++ TP_STRUCT__entry( ++ __field(unsigned int, id) ++ __array(unsigned long, args, UNKNOWN_SYSCALL_NRARGS) ++ ), ++ TP_fast_assign( ++ tp_assign(id, id) ++ tp_memcpy(args, args, UNKNOWN_SYSCALL_NRARGS * sizeof(*args)) ++ ), ++ TP_printk() ++) ++TRACE_EVENT(compat_sys_unknown, ++ TP_PROTO(unsigned int id, unsigned long *args), ++ TP_ARGS(id, args), ++ TP_STRUCT__entry( ++ __field(unsigned int, id) ++ __array(unsigned long, args, UNKNOWN_SYSCALL_NRARGS) ++ ), ++ TP_fast_assign( ++ tp_assign(id, id) ++ tp_memcpy(args, args, UNKNOWN_SYSCALL_NRARGS * sizeof(*args)) ++ ), ++ TP_printk() ++) ++/* ++ * This is going to hook on sys_exit in the kernel. ++ * We change the name so we don't clash with the sys_exit syscall entry ++ * event. ++ */ ++TRACE_EVENT(exit_syscall, ++ TP_PROTO(struct pt_regs *regs, long ret), ++ TP_ARGS(regs, ret), ++ TP_STRUCT__entry( ++ __field(long, ret) ++ ), ++ TP_fast_assign( ++ tp_assign(ret, ret) ++ ), ++ TP_printk() ++) ++ ++#endif /* _TRACE_SYSCALLS_UNKNOWN_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers.h +new file mode 100644 +index 0000000..f4ee16c +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers.h +@@ -0,0 +1,1163 @@ ++/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT */ ++#ifndef CREATE_SYSCALL_TABLE ++ ++#if !defined(_TRACE_SYSCALLS_INTEGERS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SYSCALLS_INTEGERS_H ++ ++#include <linux/tracepoint.h> ++#include <linux/syscalls.h> ++#include "x86-32-syscalls-3.1.0-rc6_integers_override.h" ++#include "syscalls_integers_override.h" ++ ++SC_DECLARE_EVENT_CLASS_NOARGS(syscalls_noargs, ++ TP_STRUCT__entry(), ++ TP_fast_assign(), ++ TP_printk() ++) ++#ifndef OVERRIDE_32_sys_restart_syscall ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_restart_syscall) ++#endif ++#ifndef OVERRIDE_32_sys_getpid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getpid) ++#endif ++#ifndef OVERRIDE_32_sys_getuid16 ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getuid16) ++#endif ++#ifndef OVERRIDE_32_sys_pause ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_pause) ++#endif ++#ifndef OVERRIDE_32_sys_sync ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_sync) ++#endif ++#ifndef OVERRIDE_32_sys_getgid16 ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getgid16) ++#endif ++#ifndef OVERRIDE_32_sys_geteuid16 ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_geteuid16) ++#endif ++#ifndef OVERRIDE_32_sys_getegid16 ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getegid16) ++#endif ++#ifndef OVERRIDE_32_sys_getppid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getppid) ++#endif ++#ifndef OVERRIDE_32_sys_getpgrp ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getpgrp) ++#endif ++#ifndef OVERRIDE_32_sys_setsid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_setsid) ++#endif ++#ifndef OVERRIDE_32_sys_sgetmask ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_sgetmask) ++#endif ++#ifndef OVERRIDE_32_sys_vhangup ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_vhangup) ++#endif ++#ifndef OVERRIDE_32_sys_munlockall ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_munlockall) ++#endif ++#ifndef OVERRIDE_32_sys_sched_yield ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_sched_yield) ++#endif ++#ifndef OVERRIDE_32_sys_getuid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getuid) ++#endif ++#ifndef OVERRIDE_32_sys_getgid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getgid) ++#endif ++#ifndef OVERRIDE_32_sys_geteuid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_geteuid) ++#endif ++#ifndef OVERRIDE_32_sys_getegid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getegid) ++#endif ++#ifndef OVERRIDE_32_sys_gettid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_gettid) ++#endif ++#ifndef OVERRIDE_32_sys_inotify_init ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_inotify_init) ++#endif ++#ifndef OVERRIDE_32_sys_exit ++SC_TRACE_EVENT(sys_exit, ++ TP_PROTO(int error_code), ++ TP_ARGS(error_code), ++ TP_STRUCT__entry(__field(int, error_code)), ++ TP_fast_assign(tp_assign(error_code, error_code)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_close ++SC_TRACE_EVENT(sys_close, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setuid16 ++SC_TRACE_EVENT(sys_setuid16, ++ TP_PROTO(old_uid_t uid), ++ TP_ARGS(uid), ++ TP_STRUCT__entry(__field(old_uid_t, uid)), ++ TP_fast_assign(tp_assign(uid, uid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_alarm ++SC_TRACE_EVENT(sys_alarm, ++ TP_PROTO(unsigned int seconds), ++ TP_ARGS(seconds), ++ TP_STRUCT__entry(__field(unsigned int, seconds)), ++ TP_fast_assign(tp_assign(seconds, seconds)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_nice ++SC_TRACE_EVENT(sys_nice, ++ TP_PROTO(int increment), ++ TP_ARGS(increment), ++ TP_STRUCT__entry(__field(int, increment)), ++ TP_fast_assign(tp_assign(increment, increment)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_dup ++SC_TRACE_EVENT(sys_dup, ++ TP_PROTO(unsigned int fildes), ++ TP_ARGS(fildes), ++ TP_STRUCT__entry(__field(unsigned int, fildes)), ++ TP_fast_assign(tp_assign(fildes, fildes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_brk ++SC_TRACE_EVENT(sys_brk, ++ TP_PROTO(unsigned long brk), ++ TP_ARGS(brk), ++ TP_STRUCT__entry(__field(unsigned long, brk)), ++ TP_fast_assign(tp_assign(brk, brk)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setgid16 ++SC_TRACE_EVENT(sys_setgid16, ++ TP_PROTO(old_gid_t gid), ++ TP_ARGS(gid), ++ TP_STRUCT__entry(__field(old_gid_t, gid)), ++ TP_fast_assign(tp_assign(gid, gid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_umask ++SC_TRACE_EVENT(sys_umask, ++ TP_PROTO(int mask), ++ TP_ARGS(mask), ++ TP_STRUCT__entry(__field(int, mask)), ++ TP_fast_assign(tp_assign(mask, mask)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ssetmask ++SC_TRACE_EVENT(sys_ssetmask, ++ TP_PROTO(int newmask), ++ TP_ARGS(newmask), ++ TP_STRUCT__entry(__field(int, newmask)), ++ TP_fast_assign(tp_assign(newmask, newmask)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fsync ++SC_TRACE_EVENT(sys_fsync, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getpgid ++SC_TRACE_EVENT(sys_getpgid, ++ TP_PROTO(pid_t pid), ++ TP_ARGS(pid), ++ TP_STRUCT__entry(__field(pid_t, pid)), ++ TP_fast_assign(tp_assign(pid, pid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fchdir ++SC_TRACE_EVENT(sys_fchdir, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_personality ++SC_TRACE_EVENT(sys_personality, ++ TP_PROTO(unsigned int personality), ++ TP_ARGS(personality), ++ TP_STRUCT__entry(__field(unsigned int, personality)), ++ TP_fast_assign(tp_assign(personality, personality)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setfsuid16 ++SC_TRACE_EVENT(sys_setfsuid16, ++ TP_PROTO(old_uid_t uid), ++ TP_ARGS(uid), ++ TP_STRUCT__entry(__field(old_uid_t, uid)), ++ TP_fast_assign(tp_assign(uid, uid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setfsgid16 ++SC_TRACE_EVENT(sys_setfsgid16, ++ TP_PROTO(old_gid_t gid), ++ TP_ARGS(gid), ++ TP_STRUCT__entry(__field(old_gid_t, gid)), ++ TP_fast_assign(tp_assign(gid, gid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getsid ++SC_TRACE_EVENT(sys_getsid, ++ TP_PROTO(pid_t pid), ++ TP_ARGS(pid), ++ TP_STRUCT__entry(__field(pid_t, pid)), ++ TP_fast_assign(tp_assign(pid, pid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fdatasync ++SC_TRACE_EVENT(sys_fdatasync, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mlockall ++SC_TRACE_EVENT(sys_mlockall, ++ TP_PROTO(int flags), ++ TP_ARGS(flags), ++ TP_STRUCT__entry(__field(int, flags)), ++ TP_fast_assign(tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_getscheduler ++SC_TRACE_EVENT(sys_sched_getscheduler, ++ TP_PROTO(pid_t pid), ++ TP_ARGS(pid), ++ TP_STRUCT__entry(__field(pid_t, pid)), ++ TP_fast_assign(tp_assign(pid, pid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_get_priority_max ++SC_TRACE_EVENT(sys_sched_get_priority_max, ++ TP_PROTO(int policy), ++ TP_ARGS(policy), ++ TP_STRUCT__entry(__field(int, policy)), ++ TP_fast_assign(tp_assign(policy, policy)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_get_priority_min ++SC_TRACE_EVENT(sys_sched_get_priority_min, ++ TP_PROTO(int policy), ++ TP_ARGS(policy), ++ TP_STRUCT__entry(__field(int, policy)), ++ TP_fast_assign(tp_assign(policy, policy)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setuid ++SC_TRACE_EVENT(sys_setuid, ++ TP_PROTO(uid_t uid), ++ TP_ARGS(uid), ++ TP_STRUCT__entry(__field(uid_t, uid)), ++ TP_fast_assign(tp_assign(uid, uid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setgid ++SC_TRACE_EVENT(sys_setgid, ++ TP_PROTO(gid_t gid), ++ TP_ARGS(gid), ++ TP_STRUCT__entry(__field(gid_t, gid)), ++ TP_fast_assign(tp_assign(gid, gid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setfsuid ++SC_TRACE_EVENT(sys_setfsuid, ++ TP_PROTO(uid_t uid), ++ TP_ARGS(uid), ++ TP_STRUCT__entry(__field(uid_t, uid)), ++ TP_fast_assign(tp_assign(uid, uid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setfsgid ++SC_TRACE_EVENT(sys_setfsgid, ++ TP_PROTO(gid_t gid), ++ TP_ARGS(gid), ++ TP_STRUCT__entry(__field(gid_t, gid)), ++ TP_fast_assign(tp_assign(gid, gid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_io_destroy ++SC_TRACE_EVENT(sys_io_destroy, ++ TP_PROTO(aio_context_t ctx), ++ TP_ARGS(ctx), ++ TP_STRUCT__entry(__field(aio_context_t, ctx)), ++ TP_fast_assign(tp_assign(ctx, ctx)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_exit_group ++SC_TRACE_EVENT(sys_exit_group, ++ TP_PROTO(int error_code), ++ TP_ARGS(error_code), ++ TP_STRUCT__entry(__field(int, error_code)), ++ TP_fast_assign(tp_assign(error_code, error_code)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_epoll_create ++SC_TRACE_EVENT(sys_epoll_create, ++ TP_PROTO(int size), ++ TP_ARGS(size), ++ TP_STRUCT__entry(__field(int, size)), ++ TP_fast_assign(tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timer_getoverrun ++SC_TRACE_EVENT(sys_timer_getoverrun, ++ TP_PROTO(timer_t timer_id), ++ TP_ARGS(timer_id), ++ TP_STRUCT__entry(__field(timer_t, timer_id)), ++ TP_fast_assign(tp_assign(timer_id, timer_id)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timer_delete ++SC_TRACE_EVENT(sys_timer_delete, ++ TP_PROTO(timer_t timer_id), ++ TP_ARGS(timer_id), ++ TP_STRUCT__entry(__field(timer_t, timer_id)), ++ TP_fast_assign(tp_assign(timer_id, timer_id)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_unshare ++SC_TRACE_EVENT(sys_unshare, ++ TP_PROTO(unsigned long unshare_flags), ++ TP_ARGS(unshare_flags), ++ TP_STRUCT__entry(__field(unsigned long, unshare_flags)), ++ TP_fast_assign(tp_assign(unshare_flags, unshare_flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_eventfd ++SC_TRACE_EVENT(sys_eventfd, ++ TP_PROTO(unsigned int count), ++ TP_ARGS(count), ++ TP_STRUCT__entry(__field(unsigned int, count)), ++ TP_fast_assign(tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_epoll_create1 ++SC_TRACE_EVENT(sys_epoll_create1, ++ TP_PROTO(int flags), ++ TP_ARGS(flags), ++ TP_STRUCT__entry(__field(int, flags)), ++ TP_fast_assign(tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_inotify_init1 ++SC_TRACE_EVENT(sys_inotify_init1, ++ TP_PROTO(int flags), ++ TP_ARGS(flags), ++ TP_STRUCT__entry(__field(int, flags)), ++ TP_fast_assign(tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_syncfs ++SC_TRACE_EVENT(sys_syncfs, ++ TP_PROTO(int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_kill ++SC_TRACE_EVENT(sys_kill, ++ TP_PROTO(pid_t pid, int sig), ++ TP_ARGS(pid, sig), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, sig)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_signal ++SC_TRACE_EVENT(sys_signal, ++ TP_PROTO(int sig, __sighandler_t handler), ++ TP_ARGS(sig, handler), ++ TP_STRUCT__entry(__field(int, sig) __field(__sighandler_t, handler)), ++ TP_fast_assign(tp_assign(sig, sig) tp_assign(handler, handler)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setpgid ++SC_TRACE_EVENT(sys_setpgid, ++ TP_PROTO(pid_t pid, pid_t pgid), ++ TP_ARGS(pid, pgid), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(pid_t, pgid)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(pgid, pgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_dup2 ++SC_TRACE_EVENT(sys_dup2, ++ TP_PROTO(unsigned int oldfd, unsigned int newfd), ++ TP_ARGS(oldfd, newfd), ++ TP_STRUCT__entry(__field(unsigned int, oldfd) __field(unsigned int, newfd)), ++ TP_fast_assign(tp_assign(oldfd, oldfd) tp_assign(newfd, newfd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setreuid16 ++SC_TRACE_EVENT(sys_setreuid16, ++ TP_PROTO(old_uid_t ruid, old_uid_t euid), ++ TP_ARGS(ruid, euid), ++ TP_STRUCT__entry(__field(old_uid_t, ruid) __field(old_uid_t, euid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setregid16 ++SC_TRACE_EVENT(sys_setregid16, ++ TP_PROTO(old_gid_t rgid, old_gid_t egid), ++ TP_ARGS(rgid, egid), ++ TP_STRUCT__entry(__field(old_gid_t, rgid) __field(old_gid_t, egid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_munmap ++SC_TRACE_EVENT(sys_munmap, ++ TP_PROTO(unsigned long addr, size_t len), ++ TP_ARGS(addr, len), ++ TP_STRUCT__entry(__field_hex(unsigned long, addr) __field(size_t, len)), ++ TP_fast_assign(tp_assign(addr, addr) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ftruncate ++SC_TRACE_EVENT(sys_ftruncate, ++ TP_PROTO(unsigned int fd, unsigned long length), ++ TP_ARGS(fd, length), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned long, length)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(length, length)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fchmod ++SC_TRACE_EVENT(sys_fchmod, ++ TP_PROTO(unsigned int fd, mode_t mode), ++ TP_ARGS(fd, mode), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(mode_t, mode)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getpriority ++SC_TRACE_EVENT(sys_getpriority, ++ TP_PROTO(int which, int who), ++ TP_ARGS(which, who), ++ TP_STRUCT__entry(__field(int, which) __field(int, who)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_bdflush ++SC_TRACE_EVENT(sys_bdflush, ++ TP_PROTO(int func, long data), ++ TP_ARGS(func, data), ++ TP_STRUCT__entry(__field(int, func) __field(long, data)), ++ TP_fast_assign(tp_assign(func, func) tp_assign(data, data)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_flock ++SC_TRACE_EVENT(sys_flock, ++ TP_PROTO(unsigned int fd, unsigned int cmd), ++ TP_ARGS(fd, cmd), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned int, cmd)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(cmd, cmd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mlock ++SC_TRACE_EVENT(sys_mlock, ++ TP_PROTO(unsigned long start, size_t len), ++ TP_ARGS(start, len), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_munlock ++SC_TRACE_EVENT(sys_munlock, ++ TP_PROTO(unsigned long start, size_t len), ++ TP_ARGS(start, len), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setreuid ++SC_TRACE_EVENT(sys_setreuid, ++ TP_PROTO(uid_t ruid, uid_t euid), ++ TP_ARGS(ruid, euid), ++ TP_STRUCT__entry(__field(uid_t, ruid) __field(uid_t, euid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setregid ++SC_TRACE_EVENT(sys_setregid, ++ TP_PROTO(gid_t rgid, gid_t egid), ++ TP_ARGS(rgid, egid), ++ TP_STRUCT__entry(__field(gid_t, rgid) __field(gid_t, egid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_tkill ++SC_TRACE_EVENT(sys_tkill, ++ TP_PROTO(pid_t pid, int sig), ++ TP_ARGS(pid, sig), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, sig)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ioprio_get ++SC_TRACE_EVENT(sys_ioprio_get, ++ TP_PROTO(int which, int who), ++ TP_ARGS(which, who), ++ TP_STRUCT__entry(__field(int, which) __field(int, who)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_inotify_rm_watch ++SC_TRACE_EVENT(sys_inotify_rm_watch, ++ TP_PROTO(int fd, __s32 wd), ++ TP_ARGS(fd, wd), ++ TP_STRUCT__entry(__field(int, fd) __field(__s32, wd)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(wd, wd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timerfd_create ++SC_TRACE_EVENT(sys_timerfd_create, ++ TP_PROTO(int clockid, int flags), ++ TP_ARGS(clockid, flags), ++ TP_STRUCT__entry(__field(int, clockid) __field(int, flags)), ++ TP_fast_assign(tp_assign(clockid, clockid) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_eventfd2 ++SC_TRACE_EVENT(sys_eventfd2, ++ TP_PROTO(unsigned int count, int flags), ++ TP_ARGS(count, flags), ++ TP_STRUCT__entry(__field(unsigned int, count) __field(int, flags)), ++ TP_fast_assign(tp_assign(count, count) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fanotify_init ++SC_TRACE_EVENT(sys_fanotify_init, ++ TP_PROTO(unsigned int flags, unsigned int event_f_flags), ++ TP_ARGS(flags, event_f_flags), ++ TP_STRUCT__entry(__field(unsigned int, flags) __field(unsigned int, event_f_flags)), ++ TP_fast_assign(tp_assign(flags, flags) tp_assign(event_f_flags, event_f_flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setns ++SC_TRACE_EVENT(sys_setns, ++ TP_PROTO(int fd, int nstype), ++ TP_ARGS(fd, nstype), ++ TP_STRUCT__entry(__field(int, fd) __field(int, nstype)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(nstype, nstype)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lseek ++SC_TRACE_EVENT(sys_lseek, ++ TP_PROTO(unsigned int fd, off_t offset, unsigned int origin), ++ TP_ARGS(fd, offset, origin), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(off_t, offset) __field(unsigned int, origin)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(offset, offset) tp_assign(origin, origin)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ioctl ++SC_TRACE_EVENT(sys_ioctl, ++ TP_PROTO(unsigned int fd, unsigned int cmd, unsigned long arg), ++ TP_ARGS(fd, cmd, arg), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned int, cmd) __field(unsigned long, arg)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(cmd, cmd) tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fcntl ++SC_TRACE_EVENT(sys_fcntl, ++ TP_PROTO(unsigned int fd, unsigned int cmd, unsigned long arg), ++ TP_ARGS(fd, cmd, arg), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned int, cmd) __field(unsigned long, arg)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(cmd, cmd) tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fchown16 ++SC_TRACE_EVENT(sys_fchown16, ++ TP_PROTO(unsigned int fd, old_uid_t user, old_gid_t group), ++ TP_ARGS(fd, user, group), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(old_uid_t, user) __field(old_gid_t, group)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setpriority ++SC_TRACE_EVENT(sys_setpriority, ++ TP_PROTO(int which, int who, int niceval), ++ TP_ARGS(which, who, niceval), ++ TP_STRUCT__entry(__field(int, which) __field(int, who) __field(int, niceval)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who) tp_assign(niceval, niceval)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mprotect ++SC_TRACE_EVENT(sys_mprotect, ++ TP_PROTO(unsigned long start, size_t len, unsigned long prot), ++ TP_ARGS(start, len, prot), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len) __field(unsigned long, prot)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len) tp_assign(prot, prot)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sysfs ++SC_TRACE_EVENT(sys_sysfs, ++ TP_PROTO(int option, unsigned long arg1, unsigned long arg2), ++ TP_ARGS(option, arg1, arg2), ++ TP_STRUCT__entry(__field(int, option) __field(unsigned long, arg1) __field(unsigned long, arg2)), ++ TP_fast_assign(tp_assign(option, option) tp_assign(arg1, arg1) tp_assign(arg2, arg2)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_msync ++SC_TRACE_EVENT(sys_msync, ++ TP_PROTO(unsigned long start, size_t len, int flags), ++ TP_ARGS(start, len, flags), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len) __field(int, flags)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setresuid16 ++SC_TRACE_EVENT(sys_setresuid16, ++ TP_PROTO(old_uid_t ruid, old_uid_t euid, old_uid_t suid), ++ TP_ARGS(ruid, euid, suid), ++ TP_STRUCT__entry(__field(old_uid_t, ruid) __field(old_uid_t, euid) __field(old_uid_t, suid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid) tp_assign(suid, suid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setresgid16 ++SC_TRACE_EVENT(sys_setresgid16, ++ TP_PROTO(old_gid_t rgid, old_gid_t egid, old_gid_t sgid), ++ TP_ARGS(rgid, egid, sgid), ++ TP_STRUCT__entry(__field(old_gid_t, rgid) __field(old_gid_t, egid) __field(old_gid_t, sgid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid) tp_assign(sgid, sgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fchown ++SC_TRACE_EVENT(sys_fchown, ++ TP_PROTO(unsigned int fd, uid_t user, gid_t group), ++ TP_ARGS(fd, user, group), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(uid_t, user) __field(gid_t, group)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setresuid ++SC_TRACE_EVENT(sys_setresuid, ++ TP_PROTO(uid_t ruid, uid_t euid, uid_t suid), ++ TP_ARGS(ruid, euid, suid), ++ TP_STRUCT__entry(__field(uid_t, ruid) __field(uid_t, euid) __field(uid_t, suid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid) tp_assign(suid, suid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setresgid ++SC_TRACE_EVENT(sys_setresgid, ++ TP_PROTO(gid_t rgid, gid_t egid, gid_t sgid), ++ TP_ARGS(rgid, egid, sgid), ++ TP_STRUCT__entry(__field(gid_t, rgid) __field(gid_t, egid) __field(gid_t, sgid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid) tp_assign(sgid, sgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_madvise ++SC_TRACE_EVENT(sys_madvise, ++ TP_PROTO(unsigned long start, size_t len_in, int behavior), ++ TP_ARGS(start, len_in, behavior), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len_in) __field(int, behavior)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len_in, len_in) tp_assign(behavior, behavior)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fcntl64 ++SC_TRACE_EVENT(sys_fcntl64, ++ TP_PROTO(unsigned int fd, unsigned int cmd, unsigned long arg), ++ TP_ARGS(fd, cmd, arg), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned int, cmd) __field(unsigned long, arg)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(cmd, cmd) tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_tgkill ++SC_TRACE_EVENT(sys_tgkill, ++ TP_PROTO(pid_t tgid, pid_t pid, int sig), ++ TP_ARGS(tgid, pid, sig), ++ TP_STRUCT__entry(__field(pid_t, tgid) __field(pid_t, pid) __field(int, sig)), ++ TP_fast_assign(tp_assign(tgid, tgid) tp_assign(pid, pid) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ioprio_set ++SC_TRACE_EVENT(sys_ioprio_set, ++ TP_PROTO(int which, int who, int ioprio), ++ TP_ARGS(which, who, ioprio), ++ TP_STRUCT__entry(__field(int, which) __field(int, who) __field(int, ioprio)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who) tp_assign(ioprio, ioprio)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_dup3 ++SC_TRACE_EVENT(sys_dup3, ++ TP_PROTO(unsigned int oldfd, unsigned int newfd, int flags), ++ TP_ARGS(oldfd, newfd, flags), ++ TP_STRUCT__entry(__field(unsigned int, oldfd) __field(unsigned int, newfd) __field(int, flags)), ++ TP_fast_assign(tp_assign(oldfd, oldfd) tp_assign(newfd, newfd) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ptrace ++SC_TRACE_EVENT(sys_ptrace, ++ TP_PROTO(long request, long pid, unsigned long addr, unsigned long data), ++ TP_ARGS(request, pid, addr, data), ++ TP_STRUCT__entry(__field(long, request) __field(long, pid) __field_hex(unsigned long, addr) __field(unsigned long, data)), ++ TP_fast_assign(tp_assign(request, request) tp_assign(pid, pid) tp_assign(addr, addr) tp_assign(data, data)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_tee ++SC_TRACE_EVENT(sys_tee, ++ TP_PROTO(int fdin, int fdout, size_t len, unsigned int flags), ++ TP_ARGS(fdin, fdout, len, flags), ++ TP_STRUCT__entry(__field(int, fdin) __field(int, fdout) __field(size_t, len) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fdin, fdin) tp_assign(fdout, fdout) tp_assign(len, len) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mremap ++SC_TRACE_EVENT(sys_mremap, ++ TP_PROTO(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr), ++ TP_ARGS(addr, old_len, new_len, flags, new_addr), ++ TP_STRUCT__entry(__field_hex(unsigned long, addr) __field(unsigned long, old_len) __field(unsigned long, new_len) __field(unsigned long, flags) __field_hex(unsigned long, new_addr)), ++ TP_fast_assign(tp_assign(addr, addr) tp_assign(old_len, old_len) tp_assign(new_len, new_len) tp_assign(flags, flags) tp_assign(new_addr, new_addr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_prctl ++SC_TRACE_EVENT(sys_prctl, ++ TP_PROTO(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5), ++ TP_ARGS(option, arg2, arg3, arg4, arg5), ++ TP_STRUCT__entry(__field(int, option) __field(unsigned long, arg2) __field(unsigned long, arg3) __field(unsigned long, arg4) __field(unsigned long, arg5)), ++ TP_fast_assign(tp_assign(option, option) tp_assign(arg2, arg2) tp_assign(arg3, arg3) tp_assign(arg4, arg4) tp_assign(arg5, arg5)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_remap_file_pages ++SC_TRACE_EVENT(sys_remap_file_pages, ++ TP_PROTO(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags), ++ TP_ARGS(start, size, prot, pgoff, flags), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(unsigned long, size) __field(unsigned long, prot) __field(unsigned long, pgoff) __field(unsigned long, flags)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(size, size) tp_assign(prot, prot) tp_assign(pgoff, pgoff) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_keyctl ++SC_TRACE_EVENT(sys_keyctl, ++ TP_PROTO(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5), ++ TP_ARGS(option, arg2, arg3, arg4, arg5), ++ TP_STRUCT__entry(__field(int, option) __field(unsigned long, arg2) __field(unsigned long, arg3) __field(unsigned long, arg4) __field(unsigned long, arg5)), ++ TP_fast_assign(tp_assign(option, option) tp_assign(arg2, arg2) tp_assign(arg3, arg3) tp_assign(arg4, arg4) tp_assign(arg5, arg5)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mmap_pgoff ++SC_TRACE_EVENT(sys_mmap_pgoff, ++ TP_PROTO(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff), ++ TP_ARGS(addr, len, prot, flags, fd, pgoff), ++ TP_STRUCT__entry(__field_hex(unsigned long, addr) __field(unsigned long, len) __field(unsigned long, prot) __field(unsigned long, flags) __field(unsigned long, fd) __field(unsigned long, pgoff)), ++ TP_fast_assign(tp_assign(addr, addr) tp_assign(len, len) tp_assign(prot, prot) tp_assign(flags, flags) tp_assign(fd, fd) tp_assign(pgoff, pgoff)), ++ TP_printk() ++) ++#endif ++ ++#endif /* _TRACE_SYSCALLS_INTEGERS_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" ++ ++#else /* CREATE_SYSCALL_TABLE */ ++ ++#include "x86-32-syscalls-3.1.0-rc6_integers_override.h" ++#include "syscalls_integers_override.h" ++ ++#ifndef OVERRIDE_TABLE_32_sys_restart_syscall ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_restart_syscall, 0, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getpid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getpid, 20, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getuid16 ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getuid16, 24, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_pause ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_pause, 29, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sync ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_sync, 36, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getgid16 ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getgid16, 47, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_geteuid16 ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_geteuid16, 49, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getegid16 ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getegid16, 50, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getppid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getppid, 64, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getpgrp ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getpgrp, 65, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setsid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_setsid, 66, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sgetmask ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_sgetmask, 68, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_vhangup ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_vhangup, 111, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_munlockall ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_munlockall, 153, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_yield ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_sched_yield, 158, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getuid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getuid, 199, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getgid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getgid, 200, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_geteuid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_geteuid, 201, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getegid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getegid, 202, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_gettid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_gettid, 224, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_inotify_init ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_inotify_init, 291, 0) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_exit ++TRACE_SYSCALL_TABLE(sys_exit, sys_exit, 1, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_close ++TRACE_SYSCALL_TABLE(sys_close, sys_close, 6, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lseek ++TRACE_SYSCALL_TABLE(sys_lseek, sys_lseek, 19, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setuid16 ++TRACE_SYSCALL_TABLE(sys_setuid16, sys_setuid16, 23, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ptrace ++TRACE_SYSCALL_TABLE(sys_ptrace, sys_ptrace, 26, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_alarm ++TRACE_SYSCALL_TABLE(sys_alarm, sys_alarm, 27, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_nice ++TRACE_SYSCALL_TABLE(sys_nice, sys_nice, 34, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_kill ++TRACE_SYSCALL_TABLE(sys_kill, sys_kill, 37, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_dup ++TRACE_SYSCALL_TABLE(sys_dup, sys_dup, 41, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_brk ++TRACE_SYSCALL_TABLE(sys_brk, sys_brk, 45, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setgid16 ++TRACE_SYSCALL_TABLE(sys_setgid16, sys_setgid16, 46, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_signal ++TRACE_SYSCALL_TABLE(sys_signal, sys_signal, 48, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ioctl ++TRACE_SYSCALL_TABLE(sys_ioctl, sys_ioctl, 54, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fcntl ++TRACE_SYSCALL_TABLE(sys_fcntl, sys_fcntl, 55, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setpgid ++TRACE_SYSCALL_TABLE(sys_setpgid, sys_setpgid, 57, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_umask ++TRACE_SYSCALL_TABLE(sys_umask, sys_umask, 60, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_dup2 ++TRACE_SYSCALL_TABLE(sys_dup2, sys_dup2, 63, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ssetmask ++TRACE_SYSCALL_TABLE(sys_ssetmask, sys_ssetmask, 69, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setreuid16 ++TRACE_SYSCALL_TABLE(sys_setreuid16, sys_setreuid16, 70, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setregid16 ++TRACE_SYSCALL_TABLE(sys_setregid16, sys_setregid16, 71, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_munmap ++TRACE_SYSCALL_TABLE(sys_munmap, sys_munmap, 91, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ftruncate ++TRACE_SYSCALL_TABLE(sys_ftruncate, sys_ftruncate, 93, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fchmod ++TRACE_SYSCALL_TABLE(sys_fchmod, sys_fchmod, 94, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fchown16 ++TRACE_SYSCALL_TABLE(sys_fchown16, sys_fchown16, 95, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getpriority ++TRACE_SYSCALL_TABLE(sys_getpriority, sys_getpriority, 96, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setpriority ++TRACE_SYSCALL_TABLE(sys_setpriority, sys_setpriority, 97, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fsync ++TRACE_SYSCALL_TABLE(sys_fsync, sys_fsync, 118, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mprotect ++TRACE_SYSCALL_TABLE(sys_mprotect, sys_mprotect, 125, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getpgid ++TRACE_SYSCALL_TABLE(sys_getpgid, sys_getpgid, 132, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fchdir ++TRACE_SYSCALL_TABLE(sys_fchdir, sys_fchdir, 133, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_bdflush ++TRACE_SYSCALL_TABLE(sys_bdflush, sys_bdflush, 134, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sysfs ++TRACE_SYSCALL_TABLE(sys_sysfs, sys_sysfs, 135, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_personality ++TRACE_SYSCALL_TABLE(sys_personality, sys_personality, 136, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setfsuid16 ++TRACE_SYSCALL_TABLE(sys_setfsuid16, sys_setfsuid16, 138, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setfsgid16 ++TRACE_SYSCALL_TABLE(sys_setfsgid16, sys_setfsgid16, 139, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_flock ++TRACE_SYSCALL_TABLE(sys_flock, sys_flock, 143, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_msync ++TRACE_SYSCALL_TABLE(sys_msync, sys_msync, 144, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getsid ++TRACE_SYSCALL_TABLE(sys_getsid, sys_getsid, 147, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fdatasync ++TRACE_SYSCALL_TABLE(sys_fdatasync, sys_fdatasync, 148, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mlock ++TRACE_SYSCALL_TABLE(sys_mlock, sys_mlock, 150, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_munlock ++TRACE_SYSCALL_TABLE(sys_munlock, sys_munlock, 151, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mlockall ++TRACE_SYSCALL_TABLE(sys_mlockall, sys_mlockall, 152, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_getscheduler ++TRACE_SYSCALL_TABLE(sys_sched_getscheduler, sys_sched_getscheduler, 157, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_get_priority_max ++TRACE_SYSCALL_TABLE(sys_sched_get_priority_max, sys_sched_get_priority_max, 159, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_get_priority_min ++TRACE_SYSCALL_TABLE(sys_sched_get_priority_min, sys_sched_get_priority_min, 160, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mremap ++TRACE_SYSCALL_TABLE(sys_mremap, sys_mremap, 163, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setresuid16 ++TRACE_SYSCALL_TABLE(sys_setresuid16, sys_setresuid16, 164, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setresgid16 ++TRACE_SYSCALL_TABLE(sys_setresgid16, sys_setresgid16, 170, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_prctl ++TRACE_SYSCALL_TABLE(sys_prctl, sys_prctl, 172, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mmap_pgoff ++TRACE_SYSCALL_TABLE(sys_mmap_pgoff, sys_mmap_pgoff, 192, 6) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setreuid ++TRACE_SYSCALL_TABLE(sys_setreuid, sys_setreuid, 203, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setregid ++TRACE_SYSCALL_TABLE(sys_setregid, sys_setregid, 204, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fchown ++TRACE_SYSCALL_TABLE(sys_fchown, sys_fchown, 207, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setresuid ++TRACE_SYSCALL_TABLE(sys_setresuid, sys_setresuid, 208, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setresgid ++TRACE_SYSCALL_TABLE(sys_setresgid, sys_setresgid, 210, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setuid ++TRACE_SYSCALL_TABLE(sys_setuid, sys_setuid, 213, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setgid ++TRACE_SYSCALL_TABLE(sys_setgid, sys_setgid, 214, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setfsuid ++TRACE_SYSCALL_TABLE(sys_setfsuid, sys_setfsuid, 215, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setfsgid ++TRACE_SYSCALL_TABLE(sys_setfsgid, sys_setfsgid, 216, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_madvise ++TRACE_SYSCALL_TABLE(sys_madvise, sys_madvise, 219, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fcntl64 ++TRACE_SYSCALL_TABLE(sys_fcntl64, sys_fcntl64, 221, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_tkill ++TRACE_SYSCALL_TABLE(sys_tkill, sys_tkill, 238, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_io_destroy ++TRACE_SYSCALL_TABLE(sys_io_destroy, sys_io_destroy, 246, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_exit_group ++TRACE_SYSCALL_TABLE(sys_exit_group, sys_exit_group, 252, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_epoll_create ++TRACE_SYSCALL_TABLE(sys_epoll_create, sys_epoll_create, 254, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_remap_file_pages ++TRACE_SYSCALL_TABLE(sys_remap_file_pages, sys_remap_file_pages, 257, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timer_getoverrun ++TRACE_SYSCALL_TABLE(sys_timer_getoverrun, sys_timer_getoverrun, 262, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timer_delete ++TRACE_SYSCALL_TABLE(sys_timer_delete, sys_timer_delete, 263, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_tgkill ++TRACE_SYSCALL_TABLE(sys_tgkill, sys_tgkill, 270, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_keyctl ++TRACE_SYSCALL_TABLE(sys_keyctl, sys_keyctl, 288, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ioprio_set ++TRACE_SYSCALL_TABLE(sys_ioprio_set, sys_ioprio_set, 289, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ioprio_get ++TRACE_SYSCALL_TABLE(sys_ioprio_get, sys_ioprio_get, 290, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_inotify_rm_watch ++TRACE_SYSCALL_TABLE(sys_inotify_rm_watch, sys_inotify_rm_watch, 293, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_unshare ++TRACE_SYSCALL_TABLE(sys_unshare, sys_unshare, 310, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_tee ++TRACE_SYSCALL_TABLE(sys_tee, sys_tee, 315, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timerfd_create ++TRACE_SYSCALL_TABLE(sys_timerfd_create, sys_timerfd_create, 322, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_eventfd ++TRACE_SYSCALL_TABLE(sys_eventfd, sys_eventfd, 323, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_eventfd2 ++TRACE_SYSCALL_TABLE(sys_eventfd2, sys_eventfd2, 328, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_epoll_create1 ++TRACE_SYSCALL_TABLE(sys_epoll_create1, sys_epoll_create1, 329, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_dup3 ++TRACE_SYSCALL_TABLE(sys_dup3, sys_dup3, 330, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_inotify_init1 ++TRACE_SYSCALL_TABLE(sys_inotify_init1, sys_inotify_init1, 332, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fanotify_init ++TRACE_SYSCALL_TABLE(sys_fanotify_init, sys_fanotify_init, 338, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_syncfs ++TRACE_SYSCALL_TABLE(sys_syncfs, sys_syncfs, 344, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setns ++TRACE_SYSCALL_TABLE(sys_setns, sys_setns, 346, 2) ++#endif ++ ++#endif /* CREATE_SYSCALL_TABLE */ +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers_override.h b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers_override.h +new file mode 100644 +index 0000000..ed2cf1f +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_integers_override.h +@@ -0,0 +1,38 @@ ++#ifndef CONFIG_UID16 ++ ++#define OVERRIDE_32_sys_getuid16 ++#define OVERRIDE_32_sys_getgid16 ++#define OVERRIDE_32_sys_geteuid16 ++#define OVERRIDE_32_sys_getegid16 ++#define OVERRIDE_32_sys_setuid16 ++#define OVERRIDE_32_sys_setgid16 ++#define OVERRIDE_32_sys_setfsuid16 ++#define OVERRIDE_32_sys_setfsgid16 ++#define OVERRIDE_32_sys_setreuid16 ++#define OVERRIDE_32_sys_setregid16 ++#define OVERRIDE_32_sys_fchown16 ++#define OVERRIDE_32_sys_setresuid16 ++#define OVERRIDE_32_sys_setresgid16 ++ ++#define OVERRIDE_TABLE_32_sys_getuid16 ++#define OVERRIDE_TABLE_32_sys_getgid16 ++#define OVERRIDE_TABLE_32_sys_geteuid16 ++#define OVERRIDE_TABLE_32_sys_getegid16 ++#define OVERRIDE_TABLE_32_sys_setuid16 ++#define OVERRIDE_TABLE_32_sys_setgid16 ++#define OVERRIDE_TABLE_32_sys_setreuid16 ++#define OVERRIDE_TABLE_32_sys_setregid16 ++#define OVERRIDE_TABLE_32_sys_fchown16 ++#define OVERRIDE_TABLE_32_sys_setfsuid16 ++#define OVERRIDE_TABLE_32_sys_setfsgid16 ++#define OVERRIDE_TABLE_32_sys_setresuid16 ++#define OVERRIDE_TABLE_32_sys_setresgid16 ++ ++#endif ++ ++#ifdef CREATE_SYSCALL_TABLE ++ ++#define OVERRIDE_TABLE_32_sys_mmap ++TRACE_SYSCALL_TABLE(sys_mmap, sys_mmap, 90, 6) ++ ++#endif +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers.h +new file mode 100644 +index 0000000..ec5b301 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers.h +@@ -0,0 +1,2232 @@ ++/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT */ ++#ifndef CREATE_SYSCALL_TABLE ++ ++#if !defined(_TRACE_SYSCALLS_POINTERS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SYSCALLS_POINTERS_H ++ ++#include <linux/tracepoint.h> ++#include <linux/syscalls.h> ++#include "x86-32-syscalls-3.1.0-rc6_pointers_override.h" ++#include "syscalls_pointers_override.h" ++ ++#ifndef OVERRIDE_32_sys_unlink ++SC_TRACE_EVENT(sys_unlink, ++ TP_PROTO(const char * pathname), ++ TP_ARGS(pathname), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_chdir ++SC_TRACE_EVENT(sys_chdir, ++ TP_PROTO(const char * filename), ++ TP_ARGS(filename), ++ TP_STRUCT__entry(__string_from_user(filename, filename)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_time ++SC_TRACE_EVENT(sys_time, ++ TP_PROTO(time_t * tloc), ++ TP_ARGS(tloc), ++ TP_STRUCT__entry(__field_hex(time_t *, tloc)), ++ TP_fast_assign(tp_assign(tloc, tloc)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_oldumount ++SC_TRACE_EVENT(sys_oldumount, ++ TP_PROTO(char * name), ++ TP_ARGS(name), ++ TP_STRUCT__entry(__string_from_user(name, name)), ++ TP_fast_assign(tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_stime ++SC_TRACE_EVENT(sys_stime, ++ TP_PROTO(time_t * tptr), ++ TP_ARGS(tptr), ++ TP_STRUCT__entry(__field_hex(time_t *, tptr)), ++ TP_fast_assign(tp_assign(tptr, tptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rmdir ++SC_TRACE_EVENT(sys_rmdir, ++ TP_PROTO(const char * pathname), ++ TP_ARGS(pathname), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_pipe ++SC_TRACE_EVENT(sys_pipe, ++ TP_PROTO(int * fildes), ++ TP_ARGS(fildes), ++ TP_STRUCT__entry(__field_hex(int *, fildes)), ++ TP_fast_assign(tp_assign(fildes, fildes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_times ++SC_TRACE_EVENT(sys_times, ++ TP_PROTO(struct tms * tbuf), ++ TP_ARGS(tbuf), ++ TP_STRUCT__entry(__field_hex(struct tms *, tbuf)), ++ TP_fast_assign(tp_assign(tbuf, tbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_acct ++SC_TRACE_EVENT(sys_acct, ++ TP_PROTO(const char * name), ++ TP_ARGS(name), ++ TP_STRUCT__entry(__string_from_user(name, name)), ++ TP_fast_assign(tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_olduname ++SC_TRACE_EVENT(sys_olduname, ++ TP_PROTO(struct oldold_utsname * name), ++ TP_ARGS(name), ++ TP_STRUCT__entry(__field_hex(struct oldold_utsname *, name)), ++ TP_fast_assign(tp_assign(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_chroot ++SC_TRACE_EVENT(sys_chroot, ++ TP_PROTO(const char * filename), ++ TP_ARGS(filename), ++ TP_STRUCT__entry(__string_from_user(filename, filename)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sigpending ++SC_TRACE_EVENT(sys_sigpending, ++ TP_PROTO(old_sigset_t * set), ++ TP_ARGS(set), ++ TP_STRUCT__entry(__field_hex(old_sigset_t *, set)), ++ TP_fast_assign(tp_assign(set, set)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_old_select ++SC_TRACE_EVENT(sys_old_select, ++ TP_PROTO(struct sel_arg_struct * arg), ++ TP_ARGS(arg), ++ TP_STRUCT__entry(__field_hex(struct sel_arg_struct *, arg)), ++ TP_fast_assign(tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_uselib ++SC_TRACE_EVENT(sys_uselib, ++ TP_PROTO(const char * library), ++ TP_ARGS(library), ++ TP_STRUCT__entry(__field_hex(const char *, library)), ++ TP_fast_assign(tp_assign(library, library)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_old_mmap ++SC_TRACE_EVENT(sys_old_mmap, ++ TP_PROTO(struct mmap_arg_struct * arg), ++ TP_ARGS(arg), ++ TP_STRUCT__entry(__field_hex(struct mmap_arg_struct *, arg)), ++ TP_fast_assign(tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_uname ++SC_TRACE_EVENT(sys_uname, ++ TP_PROTO(struct old_utsname * name), ++ TP_ARGS(name), ++ TP_STRUCT__entry(__field_hex(struct old_utsname *, name)), ++ TP_fast_assign(tp_assign(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_swapoff ++SC_TRACE_EVENT(sys_swapoff, ++ TP_PROTO(const char * specialfile), ++ TP_ARGS(specialfile), ++ TP_STRUCT__entry(__string_from_user(specialfile, specialfile)), ++ TP_fast_assign(tp_copy_string_from_user(specialfile, specialfile)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sysinfo ++SC_TRACE_EVENT(sys_sysinfo, ++ TP_PROTO(struct sysinfo * info), ++ TP_ARGS(info), ++ TP_STRUCT__entry(__field_hex(struct sysinfo *, info)), ++ TP_fast_assign(tp_assign(info, info)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_newuname ++SC_TRACE_EVENT(sys_newuname, ++ TP_PROTO(struct new_utsname * name), ++ TP_ARGS(name), ++ TP_STRUCT__entry(__field_hex(struct new_utsname *, name)), ++ TP_fast_assign(tp_assign(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_adjtimex ++SC_TRACE_EVENT(sys_adjtimex, ++ TP_PROTO(struct timex * txc_p), ++ TP_ARGS(txc_p), ++ TP_STRUCT__entry(__field_hex(struct timex *, txc_p)), ++ TP_fast_assign(tp_assign(txc_p, txc_p)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sysctl ++SC_TRACE_EVENT(sys_sysctl, ++ TP_PROTO(struct __sysctl_args * args), ++ TP_ARGS(args), ++ TP_STRUCT__entry(__field_hex(struct __sysctl_args *, args)), ++ TP_fast_assign(tp_assign(args, args)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_set_tid_address ++SC_TRACE_EVENT(sys_set_tid_address, ++ TP_PROTO(int * tidptr), ++ TP_ARGS(tidptr), ++ TP_STRUCT__entry(__field_hex(int *, tidptr)), ++ TP_fast_assign(tp_assign(tidptr, tidptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mq_unlink ++SC_TRACE_EVENT(sys_mq_unlink, ++ TP_PROTO(const char * u_name), ++ TP_ARGS(u_name), ++ TP_STRUCT__entry(__string_from_user(u_name, u_name)), ++ TP_fast_assign(tp_copy_string_from_user(u_name, u_name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_creat ++SC_TRACE_EVENT(sys_creat, ++ TP_PROTO(const char * pathname, int mode), ++ TP_ARGS(pathname, mode), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_link ++SC_TRACE_EVENT(sys_link, ++ TP_PROTO(const char * oldname, const char * newname), ++ TP_ARGS(oldname, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_chmod ++SC_TRACE_EVENT(sys_chmod, ++ TP_PROTO(const char * filename, mode_t mode), ++ TP_ARGS(filename, mode), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(mode_t, mode)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_stat ++SC_TRACE_EVENT(sys_stat, ++ TP_PROTO(const char * filename, struct __old_kernel_stat * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct __old_kernel_stat *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fstat ++SC_TRACE_EVENT(sys_fstat, ++ TP_PROTO(unsigned int fd, struct __old_kernel_stat * statbuf), ++ TP_ARGS(fd, statbuf), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct __old_kernel_stat *, statbuf)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_utime ++SC_TRACE_EVENT(sys_utime, ++ TP_PROTO(char * filename, struct utimbuf * times), ++ TP_ARGS(filename, times), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct utimbuf *, times)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(times, times)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_access ++SC_TRACE_EVENT(sys_access, ++ TP_PROTO(const char * filename, int mode), ++ TP_ARGS(filename, mode), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rename ++SC_TRACE_EVENT(sys_rename, ++ TP_PROTO(const char * oldname, const char * newname), ++ TP_ARGS(oldname, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mkdir ++SC_TRACE_EVENT(sys_mkdir, ++ TP_PROTO(const char * pathname, int mode), ++ TP_ARGS(pathname, mode), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_umount ++SC_TRACE_EVENT(sys_umount, ++ TP_PROTO(char * name, int flags), ++ TP_ARGS(name, flags), ++ TP_STRUCT__entry(__string_from_user(name, name) __field(int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(name, name) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ustat ++SC_TRACE_EVENT(sys_ustat, ++ TP_PROTO(unsigned dev, struct ustat * ubuf), ++ TP_ARGS(dev, ubuf), ++ TP_STRUCT__entry(__field(unsigned, dev) __field_hex(struct ustat *, ubuf)), ++ TP_fast_assign(tp_assign(dev, dev) tp_assign(ubuf, ubuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sethostname ++SC_TRACE_EVENT(sys_sethostname, ++ TP_PROTO(char * name, int len), ++ TP_ARGS(name, len), ++ TP_STRUCT__entry(__string_from_user(name, name) __field(int, len)), ++ TP_fast_assign(tp_copy_string_from_user(name, name) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setrlimit ++SC_TRACE_EVENT(sys_setrlimit, ++ TP_PROTO(unsigned int resource, struct rlimit * rlim), ++ TP_ARGS(resource, rlim), ++ TP_STRUCT__entry(__field(unsigned int, resource) __field_hex(struct rlimit *, rlim)), ++ TP_fast_assign(tp_assign(resource, resource) tp_assign(rlim, rlim)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_old_getrlimit ++SC_TRACE_EVENT(sys_old_getrlimit, ++ TP_PROTO(unsigned int resource, struct rlimit * rlim), ++ TP_ARGS(resource, rlim), ++ TP_STRUCT__entry(__field(unsigned int, resource) __field_hex(struct rlimit *, rlim)), ++ TP_fast_assign(tp_assign(resource, resource) tp_assign(rlim, rlim)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getrusage ++SC_TRACE_EVENT(sys_getrusage, ++ TP_PROTO(int who, struct rusage * ru), ++ TP_ARGS(who, ru), ++ TP_STRUCT__entry(__field(int, who) __field_hex(struct rusage *, ru)), ++ TP_fast_assign(tp_assign(who, who) tp_assign(ru, ru)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_gettimeofday ++SC_TRACE_EVENT(sys_gettimeofday, ++ TP_PROTO(struct timeval * tv, struct timezone * tz), ++ TP_ARGS(tv, tz), ++ TP_STRUCT__entry(__field_hex(struct timeval *, tv) __field_hex(struct timezone *, tz)), ++ TP_fast_assign(tp_assign(tv, tv) tp_assign(tz, tz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_settimeofday ++SC_TRACE_EVENT(sys_settimeofday, ++ TP_PROTO(struct timeval * tv, struct timezone * tz), ++ TP_ARGS(tv, tz), ++ TP_STRUCT__entry(__field_hex(struct timeval *, tv) __field_hex(struct timezone *, tz)), ++ TP_fast_assign(tp_assign(tv, tv) tp_assign(tz, tz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getgroups16 ++SC_TRACE_EVENT(sys_getgroups16, ++ TP_PROTO(int gidsetsize, old_gid_t * grouplist), ++ TP_ARGS(gidsetsize, grouplist), ++ TP_STRUCT__entry(__field(int, gidsetsize) __field_hex(old_gid_t *, grouplist)), ++ TP_fast_assign(tp_assign(gidsetsize, gidsetsize) tp_assign(grouplist, grouplist)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setgroups16 ++SC_TRACE_EVENT(sys_setgroups16, ++ TP_PROTO(int gidsetsize, old_gid_t * grouplist), ++ TP_ARGS(gidsetsize, grouplist), ++ TP_STRUCT__entry(__field(int, gidsetsize) __field_hex(old_gid_t *, grouplist)), ++ TP_fast_assign(tp_assign(gidsetsize, gidsetsize) tp_assign(grouplist, grouplist)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_symlink ++SC_TRACE_EVENT(sys_symlink, ++ TP_PROTO(const char * oldname, const char * newname), ++ TP_ARGS(oldname, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lstat ++SC_TRACE_EVENT(sys_lstat, ++ TP_PROTO(const char * filename, struct __old_kernel_stat * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct __old_kernel_stat *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_swapon ++SC_TRACE_EVENT(sys_swapon, ++ TP_PROTO(const char * specialfile, int swap_flags), ++ TP_ARGS(specialfile, swap_flags), ++ TP_STRUCT__entry(__string_from_user(specialfile, specialfile) __field(int, swap_flags)), ++ TP_fast_assign(tp_copy_string_from_user(specialfile, specialfile) tp_assign(swap_flags, swap_flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_truncate ++SC_TRACE_EVENT(sys_truncate, ++ TP_PROTO(const char * path, long length), ++ TP_ARGS(path, length), ++ TP_STRUCT__entry(__string_from_user(path, path) __field(long, length)), ++ TP_fast_assign(tp_copy_string_from_user(path, path) tp_assign(length, length)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_statfs ++SC_TRACE_EVENT(sys_statfs, ++ TP_PROTO(const char * pathname, struct statfs * buf), ++ TP_ARGS(pathname, buf), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field_hex(struct statfs *, buf)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fstatfs ++SC_TRACE_EVENT(sys_fstatfs, ++ TP_PROTO(unsigned int fd, struct statfs * buf), ++ TP_ARGS(fd, buf), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct statfs *, buf)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_socketcall ++SC_TRACE_EVENT(sys_socketcall, ++ TP_PROTO(int call, unsigned long * args), ++ TP_ARGS(call, args), ++ TP_STRUCT__entry(__field(int, call) __field_hex(unsigned long *, args)), ++ TP_fast_assign(tp_assign(call, call) tp_assign(args, args)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getitimer ++SC_TRACE_EVENT(sys_getitimer, ++ TP_PROTO(int which, struct itimerval * value), ++ TP_ARGS(which, value), ++ TP_STRUCT__entry(__field(int, which) __field_hex(struct itimerval *, value)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(value, value)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_newstat ++SC_TRACE_EVENT(sys_newstat, ++ TP_PROTO(const char * filename, struct stat * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct stat *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_newlstat ++SC_TRACE_EVENT(sys_newlstat, ++ TP_PROTO(const char * filename, struct stat * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct stat *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_newfstat ++SC_TRACE_EVENT(sys_newfstat, ++ TP_PROTO(unsigned int fd, struct stat * statbuf), ++ TP_ARGS(fd, statbuf), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct stat *, statbuf)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setdomainname ++SC_TRACE_EVENT(sys_setdomainname, ++ TP_PROTO(char * name, int len), ++ TP_ARGS(name, len), ++ TP_STRUCT__entry(__string_from_user(name, name) __field(int, len)), ++ TP_fast_assign(tp_copy_string_from_user(name, name) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_delete_module ++SC_TRACE_EVENT(sys_delete_module, ++ TP_PROTO(const char * name_user, unsigned int flags), ++ TP_ARGS(name_user, flags), ++ TP_STRUCT__entry(__string_from_user(name_user, name_user) __field(unsigned int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(name_user, name_user) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_setparam ++SC_TRACE_EVENT(sys_sched_setparam, ++ TP_PROTO(pid_t pid, struct sched_param * param), ++ TP_ARGS(pid, param), ++ TP_STRUCT__entry(__field(pid_t, pid) __field_hex(struct sched_param *, param)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(param, param)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_getparam ++SC_TRACE_EVENT(sys_sched_getparam, ++ TP_PROTO(pid_t pid, struct sched_param * param), ++ TP_ARGS(pid, param), ++ TP_STRUCT__entry(__field(pid_t, pid) __field_hex(struct sched_param *, param)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(param, param)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_rr_get_interval ++SC_TRACE_EVENT(sys_sched_rr_get_interval, ++ TP_PROTO(pid_t pid, struct timespec * interval), ++ TP_ARGS(pid, interval), ++ TP_STRUCT__entry(__field(pid_t, pid) __field_hex(struct timespec *, interval)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(interval, interval)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_nanosleep ++SC_TRACE_EVENT(sys_nanosleep, ++ TP_PROTO(struct timespec * rqtp, struct timespec * rmtp), ++ TP_ARGS(rqtp, rmtp), ++ TP_STRUCT__entry(__field_hex(struct timespec *, rqtp) __field_hex(struct timespec *, rmtp)), ++ TP_fast_assign(tp_assign(rqtp, rqtp) tp_assign(rmtp, rmtp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rt_sigpending ++SC_TRACE_EVENT(sys_rt_sigpending, ++ TP_PROTO(sigset_t * set, size_t sigsetsize), ++ TP_ARGS(set, sigsetsize), ++ TP_STRUCT__entry(__field_hex(sigset_t *, set) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(set, set) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rt_sigsuspend ++SC_TRACE_EVENT(sys_rt_sigsuspend, ++ TP_PROTO(sigset_t * unewset, size_t sigsetsize), ++ TP_ARGS(unewset, sigsetsize), ++ TP_STRUCT__entry(__field_hex(sigset_t *, unewset) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(unewset, unewset) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getcwd ++SC_TRACE_EVENT(sys_getcwd, ++ TP_PROTO(char * buf, unsigned long size), ++ TP_ARGS(buf, size), ++ TP_STRUCT__entry(__field_hex(char *, buf) __field(unsigned long, size)), ++ TP_fast_assign(tp_assign(buf, buf) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getrlimit ++SC_TRACE_EVENT(sys_getrlimit, ++ TP_PROTO(unsigned int resource, struct rlimit * rlim), ++ TP_ARGS(resource, rlim), ++ TP_STRUCT__entry(__field(unsigned int, resource) __field_hex(struct rlimit *, rlim)), ++ TP_fast_assign(tp_assign(resource, resource) tp_assign(rlim, rlim)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_stat64 ++SC_TRACE_EVENT(sys_stat64, ++ TP_PROTO(const char * filename, struct stat64 * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct stat64 *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lstat64 ++SC_TRACE_EVENT(sys_lstat64, ++ TP_PROTO(const char * filename, struct stat64 * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct stat64 *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fstat64 ++SC_TRACE_EVENT(sys_fstat64, ++ TP_PROTO(unsigned long fd, struct stat64 * statbuf), ++ TP_ARGS(fd, statbuf), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(struct stat64 *, statbuf)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getgroups ++SC_TRACE_EVENT(sys_getgroups, ++ TP_PROTO(int gidsetsize, gid_t * grouplist), ++ TP_ARGS(gidsetsize, grouplist), ++ TP_STRUCT__entry(__field(int, gidsetsize) __field_hex(gid_t *, grouplist)), ++ TP_fast_assign(tp_assign(gidsetsize, gidsetsize) tp_assign(grouplist, grouplist)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setgroups ++SC_TRACE_EVENT(sys_setgroups, ++ TP_PROTO(int gidsetsize, gid_t * grouplist), ++ TP_ARGS(gidsetsize, grouplist), ++ TP_STRUCT__entry(__field(int, gidsetsize) __field_hex(gid_t *, grouplist)), ++ TP_fast_assign(tp_assign(gidsetsize, gidsetsize) tp_assign(grouplist, grouplist)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_pivot_root ++SC_TRACE_EVENT(sys_pivot_root, ++ TP_PROTO(const char * new_root, const char * put_old), ++ TP_ARGS(new_root, put_old), ++ TP_STRUCT__entry(__string_from_user(new_root, new_root) __string_from_user(put_old, put_old)), ++ TP_fast_assign(tp_copy_string_from_user(new_root, new_root) tp_copy_string_from_user(put_old, put_old)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_removexattr ++SC_TRACE_EVENT(sys_removexattr, ++ TP_PROTO(const char * pathname, const char * name), ++ TP_ARGS(pathname, name), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lremovexattr ++SC_TRACE_EVENT(sys_lremovexattr, ++ TP_PROTO(const char * pathname, const char * name), ++ TP_ARGS(pathname, name), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fremovexattr ++SC_TRACE_EVENT(sys_fremovexattr, ++ TP_PROTO(int fd, const char * name), ++ TP_ARGS(fd, name), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(name, name)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_io_setup ++SC_TRACE_EVENT(sys_io_setup, ++ TP_PROTO(unsigned nr_events, aio_context_t * ctxp), ++ TP_ARGS(nr_events, ctxp), ++ TP_STRUCT__entry(__field(unsigned, nr_events) __field_hex(aio_context_t *, ctxp)), ++ TP_fast_assign(tp_assign(nr_events, nr_events) tp_assign(ctxp, ctxp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timer_gettime ++SC_TRACE_EVENT(sys_timer_gettime, ++ TP_PROTO(timer_t timer_id, struct itimerspec * setting), ++ TP_ARGS(timer_id, setting), ++ TP_STRUCT__entry(__field(timer_t, timer_id) __field_hex(struct itimerspec *, setting)), ++ TP_fast_assign(tp_assign(timer_id, timer_id) tp_assign(setting, setting)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_clock_settime ++SC_TRACE_EVENT(sys_clock_settime, ++ TP_PROTO(const clockid_t which_clock, const struct timespec * tp), ++ TP_ARGS(which_clock, tp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(const struct timespec *, tp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(tp, tp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_clock_gettime ++SC_TRACE_EVENT(sys_clock_gettime, ++ TP_PROTO(const clockid_t which_clock, struct timespec * tp), ++ TP_ARGS(which_clock, tp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct timespec *, tp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(tp, tp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_clock_getres ++SC_TRACE_EVENT(sys_clock_getres, ++ TP_PROTO(const clockid_t which_clock, struct timespec * tp), ++ TP_ARGS(which_clock, tp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct timespec *, tp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(tp, tp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_utimes ++SC_TRACE_EVENT(sys_utimes, ++ TP_PROTO(char * filename, struct timeval * utimes), ++ TP_ARGS(filename, utimes), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct timeval *, utimes)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(utimes, utimes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mq_notify ++SC_TRACE_EVENT(sys_mq_notify, ++ TP_PROTO(mqd_t mqdes, const struct sigevent * u_notification), ++ TP_ARGS(mqdes, u_notification), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(const struct sigevent *, u_notification)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_notification, u_notification)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_set_robust_list ++SC_TRACE_EVENT(sys_set_robust_list, ++ TP_PROTO(struct robust_list_head * head, size_t len), ++ TP_ARGS(head, len), ++ TP_STRUCT__entry(__field_hex(struct robust_list_head *, head) __field(size_t, len)), ++ TP_fast_assign(tp_assign(head, head) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timerfd_gettime ++SC_TRACE_EVENT(sys_timerfd_gettime, ++ TP_PROTO(int ufd, struct itimerspec * otmr), ++ TP_ARGS(ufd, otmr), ++ TP_STRUCT__entry(__field(int, ufd) __field_hex(struct itimerspec *, otmr)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(otmr, otmr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_pipe2 ++SC_TRACE_EVENT(sys_pipe2, ++ TP_PROTO(int * fildes, int flags), ++ TP_ARGS(fildes, flags), ++ TP_STRUCT__entry(__field_hex(int *, fildes) __field(int, flags)), ++ TP_fast_assign(tp_assign(fildes, fildes) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_clock_adjtime ++SC_TRACE_EVENT(sys_clock_adjtime, ++ TP_PROTO(const clockid_t which_clock, struct timex * utx), ++ TP_ARGS(which_clock, utx), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct timex *, utx)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(utx, utx)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_read ++SC_TRACE_EVENT(sys_read, ++ TP_PROTO(unsigned int fd, char * buf, size_t count), ++ TP_ARGS(fd, buf, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(char *, buf) __field(size_t, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(buf, buf) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_write ++SC_TRACE_EVENT(sys_write, ++ TP_PROTO(unsigned int fd, const char * buf, size_t count), ++ TP_ARGS(fd, buf, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(const char *, buf) __field(size_t, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(buf, buf) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_open ++SC_TRACE_EVENT(sys_open, ++ TP_PROTO(const char * filename, int flags, int mode), ++ TP_ARGS(filename, flags, mode), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(int, flags) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(flags, flags) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_waitpid ++SC_TRACE_EVENT(sys_waitpid, ++ TP_PROTO(pid_t pid, int * stat_addr, int options), ++ TP_ARGS(pid, stat_addr, options), ++ TP_STRUCT__entry(__field(pid_t, pid) __field_hex(int *, stat_addr) __field(int, options)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(stat_addr, stat_addr) tp_assign(options, options)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mknod ++SC_TRACE_EVENT(sys_mknod, ++ TP_PROTO(const char * filename, int mode, unsigned dev), ++ TP_ARGS(filename, mode, dev), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(int, mode) __field(unsigned, dev)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(mode, mode) tp_assign(dev, dev)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lchown16 ++SC_TRACE_EVENT(sys_lchown16, ++ TP_PROTO(const char * filename, old_uid_t user, old_gid_t group), ++ TP_ARGS(filename, user, group), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(old_uid_t, user) __field(old_gid_t, group)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_readlink ++SC_TRACE_EVENT(sys_readlink, ++ TP_PROTO(const char * path, char * buf, int bufsiz), ++ TP_ARGS(path, buf, bufsiz), ++ TP_STRUCT__entry(__string_from_user(path, path) __field_hex(char *, buf) __field(int, bufsiz)), ++ TP_fast_assign(tp_copy_string_from_user(path, path) tp_assign(buf, buf) tp_assign(bufsiz, bufsiz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_old_readdir ++SC_TRACE_EVENT(sys_old_readdir, ++ TP_PROTO(unsigned int fd, struct old_linux_dirent * dirent, unsigned int count), ++ TP_ARGS(fd, dirent, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct old_linux_dirent *, dirent) __field(unsigned int, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(dirent, dirent) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_syslog ++SC_TRACE_EVENT(sys_syslog, ++ TP_PROTO(int type, char * buf, int len), ++ TP_ARGS(type, buf, len), ++ TP_STRUCT__entry(__field(int, type) __field_hex(char *, buf) __field(int, len)), ++ TP_fast_assign(tp_assign(type, type) tp_assign(buf, buf) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setitimer ++SC_TRACE_EVENT(sys_setitimer, ++ TP_PROTO(int which, struct itimerval * value, struct itimerval * ovalue), ++ TP_ARGS(which, value, ovalue), ++ TP_STRUCT__entry(__field(int, which) __field_hex(struct itimerval *, value) __field_hex(struct itimerval *, ovalue)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(value, value) tp_assign(ovalue, ovalue)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sigprocmask ++SC_TRACE_EVENT(sys_sigprocmask, ++ TP_PROTO(int how, old_sigset_t * nset, old_sigset_t * oset), ++ TP_ARGS(how, nset, oset), ++ TP_STRUCT__entry(__field(int, how) __field_hex(old_sigset_t *, nset) __field_hex(old_sigset_t *, oset)), ++ TP_fast_assign(tp_assign(how, how) tp_assign(nset, nset) tp_assign(oset, oset)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_init_module ++SC_TRACE_EVENT(sys_init_module, ++ TP_PROTO(void * umod, unsigned long len, const char * uargs), ++ TP_ARGS(umod, len, uargs), ++ TP_STRUCT__entry(__field_hex(void *, umod) __field(unsigned long, len) __field_hex(const char *, uargs)), ++ TP_fast_assign(tp_assign(umod, umod) tp_assign(len, len) tp_assign(uargs, uargs)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getdents ++SC_TRACE_EVENT(sys_getdents, ++ TP_PROTO(unsigned int fd, struct linux_dirent * dirent, unsigned int count), ++ TP_ARGS(fd, dirent, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct linux_dirent *, dirent) __field(unsigned int, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(dirent, dirent) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_readv ++SC_TRACE_EVENT(sys_readv, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen), ++ TP_ARGS(fd, vec, vlen), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_writev ++SC_TRACE_EVENT(sys_writev, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen), ++ TP_ARGS(fd, vec, vlen), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_setscheduler ++SC_TRACE_EVENT(sys_sched_setscheduler, ++ TP_PROTO(pid_t pid, int policy, struct sched_param * param), ++ TP_ARGS(pid, policy, param), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, policy) __field_hex(struct sched_param *, param)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(policy, policy) tp_assign(param, param)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getresuid16 ++SC_TRACE_EVENT(sys_getresuid16, ++ TP_PROTO(old_uid_t * ruid, old_uid_t * euid, old_uid_t * suid), ++ TP_ARGS(ruid, euid, suid), ++ TP_STRUCT__entry(__field_hex(old_uid_t *, ruid) __field_hex(old_uid_t *, euid) __field_hex(old_uid_t *, suid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid) tp_assign(suid, suid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_poll ++SC_TRACE_EVENT(sys_poll, ++ TP_PROTO(struct pollfd * ufds, unsigned int nfds, long timeout_msecs), ++ TP_ARGS(ufds, nfds, timeout_msecs), ++ TP_STRUCT__entry(__field_hex(struct pollfd *, ufds) __field(unsigned int, nfds) __field(long, timeout_msecs)), ++ TP_fast_assign(tp_assign(ufds, ufds) tp_assign(nfds, nfds) tp_assign(timeout_msecs, timeout_msecs)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getresgid16 ++SC_TRACE_EVENT(sys_getresgid16, ++ TP_PROTO(old_gid_t * rgid, old_gid_t * egid, old_gid_t * sgid), ++ TP_ARGS(rgid, egid, sgid), ++ TP_STRUCT__entry(__field_hex(old_gid_t *, rgid) __field_hex(old_gid_t *, egid) __field_hex(old_gid_t *, sgid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid) tp_assign(sgid, sgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rt_sigqueueinfo ++SC_TRACE_EVENT(sys_rt_sigqueueinfo, ++ TP_PROTO(pid_t pid, int sig, siginfo_t * uinfo), ++ TP_ARGS(pid, sig, uinfo), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, sig) __field_hex(siginfo_t *, uinfo)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(sig, sig) tp_assign(uinfo, uinfo)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_chown16 ++SC_TRACE_EVENT(sys_chown16, ++ TP_PROTO(const char * filename, old_uid_t user, old_gid_t group), ++ TP_ARGS(filename, user, group), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(old_uid_t, user) __field(old_gid_t, group)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lchown ++SC_TRACE_EVENT(sys_lchown, ++ TP_PROTO(const char * filename, uid_t user, gid_t group), ++ TP_ARGS(filename, user, group), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(uid_t, user) __field(gid_t, group)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getresuid ++SC_TRACE_EVENT(sys_getresuid, ++ TP_PROTO(uid_t * ruid, uid_t * euid, uid_t * suid), ++ TP_ARGS(ruid, euid, suid), ++ TP_STRUCT__entry(__field_hex(uid_t *, ruid) __field_hex(uid_t *, euid) __field_hex(uid_t *, suid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid) tp_assign(suid, suid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getresgid ++SC_TRACE_EVENT(sys_getresgid, ++ TP_PROTO(gid_t * rgid, gid_t * egid, gid_t * sgid), ++ TP_ARGS(rgid, egid, sgid), ++ TP_STRUCT__entry(__field_hex(gid_t *, rgid) __field_hex(gid_t *, egid) __field_hex(gid_t *, sgid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid) tp_assign(sgid, sgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_chown ++SC_TRACE_EVENT(sys_chown, ++ TP_PROTO(const char * filename, uid_t user, gid_t group), ++ TP_ARGS(filename, user, group), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(uid_t, user) __field(gid_t, group)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mincore ++SC_TRACE_EVENT(sys_mincore, ++ TP_PROTO(unsigned long start, size_t len, unsigned char * vec), ++ TP_ARGS(start, len, vec), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len) __field_hex(unsigned char *, vec)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len) tp_assign(vec, vec)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getdents64 ++SC_TRACE_EVENT(sys_getdents64, ++ TP_PROTO(unsigned int fd, struct linux_dirent64 * dirent, unsigned int count), ++ TP_ARGS(fd, dirent, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct linux_dirent64 *, dirent) __field(unsigned int, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(dirent, dirent) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_listxattr ++SC_TRACE_EVENT(sys_listxattr, ++ TP_PROTO(const char * pathname, char * list, size_t size), ++ TP_ARGS(pathname, list, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field_hex(char *, list) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(list, list) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_llistxattr ++SC_TRACE_EVENT(sys_llistxattr, ++ TP_PROTO(const char * pathname, char * list, size_t size), ++ TP_ARGS(pathname, list, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field_hex(char *, list) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(list, list) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_flistxattr ++SC_TRACE_EVENT(sys_flistxattr, ++ TP_PROTO(int fd, char * list, size_t size), ++ TP_ARGS(fd, list, size), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(char *, list) __field(size_t, size)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(list, list) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_setaffinity ++SC_TRACE_EVENT(sys_sched_setaffinity, ++ TP_PROTO(pid_t pid, unsigned int len, unsigned long * user_mask_ptr), ++ TP_ARGS(pid, len, user_mask_ptr), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(unsigned int, len) __field_hex(unsigned long *, user_mask_ptr)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(len, len) tp_assign(user_mask_ptr, user_mask_ptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sched_getaffinity ++SC_TRACE_EVENT(sys_sched_getaffinity, ++ TP_PROTO(pid_t pid, unsigned int len, unsigned long * user_mask_ptr), ++ TP_ARGS(pid, len, user_mask_ptr), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(unsigned int, len) __field_hex(unsigned long *, user_mask_ptr)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(len, len) tp_assign(user_mask_ptr, user_mask_ptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_io_submit ++SC_TRACE_EVENT(sys_io_submit, ++ TP_PROTO(aio_context_t ctx_id, long nr, struct iocb * * iocbpp), ++ TP_ARGS(ctx_id, nr, iocbpp), ++ TP_STRUCT__entry(__field(aio_context_t, ctx_id) __field(long, nr) __field_hex(struct iocb * *, iocbpp)), ++ TP_fast_assign(tp_assign(ctx_id, ctx_id) tp_assign(nr, nr) tp_assign(iocbpp, iocbpp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_io_cancel ++SC_TRACE_EVENT(sys_io_cancel, ++ TP_PROTO(aio_context_t ctx_id, struct iocb * iocb, struct io_event * result), ++ TP_ARGS(ctx_id, iocb, result), ++ TP_STRUCT__entry(__field(aio_context_t, ctx_id) __field_hex(struct iocb *, iocb) __field_hex(struct io_event *, result)), ++ TP_fast_assign(tp_assign(ctx_id, ctx_id) tp_assign(iocb, iocb) tp_assign(result, result)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timer_create ++SC_TRACE_EVENT(sys_timer_create, ++ TP_PROTO(const clockid_t which_clock, struct sigevent * timer_event_spec, timer_t * created_timer_id), ++ TP_ARGS(which_clock, timer_event_spec, created_timer_id), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct sigevent *, timer_event_spec) __field_hex(timer_t *, created_timer_id)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(timer_event_spec, timer_event_spec) tp_assign(created_timer_id, created_timer_id)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_statfs64 ++SC_TRACE_EVENT(sys_statfs64, ++ TP_PROTO(const char * pathname, size_t sz, struct statfs64 * buf), ++ TP_ARGS(pathname, sz, buf), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field(size_t, sz) __field_hex(struct statfs64 *, buf)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(sz, sz) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fstatfs64 ++SC_TRACE_EVENT(sys_fstatfs64, ++ TP_PROTO(unsigned int fd, size_t sz, struct statfs64 * buf), ++ TP_ARGS(fd, sz, buf), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(size_t, sz) __field_hex(struct statfs64 *, buf)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(sz, sz) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mq_getsetattr ++SC_TRACE_EVENT(sys_mq_getsetattr, ++ TP_PROTO(mqd_t mqdes, const struct mq_attr * u_mqstat, struct mq_attr * u_omqstat), ++ TP_ARGS(mqdes, u_mqstat, u_omqstat), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(const struct mq_attr *, u_mqstat) __field_hex(struct mq_attr *, u_omqstat)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_mqstat, u_mqstat) tp_assign(u_omqstat, u_omqstat)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_inotify_add_watch ++SC_TRACE_EVENT(sys_inotify_add_watch, ++ TP_PROTO(int fd, const char * pathname, u32 mask), ++ TP_ARGS(fd, pathname, mask), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(pathname, pathname) __field(u32, mask)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(pathname, pathname) tp_assign(mask, mask)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mkdirat ++SC_TRACE_EVENT(sys_mkdirat, ++ TP_PROTO(int dfd, const char * pathname, int mode), ++ TP_ARGS(dfd, pathname, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(pathname, pathname) __field(int, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(pathname, pathname) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_futimesat ++SC_TRACE_EVENT(sys_futimesat, ++ TP_PROTO(int dfd, const char * filename, struct timeval * utimes), ++ TP_ARGS(dfd, filename, utimes), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field_hex(struct timeval *, utimes)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(utimes, utimes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_unlinkat ++SC_TRACE_EVENT(sys_unlinkat, ++ TP_PROTO(int dfd, const char * pathname, int flag), ++ TP_ARGS(dfd, pathname, flag), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(pathname, pathname) __field(int, flag)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(pathname, pathname) tp_assign(flag, flag)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_symlinkat ++SC_TRACE_EVENT(sys_symlinkat, ++ TP_PROTO(const char * oldname, int newdfd, const char * newname), ++ TP_ARGS(oldname, newdfd, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __field(int, newdfd) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_assign(newdfd, newdfd) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fchmodat ++SC_TRACE_EVENT(sys_fchmodat, ++ TP_PROTO(int dfd, const char * filename, mode_t mode), ++ TP_ARGS(dfd, filename, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(mode_t, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_faccessat ++SC_TRACE_EVENT(sys_faccessat, ++ TP_PROTO(int dfd, const char * filename, int mode), ++ TP_ARGS(dfd, filename, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(int, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_get_robust_list ++SC_TRACE_EVENT(sys_get_robust_list, ++ TP_PROTO(int pid, struct robust_list_head * * head_ptr, size_t * len_ptr), ++ TP_ARGS(pid, head_ptr, len_ptr), ++ TP_STRUCT__entry(__field(int, pid) __field_hex(struct robust_list_head * *, head_ptr) __field_hex(size_t *, len_ptr)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(head_ptr, head_ptr) tp_assign(len_ptr, len_ptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getcpu ++SC_TRACE_EVENT(sys_getcpu, ++ TP_PROTO(unsigned * cpup, unsigned * nodep, struct getcpu_cache * unused), ++ TP_ARGS(cpup, nodep, unused), ++ TP_STRUCT__entry(__field_hex(unsigned *, cpup) __field_hex(unsigned *, nodep) __field_hex(struct getcpu_cache *, unused)), ++ TP_fast_assign(tp_assign(cpup, cpup) tp_assign(nodep, nodep) tp_assign(unused, unused)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_signalfd ++SC_TRACE_EVENT(sys_signalfd, ++ TP_PROTO(int ufd, sigset_t * user_mask, size_t sizemask), ++ TP_ARGS(ufd, user_mask, sizemask), ++ TP_STRUCT__entry(__field(int, ufd) __field_hex(sigset_t *, user_mask) __field(size_t, sizemask)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(user_mask, user_mask) tp_assign(sizemask, sizemask)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_reboot ++SC_TRACE_EVENT(sys_reboot, ++ TP_PROTO(int magic1, int magic2, unsigned int cmd, void * arg), ++ TP_ARGS(magic1, magic2, cmd, arg), ++ TP_STRUCT__entry(__field(int, magic1) __field(int, magic2) __field(unsigned int, cmd) __field_hex(void *, arg)), ++ TP_fast_assign(tp_assign(magic1, magic1) tp_assign(magic2, magic2) tp_assign(cmd, cmd) tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_wait4 ++SC_TRACE_EVENT(sys_wait4, ++ TP_PROTO(pid_t upid, int * stat_addr, int options, struct rusage * ru), ++ TP_ARGS(upid, stat_addr, options, ru), ++ TP_STRUCT__entry(__field(pid_t, upid) __field_hex(int *, stat_addr) __field(int, options) __field_hex(struct rusage *, ru)), ++ TP_fast_assign(tp_assign(upid, upid) tp_assign(stat_addr, stat_addr) tp_assign(options, options) tp_assign(ru, ru)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_quotactl ++SC_TRACE_EVENT(sys_quotactl, ++ TP_PROTO(unsigned int cmd, const char * special, qid_t id, void * addr), ++ TP_ARGS(cmd, special, id, addr), ++ TP_STRUCT__entry(__field(unsigned int, cmd) __field_hex(const char *, special) __field(qid_t, id) __field_hex(void *, addr)), ++ TP_fast_assign(tp_assign(cmd, cmd) tp_assign(special, special) tp_assign(id, id) tp_assign(addr, addr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rt_sigaction ++SC_TRACE_EVENT(sys_rt_sigaction, ++ TP_PROTO(int sig, const struct sigaction * act, struct sigaction * oact, size_t sigsetsize), ++ TP_ARGS(sig, act, oact, sigsetsize), ++ TP_STRUCT__entry(__field(int, sig) __field_hex(const struct sigaction *, act) __field_hex(struct sigaction *, oact) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(sig, sig) tp_assign(act, act) tp_assign(oact, oact) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rt_sigprocmask ++SC_TRACE_EVENT(sys_rt_sigprocmask, ++ TP_PROTO(int how, sigset_t * nset, sigset_t * oset, size_t sigsetsize), ++ TP_ARGS(how, nset, oset, sigsetsize), ++ TP_STRUCT__entry(__field(int, how) __field_hex(sigset_t *, nset) __field_hex(sigset_t *, oset) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(how, how) tp_assign(nset, nset) tp_assign(oset, oset) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rt_sigtimedwait ++SC_TRACE_EVENT(sys_rt_sigtimedwait, ++ TP_PROTO(const sigset_t * uthese, siginfo_t * uinfo, const struct timespec * uts, size_t sigsetsize), ++ TP_ARGS(uthese, uinfo, uts, sigsetsize), ++ TP_STRUCT__entry(__field_hex(const sigset_t *, uthese) __field_hex(siginfo_t *, uinfo) __field_hex(const struct timespec *, uts) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(uthese, uthese) tp_assign(uinfo, uinfo) tp_assign(uts, uts) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sendfile ++SC_TRACE_EVENT(sys_sendfile, ++ TP_PROTO(int out_fd, int in_fd, off_t * offset, size_t count), ++ TP_ARGS(out_fd, in_fd, offset, count), ++ TP_STRUCT__entry(__field(int, out_fd) __field(int, in_fd) __field_hex(off_t *, offset) __field(size_t, count)), ++ TP_fast_assign(tp_assign(out_fd, out_fd) tp_assign(in_fd, in_fd) tp_assign(offset, offset) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_getxattr ++SC_TRACE_EVENT(sys_getxattr, ++ TP_PROTO(const char * pathname, const char * name, void * value, size_t size), ++ TP_ARGS(pathname, name, value, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(void *, value) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lgetxattr ++SC_TRACE_EVENT(sys_lgetxattr, ++ TP_PROTO(const char * pathname, const char * name, void * value, size_t size), ++ TP_ARGS(pathname, name, value, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(void *, value) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fgetxattr ++SC_TRACE_EVENT(sys_fgetxattr, ++ TP_PROTO(int fd, const char * name, void * value, size_t size), ++ TP_ARGS(fd, name, value, size), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(name, name) __field_hex(void *, value) __field(size_t, size)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sendfile64 ++SC_TRACE_EVENT(sys_sendfile64, ++ TP_PROTO(int out_fd, int in_fd, loff_t * offset, size_t count), ++ TP_ARGS(out_fd, in_fd, offset, count), ++ TP_STRUCT__entry(__field(int, out_fd) __field(int, in_fd) __field_hex(loff_t *, offset) __field(size_t, count)), ++ TP_fast_assign(tp_assign(out_fd, out_fd) tp_assign(in_fd, in_fd) tp_assign(offset, offset) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_epoll_ctl ++SC_TRACE_EVENT(sys_epoll_ctl, ++ TP_PROTO(int epfd, int op, int fd, struct epoll_event * event), ++ TP_ARGS(epfd, op, fd, event), ++ TP_STRUCT__entry(__field(int, epfd) __field(int, op) __field(int, fd) __field_hex(struct epoll_event *, event)), ++ TP_fast_assign(tp_assign(epfd, epfd) tp_assign(op, op) tp_assign(fd, fd) tp_assign(event, event)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_epoll_wait ++SC_TRACE_EVENT(sys_epoll_wait, ++ TP_PROTO(int epfd, struct epoll_event * events, int maxevents, int timeout), ++ TP_ARGS(epfd, events, maxevents, timeout), ++ TP_STRUCT__entry(__field(int, epfd) __field_hex(struct epoll_event *, events) __field(int, maxevents) __field(int, timeout)), ++ TP_fast_assign(tp_assign(epfd, epfd) tp_assign(events, events) tp_assign(maxevents, maxevents) tp_assign(timeout, timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timer_settime ++SC_TRACE_EVENT(sys_timer_settime, ++ TP_PROTO(timer_t timer_id, int flags, const struct itimerspec * new_setting, struct itimerspec * old_setting), ++ TP_ARGS(timer_id, flags, new_setting, old_setting), ++ TP_STRUCT__entry(__field(timer_t, timer_id) __field(int, flags) __field_hex(const struct itimerspec *, new_setting) __field_hex(struct itimerspec *, old_setting)), ++ TP_fast_assign(tp_assign(timer_id, timer_id) tp_assign(flags, flags) tp_assign(new_setting, new_setting) tp_assign(old_setting, old_setting)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_clock_nanosleep ++SC_TRACE_EVENT(sys_clock_nanosleep, ++ TP_PROTO(const clockid_t which_clock, int flags, const struct timespec * rqtp, struct timespec * rmtp), ++ TP_ARGS(which_clock, flags, rqtp, rmtp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field(int, flags) __field_hex(const struct timespec *, rqtp) __field_hex(struct timespec *, rmtp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(flags, flags) tp_assign(rqtp, rqtp) tp_assign(rmtp, rmtp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mq_open ++SC_TRACE_EVENT(sys_mq_open, ++ TP_PROTO(const char * u_name, int oflag, mode_t mode, struct mq_attr * u_attr), ++ TP_ARGS(u_name, oflag, mode, u_attr), ++ TP_STRUCT__entry(__string_from_user(u_name, u_name) __field(int, oflag) __field(mode_t, mode) __field_hex(struct mq_attr *, u_attr)), ++ TP_fast_assign(tp_copy_string_from_user(u_name, u_name) tp_assign(oflag, oflag) tp_assign(mode, mode) tp_assign(u_attr, u_attr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_kexec_load ++SC_TRACE_EVENT(sys_kexec_load, ++ TP_PROTO(unsigned long entry, unsigned long nr_segments, struct kexec_segment * segments, unsigned long flags), ++ TP_ARGS(entry, nr_segments, segments, flags), ++ TP_STRUCT__entry(__field(unsigned long, entry) __field(unsigned long, nr_segments) __field_hex(struct kexec_segment *, segments) __field(unsigned long, flags)), ++ TP_fast_assign(tp_assign(entry, entry) tp_assign(nr_segments, nr_segments) tp_assign(segments, segments) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_request_key ++SC_TRACE_EVENT(sys_request_key, ++ TP_PROTO(const char * _type, const char * _description, const char * _callout_info, key_serial_t destringid), ++ TP_ARGS(_type, _description, _callout_info, destringid), ++ TP_STRUCT__entry(__string_from_user(_type, _type) __field_hex(const char *, _description) __field_hex(const char *, _callout_info) __field(key_serial_t, destringid)), ++ TP_fast_assign(tp_copy_string_from_user(_type, _type) tp_assign(_description, _description) tp_assign(_callout_info, _callout_info) tp_assign(destringid, destringid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_openat ++SC_TRACE_EVENT(sys_openat, ++ TP_PROTO(int dfd, const char * filename, int flags, int mode), ++ TP_ARGS(dfd, filename, flags, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(int, flags) __field(int, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(flags, flags) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mknodat ++SC_TRACE_EVENT(sys_mknodat, ++ TP_PROTO(int dfd, const char * filename, int mode, unsigned dev), ++ TP_ARGS(dfd, filename, mode, dev), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(int, mode) __field(unsigned, dev)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(mode, mode) tp_assign(dev, dev)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fstatat64 ++SC_TRACE_EVENT(sys_fstatat64, ++ TP_PROTO(int dfd, const char * filename, struct stat64 * statbuf, int flag), ++ TP_ARGS(dfd, filename, statbuf, flag), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field_hex(struct stat64 *, statbuf) __field(int, flag)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf) tp_assign(flag, flag)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_renameat ++SC_TRACE_EVENT(sys_renameat, ++ TP_PROTO(int olddfd, const char * oldname, int newdfd, const char * newname), ++ TP_ARGS(olddfd, oldname, newdfd, newname), ++ TP_STRUCT__entry(__field(int, olddfd) __string_from_user(oldname, oldname) __field(int, newdfd) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_assign(olddfd, olddfd) tp_copy_string_from_user(oldname, oldname) tp_assign(newdfd, newdfd) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_readlinkat ++SC_TRACE_EVENT(sys_readlinkat, ++ TP_PROTO(int dfd, const char * pathname, char * buf, int bufsiz), ++ TP_ARGS(dfd, pathname, buf, bufsiz), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(pathname, pathname) __field_hex(char *, buf) __field(int, bufsiz)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(pathname, pathname) tp_assign(buf, buf) tp_assign(bufsiz, bufsiz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_vmsplice ++SC_TRACE_EVENT(sys_vmsplice, ++ TP_PROTO(int fd, const struct iovec * iov, unsigned long nr_segs, unsigned int flags), ++ TP_ARGS(fd, iov, nr_segs, flags), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(const struct iovec *, iov) __field(unsigned long, nr_segs) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(iov, iov) tp_assign(nr_segs, nr_segs) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_utimensat ++SC_TRACE_EVENT(sys_utimensat, ++ TP_PROTO(int dfd, const char * filename, struct timespec * utimes, int flags), ++ TP_ARGS(dfd, filename, utimes, flags), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field_hex(struct timespec *, utimes) __field(int, flags)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(utimes, utimes) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_timerfd_settime ++SC_TRACE_EVENT(sys_timerfd_settime, ++ TP_PROTO(int ufd, int flags, const struct itimerspec * utmr, struct itimerspec * otmr), ++ TP_ARGS(ufd, flags, utmr, otmr), ++ TP_STRUCT__entry(__field(int, ufd) __field(int, flags) __field_hex(const struct itimerspec *, utmr) __field_hex(struct itimerspec *, otmr)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(flags, flags) tp_assign(utmr, utmr) tp_assign(otmr, otmr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_signalfd4 ++SC_TRACE_EVENT(sys_signalfd4, ++ TP_PROTO(int ufd, sigset_t * user_mask, size_t sizemask, int flags), ++ TP_ARGS(ufd, user_mask, sizemask, flags), ++ TP_STRUCT__entry(__field(int, ufd) __field_hex(sigset_t *, user_mask) __field(size_t, sizemask) __field(int, flags)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(user_mask, user_mask) tp_assign(sizemask, sizemask) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_rt_tgsigqueueinfo ++SC_TRACE_EVENT(sys_rt_tgsigqueueinfo, ++ TP_PROTO(pid_t tgid, pid_t pid, int sig, siginfo_t * uinfo), ++ TP_ARGS(tgid, pid, sig, uinfo), ++ TP_STRUCT__entry(__field(pid_t, tgid) __field(pid_t, pid) __field(int, sig) __field_hex(siginfo_t *, uinfo)), ++ TP_fast_assign(tp_assign(tgid, tgid) tp_assign(pid, pid) tp_assign(sig, sig) tp_assign(uinfo, uinfo)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_prlimit64 ++SC_TRACE_EVENT(sys_prlimit64, ++ TP_PROTO(pid_t pid, unsigned int resource, const struct rlimit64 * new_rlim, struct rlimit64 * old_rlim), ++ TP_ARGS(pid, resource, new_rlim, old_rlim), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(unsigned int, resource) __field_hex(const struct rlimit64 *, new_rlim) __field_hex(struct rlimit64 *, old_rlim)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(resource, resource) tp_assign(new_rlim, new_rlim) tp_assign(old_rlim, old_rlim)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_sendmmsg ++SC_TRACE_EVENT(sys_sendmmsg, ++ TP_PROTO(int fd, struct mmsghdr * mmsg, unsigned int vlen, unsigned int flags), ++ TP_ARGS(fd, mmsg, vlen, flags), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct mmsghdr *, mmsg) __field(unsigned int, vlen) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(mmsg, mmsg) tp_assign(vlen, vlen) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mount ++SC_TRACE_EVENT(sys_mount, ++ TP_PROTO(char * dev_name, char * dir_name, char * type, unsigned long flags, void * data), ++ TP_ARGS(dev_name, dir_name, type, flags, data), ++ TP_STRUCT__entry(__string_from_user(dev_name, dev_name) __string_from_user(dir_name, dir_name) __string_from_user(type, type) __field(unsigned long, flags) __field_hex(void *, data)), ++ TP_fast_assign(tp_copy_string_from_user(dev_name, dev_name) tp_copy_string_from_user(dir_name, dir_name) tp_copy_string_from_user(type, type) tp_assign(flags, flags) tp_assign(data, data)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_llseek ++SC_TRACE_EVENT(sys_llseek, ++ TP_PROTO(unsigned int fd, unsigned long offset_high, unsigned long offset_low, loff_t * result, unsigned int origin), ++ TP_ARGS(fd, offset_high, offset_low, result, origin), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned long, offset_high) __field(unsigned long, offset_low) __field_hex(loff_t *, result) __field(unsigned int, origin)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(offset_high, offset_high) tp_assign(offset_low, offset_low) tp_assign(result, result) tp_assign(origin, origin)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_select ++SC_TRACE_EVENT(sys_select, ++ TP_PROTO(int n, fd_set * inp, fd_set * outp, fd_set * exp, struct timeval * tvp), ++ TP_ARGS(n, inp, outp, exp, tvp), ++ TP_STRUCT__entry(__field(int, n) __field_hex(fd_set *, inp) __field_hex(fd_set *, outp) __field_hex(fd_set *, exp) __field_hex(struct timeval *, tvp)), ++ TP_fast_assign(tp_assign(n, n) tp_assign(inp, inp) tp_assign(outp, outp) tp_assign(exp, exp) tp_assign(tvp, tvp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_setxattr ++SC_TRACE_EVENT(sys_setxattr, ++ TP_PROTO(const char * pathname, const char * name, const void * value, size_t size, int flags), ++ TP_ARGS(pathname, name, value, size, flags), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(const void *, value) __field(size_t, size) __field(int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_lsetxattr ++SC_TRACE_EVENT(sys_lsetxattr, ++ TP_PROTO(const char * pathname, const char * name, const void * value, size_t size, int flags), ++ TP_ARGS(pathname, name, value, size, flags), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(const void *, value) __field(size_t, size) __field(int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fsetxattr ++SC_TRACE_EVENT(sys_fsetxattr, ++ TP_PROTO(int fd, const char * name, const void * value, size_t size, int flags), ++ TP_ARGS(fd, name, value, size, flags), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(name, name) __field_hex(const void *, value) __field(size_t, size) __field(int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_io_getevents ++SC_TRACE_EVENT(sys_io_getevents, ++ TP_PROTO(aio_context_t ctx_id, long min_nr, long nr, struct io_event * events, struct timespec * timeout), ++ TP_ARGS(ctx_id, min_nr, nr, events, timeout), ++ TP_STRUCT__entry(__field(aio_context_t, ctx_id) __field(long, min_nr) __field(long, nr) __field_hex(struct io_event *, events) __field_hex(struct timespec *, timeout)), ++ TP_fast_assign(tp_assign(ctx_id, ctx_id) tp_assign(min_nr, min_nr) tp_assign(nr, nr) tp_assign(events, events) tp_assign(timeout, timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mq_timedsend ++SC_TRACE_EVENT(sys_mq_timedsend, ++ TP_PROTO(mqd_t mqdes, const char * u_msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec * u_abs_timeout), ++ TP_ARGS(mqdes, u_msg_ptr, msg_len, msg_prio, u_abs_timeout), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(const char *, u_msg_ptr) __field(size_t, msg_len) __field(unsigned int, msg_prio) __field_hex(const struct timespec *, u_abs_timeout)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_msg_ptr, u_msg_ptr) tp_assign(msg_len, msg_len) tp_assign(msg_prio, msg_prio) tp_assign(u_abs_timeout, u_abs_timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_mq_timedreceive ++SC_TRACE_EVENT(sys_mq_timedreceive, ++ TP_PROTO(mqd_t mqdes, char * u_msg_ptr, size_t msg_len, unsigned int * u_msg_prio, const struct timespec * u_abs_timeout), ++ TP_ARGS(mqdes, u_msg_ptr, msg_len, u_msg_prio, u_abs_timeout), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(char *, u_msg_ptr) __field(size_t, msg_len) __field_hex(unsigned int *, u_msg_prio) __field_hex(const struct timespec *, u_abs_timeout)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_msg_ptr, u_msg_ptr) tp_assign(msg_len, msg_len) tp_assign(u_msg_prio, u_msg_prio) tp_assign(u_abs_timeout, u_abs_timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_waitid ++SC_TRACE_EVENT(sys_waitid, ++ TP_PROTO(int which, pid_t upid, struct siginfo * infop, int options, struct rusage * ru), ++ TP_ARGS(which, upid, infop, options, ru), ++ TP_STRUCT__entry(__field(int, which) __field(pid_t, upid) __field_hex(struct siginfo *, infop) __field(int, options) __field_hex(struct rusage *, ru)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(upid, upid) tp_assign(infop, infop) tp_assign(options, options) tp_assign(ru, ru)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_add_key ++SC_TRACE_EVENT(sys_add_key, ++ TP_PROTO(const char * _type, const char * _description, const void * _payload, size_t plen, key_serial_t ringid), ++ TP_ARGS(_type, _description, _payload, plen, ringid), ++ TP_STRUCT__entry(__string_from_user(_type, _type) __field_hex(const char *, _description) __field_hex(const void *, _payload) __field(size_t, plen) __field(key_serial_t, ringid)), ++ TP_fast_assign(tp_copy_string_from_user(_type, _type) tp_assign(_description, _description) tp_assign(_payload, _payload) tp_assign(plen, plen) tp_assign(ringid, ringid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_fchownat ++SC_TRACE_EVENT(sys_fchownat, ++ TP_PROTO(int dfd, const char * filename, uid_t user, gid_t group, int flag), ++ TP_ARGS(dfd, filename, user, group, flag), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(uid_t, user) __field(gid_t, group) __field(int, flag)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group) tp_assign(flag, flag)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_linkat ++SC_TRACE_EVENT(sys_linkat, ++ TP_PROTO(int olddfd, const char * oldname, int newdfd, const char * newname, int flags), ++ TP_ARGS(olddfd, oldname, newdfd, newname, flags), ++ TP_STRUCT__entry(__field(int, olddfd) __string_from_user(oldname, oldname) __field(int, newdfd) __string_from_user(newname, newname) __field(int, flags)), ++ TP_fast_assign(tp_assign(olddfd, olddfd) tp_copy_string_from_user(oldname, oldname) tp_assign(newdfd, newdfd) tp_copy_string_from_user(newname, newname) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ppoll ++SC_TRACE_EVENT(sys_ppoll, ++ TP_PROTO(struct pollfd * ufds, unsigned int nfds, struct timespec * tsp, const sigset_t * sigmask, size_t sigsetsize), ++ TP_ARGS(ufds, nfds, tsp, sigmask, sigsetsize), ++ TP_STRUCT__entry(__field_hex(struct pollfd *, ufds) __field(unsigned int, nfds) __field_hex(struct timespec *, tsp) __field_hex(const sigset_t *, sigmask) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(ufds, ufds) tp_assign(nfds, nfds) tp_assign(tsp, tsp) tp_assign(sigmask, sigmask) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_preadv ++SC_TRACE_EVENT(sys_preadv, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h), ++ TP_ARGS(fd, vec, vlen, pos_l, pos_h), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen) __field(unsigned long, pos_l) __field(unsigned long, pos_h)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen) tp_assign(pos_l, pos_l) tp_assign(pos_h, pos_h)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_pwritev ++SC_TRACE_EVENT(sys_pwritev, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h), ++ TP_ARGS(fd, vec, vlen, pos_l, pos_h), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen) __field(unsigned long, pos_l) __field(unsigned long, pos_h)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen) tp_assign(pos_l, pos_l) tp_assign(pos_h, pos_h)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_perf_event_open ++SC_TRACE_EVENT(sys_perf_event_open, ++ TP_PROTO(struct perf_event_attr * attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags), ++ TP_ARGS(attr_uptr, pid, cpu, group_fd, flags), ++ TP_STRUCT__entry(__field_hex(struct perf_event_attr *, attr_uptr) __field(pid_t, pid) __field(int, cpu) __field(int, group_fd) __field(unsigned long, flags)), ++ TP_fast_assign(tp_assign(attr_uptr, attr_uptr) tp_assign(pid, pid) tp_assign(cpu, cpu) tp_assign(group_fd, group_fd) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_recvmmsg ++SC_TRACE_EVENT(sys_recvmmsg, ++ TP_PROTO(int fd, struct mmsghdr * mmsg, unsigned int vlen, unsigned int flags, struct timespec * timeout), ++ TP_ARGS(fd, mmsg, vlen, flags, timeout), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct mmsghdr *, mmsg) __field(unsigned int, vlen) __field(unsigned int, flags) __field_hex(struct timespec *, timeout)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(mmsg, mmsg) tp_assign(vlen, vlen) tp_assign(flags, flags) tp_assign(timeout, timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_ipc ++SC_TRACE_EVENT(sys_ipc, ++ TP_PROTO(unsigned int call, int first, unsigned long second, unsigned long third, void * ptr, long fifth), ++ TP_ARGS(call, first, second, third, ptr, fifth), ++ TP_STRUCT__entry(__field(unsigned int, call) __field(int, first) __field(unsigned long, second) __field(unsigned long, third) __field_hex(void *, ptr) __field(long, fifth)), ++ TP_fast_assign(tp_assign(call, call) tp_assign(first, first) tp_assign(second, second) tp_assign(third, third) tp_assign(ptr, ptr) tp_assign(fifth, fifth)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_futex ++SC_TRACE_EVENT(sys_futex, ++ TP_PROTO(u32 * uaddr, int op, u32 val, struct timespec * utime, u32 * uaddr2, u32 val3), ++ TP_ARGS(uaddr, op, val, utime, uaddr2, val3), ++ TP_STRUCT__entry(__field_hex(u32 *, uaddr) __field(int, op) __field(u32, val) __field_hex(struct timespec *, utime) __field_hex(u32 *, uaddr2) __field(u32, val3)), ++ TP_fast_assign(tp_assign(uaddr, uaddr) tp_assign(op, op) tp_assign(val, val) tp_assign(utime, utime) tp_assign(uaddr2, uaddr2) tp_assign(val3, val3)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_pselect6 ++SC_TRACE_EVENT(sys_pselect6, ++ TP_PROTO(int n, fd_set * inp, fd_set * outp, fd_set * exp, struct timespec * tsp, void * sig), ++ TP_ARGS(n, inp, outp, exp, tsp, sig), ++ TP_STRUCT__entry(__field(int, n) __field_hex(fd_set *, inp) __field_hex(fd_set *, outp) __field_hex(fd_set *, exp) __field_hex(struct timespec *, tsp) __field_hex(void *, sig)), ++ TP_fast_assign(tp_assign(n, n) tp_assign(inp, inp) tp_assign(outp, outp) tp_assign(exp, exp) tp_assign(tsp, tsp) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_splice ++SC_TRACE_EVENT(sys_splice, ++ TP_PROTO(int fd_in, loff_t * off_in, int fd_out, loff_t * off_out, size_t len, unsigned int flags), ++ TP_ARGS(fd_in, off_in, fd_out, off_out, len, flags), ++ TP_STRUCT__entry(__field(int, fd_in) __field_hex(loff_t *, off_in) __field(int, fd_out) __field_hex(loff_t *, off_out) __field(size_t, len) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fd_in, fd_in) tp_assign(off_in, off_in) tp_assign(fd_out, fd_out) tp_assign(off_out, off_out) tp_assign(len, len) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_32_sys_epoll_pwait ++SC_TRACE_EVENT(sys_epoll_pwait, ++ TP_PROTO(int epfd, struct epoll_event * events, int maxevents, int timeout, const sigset_t * sigmask, size_t sigsetsize), ++ TP_ARGS(epfd, events, maxevents, timeout, sigmask, sigsetsize), ++ TP_STRUCT__entry(__field(int, epfd) __field_hex(struct epoll_event *, events) __field(int, maxevents) __field(int, timeout) __field_hex(const sigset_t *, sigmask) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(epfd, epfd) tp_assign(events, events) tp_assign(maxevents, maxevents) tp_assign(timeout, timeout) tp_assign(sigmask, sigmask) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++ ++#endif /* _TRACE_SYSCALLS_POINTERS_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" ++ ++#else /* CREATE_SYSCALL_TABLE */ ++ ++#include "x86-32-syscalls-3.1.0-rc6_pointers_override.h" ++#include "syscalls_pointers_override.h" ++ ++#ifndef OVERRIDE_TABLE_32_sys_read ++TRACE_SYSCALL_TABLE(sys_read, sys_read, 3, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_write ++TRACE_SYSCALL_TABLE(sys_write, sys_write, 4, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_open ++TRACE_SYSCALL_TABLE(sys_open, sys_open, 5, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_waitpid ++TRACE_SYSCALL_TABLE(sys_waitpid, sys_waitpid, 7, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_creat ++TRACE_SYSCALL_TABLE(sys_creat, sys_creat, 8, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_link ++TRACE_SYSCALL_TABLE(sys_link, sys_link, 9, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_unlink ++TRACE_SYSCALL_TABLE(sys_unlink, sys_unlink, 10, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_chdir ++TRACE_SYSCALL_TABLE(sys_chdir, sys_chdir, 12, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_time ++TRACE_SYSCALL_TABLE(sys_time, sys_time, 13, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mknod ++TRACE_SYSCALL_TABLE(sys_mknod, sys_mknod, 14, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_chmod ++TRACE_SYSCALL_TABLE(sys_chmod, sys_chmod, 15, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lchown16 ++TRACE_SYSCALL_TABLE(sys_lchown16, sys_lchown16, 16, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_stat ++TRACE_SYSCALL_TABLE(sys_stat, sys_stat, 18, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mount ++TRACE_SYSCALL_TABLE(sys_mount, sys_mount, 21, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_oldumount ++TRACE_SYSCALL_TABLE(sys_oldumount, sys_oldumount, 22, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_stime ++TRACE_SYSCALL_TABLE(sys_stime, sys_stime, 25, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fstat ++TRACE_SYSCALL_TABLE(sys_fstat, sys_fstat, 28, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_utime ++TRACE_SYSCALL_TABLE(sys_utime, sys_utime, 30, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_access ++TRACE_SYSCALL_TABLE(sys_access, sys_access, 33, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rename ++TRACE_SYSCALL_TABLE(sys_rename, sys_rename, 38, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mkdir ++TRACE_SYSCALL_TABLE(sys_mkdir, sys_mkdir, 39, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rmdir ++TRACE_SYSCALL_TABLE(sys_rmdir, sys_rmdir, 40, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_pipe ++TRACE_SYSCALL_TABLE(sys_pipe, sys_pipe, 42, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_times ++TRACE_SYSCALL_TABLE(sys_times, sys_times, 43, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_acct ++TRACE_SYSCALL_TABLE(sys_acct, sys_acct, 51, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_umount ++TRACE_SYSCALL_TABLE(sys_umount, sys_umount, 52, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_olduname ++TRACE_SYSCALL_TABLE(sys_olduname, sys_olduname, 59, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_chroot ++TRACE_SYSCALL_TABLE(sys_chroot, sys_chroot, 61, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ustat ++TRACE_SYSCALL_TABLE(sys_ustat, sys_ustat, 62, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sigpending ++TRACE_SYSCALL_TABLE(sys_sigpending, sys_sigpending, 73, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sethostname ++TRACE_SYSCALL_TABLE(sys_sethostname, sys_sethostname, 74, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setrlimit ++TRACE_SYSCALL_TABLE(sys_setrlimit, sys_setrlimit, 75, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_old_getrlimit ++TRACE_SYSCALL_TABLE(sys_old_getrlimit, sys_old_getrlimit, 76, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getrusage ++TRACE_SYSCALL_TABLE(sys_getrusage, sys_getrusage, 77, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_gettimeofday ++TRACE_SYSCALL_TABLE(sys_gettimeofday, sys_gettimeofday, 78, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_settimeofday ++TRACE_SYSCALL_TABLE(sys_settimeofday, sys_settimeofday, 79, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getgroups16 ++TRACE_SYSCALL_TABLE(sys_getgroups16, sys_getgroups16, 80, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setgroups16 ++TRACE_SYSCALL_TABLE(sys_setgroups16, sys_setgroups16, 81, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_old_select ++TRACE_SYSCALL_TABLE(sys_old_select, sys_old_select, 82, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_symlink ++TRACE_SYSCALL_TABLE(sys_symlink, sys_symlink, 83, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lstat ++TRACE_SYSCALL_TABLE(sys_lstat, sys_lstat, 84, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_readlink ++TRACE_SYSCALL_TABLE(sys_readlink, sys_readlink, 85, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_uselib ++TRACE_SYSCALL_TABLE(sys_uselib, sys_uselib, 86, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_swapon ++TRACE_SYSCALL_TABLE(sys_swapon, sys_swapon, 87, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_reboot ++TRACE_SYSCALL_TABLE(sys_reboot, sys_reboot, 88, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_old_readdir ++TRACE_SYSCALL_TABLE(sys_old_readdir, sys_old_readdir, 89, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_old_mmap ++TRACE_SYSCALL_TABLE(sys_old_mmap, sys_old_mmap, 90, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_truncate ++TRACE_SYSCALL_TABLE(sys_truncate, sys_truncate, 92, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_statfs ++TRACE_SYSCALL_TABLE(sys_statfs, sys_statfs, 99, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fstatfs ++TRACE_SYSCALL_TABLE(sys_fstatfs, sys_fstatfs, 100, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_socketcall ++TRACE_SYSCALL_TABLE(sys_socketcall, sys_socketcall, 102, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_syslog ++TRACE_SYSCALL_TABLE(sys_syslog, sys_syslog, 103, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setitimer ++TRACE_SYSCALL_TABLE(sys_setitimer, sys_setitimer, 104, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getitimer ++TRACE_SYSCALL_TABLE(sys_getitimer, sys_getitimer, 105, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_newstat ++TRACE_SYSCALL_TABLE(sys_newstat, sys_newstat, 106, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_newlstat ++TRACE_SYSCALL_TABLE(sys_newlstat, sys_newlstat, 107, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_newfstat ++TRACE_SYSCALL_TABLE(sys_newfstat, sys_newfstat, 108, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_uname ++TRACE_SYSCALL_TABLE(sys_uname, sys_uname, 109, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_wait4 ++TRACE_SYSCALL_TABLE(sys_wait4, sys_wait4, 114, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_swapoff ++TRACE_SYSCALL_TABLE(sys_swapoff, sys_swapoff, 115, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sysinfo ++TRACE_SYSCALL_TABLE(sys_sysinfo, sys_sysinfo, 116, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ipc ++TRACE_SYSCALL_TABLE(sys_ipc, sys_ipc, 117, 6) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setdomainname ++TRACE_SYSCALL_TABLE(sys_setdomainname, sys_setdomainname, 121, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_newuname ++TRACE_SYSCALL_TABLE(sys_newuname, sys_newuname, 122, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_adjtimex ++TRACE_SYSCALL_TABLE(sys_adjtimex, sys_adjtimex, 124, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sigprocmask ++TRACE_SYSCALL_TABLE(sys_sigprocmask, sys_sigprocmask, 126, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_init_module ++TRACE_SYSCALL_TABLE(sys_init_module, sys_init_module, 128, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_delete_module ++TRACE_SYSCALL_TABLE(sys_delete_module, sys_delete_module, 129, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_quotactl ++TRACE_SYSCALL_TABLE(sys_quotactl, sys_quotactl, 131, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_llseek ++TRACE_SYSCALL_TABLE(sys_llseek, sys_llseek, 140, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getdents ++TRACE_SYSCALL_TABLE(sys_getdents, sys_getdents, 141, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_select ++TRACE_SYSCALL_TABLE(sys_select, sys_select, 142, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_readv ++TRACE_SYSCALL_TABLE(sys_readv, sys_readv, 145, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_writev ++TRACE_SYSCALL_TABLE(sys_writev, sys_writev, 146, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sysctl ++TRACE_SYSCALL_TABLE(sys_sysctl, sys_sysctl, 149, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_setparam ++TRACE_SYSCALL_TABLE(sys_sched_setparam, sys_sched_setparam, 154, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_getparam ++TRACE_SYSCALL_TABLE(sys_sched_getparam, sys_sched_getparam, 155, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_setscheduler ++TRACE_SYSCALL_TABLE(sys_sched_setscheduler, sys_sched_setscheduler, 156, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_rr_get_interval ++TRACE_SYSCALL_TABLE(sys_sched_rr_get_interval, sys_sched_rr_get_interval, 161, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_nanosleep ++TRACE_SYSCALL_TABLE(sys_nanosleep, sys_nanosleep, 162, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getresuid16 ++TRACE_SYSCALL_TABLE(sys_getresuid16, sys_getresuid16, 165, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_poll ++TRACE_SYSCALL_TABLE(sys_poll, sys_poll, 168, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getresgid16 ++TRACE_SYSCALL_TABLE(sys_getresgid16, sys_getresgid16, 171, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rt_sigaction ++TRACE_SYSCALL_TABLE(sys_rt_sigaction, sys_rt_sigaction, 174, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rt_sigprocmask ++TRACE_SYSCALL_TABLE(sys_rt_sigprocmask, sys_rt_sigprocmask, 175, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rt_sigpending ++TRACE_SYSCALL_TABLE(sys_rt_sigpending, sys_rt_sigpending, 176, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rt_sigtimedwait ++TRACE_SYSCALL_TABLE(sys_rt_sigtimedwait, sys_rt_sigtimedwait, 177, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rt_sigqueueinfo ++TRACE_SYSCALL_TABLE(sys_rt_sigqueueinfo, sys_rt_sigqueueinfo, 178, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rt_sigsuspend ++TRACE_SYSCALL_TABLE(sys_rt_sigsuspend, sys_rt_sigsuspend, 179, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_chown16 ++TRACE_SYSCALL_TABLE(sys_chown16, sys_chown16, 182, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getcwd ++TRACE_SYSCALL_TABLE(sys_getcwd, sys_getcwd, 183, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sendfile ++TRACE_SYSCALL_TABLE(sys_sendfile, sys_sendfile, 187, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getrlimit ++TRACE_SYSCALL_TABLE(sys_getrlimit, sys_getrlimit, 191, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_stat64 ++TRACE_SYSCALL_TABLE(sys_stat64, sys_stat64, 195, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lstat64 ++TRACE_SYSCALL_TABLE(sys_lstat64, sys_lstat64, 196, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fstat64 ++TRACE_SYSCALL_TABLE(sys_fstat64, sys_fstat64, 197, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lchown ++TRACE_SYSCALL_TABLE(sys_lchown, sys_lchown, 198, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getgroups ++TRACE_SYSCALL_TABLE(sys_getgroups, sys_getgroups, 205, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setgroups ++TRACE_SYSCALL_TABLE(sys_setgroups, sys_setgroups, 206, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getresuid ++TRACE_SYSCALL_TABLE(sys_getresuid, sys_getresuid, 209, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getresgid ++TRACE_SYSCALL_TABLE(sys_getresgid, sys_getresgid, 211, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_chown ++TRACE_SYSCALL_TABLE(sys_chown, sys_chown, 212, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_pivot_root ++TRACE_SYSCALL_TABLE(sys_pivot_root, sys_pivot_root, 217, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mincore ++TRACE_SYSCALL_TABLE(sys_mincore, sys_mincore, 218, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getdents64 ++TRACE_SYSCALL_TABLE(sys_getdents64, sys_getdents64, 220, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_setxattr ++TRACE_SYSCALL_TABLE(sys_setxattr, sys_setxattr, 226, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lsetxattr ++TRACE_SYSCALL_TABLE(sys_lsetxattr, sys_lsetxattr, 227, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fsetxattr ++TRACE_SYSCALL_TABLE(sys_fsetxattr, sys_fsetxattr, 228, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getxattr ++TRACE_SYSCALL_TABLE(sys_getxattr, sys_getxattr, 229, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lgetxattr ++TRACE_SYSCALL_TABLE(sys_lgetxattr, sys_lgetxattr, 230, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fgetxattr ++TRACE_SYSCALL_TABLE(sys_fgetxattr, sys_fgetxattr, 231, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_listxattr ++TRACE_SYSCALL_TABLE(sys_listxattr, sys_listxattr, 232, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_llistxattr ++TRACE_SYSCALL_TABLE(sys_llistxattr, sys_llistxattr, 233, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_flistxattr ++TRACE_SYSCALL_TABLE(sys_flistxattr, sys_flistxattr, 234, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_removexattr ++TRACE_SYSCALL_TABLE(sys_removexattr, sys_removexattr, 235, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_lremovexattr ++TRACE_SYSCALL_TABLE(sys_lremovexattr, sys_lremovexattr, 236, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fremovexattr ++TRACE_SYSCALL_TABLE(sys_fremovexattr, sys_fremovexattr, 237, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sendfile64 ++TRACE_SYSCALL_TABLE(sys_sendfile64, sys_sendfile64, 239, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_futex ++TRACE_SYSCALL_TABLE(sys_futex, sys_futex, 240, 6) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_setaffinity ++TRACE_SYSCALL_TABLE(sys_sched_setaffinity, sys_sched_setaffinity, 241, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sched_getaffinity ++TRACE_SYSCALL_TABLE(sys_sched_getaffinity, sys_sched_getaffinity, 242, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_io_setup ++TRACE_SYSCALL_TABLE(sys_io_setup, sys_io_setup, 245, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_io_getevents ++TRACE_SYSCALL_TABLE(sys_io_getevents, sys_io_getevents, 247, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_io_submit ++TRACE_SYSCALL_TABLE(sys_io_submit, sys_io_submit, 248, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_io_cancel ++TRACE_SYSCALL_TABLE(sys_io_cancel, sys_io_cancel, 249, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_epoll_ctl ++TRACE_SYSCALL_TABLE(sys_epoll_ctl, sys_epoll_ctl, 255, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_epoll_wait ++TRACE_SYSCALL_TABLE(sys_epoll_wait, sys_epoll_wait, 256, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_set_tid_address ++TRACE_SYSCALL_TABLE(sys_set_tid_address, sys_set_tid_address, 258, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timer_create ++TRACE_SYSCALL_TABLE(sys_timer_create, sys_timer_create, 259, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timer_settime ++TRACE_SYSCALL_TABLE(sys_timer_settime, sys_timer_settime, 260, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timer_gettime ++TRACE_SYSCALL_TABLE(sys_timer_gettime, sys_timer_gettime, 261, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_clock_settime ++TRACE_SYSCALL_TABLE(sys_clock_settime, sys_clock_settime, 264, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_clock_gettime ++TRACE_SYSCALL_TABLE(sys_clock_gettime, sys_clock_gettime, 265, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_clock_getres ++TRACE_SYSCALL_TABLE(sys_clock_getres, sys_clock_getres, 266, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_clock_nanosleep ++TRACE_SYSCALL_TABLE(sys_clock_nanosleep, sys_clock_nanosleep, 267, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_statfs64 ++TRACE_SYSCALL_TABLE(sys_statfs64, sys_statfs64, 268, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fstatfs64 ++TRACE_SYSCALL_TABLE(sys_fstatfs64, sys_fstatfs64, 269, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_utimes ++TRACE_SYSCALL_TABLE(sys_utimes, sys_utimes, 271, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mq_open ++TRACE_SYSCALL_TABLE(sys_mq_open, sys_mq_open, 277, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mq_unlink ++TRACE_SYSCALL_TABLE(sys_mq_unlink, sys_mq_unlink, 278, 1) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mq_timedsend ++TRACE_SYSCALL_TABLE(sys_mq_timedsend, sys_mq_timedsend, 279, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mq_timedreceive ++TRACE_SYSCALL_TABLE(sys_mq_timedreceive, sys_mq_timedreceive, 280, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mq_notify ++TRACE_SYSCALL_TABLE(sys_mq_notify, sys_mq_notify, 281, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mq_getsetattr ++TRACE_SYSCALL_TABLE(sys_mq_getsetattr, sys_mq_getsetattr, 282, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_kexec_load ++TRACE_SYSCALL_TABLE(sys_kexec_load, sys_kexec_load, 283, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_waitid ++TRACE_SYSCALL_TABLE(sys_waitid, sys_waitid, 284, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_add_key ++TRACE_SYSCALL_TABLE(sys_add_key, sys_add_key, 286, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_request_key ++TRACE_SYSCALL_TABLE(sys_request_key, sys_request_key, 287, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_inotify_add_watch ++TRACE_SYSCALL_TABLE(sys_inotify_add_watch, sys_inotify_add_watch, 292, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_openat ++TRACE_SYSCALL_TABLE(sys_openat, sys_openat, 295, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mkdirat ++TRACE_SYSCALL_TABLE(sys_mkdirat, sys_mkdirat, 296, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_mknodat ++TRACE_SYSCALL_TABLE(sys_mknodat, sys_mknodat, 297, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fchownat ++TRACE_SYSCALL_TABLE(sys_fchownat, sys_fchownat, 298, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_futimesat ++TRACE_SYSCALL_TABLE(sys_futimesat, sys_futimesat, 299, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fstatat64 ++TRACE_SYSCALL_TABLE(sys_fstatat64, sys_fstatat64, 300, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_unlinkat ++TRACE_SYSCALL_TABLE(sys_unlinkat, sys_unlinkat, 301, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_renameat ++TRACE_SYSCALL_TABLE(sys_renameat, sys_renameat, 302, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_linkat ++TRACE_SYSCALL_TABLE(sys_linkat, sys_linkat, 303, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_symlinkat ++TRACE_SYSCALL_TABLE(sys_symlinkat, sys_symlinkat, 304, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_readlinkat ++TRACE_SYSCALL_TABLE(sys_readlinkat, sys_readlinkat, 305, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_fchmodat ++TRACE_SYSCALL_TABLE(sys_fchmodat, sys_fchmodat, 306, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_faccessat ++TRACE_SYSCALL_TABLE(sys_faccessat, sys_faccessat, 307, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_pselect6 ++TRACE_SYSCALL_TABLE(sys_pselect6, sys_pselect6, 308, 6) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_ppoll ++TRACE_SYSCALL_TABLE(sys_ppoll, sys_ppoll, 309, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_set_robust_list ++TRACE_SYSCALL_TABLE(sys_set_robust_list, sys_set_robust_list, 311, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_get_robust_list ++TRACE_SYSCALL_TABLE(sys_get_robust_list, sys_get_robust_list, 312, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_splice ++TRACE_SYSCALL_TABLE(sys_splice, sys_splice, 313, 6) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_vmsplice ++TRACE_SYSCALL_TABLE(sys_vmsplice, sys_vmsplice, 316, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_getcpu ++TRACE_SYSCALL_TABLE(sys_getcpu, sys_getcpu, 318, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_epoll_pwait ++TRACE_SYSCALL_TABLE(sys_epoll_pwait, sys_epoll_pwait, 319, 6) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_utimensat ++TRACE_SYSCALL_TABLE(sys_utimensat, sys_utimensat, 320, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_signalfd ++TRACE_SYSCALL_TABLE(sys_signalfd, sys_signalfd, 321, 3) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timerfd_settime ++TRACE_SYSCALL_TABLE(sys_timerfd_settime, sys_timerfd_settime, 325, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_timerfd_gettime ++TRACE_SYSCALL_TABLE(sys_timerfd_gettime, sys_timerfd_gettime, 326, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_signalfd4 ++TRACE_SYSCALL_TABLE(sys_signalfd4, sys_signalfd4, 327, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_pipe2 ++TRACE_SYSCALL_TABLE(sys_pipe2, sys_pipe2, 331, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_preadv ++TRACE_SYSCALL_TABLE(sys_preadv, sys_preadv, 333, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_pwritev ++TRACE_SYSCALL_TABLE(sys_pwritev, sys_pwritev, 334, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_rt_tgsigqueueinfo ++TRACE_SYSCALL_TABLE(sys_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo, 335, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_perf_event_open ++TRACE_SYSCALL_TABLE(sys_perf_event_open, sys_perf_event_open, 336, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_recvmmsg ++TRACE_SYSCALL_TABLE(sys_recvmmsg, sys_recvmmsg, 337, 5) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_prlimit64 ++TRACE_SYSCALL_TABLE(sys_prlimit64, sys_prlimit64, 340, 4) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_clock_adjtime ++TRACE_SYSCALL_TABLE(sys_clock_adjtime, sys_clock_adjtime, 343, 2) ++#endif ++#ifndef OVERRIDE_TABLE_32_sys_sendmmsg ++TRACE_SYSCALL_TABLE(sys_sendmmsg, sys_sendmmsg, 345, 4) ++#endif ++ ++#endif /* CREATE_SYSCALL_TABLE */ +diff --git 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 +new file mode 100644 +index 0000000..d35657c +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-32-syscalls-3.1.0-rc6_pointers_override.h +@@ -0,0 +1,17 @@ ++#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 ++ ++#endif +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers.h +new file mode 100644 +index 0000000..6d0dbb9 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers.h +@@ -0,0 +1,1013 @@ ++/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT */ ++#ifndef CREATE_SYSCALL_TABLE ++ ++#if !defined(_TRACE_SYSCALLS_INTEGERS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SYSCALLS_INTEGERS_H ++ ++#include <linux/tracepoint.h> ++#include <linux/syscalls.h> ++#include "x86-64-syscalls-3.0.4_integers_override.h" ++#include "syscalls_integers_override.h" ++ ++SC_DECLARE_EVENT_CLASS_NOARGS(syscalls_noargs, ++ TP_STRUCT__entry(), ++ TP_fast_assign(), ++ TP_printk() ++) ++#ifndef OVERRIDE_64_sys_sched_yield ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_sched_yield) ++#endif ++#ifndef OVERRIDE_64_sys_pause ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_pause) ++#endif ++#ifndef OVERRIDE_64_sys_getpid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getpid) ++#endif ++#ifndef OVERRIDE_64_sys_getuid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getuid) ++#endif ++#ifndef OVERRIDE_64_sys_getgid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getgid) ++#endif ++#ifndef OVERRIDE_64_sys_geteuid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_geteuid) ++#endif ++#ifndef OVERRIDE_64_sys_getegid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getegid) ++#endif ++#ifndef OVERRIDE_64_sys_getppid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getppid) ++#endif ++#ifndef OVERRIDE_64_sys_getpgrp ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_getpgrp) ++#endif ++#ifndef OVERRIDE_64_sys_setsid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_setsid) ++#endif ++#ifndef OVERRIDE_64_sys_munlockall ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_munlockall) ++#endif ++#ifndef OVERRIDE_64_sys_vhangup ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_vhangup) ++#endif ++#ifndef OVERRIDE_64_sys_sync ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_sync) ++#endif ++#ifndef OVERRIDE_64_sys_gettid ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_gettid) ++#endif ++#ifndef OVERRIDE_64_sys_restart_syscall ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_restart_syscall) ++#endif ++#ifndef OVERRIDE_64_sys_inotify_init ++SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_inotify_init) ++#endif ++#ifndef OVERRIDE_64_sys_close ++SC_TRACE_EVENT(sys_close, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_brk ++SC_TRACE_EVENT(sys_brk, ++ TP_PROTO(unsigned long brk), ++ TP_ARGS(brk), ++ TP_STRUCT__entry(__field(unsigned long, brk)), ++ TP_fast_assign(tp_assign(brk, brk)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_dup ++SC_TRACE_EVENT(sys_dup, ++ TP_PROTO(unsigned int fildes), ++ TP_ARGS(fildes), ++ TP_STRUCT__entry(__field(unsigned int, fildes)), ++ TP_fast_assign(tp_assign(fildes, fildes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_alarm ++SC_TRACE_EVENT(sys_alarm, ++ TP_PROTO(unsigned int seconds), ++ TP_ARGS(seconds), ++ TP_STRUCT__entry(__field(unsigned int, seconds)), ++ TP_fast_assign(tp_assign(seconds, seconds)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_exit ++SC_TRACE_EVENT(sys_exit, ++ TP_PROTO(int error_code), ++ TP_ARGS(error_code), ++ TP_STRUCT__entry(__field(int, error_code)), ++ TP_fast_assign(tp_assign(error_code, error_code)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fsync ++SC_TRACE_EVENT(sys_fsync, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fdatasync ++SC_TRACE_EVENT(sys_fdatasync, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fchdir ++SC_TRACE_EVENT(sys_fchdir, ++ TP_PROTO(unsigned int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(unsigned int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_umask ++SC_TRACE_EVENT(sys_umask, ++ TP_PROTO(int mask), ++ TP_ARGS(mask), ++ TP_STRUCT__entry(__field(int, mask)), ++ TP_fast_assign(tp_assign(mask, mask)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setuid ++SC_TRACE_EVENT(sys_setuid, ++ TP_PROTO(uid_t uid), ++ TP_ARGS(uid), ++ TP_STRUCT__entry(__field(uid_t, uid)), ++ TP_fast_assign(tp_assign(uid, uid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setgid ++SC_TRACE_EVENT(sys_setgid, ++ TP_PROTO(gid_t gid), ++ TP_ARGS(gid), ++ TP_STRUCT__entry(__field(gid_t, gid)), ++ TP_fast_assign(tp_assign(gid, gid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getpgid ++SC_TRACE_EVENT(sys_getpgid, ++ TP_PROTO(pid_t pid), ++ TP_ARGS(pid), ++ TP_STRUCT__entry(__field(pid_t, pid)), ++ TP_fast_assign(tp_assign(pid, pid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setfsuid ++SC_TRACE_EVENT(sys_setfsuid, ++ TP_PROTO(uid_t uid), ++ TP_ARGS(uid), ++ TP_STRUCT__entry(__field(uid_t, uid)), ++ TP_fast_assign(tp_assign(uid, uid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setfsgid ++SC_TRACE_EVENT(sys_setfsgid, ++ TP_PROTO(gid_t gid), ++ TP_ARGS(gid), ++ TP_STRUCT__entry(__field(gid_t, gid)), ++ TP_fast_assign(tp_assign(gid, gid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getsid ++SC_TRACE_EVENT(sys_getsid, ++ TP_PROTO(pid_t pid), ++ TP_ARGS(pid), ++ TP_STRUCT__entry(__field(pid_t, pid)), ++ TP_fast_assign(tp_assign(pid, pid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_personality ++SC_TRACE_EVENT(sys_personality, ++ TP_PROTO(unsigned int personality), ++ TP_ARGS(personality), ++ TP_STRUCT__entry(__field(unsigned int, personality)), ++ TP_fast_assign(tp_assign(personality, personality)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_getscheduler ++SC_TRACE_EVENT(sys_sched_getscheduler, ++ TP_PROTO(pid_t pid), ++ TP_ARGS(pid), ++ TP_STRUCT__entry(__field(pid_t, pid)), ++ TP_fast_assign(tp_assign(pid, pid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_get_priority_max ++SC_TRACE_EVENT(sys_sched_get_priority_max, ++ TP_PROTO(int policy), ++ TP_ARGS(policy), ++ TP_STRUCT__entry(__field(int, policy)), ++ TP_fast_assign(tp_assign(policy, policy)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_get_priority_min ++SC_TRACE_EVENT(sys_sched_get_priority_min, ++ TP_PROTO(int policy), ++ TP_ARGS(policy), ++ TP_STRUCT__entry(__field(int, policy)), ++ TP_fast_assign(tp_assign(policy, policy)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mlockall ++SC_TRACE_EVENT(sys_mlockall, ++ TP_PROTO(int flags), ++ TP_ARGS(flags), ++ TP_STRUCT__entry(__field(int, flags)), ++ TP_fast_assign(tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_io_destroy ++SC_TRACE_EVENT(sys_io_destroy, ++ TP_PROTO(aio_context_t ctx), ++ TP_ARGS(ctx), ++ TP_STRUCT__entry(__field(aio_context_t, ctx)), ++ TP_fast_assign(tp_assign(ctx, ctx)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_epoll_create ++SC_TRACE_EVENT(sys_epoll_create, ++ TP_PROTO(int size), ++ TP_ARGS(size), ++ TP_STRUCT__entry(__field(int, size)), ++ TP_fast_assign(tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timer_getoverrun ++SC_TRACE_EVENT(sys_timer_getoverrun, ++ TP_PROTO(timer_t timer_id), ++ TP_ARGS(timer_id), ++ TP_STRUCT__entry(__field(timer_t, timer_id)), ++ TP_fast_assign(tp_assign(timer_id, timer_id)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timer_delete ++SC_TRACE_EVENT(sys_timer_delete, ++ TP_PROTO(timer_t timer_id), ++ TP_ARGS(timer_id), ++ TP_STRUCT__entry(__field(timer_t, timer_id)), ++ TP_fast_assign(tp_assign(timer_id, timer_id)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_exit_group ++SC_TRACE_EVENT(sys_exit_group, ++ TP_PROTO(int error_code), ++ TP_ARGS(error_code), ++ TP_STRUCT__entry(__field(int, error_code)), ++ TP_fast_assign(tp_assign(error_code, error_code)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_unshare ++SC_TRACE_EVENT(sys_unshare, ++ TP_PROTO(unsigned long unshare_flags), ++ TP_ARGS(unshare_flags), ++ TP_STRUCT__entry(__field(unsigned long, unshare_flags)), ++ TP_fast_assign(tp_assign(unshare_flags, unshare_flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_eventfd ++SC_TRACE_EVENT(sys_eventfd, ++ TP_PROTO(unsigned int count), ++ TP_ARGS(count), ++ TP_STRUCT__entry(__field(unsigned int, count)), ++ TP_fast_assign(tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_epoll_create1 ++SC_TRACE_EVENT(sys_epoll_create1, ++ TP_PROTO(int flags), ++ TP_ARGS(flags), ++ TP_STRUCT__entry(__field(int, flags)), ++ TP_fast_assign(tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_inotify_init1 ++SC_TRACE_EVENT(sys_inotify_init1, ++ TP_PROTO(int flags), ++ TP_ARGS(flags), ++ TP_STRUCT__entry(__field(int, flags)), ++ TP_fast_assign(tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_syncfs ++SC_TRACE_EVENT(sys_syncfs, ++ TP_PROTO(int fd), ++ TP_ARGS(fd), ++ TP_STRUCT__entry(__field(int, fd)), ++ TP_fast_assign(tp_assign(fd, fd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_munmap ++SC_TRACE_EVENT(sys_munmap, ++ TP_PROTO(unsigned long addr, size_t len), ++ TP_ARGS(addr, len), ++ TP_STRUCT__entry(__field_hex(unsigned long, addr) __field(size_t, len)), ++ TP_fast_assign(tp_assign(addr, addr) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_dup2 ++SC_TRACE_EVENT(sys_dup2, ++ TP_PROTO(unsigned int oldfd, unsigned int newfd), ++ TP_ARGS(oldfd, newfd), ++ TP_STRUCT__entry(__field(unsigned int, oldfd) __field(unsigned int, newfd)), ++ TP_fast_assign(tp_assign(oldfd, oldfd) tp_assign(newfd, newfd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_shutdown ++SC_TRACE_EVENT(sys_shutdown, ++ TP_PROTO(int fd, int how), ++ TP_ARGS(fd, how), ++ TP_STRUCT__entry(__field(int, fd) __field(int, how)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(how, how)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_listen ++SC_TRACE_EVENT(sys_listen, ++ TP_PROTO(int fd, int backlog), ++ TP_ARGS(fd, backlog), ++ TP_STRUCT__entry(__field(int, fd) __field(int, backlog)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(backlog, backlog)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_kill ++SC_TRACE_EVENT(sys_kill, ++ TP_PROTO(pid_t pid, int sig), ++ TP_ARGS(pid, sig), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, sig)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_msgget ++SC_TRACE_EVENT(sys_msgget, ++ TP_PROTO(key_t key, int msgflg), ++ TP_ARGS(key, msgflg), ++ TP_STRUCT__entry(__field(key_t, key) __field(int, msgflg)), ++ TP_fast_assign(tp_assign(key, key) tp_assign(msgflg, msgflg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_flock ++SC_TRACE_EVENT(sys_flock, ++ TP_PROTO(unsigned int fd, unsigned int cmd), ++ TP_ARGS(fd, cmd), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned int, cmd)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(cmd, cmd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_ftruncate ++SC_TRACE_EVENT(sys_ftruncate, ++ TP_PROTO(unsigned int fd, unsigned long length), ++ TP_ARGS(fd, length), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned long, length)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(length, length)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fchmod ++SC_TRACE_EVENT(sys_fchmod, ++ TP_PROTO(unsigned int fd, mode_t mode), ++ TP_ARGS(fd, mode), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(mode_t, mode)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setpgid ++SC_TRACE_EVENT(sys_setpgid, ++ TP_PROTO(pid_t pid, pid_t pgid), ++ TP_ARGS(pid, pgid), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(pid_t, pgid)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(pgid, pgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setreuid ++SC_TRACE_EVENT(sys_setreuid, ++ TP_PROTO(uid_t ruid, uid_t euid), ++ TP_ARGS(ruid, euid), ++ TP_STRUCT__entry(__field(uid_t, ruid) __field(uid_t, euid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setregid ++SC_TRACE_EVENT(sys_setregid, ++ TP_PROTO(gid_t rgid, gid_t egid), ++ TP_ARGS(rgid, egid), ++ TP_STRUCT__entry(__field(gid_t, rgid) __field(gid_t, egid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getpriority ++SC_TRACE_EVENT(sys_getpriority, ++ TP_PROTO(int which, int who), ++ TP_ARGS(which, who), ++ TP_STRUCT__entry(__field(int, which) __field(int, who)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mlock ++SC_TRACE_EVENT(sys_mlock, ++ TP_PROTO(unsigned long start, size_t len), ++ TP_ARGS(start, len), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_munlock ++SC_TRACE_EVENT(sys_munlock, ++ TP_PROTO(unsigned long start, size_t len), ++ TP_ARGS(start, len), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_tkill ++SC_TRACE_EVENT(sys_tkill, ++ TP_PROTO(pid_t pid, int sig), ++ TP_ARGS(pid, sig), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, sig)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_ioprio_get ++SC_TRACE_EVENT(sys_ioprio_get, ++ TP_PROTO(int which, int who), ++ TP_ARGS(which, who), ++ TP_STRUCT__entry(__field(int, which) __field(int, who)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_inotify_rm_watch ++SC_TRACE_EVENT(sys_inotify_rm_watch, ++ TP_PROTO(int fd, __s32 wd), ++ TP_ARGS(fd, wd), ++ TP_STRUCT__entry(__field(int, fd) __field(__s32, wd)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(wd, wd)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timerfd_create ++SC_TRACE_EVENT(sys_timerfd_create, ++ TP_PROTO(int clockid, int flags), ++ TP_ARGS(clockid, flags), ++ TP_STRUCT__entry(__field(int, clockid) __field(int, flags)), ++ TP_fast_assign(tp_assign(clockid, clockid) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_eventfd2 ++SC_TRACE_EVENT(sys_eventfd2, ++ TP_PROTO(unsigned int count, int flags), ++ TP_ARGS(count, flags), ++ TP_STRUCT__entry(__field(unsigned int, count) __field(int, flags)), ++ TP_fast_assign(tp_assign(count, count) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setns ++SC_TRACE_EVENT(sys_setns, ++ TP_PROTO(int fd, int nstype), ++ TP_ARGS(fd, nstype), ++ TP_STRUCT__entry(__field(int, fd) __field(int, nstype)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(nstype, nstype)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_lseek ++SC_TRACE_EVENT(sys_lseek, ++ TP_PROTO(unsigned int fd, off_t offset, unsigned int origin), ++ TP_ARGS(fd, offset, origin), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(off_t, offset) __field(unsigned int, origin)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(offset, offset) tp_assign(origin, origin)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mprotect ++SC_TRACE_EVENT(sys_mprotect, ++ TP_PROTO(unsigned long start, size_t len, unsigned long prot), ++ TP_ARGS(start, len, prot), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len) __field(unsigned long, prot)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len) tp_assign(prot, prot)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_ioctl ++SC_TRACE_EVENT(sys_ioctl, ++ TP_PROTO(unsigned int fd, unsigned int cmd, unsigned long arg), ++ TP_ARGS(fd, cmd, arg), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned int, cmd) __field(unsigned long, arg)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(cmd, cmd) tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_msync ++SC_TRACE_EVENT(sys_msync, ++ TP_PROTO(unsigned long start, size_t len, int flags), ++ TP_ARGS(start, len, flags), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len) __field(int, flags)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_madvise ++SC_TRACE_EVENT(sys_madvise, ++ TP_PROTO(unsigned long start, size_t len_in, int behavior), ++ TP_ARGS(start, len_in, behavior), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len_in) __field(int, behavior)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len_in, len_in) tp_assign(behavior, behavior)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_shmget ++SC_TRACE_EVENT(sys_shmget, ++ TP_PROTO(key_t key, size_t size, int shmflg), ++ TP_ARGS(key, size, shmflg), ++ TP_STRUCT__entry(__field(key_t, key) __field(size_t, size) __field(int, shmflg)), ++ TP_fast_assign(tp_assign(key, key) tp_assign(size, size) tp_assign(shmflg, shmflg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_socket ++SC_TRACE_EVENT(sys_socket, ++ TP_PROTO(int family, int type, int protocol), ++ TP_ARGS(family, type, protocol), ++ TP_STRUCT__entry(__field(int, family) __field(int, type) __field(int, protocol)), ++ TP_fast_assign(tp_assign(family, family) tp_assign(type, type) tp_assign(protocol, protocol)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_semget ++SC_TRACE_EVENT(sys_semget, ++ TP_PROTO(key_t key, int nsems, int semflg), ++ TP_ARGS(key, nsems, semflg), ++ TP_STRUCT__entry(__field(key_t, key) __field(int, nsems) __field(int, semflg)), ++ TP_fast_assign(tp_assign(key, key) tp_assign(nsems, nsems) tp_assign(semflg, semflg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fcntl ++SC_TRACE_EVENT(sys_fcntl, ++ TP_PROTO(unsigned int fd, unsigned int cmd, unsigned long arg), ++ TP_ARGS(fd, cmd, arg), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(unsigned int, cmd) __field(unsigned long, arg)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(cmd, cmd) tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fchown ++SC_TRACE_EVENT(sys_fchown, ++ TP_PROTO(unsigned int fd, uid_t user, gid_t group), ++ TP_ARGS(fd, user, group), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field(uid_t, user) __field(gid_t, group)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setresuid ++SC_TRACE_EVENT(sys_setresuid, ++ TP_PROTO(uid_t ruid, uid_t euid, uid_t suid), ++ TP_ARGS(ruid, euid, suid), ++ TP_STRUCT__entry(__field(uid_t, ruid) __field(uid_t, euid) __field(uid_t, suid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid) tp_assign(suid, suid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setresgid ++SC_TRACE_EVENT(sys_setresgid, ++ TP_PROTO(gid_t rgid, gid_t egid, gid_t sgid), ++ TP_ARGS(rgid, egid, sgid), ++ TP_STRUCT__entry(__field(gid_t, rgid) __field(gid_t, egid) __field(gid_t, sgid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid) tp_assign(sgid, sgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sysfs ++SC_TRACE_EVENT(sys_sysfs, ++ TP_PROTO(int option, unsigned long arg1, unsigned long arg2), ++ TP_ARGS(option, arg1, arg2), ++ TP_STRUCT__entry(__field(int, option) __field(unsigned long, arg1) __field(unsigned long, arg2)), ++ TP_fast_assign(tp_assign(option, option) tp_assign(arg1, arg1) tp_assign(arg2, arg2)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setpriority ++SC_TRACE_EVENT(sys_setpriority, ++ TP_PROTO(int which, int who, int niceval), ++ TP_ARGS(which, who, niceval), ++ TP_STRUCT__entry(__field(int, which) __field(int, who) __field(int, niceval)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who) tp_assign(niceval, niceval)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_tgkill ++SC_TRACE_EVENT(sys_tgkill, ++ TP_PROTO(pid_t tgid, pid_t pid, int sig), ++ TP_ARGS(tgid, pid, sig), ++ TP_STRUCT__entry(__field(pid_t, tgid) __field(pid_t, pid) __field(int, sig)), ++ TP_fast_assign(tp_assign(tgid, tgid) tp_assign(pid, pid) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_ioprio_set ++SC_TRACE_EVENT(sys_ioprio_set, ++ TP_PROTO(int which, int who, int ioprio), ++ TP_ARGS(which, who, ioprio), ++ TP_STRUCT__entry(__field(int, which) __field(int, who) __field(int, ioprio)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(who, who) tp_assign(ioprio, ioprio)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_dup3 ++SC_TRACE_EVENT(sys_dup3, ++ TP_PROTO(unsigned int oldfd, unsigned int newfd, int flags), ++ TP_ARGS(oldfd, newfd, flags), ++ TP_STRUCT__entry(__field(unsigned int, oldfd) __field(unsigned int, newfd) __field(int, flags)), ++ TP_fast_assign(tp_assign(oldfd, oldfd) tp_assign(newfd, newfd) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_ptrace ++SC_TRACE_EVENT(sys_ptrace, ++ TP_PROTO(long request, long pid, unsigned long addr, unsigned long data), ++ TP_ARGS(request, pid, addr, data), ++ TP_STRUCT__entry(__field(long, request) __field(long, pid) __field_hex(unsigned long, addr) __field(unsigned long, data)), ++ TP_fast_assign(tp_assign(request, request) tp_assign(pid, pid) tp_assign(addr, addr) tp_assign(data, data)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_tee ++SC_TRACE_EVENT(sys_tee, ++ TP_PROTO(int fdin, int fdout, size_t len, unsigned int flags), ++ TP_ARGS(fdin, fdout, len, flags), ++ TP_STRUCT__entry(__field(int, fdin) __field(int, fdout) __field(size_t, len) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fdin, fdin) tp_assign(fdout, fdout) tp_assign(len, len) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mremap ++SC_TRACE_EVENT(sys_mremap, ++ TP_PROTO(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr), ++ TP_ARGS(addr, old_len, new_len, flags, new_addr), ++ TP_STRUCT__entry(__field_hex(unsigned long, addr) __field(unsigned long, old_len) __field(unsigned long, new_len) __field(unsigned long, flags) __field_hex(unsigned long, new_addr)), ++ TP_fast_assign(tp_assign(addr, addr) tp_assign(old_len, old_len) tp_assign(new_len, new_len) tp_assign(flags, flags) tp_assign(new_addr, new_addr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_prctl ++SC_TRACE_EVENT(sys_prctl, ++ TP_PROTO(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5), ++ TP_ARGS(option, arg2, arg3, arg4, arg5), ++ TP_STRUCT__entry(__field(int, option) __field(unsigned long, arg2) __field(unsigned long, arg3) __field(unsigned long, arg4) __field(unsigned long, arg5)), ++ TP_fast_assign(tp_assign(option, option) tp_assign(arg2, arg2) tp_assign(arg3, arg3) tp_assign(arg4, arg4) tp_assign(arg5, arg5)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_remap_file_pages ++SC_TRACE_EVENT(sys_remap_file_pages, ++ TP_PROTO(unsigned long start, unsigned long size, unsigned long prot, unsigned long pgoff, unsigned long flags), ++ TP_ARGS(start, size, prot, pgoff, flags), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(unsigned long, size) __field(unsigned long, prot) __field(unsigned long, pgoff) __field(unsigned long, flags)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(size, size) tp_assign(prot, prot) tp_assign(pgoff, pgoff) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mmap ++SC_TRACE_EVENT(sys_mmap, ++ TP_PROTO(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long off), ++ TP_ARGS(addr, len, prot, flags, fd, off), ++ TP_STRUCT__entry(__field_hex(unsigned long, addr) __field(unsigned long, len) __field(unsigned long, prot) __field(unsigned long, flags) __field(unsigned long, fd) __field(unsigned long, off)), ++ TP_fast_assign(tp_assign(addr, addr) tp_assign(len, len) tp_assign(prot, prot) tp_assign(flags, flags) tp_assign(fd, fd) tp_assign(off, off)), ++ TP_printk() ++) ++#endif ++ ++#endif /* _TRACE_SYSCALLS_INTEGERS_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" ++ ++#else /* CREATE_SYSCALL_TABLE */ ++ ++#include "x86-64-syscalls-3.0.4_integers_override.h" ++#include "syscalls_integers_override.h" ++ ++#ifndef OVERRIDE_TABLE_64_sys_sched_yield ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_sched_yield, 24, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_pause ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_pause, 34, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getpid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getpid, 39, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getuid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getuid, 102, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getgid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getgid, 104, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_geteuid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_geteuid, 107, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getegid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getegid, 108, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getppid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getppid, 110, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getpgrp ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_getpgrp, 111, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setsid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_setsid, 112, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_munlockall ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_munlockall, 152, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_vhangup ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_vhangup, 153, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sync ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_sync, 162, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_gettid ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_gettid, 186, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_restart_syscall ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_restart_syscall, 219, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_inotify_init ++TRACE_SYSCALL_TABLE(syscalls_noargs, sys_inotify_init, 253, 0) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_close ++TRACE_SYSCALL_TABLE(sys_close, sys_close, 3, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_lseek ++TRACE_SYSCALL_TABLE(sys_lseek, sys_lseek, 8, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mmap ++TRACE_SYSCALL_TABLE(sys_mmap, sys_mmap, 9, 6) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mprotect ++TRACE_SYSCALL_TABLE(sys_mprotect, sys_mprotect, 10, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_munmap ++TRACE_SYSCALL_TABLE(sys_munmap, sys_munmap, 11, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_brk ++TRACE_SYSCALL_TABLE(sys_brk, sys_brk, 12, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_ioctl ++TRACE_SYSCALL_TABLE(sys_ioctl, sys_ioctl, 16, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mremap ++TRACE_SYSCALL_TABLE(sys_mremap, sys_mremap, 25, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_msync ++TRACE_SYSCALL_TABLE(sys_msync, sys_msync, 26, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_madvise ++TRACE_SYSCALL_TABLE(sys_madvise, sys_madvise, 28, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_shmget ++TRACE_SYSCALL_TABLE(sys_shmget, sys_shmget, 29, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_dup ++TRACE_SYSCALL_TABLE(sys_dup, sys_dup, 32, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_dup2 ++TRACE_SYSCALL_TABLE(sys_dup2, sys_dup2, 33, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_alarm ++TRACE_SYSCALL_TABLE(sys_alarm, sys_alarm, 37, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_socket ++TRACE_SYSCALL_TABLE(sys_socket, sys_socket, 41, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_shutdown ++TRACE_SYSCALL_TABLE(sys_shutdown, sys_shutdown, 48, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_listen ++TRACE_SYSCALL_TABLE(sys_listen, sys_listen, 50, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_exit ++TRACE_SYSCALL_TABLE(sys_exit, sys_exit, 60, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_kill ++TRACE_SYSCALL_TABLE(sys_kill, sys_kill, 62, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_semget ++TRACE_SYSCALL_TABLE(sys_semget, sys_semget, 64, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_msgget ++TRACE_SYSCALL_TABLE(sys_msgget, sys_msgget, 68, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fcntl ++TRACE_SYSCALL_TABLE(sys_fcntl, sys_fcntl, 72, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_flock ++TRACE_SYSCALL_TABLE(sys_flock, sys_flock, 73, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fsync ++TRACE_SYSCALL_TABLE(sys_fsync, sys_fsync, 74, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fdatasync ++TRACE_SYSCALL_TABLE(sys_fdatasync, sys_fdatasync, 75, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_ftruncate ++TRACE_SYSCALL_TABLE(sys_ftruncate, sys_ftruncate, 77, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fchdir ++TRACE_SYSCALL_TABLE(sys_fchdir, sys_fchdir, 81, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fchmod ++TRACE_SYSCALL_TABLE(sys_fchmod, sys_fchmod, 91, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fchown ++TRACE_SYSCALL_TABLE(sys_fchown, sys_fchown, 93, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_umask ++TRACE_SYSCALL_TABLE(sys_umask, sys_umask, 95, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_ptrace ++TRACE_SYSCALL_TABLE(sys_ptrace, sys_ptrace, 101, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setuid ++TRACE_SYSCALL_TABLE(sys_setuid, sys_setuid, 105, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setgid ++TRACE_SYSCALL_TABLE(sys_setgid, sys_setgid, 106, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setpgid ++TRACE_SYSCALL_TABLE(sys_setpgid, sys_setpgid, 109, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setreuid ++TRACE_SYSCALL_TABLE(sys_setreuid, sys_setreuid, 113, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setregid ++TRACE_SYSCALL_TABLE(sys_setregid, sys_setregid, 114, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setresuid ++TRACE_SYSCALL_TABLE(sys_setresuid, sys_setresuid, 117, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setresgid ++TRACE_SYSCALL_TABLE(sys_setresgid, sys_setresgid, 119, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getpgid ++TRACE_SYSCALL_TABLE(sys_getpgid, sys_getpgid, 121, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setfsuid ++TRACE_SYSCALL_TABLE(sys_setfsuid, sys_setfsuid, 122, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setfsgid ++TRACE_SYSCALL_TABLE(sys_setfsgid, sys_setfsgid, 123, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getsid ++TRACE_SYSCALL_TABLE(sys_getsid, sys_getsid, 124, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_personality ++TRACE_SYSCALL_TABLE(sys_personality, sys_personality, 135, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sysfs ++TRACE_SYSCALL_TABLE(sys_sysfs, sys_sysfs, 139, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getpriority ++TRACE_SYSCALL_TABLE(sys_getpriority, sys_getpriority, 140, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setpriority ++TRACE_SYSCALL_TABLE(sys_setpriority, sys_setpriority, 141, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_getscheduler ++TRACE_SYSCALL_TABLE(sys_sched_getscheduler, sys_sched_getscheduler, 145, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_get_priority_max ++TRACE_SYSCALL_TABLE(sys_sched_get_priority_max, sys_sched_get_priority_max, 146, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_get_priority_min ++TRACE_SYSCALL_TABLE(sys_sched_get_priority_min, sys_sched_get_priority_min, 147, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mlock ++TRACE_SYSCALL_TABLE(sys_mlock, sys_mlock, 149, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_munlock ++TRACE_SYSCALL_TABLE(sys_munlock, sys_munlock, 150, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mlockall ++TRACE_SYSCALL_TABLE(sys_mlockall, sys_mlockall, 151, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_prctl ++TRACE_SYSCALL_TABLE(sys_prctl, sys_prctl, 157, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_tkill ++TRACE_SYSCALL_TABLE(sys_tkill, sys_tkill, 200, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_io_destroy ++TRACE_SYSCALL_TABLE(sys_io_destroy, sys_io_destroy, 207, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_epoll_create ++TRACE_SYSCALL_TABLE(sys_epoll_create, sys_epoll_create, 213, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_remap_file_pages ++TRACE_SYSCALL_TABLE(sys_remap_file_pages, sys_remap_file_pages, 216, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timer_getoverrun ++TRACE_SYSCALL_TABLE(sys_timer_getoverrun, sys_timer_getoverrun, 225, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timer_delete ++TRACE_SYSCALL_TABLE(sys_timer_delete, sys_timer_delete, 226, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_exit_group ++TRACE_SYSCALL_TABLE(sys_exit_group, sys_exit_group, 231, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_tgkill ++TRACE_SYSCALL_TABLE(sys_tgkill, sys_tgkill, 234, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_ioprio_set ++TRACE_SYSCALL_TABLE(sys_ioprio_set, sys_ioprio_set, 251, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_ioprio_get ++TRACE_SYSCALL_TABLE(sys_ioprio_get, sys_ioprio_get, 252, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_inotify_rm_watch ++TRACE_SYSCALL_TABLE(sys_inotify_rm_watch, sys_inotify_rm_watch, 255, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_unshare ++TRACE_SYSCALL_TABLE(sys_unshare, sys_unshare, 272, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_tee ++TRACE_SYSCALL_TABLE(sys_tee, sys_tee, 276, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timerfd_create ++TRACE_SYSCALL_TABLE(sys_timerfd_create, sys_timerfd_create, 283, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_eventfd ++TRACE_SYSCALL_TABLE(sys_eventfd, sys_eventfd, 284, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_eventfd2 ++TRACE_SYSCALL_TABLE(sys_eventfd2, sys_eventfd2, 290, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_epoll_create1 ++TRACE_SYSCALL_TABLE(sys_epoll_create1, sys_epoll_create1, 291, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_dup3 ++TRACE_SYSCALL_TABLE(sys_dup3, sys_dup3, 292, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_inotify_init1 ++TRACE_SYSCALL_TABLE(sys_inotify_init1, sys_inotify_init1, 294, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_syncfs ++TRACE_SYSCALL_TABLE(sys_syncfs, sys_syncfs, 306, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setns ++TRACE_SYSCALL_TABLE(sys_setns, sys_setns, 308, 2) ++#endif ++ ++#endif /* CREATE_SYSCALL_TABLE */ +diff --git 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 +new file mode 100644 +index 0000000..3d400f7 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_integers_override.h +@@ -0,0 +1,3 @@ ++/* ++ * this is a place-holder for x86_64 interger syscall definition override. ++ */ +diff --git a/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers.h b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers.h +new file mode 100644 +index 0000000..e926a60 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers.h +@@ -0,0 +1,2076 @@ ++/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT */ ++#ifndef CREATE_SYSCALL_TABLE ++ ++#if !defined(_TRACE_SYSCALLS_POINTERS_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SYSCALLS_POINTERS_H ++ ++#include <linux/tracepoint.h> ++#include <linux/syscalls.h> ++#include "x86-64-syscalls-3.0.4_pointers_override.h" ++#include "syscalls_pointers_override.h" ++ ++#ifndef OVERRIDE_64_sys_pipe ++SC_TRACE_EVENT(sys_pipe, ++ TP_PROTO(int * fildes), ++ TP_ARGS(fildes), ++ TP_STRUCT__entry(__field_hex(int *, fildes)), ++ TP_fast_assign(tp_assign(fildes, fildes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_newuname ++SC_TRACE_EVENT(sys_newuname, ++ TP_PROTO(struct new_utsname * name), ++ TP_ARGS(name), ++ TP_STRUCT__entry(__field_hex(struct new_utsname *, name)), ++ TP_fast_assign(tp_assign(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_shmdt ++SC_TRACE_EVENT(sys_shmdt, ++ TP_PROTO(char * shmaddr), ++ TP_ARGS(shmaddr), ++ TP_STRUCT__entry(__field_hex(char *, shmaddr)), ++ TP_fast_assign(tp_assign(shmaddr, shmaddr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_chdir ++SC_TRACE_EVENT(sys_chdir, ++ TP_PROTO(const char * filename), ++ TP_ARGS(filename), ++ TP_STRUCT__entry(__string_from_user(filename, filename)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rmdir ++SC_TRACE_EVENT(sys_rmdir, ++ TP_PROTO(const char * pathname), ++ TP_ARGS(pathname), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_unlink ++SC_TRACE_EVENT(sys_unlink, ++ TP_PROTO(const char * pathname), ++ TP_ARGS(pathname), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sysinfo ++SC_TRACE_EVENT(sys_sysinfo, ++ TP_PROTO(struct sysinfo * info), ++ TP_ARGS(info), ++ TP_STRUCT__entry(__field_hex(struct sysinfo *, info)), ++ TP_fast_assign(tp_assign(info, info)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_times ++SC_TRACE_EVENT(sys_times, ++ TP_PROTO(struct tms * tbuf), ++ TP_ARGS(tbuf), ++ TP_STRUCT__entry(__field_hex(struct tms *, tbuf)), ++ TP_fast_assign(tp_assign(tbuf, tbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sysctl ++SC_TRACE_EVENT(sys_sysctl, ++ TP_PROTO(struct __sysctl_args * args), ++ TP_ARGS(args), ++ TP_STRUCT__entry(__field_hex(struct __sysctl_args *, args)), ++ TP_fast_assign(tp_assign(args, args)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_adjtimex ++SC_TRACE_EVENT(sys_adjtimex, ++ TP_PROTO(struct timex * txc_p), ++ TP_ARGS(txc_p), ++ TP_STRUCT__entry(__field_hex(struct timex *, txc_p)), ++ TP_fast_assign(tp_assign(txc_p, txc_p)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_chroot ++SC_TRACE_EVENT(sys_chroot, ++ TP_PROTO(const char * filename), ++ TP_ARGS(filename), ++ TP_STRUCT__entry(__string_from_user(filename, filename)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_swapoff ++SC_TRACE_EVENT(sys_swapoff, ++ TP_PROTO(const char * specialfile), ++ TP_ARGS(specialfile), ++ TP_STRUCT__entry(__string_from_user(specialfile, specialfile)), ++ TP_fast_assign(tp_copy_string_from_user(specialfile, specialfile)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_time ++SC_TRACE_EVENT(sys_time, ++ TP_PROTO(time_t * tloc), ++ TP_ARGS(tloc), ++ TP_STRUCT__entry(__field_hex(time_t *, tloc)), ++ TP_fast_assign(tp_assign(tloc, tloc)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_set_tid_address ++SC_TRACE_EVENT(sys_set_tid_address, ++ TP_PROTO(int * tidptr), ++ TP_ARGS(tidptr), ++ TP_STRUCT__entry(__field_hex(int *, tidptr)), ++ TP_fast_assign(tp_assign(tidptr, tidptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mq_unlink ++SC_TRACE_EVENT(sys_mq_unlink, ++ TP_PROTO(const char * u_name), ++ TP_ARGS(u_name), ++ TP_STRUCT__entry(__string_from_user(u_name, u_name)), ++ TP_fast_assign(tp_copy_string_from_user(u_name, u_name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_newstat ++SC_TRACE_EVENT(sys_newstat, ++ TP_PROTO(const char * filename, struct stat * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct stat *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_newfstat ++SC_TRACE_EVENT(sys_newfstat, ++ TP_PROTO(unsigned int fd, struct stat * statbuf), ++ TP_ARGS(fd, statbuf), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct stat *, statbuf)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_newlstat ++SC_TRACE_EVENT(sys_newlstat, ++ TP_PROTO(const char * filename, struct stat * statbuf), ++ TP_ARGS(filename, statbuf), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct stat *, statbuf)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_access ++SC_TRACE_EVENT(sys_access, ++ TP_PROTO(const char * filename, int mode), ++ TP_ARGS(filename, mode), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_nanosleep ++SC_TRACE_EVENT(sys_nanosleep, ++ TP_PROTO(struct timespec * rqtp, struct timespec * rmtp), ++ TP_ARGS(rqtp, rmtp), ++ TP_STRUCT__entry(__field_hex(struct timespec *, rqtp) __field_hex(struct timespec *, rmtp)), ++ TP_fast_assign(tp_assign(rqtp, rqtp) tp_assign(rmtp, rmtp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getitimer ++SC_TRACE_EVENT(sys_getitimer, ++ TP_PROTO(int which, struct itimerval * value), ++ TP_ARGS(which, value), ++ TP_STRUCT__entry(__field(int, which) __field_hex(struct itimerval *, value)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(value, value)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_truncate ++SC_TRACE_EVENT(sys_truncate, ++ TP_PROTO(const char * path, long length), ++ TP_ARGS(path, length), ++ TP_STRUCT__entry(__string_from_user(path, path) __field(long, length)), ++ TP_fast_assign(tp_copy_string_from_user(path, path) tp_assign(length, length)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getcwd ++SC_TRACE_EVENT(sys_getcwd, ++ TP_PROTO(char * buf, unsigned long size), ++ TP_ARGS(buf, size), ++ TP_STRUCT__entry(__field_hex(char *, buf) __field(unsigned long, size)), ++ TP_fast_assign(tp_assign(buf, buf) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rename ++SC_TRACE_EVENT(sys_rename, ++ TP_PROTO(const char * oldname, const char * newname), ++ TP_ARGS(oldname, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mkdir ++SC_TRACE_EVENT(sys_mkdir, ++ TP_PROTO(const char * pathname, int mode), ++ TP_ARGS(pathname, mode), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_creat ++SC_TRACE_EVENT(sys_creat, ++ TP_PROTO(const char * pathname, int mode), ++ TP_ARGS(pathname, mode), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_link ++SC_TRACE_EVENT(sys_link, ++ TP_PROTO(const char * oldname, const char * newname), ++ TP_ARGS(oldname, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_symlink ++SC_TRACE_EVENT(sys_symlink, ++ TP_PROTO(const char * oldname, const char * newname), ++ TP_ARGS(oldname, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_chmod ++SC_TRACE_EVENT(sys_chmod, ++ TP_PROTO(const char * filename, mode_t mode), ++ TP_ARGS(filename, mode), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(mode_t, mode)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_gettimeofday ++SC_TRACE_EVENT(sys_gettimeofday, ++ TP_PROTO(struct timeval * tv, struct timezone * tz), ++ TP_ARGS(tv, tz), ++ TP_STRUCT__entry(__field_hex(struct timeval *, tv) __field_hex(struct timezone *, tz)), ++ TP_fast_assign(tp_assign(tv, tv) tp_assign(tz, tz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getrlimit ++SC_TRACE_EVENT(sys_getrlimit, ++ TP_PROTO(unsigned int resource, struct rlimit * rlim), ++ TP_ARGS(resource, rlim), ++ TP_STRUCT__entry(__field(unsigned int, resource) __field_hex(struct rlimit *, rlim)), ++ TP_fast_assign(tp_assign(resource, resource) tp_assign(rlim, rlim)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getrusage ++SC_TRACE_EVENT(sys_getrusage, ++ TP_PROTO(int who, struct rusage * ru), ++ TP_ARGS(who, ru), ++ TP_STRUCT__entry(__field(int, who) __field_hex(struct rusage *, ru)), ++ TP_fast_assign(tp_assign(who, who) tp_assign(ru, ru)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getgroups ++SC_TRACE_EVENT(sys_getgroups, ++ TP_PROTO(int gidsetsize, gid_t * grouplist), ++ TP_ARGS(gidsetsize, grouplist), ++ TP_STRUCT__entry(__field(int, gidsetsize) __field_hex(gid_t *, grouplist)), ++ TP_fast_assign(tp_assign(gidsetsize, gidsetsize) tp_assign(grouplist, grouplist)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setgroups ++SC_TRACE_EVENT(sys_setgroups, ++ TP_PROTO(int gidsetsize, gid_t * grouplist), ++ TP_ARGS(gidsetsize, grouplist), ++ TP_STRUCT__entry(__field(int, gidsetsize) __field_hex(gid_t *, grouplist)), ++ TP_fast_assign(tp_assign(gidsetsize, gidsetsize) tp_assign(grouplist, grouplist)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rt_sigpending ++SC_TRACE_EVENT(sys_rt_sigpending, ++ TP_PROTO(sigset_t * set, size_t sigsetsize), ++ TP_ARGS(set, sigsetsize), ++ TP_STRUCT__entry(__field_hex(sigset_t *, set) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(set, set) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rt_sigsuspend ++SC_TRACE_EVENT(sys_rt_sigsuspend, ++ TP_PROTO(sigset_t * unewset, size_t sigsetsize), ++ TP_ARGS(unewset, sigsetsize), ++ TP_STRUCT__entry(__field_hex(sigset_t *, unewset) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(unewset, unewset) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_utime ++SC_TRACE_EVENT(sys_utime, ++ TP_PROTO(char * filename, struct utimbuf * times), ++ TP_ARGS(filename, times), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct utimbuf *, times)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(times, times)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_ustat ++SC_TRACE_EVENT(sys_ustat, ++ TP_PROTO(unsigned dev, struct ustat * ubuf), ++ TP_ARGS(dev, ubuf), ++ TP_STRUCT__entry(__field(unsigned, dev) __field_hex(struct ustat *, ubuf)), ++ TP_fast_assign(tp_assign(dev, dev) tp_assign(ubuf, ubuf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_statfs ++SC_TRACE_EVENT(sys_statfs, ++ TP_PROTO(const char * pathname, struct statfs * buf), ++ TP_ARGS(pathname, buf), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field_hex(struct statfs *, buf)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fstatfs ++SC_TRACE_EVENT(sys_fstatfs, ++ TP_PROTO(unsigned int fd, struct statfs * buf), ++ TP_ARGS(fd, buf), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct statfs *, buf)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_setparam ++SC_TRACE_EVENT(sys_sched_setparam, ++ TP_PROTO(pid_t pid, struct sched_param * param), ++ TP_ARGS(pid, param), ++ TP_STRUCT__entry(__field(pid_t, pid) __field_hex(struct sched_param *, param)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(param, param)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_getparam ++SC_TRACE_EVENT(sys_sched_getparam, ++ TP_PROTO(pid_t pid, struct sched_param * param), ++ TP_ARGS(pid, param), ++ TP_STRUCT__entry(__field(pid_t, pid) __field_hex(struct sched_param *, param)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(param, param)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_rr_get_interval ++SC_TRACE_EVENT(sys_sched_rr_get_interval, ++ TP_PROTO(pid_t pid, struct timespec * interval), ++ TP_ARGS(pid, interval), ++ TP_STRUCT__entry(__field(pid_t, pid) __field_hex(struct timespec *, interval)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(interval, interval)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_pivot_root ++SC_TRACE_EVENT(sys_pivot_root, ++ TP_PROTO(const char * new_root, const char * put_old), ++ TP_ARGS(new_root, put_old), ++ TP_STRUCT__entry(__string_from_user(new_root, new_root) __string_from_user(put_old, put_old)), ++ TP_fast_assign(tp_copy_string_from_user(new_root, new_root) tp_copy_string_from_user(put_old, put_old)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setrlimit ++SC_TRACE_EVENT(sys_setrlimit, ++ TP_PROTO(unsigned int resource, struct rlimit * rlim), ++ TP_ARGS(resource, rlim), ++ TP_STRUCT__entry(__field(unsigned int, resource) __field_hex(struct rlimit *, rlim)), ++ TP_fast_assign(tp_assign(resource, resource) tp_assign(rlim, rlim)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_settimeofday ++SC_TRACE_EVENT(sys_settimeofday, ++ TP_PROTO(struct timeval * tv, struct timezone * tz), ++ TP_ARGS(tv, tz), ++ TP_STRUCT__entry(__field_hex(struct timeval *, tv) __field_hex(struct timezone *, tz)), ++ TP_fast_assign(tp_assign(tv, tv) tp_assign(tz, tz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_umount ++SC_TRACE_EVENT(sys_umount, ++ TP_PROTO(char * name, int flags), ++ TP_ARGS(name, flags), ++ TP_STRUCT__entry(__string_from_user(name, name) __field(int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(name, name) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_swapon ++SC_TRACE_EVENT(sys_swapon, ++ TP_PROTO(const char * specialfile, int swap_flags), ++ TP_ARGS(specialfile, swap_flags), ++ TP_STRUCT__entry(__string_from_user(specialfile, specialfile) __field(int, swap_flags)), ++ TP_fast_assign(tp_copy_string_from_user(specialfile, specialfile) tp_assign(swap_flags, swap_flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sethostname ++SC_TRACE_EVENT(sys_sethostname, ++ TP_PROTO(char * name, int len), ++ TP_ARGS(name, len), ++ TP_STRUCT__entry(__string_from_user(name, name) __field(int, len)), ++ TP_fast_assign(tp_copy_string_from_user(name, name) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setdomainname ++SC_TRACE_EVENT(sys_setdomainname, ++ TP_PROTO(char * name, int len), ++ TP_ARGS(name, len), ++ TP_STRUCT__entry(__string_from_user(name, name) __field(int, len)), ++ TP_fast_assign(tp_copy_string_from_user(name, name) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_delete_module ++SC_TRACE_EVENT(sys_delete_module, ++ TP_PROTO(const char * name_user, unsigned int flags), ++ TP_ARGS(name_user, flags), ++ TP_STRUCT__entry(__string_from_user(name_user, name_user) __field(unsigned int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(name_user, name_user) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_removexattr ++SC_TRACE_EVENT(sys_removexattr, ++ TP_PROTO(const char * pathname, const char * name), ++ TP_ARGS(pathname, name), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_lremovexattr ++SC_TRACE_EVENT(sys_lremovexattr, ++ TP_PROTO(const char * pathname, const char * name), ++ TP_ARGS(pathname, name), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fremovexattr ++SC_TRACE_EVENT(sys_fremovexattr, ++ TP_PROTO(int fd, const char * name), ++ TP_ARGS(fd, name), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(name, name)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(name, name)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_io_setup ++SC_TRACE_EVENT(sys_io_setup, ++ TP_PROTO(unsigned nr_events, aio_context_t * ctxp), ++ TP_ARGS(nr_events, ctxp), ++ TP_STRUCT__entry(__field(unsigned, nr_events) __field_hex(aio_context_t *, ctxp)), ++ TP_fast_assign(tp_assign(nr_events, nr_events) tp_assign(ctxp, ctxp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timer_gettime ++SC_TRACE_EVENT(sys_timer_gettime, ++ TP_PROTO(timer_t timer_id, struct itimerspec * setting), ++ TP_ARGS(timer_id, setting), ++ TP_STRUCT__entry(__field(timer_t, timer_id) __field_hex(struct itimerspec *, setting)), ++ TP_fast_assign(tp_assign(timer_id, timer_id) tp_assign(setting, setting)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_clock_settime ++SC_TRACE_EVENT(sys_clock_settime, ++ TP_PROTO(const clockid_t which_clock, const struct timespec * tp), ++ TP_ARGS(which_clock, tp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(const struct timespec *, tp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(tp, tp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_clock_gettime ++SC_TRACE_EVENT(sys_clock_gettime, ++ TP_PROTO(const clockid_t which_clock, struct timespec * tp), ++ TP_ARGS(which_clock, tp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct timespec *, tp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(tp, tp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_clock_getres ++SC_TRACE_EVENT(sys_clock_getres, ++ TP_PROTO(const clockid_t which_clock, struct timespec * tp), ++ TP_ARGS(which_clock, tp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct timespec *, tp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(tp, tp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_utimes ++SC_TRACE_EVENT(sys_utimes, ++ TP_PROTO(char * filename, struct timeval * utimes), ++ TP_ARGS(filename, utimes), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field_hex(struct timeval *, utimes)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(utimes, utimes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mq_notify ++SC_TRACE_EVENT(sys_mq_notify, ++ TP_PROTO(mqd_t mqdes, const struct sigevent * u_notification), ++ TP_ARGS(mqdes, u_notification), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(const struct sigevent *, u_notification)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_notification, u_notification)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_set_robust_list ++SC_TRACE_EVENT(sys_set_robust_list, ++ TP_PROTO(struct robust_list_head * head, size_t len), ++ TP_ARGS(head, len), ++ TP_STRUCT__entry(__field_hex(struct robust_list_head *, head) __field(size_t, len)), ++ TP_fast_assign(tp_assign(head, head) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timerfd_gettime ++SC_TRACE_EVENT(sys_timerfd_gettime, ++ TP_PROTO(int ufd, struct itimerspec * otmr), ++ TP_ARGS(ufd, otmr), ++ TP_STRUCT__entry(__field(int, ufd) __field_hex(struct itimerspec *, otmr)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(otmr, otmr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_pipe2 ++SC_TRACE_EVENT(sys_pipe2, ++ TP_PROTO(int * fildes, int flags), ++ TP_ARGS(fildes, flags), ++ TP_STRUCT__entry(__field_hex(int *, fildes) __field(int, flags)), ++ TP_fast_assign(tp_assign(fildes, fildes) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_clock_adjtime ++SC_TRACE_EVENT(sys_clock_adjtime, ++ TP_PROTO(const clockid_t which_clock, struct timex * utx), ++ TP_ARGS(which_clock, utx), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct timex *, utx)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(utx, utx)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_read ++SC_TRACE_EVENT(sys_read, ++ TP_PROTO(unsigned int fd, char * buf, size_t count), ++ TP_ARGS(fd, buf, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(char *, buf) __field(size_t, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(buf, buf) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_write ++SC_TRACE_EVENT(sys_write, ++ TP_PROTO(unsigned int fd, const char * buf, size_t count), ++ TP_ARGS(fd, buf, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(const char *, buf) __field(size_t, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(buf, buf) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_open ++SC_TRACE_EVENT(sys_open, ++ TP_PROTO(const char * filename, int flags, int mode), ++ TP_ARGS(filename, flags, mode), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(int, flags) __field(int, mode)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(flags, flags) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_poll ++SC_TRACE_EVENT(sys_poll, ++ TP_PROTO(struct pollfd * ufds, unsigned int nfds, long timeout_msecs), ++ TP_ARGS(ufds, nfds, timeout_msecs), ++ TP_STRUCT__entry(__field_hex(struct pollfd *, ufds) __field(unsigned int, nfds) __field(long, timeout_msecs)), ++ TP_fast_assign(tp_assign(ufds, ufds) tp_assign(nfds, nfds) tp_assign(timeout_msecs, timeout_msecs)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_readv ++SC_TRACE_EVENT(sys_readv, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen), ++ TP_ARGS(fd, vec, vlen), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_writev ++SC_TRACE_EVENT(sys_writev, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen), ++ TP_ARGS(fd, vec, vlen), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mincore ++SC_TRACE_EVENT(sys_mincore, ++ TP_PROTO(unsigned long start, size_t len, unsigned char * vec), ++ TP_ARGS(start, len, vec), ++ TP_STRUCT__entry(__field(unsigned long, start) __field(size_t, len) __field_hex(unsigned char *, vec)), ++ TP_fast_assign(tp_assign(start, start) tp_assign(len, len) tp_assign(vec, vec)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_shmat ++SC_TRACE_EVENT(sys_shmat, ++ TP_PROTO(int shmid, char * shmaddr, int shmflg), ++ TP_ARGS(shmid, shmaddr, shmflg), ++ TP_STRUCT__entry(__field(int, shmid) __field_hex(char *, shmaddr) __field(int, shmflg)), ++ TP_fast_assign(tp_assign(shmid, shmid) tp_assign(shmaddr, shmaddr) tp_assign(shmflg, shmflg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_shmctl ++SC_TRACE_EVENT(sys_shmctl, ++ TP_PROTO(int shmid, int cmd, struct shmid_ds * buf), ++ TP_ARGS(shmid, cmd, buf), ++ TP_STRUCT__entry(__field(int, shmid) __field(int, cmd) __field_hex(struct shmid_ds *, buf)), ++ TP_fast_assign(tp_assign(shmid, shmid) tp_assign(cmd, cmd) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setitimer ++SC_TRACE_EVENT(sys_setitimer, ++ TP_PROTO(int which, struct itimerval * value, struct itimerval * ovalue), ++ TP_ARGS(which, value, ovalue), ++ TP_STRUCT__entry(__field(int, which) __field_hex(struct itimerval *, value) __field_hex(struct itimerval *, ovalue)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(value, value) tp_assign(ovalue, ovalue)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_connect ++SC_TRACE_EVENT(sys_connect, ++ TP_PROTO(int fd, struct sockaddr * uservaddr, int addrlen), ++ TP_ARGS(fd, uservaddr, addrlen), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct sockaddr *, uservaddr) __field_hex(int, addrlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(uservaddr, uservaddr) tp_assign(addrlen, addrlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_accept ++SC_TRACE_EVENT(sys_accept, ++ TP_PROTO(int fd, struct sockaddr * upeer_sockaddr, int * upeer_addrlen), ++ TP_ARGS(fd, upeer_sockaddr, upeer_addrlen), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct sockaddr *, upeer_sockaddr) __field_hex(int *, upeer_addrlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(upeer_sockaddr, upeer_sockaddr) tp_assign(upeer_addrlen, upeer_addrlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sendmsg ++SC_TRACE_EVENT(sys_sendmsg, ++ TP_PROTO(int fd, struct msghdr * msg, unsigned flags), ++ TP_ARGS(fd, msg, flags), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct msghdr *, msg) __field(unsigned, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(msg, msg) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_recvmsg ++SC_TRACE_EVENT(sys_recvmsg, ++ TP_PROTO(int fd, struct msghdr * msg, unsigned int flags), ++ TP_ARGS(fd, msg, flags), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct msghdr *, msg) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(msg, msg) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_bind ++SC_TRACE_EVENT(sys_bind, ++ TP_PROTO(int fd, struct sockaddr * umyaddr, int addrlen), ++ TP_ARGS(fd, umyaddr, addrlen), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct sockaddr *, umyaddr) __field_hex(int, addrlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(umyaddr, umyaddr) tp_assign(addrlen, addrlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getsockname ++SC_TRACE_EVENT(sys_getsockname, ++ TP_PROTO(int fd, struct sockaddr * usockaddr, int * usockaddr_len), ++ TP_ARGS(fd, usockaddr, usockaddr_len), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct sockaddr *, usockaddr) __field_hex(int *, usockaddr_len)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(usockaddr, usockaddr) tp_assign(usockaddr_len, usockaddr_len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getpeername ++SC_TRACE_EVENT(sys_getpeername, ++ TP_PROTO(int fd, struct sockaddr * usockaddr, int * usockaddr_len), ++ TP_ARGS(fd, usockaddr, usockaddr_len), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct sockaddr *, usockaddr) __field_hex(int *, usockaddr_len)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(usockaddr, usockaddr) tp_assign(usockaddr_len, usockaddr_len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_semop ++SC_TRACE_EVENT(sys_semop, ++ TP_PROTO(int semid, struct sembuf * tsops, unsigned nsops), ++ TP_ARGS(semid, tsops, nsops), ++ TP_STRUCT__entry(__field(int, semid) __field_hex(struct sembuf *, tsops) __field(unsigned, nsops)), ++ TP_fast_assign(tp_assign(semid, semid) tp_assign(tsops, tsops) tp_assign(nsops, nsops)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_msgctl ++SC_TRACE_EVENT(sys_msgctl, ++ TP_PROTO(int msqid, int cmd, struct msqid_ds * buf), ++ TP_ARGS(msqid, cmd, buf), ++ TP_STRUCT__entry(__field(int, msqid) __field(int, cmd) __field_hex(struct msqid_ds *, buf)), ++ TP_fast_assign(tp_assign(msqid, msqid) tp_assign(cmd, cmd) tp_assign(buf, buf)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getdents ++SC_TRACE_EVENT(sys_getdents, ++ TP_PROTO(unsigned int fd, struct linux_dirent * dirent, unsigned int count), ++ TP_ARGS(fd, dirent, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct linux_dirent *, dirent) __field(unsigned int, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(dirent, dirent) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_readlink ++SC_TRACE_EVENT(sys_readlink, ++ TP_PROTO(const char * path, char * buf, int bufsiz), ++ TP_ARGS(path, buf, bufsiz), ++ TP_STRUCT__entry(__string_from_user(path, path) __field_hex(char *, buf) __field(int, bufsiz)), ++ TP_fast_assign(tp_copy_string_from_user(path, path) tp_assign(buf, buf) tp_assign(bufsiz, bufsiz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_chown ++SC_TRACE_EVENT(sys_chown, ++ TP_PROTO(const char * filename, uid_t user, gid_t group), ++ TP_ARGS(filename, user, group), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(uid_t, user) __field(gid_t, group)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_lchown ++SC_TRACE_EVENT(sys_lchown, ++ TP_PROTO(const char * filename, uid_t user, gid_t group), ++ TP_ARGS(filename, user, group), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(uid_t, user) __field(gid_t, group)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_syslog ++SC_TRACE_EVENT(sys_syslog, ++ TP_PROTO(int type, char * buf, int len), ++ TP_ARGS(type, buf, len), ++ TP_STRUCT__entry(__field(int, type) __field_hex(char *, buf) __field(int, len)), ++ TP_fast_assign(tp_assign(type, type) tp_assign(buf, buf) tp_assign(len, len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getresuid ++SC_TRACE_EVENT(sys_getresuid, ++ TP_PROTO(uid_t * ruid, uid_t * euid, uid_t * suid), ++ TP_ARGS(ruid, euid, suid), ++ TP_STRUCT__entry(__field_hex(uid_t *, ruid) __field_hex(uid_t *, euid) __field_hex(uid_t *, suid)), ++ TP_fast_assign(tp_assign(ruid, ruid) tp_assign(euid, euid) tp_assign(suid, suid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getresgid ++SC_TRACE_EVENT(sys_getresgid, ++ TP_PROTO(gid_t * rgid, gid_t * egid, gid_t * sgid), ++ TP_ARGS(rgid, egid, sgid), ++ TP_STRUCT__entry(__field_hex(gid_t *, rgid) __field_hex(gid_t *, egid) __field_hex(gid_t *, sgid)), ++ TP_fast_assign(tp_assign(rgid, rgid) tp_assign(egid, egid) tp_assign(sgid, sgid)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rt_sigqueueinfo ++SC_TRACE_EVENT(sys_rt_sigqueueinfo, ++ TP_PROTO(pid_t pid, int sig, siginfo_t * uinfo), ++ TP_ARGS(pid, sig, uinfo), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, sig) __field_hex(siginfo_t *, uinfo)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(sig, sig) tp_assign(uinfo, uinfo)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mknod ++SC_TRACE_EVENT(sys_mknod, ++ TP_PROTO(const char * filename, int mode, unsigned dev), ++ TP_ARGS(filename, mode, dev), ++ TP_STRUCT__entry(__string_from_user(filename, filename) __field(int, mode) __field(unsigned, dev)), ++ TP_fast_assign(tp_copy_string_from_user(filename, filename) tp_assign(mode, mode) tp_assign(dev, dev)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_setscheduler ++SC_TRACE_EVENT(sys_sched_setscheduler, ++ TP_PROTO(pid_t pid, int policy, struct sched_param * param), ++ TP_ARGS(pid, policy, param), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(int, policy) __field_hex(struct sched_param *, param)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(policy, policy) tp_assign(param, param)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_init_module ++SC_TRACE_EVENT(sys_init_module, ++ TP_PROTO(void * umod, unsigned long len, const char * uargs), ++ TP_ARGS(umod, len, uargs), ++ TP_STRUCT__entry(__field_hex(void *, umod) __field(unsigned long, len) __field_hex(const char *, uargs)), ++ TP_fast_assign(tp_assign(umod, umod) tp_assign(len, len) tp_assign(uargs, uargs)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_nfsservctl ++SC_TRACE_EVENT(sys_nfsservctl, ++ TP_PROTO(int cmd, struct nfsctl_arg * arg, void * res), ++ TP_ARGS(cmd, arg, res), ++ TP_STRUCT__entry(__field(int, cmd) __field_hex(struct nfsctl_arg *, arg) __field_hex(void *, res)), ++ TP_fast_assign(tp_assign(cmd, cmd) tp_assign(arg, arg) tp_assign(res, res)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_listxattr ++SC_TRACE_EVENT(sys_listxattr, ++ TP_PROTO(const char * pathname, char * list, size_t size), ++ TP_ARGS(pathname, list, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field_hex(char *, list) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(list, list) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_llistxattr ++SC_TRACE_EVENT(sys_llistxattr, ++ TP_PROTO(const char * pathname, char * list, size_t size), ++ TP_ARGS(pathname, list, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __field_hex(char *, list) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_assign(list, list) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_flistxattr ++SC_TRACE_EVENT(sys_flistxattr, ++ TP_PROTO(int fd, char * list, size_t size), ++ TP_ARGS(fd, list, size), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(char *, list) __field(size_t, size)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(list, list) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_setaffinity ++SC_TRACE_EVENT(sys_sched_setaffinity, ++ TP_PROTO(pid_t pid, unsigned int len, unsigned long * user_mask_ptr), ++ TP_ARGS(pid, len, user_mask_ptr), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(unsigned int, len) __field_hex(unsigned long *, user_mask_ptr)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(len, len) tp_assign(user_mask_ptr, user_mask_ptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sched_getaffinity ++SC_TRACE_EVENT(sys_sched_getaffinity, ++ TP_PROTO(pid_t pid, unsigned int len, unsigned long * user_mask_ptr), ++ TP_ARGS(pid, len, user_mask_ptr), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(unsigned int, len) __field_hex(unsigned long *, user_mask_ptr)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(len, len) tp_assign(user_mask_ptr, user_mask_ptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_io_submit ++SC_TRACE_EVENT(sys_io_submit, ++ TP_PROTO(aio_context_t ctx_id, long nr, struct iocb * * iocbpp), ++ TP_ARGS(ctx_id, nr, iocbpp), ++ TP_STRUCT__entry(__field(aio_context_t, ctx_id) __field(long, nr) __field_hex(struct iocb * *, iocbpp)), ++ TP_fast_assign(tp_assign(ctx_id, ctx_id) tp_assign(nr, nr) tp_assign(iocbpp, iocbpp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_io_cancel ++SC_TRACE_EVENT(sys_io_cancel, ++ TP_PROTO(aio_context_t ctx_id, struct iocb * iocb, struct io_event * result), ++ TP_ARGS(ctx_id, iocb, result), ++ TP_STRUCT__entry(__field(aio_context_t, ctx_id) __field_hex(struct iocb *, iocb) __field_hex(struct io_event *, result)), ++ TP_fast_assign(tp_assign(ctx_id, ctx_id) tp_assign(iocb, iocb) tp_assign(result, result)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getdents64 ++SC_TRACE_EVENT(sys_getdents64, ++ TP_PROTO(unsigned int fd, struct linux_dirent64 * dirent, unsigned int count), ++ TP_ARGS(fd, dirent, count), ++ TP_STRUCT__entry(__field(unsigned int, fd) __field_hex(struct linux_dirent64 *, dirent) __field(unsigned int, count)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(dirent, dirent) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timer_create ++SC_TRACE_EVENT(sys_timer_create, ++ TP_PROTO(const clockid_t which_clock, struct sigevent * timer_event_spec, timer_t * created_timer_id), ++ TP_ARGS(which_clock, timer_event_spec, created_timer_id), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field_hex(struct sigevent *, timer_event_spec) __field_hex(timer_t *, created_timer_id)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(timer_event_spec, timer_event_spec) tp_assign(created_timer_id, created_timer_id)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mq_getsetattr ++SC_TRACE_EVENT(sys_mq_getsetattr, ++ TP_PROTO(mqd_t mqdes, const struct mq_attr * u_mqstat, struct mq_attr * u_omqstat), ++ TP_ARGS(mqdes, u_mqstat, u_omqstat), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(const struct mq_attr *, u_mqstat) __field_hex(struct mq_attr *, u_omqstat)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_mqstat, u_mqstat) tp_assign(u_omqstat, u_omqstat)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_inotify_add_watch ++SC_TRACE_EVENT(sys_inotify_add_watch, ++ TP_PROTO(int fd, const char * pathname, u32 mask), ++ TP_ARGS(fd, pathname, mask), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(pathname, pathname) __field(u32, mask)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(pathname, pathname) tp_assign(mask, mask)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mkdirat ++SC_TRACE_EVENT(sys_mkdirat, ++ TP_PROTO(int dfd, const char * pathname, int mode), ++ TP_ARGS(dfd, pathname, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(pathname, pathname) __field(int, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(pathname, pathname) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_futimesat ++SC_TRACE_EVENT(sys_futimesat, ++ TP_PROTO(int dfd, const char * filename, struct timeval * utimes), ++ TP_ARGS(dfd, filename, utimes), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field_hex(struct timeval *, utimes)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(utimes, utimes)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_unlinkat ++SC_TRACE_EVENT(sys_unlinkat, ++ TP_PROTO(int dfd, const char * pathname, int flag), ++ TP_ARGS(dfd, pathname, flag), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(pathname, pathname) __field(int, flag)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(pathname, pathname) tp_assign(flag, flag)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_symlinkat ++SC_TRACE_EVENT(sys_symlinkat, ++ TP_PROTO(const char * oldname, int newdfd, const char * newname), ++ TP_ARGS(oldname, newdfd, newname), ++ TP_STRUCT__entry(__string_from_user(oldname, oldname) __field(int, newdfd) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_copy_string_from_user(oldname, oldname) tp_assign(newdfd, newdfd) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fchmodat ++SC_TRACE_EVENT(sys_fchmodat, ++ TP_PROTO(int dfd, const char * filename, mode_t mode), ++ TP_ARGS(dfd, filename, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(mode_t, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_faccessat ++SC_TRACE_EVENT(sys_faccessat, ++ TP_PROTO(int dfd, const char * filename, int mode), ++ TP_ARGS(dfd, filename, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(int, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_get_robust_list ++SC_TRACE_EVENT(sys_get_robust_list, ++ TP_PROTO(int pid, struct robust_list_head * * head_ptr, size_t * len_ptr), ++ TP_ARGS(pid, head_ptr, len_ptr), ++ TP_STRUCT__entry(__field(int, pid) __field_hex(struct robust_list_head * *, head_ptr) __field_hex(size_t *, len_ptr)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(head_ptr, head_ptr) tp_assign(len_ptr, len_ptr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_signalfd ++SC_TRACE_EVENT(sys_signalfd, ++ TP_PROTO(int ufd, sigset_t * user_mask, size_t sizemask), ++ TP_ARGS(ufd, user_mask, sizemask), ++ TP_STRUCT__entry(__field(int, ufd) __field_hex(sigset_t *, user_mask) __field(size_t, sizemask)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(user_mask, user_mask) tp_assign(sizemask, sizemask)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rt_sigaction ++SC_TRACE_EVENT(sys_rt_sigaction, ++ TP_PROTO(int sig, const struct sigaction * act, struct sigaction * oact, size_t sigsetsize), ++ TP_ARGS(sig, act, oact, sigsetsize), ++ TP_STRUCT__entry(__field(int, sig) __field_hex(const struct sigaction *, act) __field_hex(struct sigaction *, oact) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(sig, sig) tp_assign(act, act) tp_assign(oact, oact) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rt_sigprocmask ++SC_TRACE_EVENT(sys_rt_sigprocmask, ++ TP_PROTO(int how, sigset_t * nset, sigset_t * oset, size_t sigsetsize), ++ TP_ARGS(how, nset, oset, sigsetsize), ++ TP_STRUCT__entry(__field(int, how) __field_hex(sigset_t *, nset) __field_hex(sigset_t *, oset) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(how, how) tp_assign(nset, nset) tp_assign(oset, oset) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sendfile64 ++SC_TRACE_EVENT(sys_sendfile64, ++ TP_PROTO(int out_fd, int in_fd, loff_t * offset, size_t count), ++ TP_ARGS(out_fd, in_fd, offset, count), ++ TP_STRUCT__entry(__field(int, out_fd) __field(int, in_fd) __field_hex(loff_t *, offset) __field(size_t, count)), ++ TP_fast_assign(tp_assign(out_fd, out_fd) tp_assign(in_fd, in_fd) tp_assign(offset, offset) tp_assign(count, count)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_socketpair ++SC_TRACE_EVENT(sys_socketpair, ++ TP_PROTO(int family, int type, int protocol, int * usockvec), ++ TP_ARGS(family, type, protocol, usockvec), ++ TP_STRUCT__entry(__field(int, family) __field(int, type) __field(int, protocol) __field_hex(int *, usockvec)), ++ TP_fast_assign(tp_assign(family, family) tp_assign(type, type) tp_assign(protocol, protocol) tp_assign(usockvec, usockvec)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_wait4 ++SC_TRACE_EVENT(sys_wait4, ++ TP_PROTO(pid_t upid, int * stat_addr, int options, struct rusage * ru), ++ TP_ARGS(upid, stat_addr, options, ru), ++ TP_STRUCT__entry(__field(pid_t, upid) __field_hex(int *, stat_addr) __field(int, options) __field_hex(struct rusage *, ru)), ++ TP_fast_assign(tp_assign(upid, upid) tp_assign(stat_addr, stat_addr) tp_assign(options, options) tp_assign(ru, ru)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_msgsnd ++SC_TRACE_EVENT(sys_msgsnd, ++ TP_PROTO(int msqid, struct msgbuf * msgp, size_t msgsz, int msgflg), ++ TP_ARGS(msqid, msgp, msgsz, msgflg), ++ TP_STRUCT__entry(__field(int, msqid) __field_hex(struct msgbuf *, msgp) __field(size_t, msgsz) __field(int, msgflg)), ++ TP_fast_assign(tp_assign(msqid, msqid) tp_assign(msgp, msgp) tp_assign(msgsz, msgsz) tp_assign(msgflg, msgflg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rt_sigtimedwait ++SC_TRACE_EVENT(sys_rt_sigtimedwait, ++ TP_PROTO(const sigset_t * uthese, siginfo_t * uinfo, const struct timespec * uts, size_t sigsetsize), ++ TP_ARGS(uthese, uinfo, uts, sigsetsize), ++ TP_STRUCT__entry(__field_hex(const sigset_t *, uthese) __field_hex(siginfo_t *, uinfo) __field_hex(const struct timespec *, uts) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(uthese, uthese) tp_assign(uinfo, uinfo) tp_assign(uts, uts) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_reboot ++SC_TRACE_EVENT(sys_reboot, ++ TP_PROTO(int magic1, int magic2, unsigned int cmd, void * arg), ++ TP_ARGS(magic1, magic2, cmd, arg), ++ TP_STRUCT__entry(__field(int, magic1) __field(int, magic2) __field(unsigned int, cmd) __field_hex(void *, arg)), ++ TP_fast_assign(tp_assign(magic1, magic1) tp_assign(magic2, magic2) tp_assign(cmd, cmd) tp_assign(arg, arg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getxattr ++SC_TRACE_EVENT(sys_getxattr, ++ TP_PROTO(const char * pathname, const char * name, void * value, size_t size), ++ TP_ARGS(pathname, name, value, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(void *, value) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_lgetxattr ++SC_TRACE_EVENT(sys_lgetxattr, ++ TP_PROTO(const char * pathname, const char * name, void * value, size_t size), ++ TP_ARGS(pathname, name, value, size), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(void *, value) __field(size_t, size)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fgetxattr ++SC_TRACE_EVENT(sys_fgetxattr, ++ TP_PROTO(int fd, const char * name, void * value, size_t size), ++ TP_ARGS(fd, name, value, size), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(name, name) __field_hex(void *, value) __field(size_t, size)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_semtimedop ++SC_TRACE_EVENT(sys_semtimedop, ++ TP_PROTO(int semid, struct sembuf * tsops, unsigned nsops, const struct timespec * timeout), ++ TP_ARGS(semid, tsops, nsops, timeout), ++ TP_STRUCT__entry(__field(int, semid) __field_hex(struct sembuf *, tsops) __field(unsigned, nsops) __field_hex(const struct timespec *, timeout)), ++ TP_fast_assign(tp_assign(semid, semid) tp_assign(tsops, tsops) tp_assign(nsops, nsops) tp_assign(timeout, timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timer_settime ++SC_TRACE_EVENT(sys_timer_settime, ++ TP_PROTO(timer_t timer_id, int flags, const struct itimerspec * new_setting, struct itimerspec * old_setting), ++ TP_ARGS(timer_id, flags, new_setting, old_setting), ++ TP_STRUCT__entry(__field(timer_t, timer_id) __field(int, flags) __field_hex(const struct itimerspec *, new_setting) __field_hex(struct itimerspec *, old_setting)), ++ TP_fast_assign(tp_assign(timer_id, timer_id) tp_assign(flags, flags) tp_assign(new_setting, new_setting) tp_assign(old_setting, old_setting)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_clock_nanosleep ++SC_TRACE_EVENT(sys_clock_nanosleep, ++ TP_PROTO(const clockid_t which_clock, int flags, const struct timespec * rqtp, struct timespec * rmtp), ++ TP_ARGS(which_clock, flags, rqtp, rmtp), ++ TP_STRUCT__entry(__field(const clockid_t, which_clock) __field(int, flags) __field_hex(const struct timespec *, rqtp) __field_hex(struct timespec *, rmtp)), ++ TP_fast_assign(tp_assign(which_clock, which_clock) tp_assign(flags, flags) tp_assign(rqtp, rqtp) tp_assign(rmtp, rmtp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_epoll_wait ++SC_TRACE_EVENT(sys_epoll_wait, ++ TP_PROTO(int epfd, struct epoll_event * events, int maxevents, int timeout), ++ TP_ARGS(epfd, events, maxevents, timeout), ++ TP_STRUCT__entry(__field(int, epfd) __field_hex(struct epoll_event *, events) __field(int, maxevents) __field(int, timeout)), ++ TP_fast_assign(tp_assign(epfd, epfd) tp_assign(events, events) tp_assign(maxevents, maxevents) tp_assign(timeout, timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_epoll_ctl ++SC_TRACE_EVENT(sys_epoll_ctl, ++ TP_PROTO(int epfd, int op, int fd, struct epoll_event * event), ++ TP_ARGS(epfd, op, fd, event), ++ TP_STRUCT__entry(__field(int, epfd) __field(int, op) __field(int, fd) __field_hex(struct epoll_event *, event)), ++ TP_fast_assign(tp_assign(epfd, epfd) tp_assign(op, op) tp_assign(fd, fd) tp_assign(event, event)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mq_open ++SC_TRACE_EVENT(sys_mq_open, ++ TP_PROTO(const char * u_name, int oflag, mode_t mode, struct mq_attr * u_attr), ++ TP_ARGS(u_name, oflag, mode, u_attr), ++ TP_STRUCT__entry(__string_from_user(u_name, u_name) __field(int, oflag) __field(mode_t, mode) __field_hex(struct mq_attr *, u_attr)), ++ TP_fast_assign(tp_copy_string_from_user(u_name, u_name) tp_assign(oflag, oflag) tp_assign(mode, mode) tp_assign(u_attr, u_attr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_kexec_load ++SC_TRACE_EVENT(sys_kexec_load, ++ TP_PROTO(unsigned long entry, unsigned long nr_segments, struct kexec_segment * segments, unsigned long flags), ++ TP_ARGS(entry, nr_segments, segments, flags), ++ TP_STRUCT__entry(__field(unsigned long, entry) __field(unsigned long, nr_segments) __field_hex(struct kexec_segment *, segments) __field(unsigned long, flags)), ++ TP_fast_assign(tp_assign(entry, entry) tp_assign(nr_segments, nr_segments) tp_assign(segments, segments) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_openat ++SC_TRACE_EVENT(sys_openat, ++ TP_PROTO(int dfd, const char * filename, int flags, int mode), ++ TP_ARGS(dfd, filename, flags, mode), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(int, flags) __field(int, mode)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(flags, flags) tp_assign(mode, mode)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mknodat ++SC_TRACE_EVENT(sys_mknodat, ++ TP_PROTO(int dfd, const char * filename, int mode, unsigned dev), ++ TP_ARGS(dfd, filename, mode, dev), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(int, mode) __field(unsigned, dev)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(mode, mode) tp_assign(dev, dev)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_newfstatat ++SC_TRACE_EVENT(sys_newfstatat, ++ TP_PROTO(int dfd, const char * filename, struct stat * statbuf, int flag), ++ TP_ARGS(dfd, filename, statbuf, flag), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field_hex(struct stat *, statbuf) __field(int, flag)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(statbuf, statbuf) tp_assign(flag, flag)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_renameat ++SC_TRACE_EVENT(sys_renameat, ++ TP_PROTO(int olddfd, const char * oldname, int newdfd, const char * newname), ++ TP_ARGS(olddfd, oldname, newdfd, newname), ++ TP_STRUCT__entry(__field(int, olddfd) __string_from_user(oldname, oldname) __field(int, newdfd) __string_from_user(newname, newname)), ++ TP_fast_assign(tp_assign(olddfd, olddfd) tp_copy_string_from_user(oldname, oldname) tp_assign(newdfd, newdfd) tp_copy_string_from_user(newname, newname)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_readlinkat ++SC_TRACE_EVENT(sys_readlinkat, ++ TP_PROTO(int dfd, const char * pathname, char * buf, int bufsiz), ++ TP_ARGS(dfd, pathname, buf, bufsiz), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(pathname, pathname) __field_hex(char *, buf) __field(int, bufsiz)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(pathname, pathname) tp_assign(buf, buf) tp_assign(bufsiz, bufsiz)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_vmsplice ++SC_TRACE_EVENT(sys_vmsplice, ++ TP_PROTO(int fd, const struct iovec * iov, unsigned long nr_segs, unsigned int flags), ++ TP_ARGS(fd, iov, nr_segs, flags), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(const struct iovec *, iov) __field(unsigned long, nr_segs) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(iov, iov) tp_assign(nr_segs, nr_segs) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_utimensat ++SC_TRACE_EVENT(sys_utimensat, ++ TP_PROTO(int dfd, const char * filename, struct timespec * utimes, int flags), ++ TP_ARGS(dfd, filename, utimes, flags), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field_hex(struct timespec *, utimes) __field(int, flags)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(utimes, utimes) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_timerfd_settime ++SC_TRACE_EVENT(sys_timerfd_settime, ++ TP_PROTO(int ufd, int flags, const struct itimerspec * utmr, struct itimerspec * otmr), ++ TP_ARGS(ufd, flags, utmr, otmr), ++ TP_STRUCT__entry(__field(int, ufd) __field(int, flags) __field_hex(const struct itimerspec *, utmr) __field_hex(struct itimerspec *, otmr)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(flags, flags) tp_assign(utmr, utmr) tp_assign(otmr, otmr)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_accept4 ++SC_TRACE_EVENT(sys_accept4, ++ TP_PROTO(int fd, struct sockaddr * upeer_sockaddr, int * upeer_addrlen, int flags), ++ TP_ARGS(fd, upeer_sockaddr, upeer_addrlen, flags), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct sockaddr *, upeer_sockaddr) __field_hex(int *, upeer_addrlen) __field(int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(upeer_sockaddr, upeer_sockaddr) tp_assign(upeer_addrlen, upeer_addrlen) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_signalfd4 ++SC_TRACE_EVENT(sys_signalfd4, ++ TP_PROTO(int ufd, sigset_t * user_mask, size_t sizemask, int flags), ++ TP_ARGS(ufd, user_mask, sizemask, flags), ++ TP_STRUCT__entry(__field(int, ufd) __field_hex(sigset_t *, user_mask) __field(size_t, sizemask) __field(int, flags)), ++ TP_fast_assign(tp_assign(ufd, ufd) tp_assign(user_mask, user_mask) tp_assign(sizemask, sizemask) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_rt_tgsigqueueinfo ++SC_TRACE_EVENT(sys_rt_tgsigqueueinfo, ++ TP_PROTO(pid_t tgid, pid_t pid, int sig, siginfo_t * uinfo), ++ TP_ARGS(tgid, pid, sig, uinfo), ++ TP_STRUCT__entry(__field(pid_t, tgid) __field(pid_t, pid) __field(int, sig) __field_hex(siginfo_t *, uinfo)), ++ TP_fast_assign(tp_assign(tgid, tgid) tp_assign(pid, pid) tp_assign(sig, sig) tp_assign(uinfo, uinfo)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_prlimit64 ++SC_TRACE_EVENT(sys_prlimit64, ++ TP_PROTO(pid_t pid, unsigned int resource, const struct rlimit64 * new_rlim, struct rlimit64 * old_rlim), ++ TP_ARGS(pid, resource, new_rlim, old_rlim), ++ TP_STRUCT__entry(__field(pid_t, pid) __field(unsigned int, resource) __field_hex(const struct rlimit64 *, new_rlim) __field_hex(struct rlimit64 *, old_rlim)), ++ TP_fast_assign(tp_assign(pid, pid) tp_assign(resource, resource) tp_assign(new_rlim, new_rlim) tp_assign(old_rlim, old_rlim)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sendmmsg ++SC_TRACE_EVENT(sys_sendmmsg, ++ TP_PROTO(int fd, struct mmsghdr * mmsg, unsigned int vlen, unsigned int flags), ++ TP_ARGS(fd, mmsg, vlen, flags), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct mmsghdr *, mmsg) __field(unsigned int, vlen) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(mmsg, mmsg) tp_assign(vlen, vlen) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_select ++SC_TRACE_EVENT(sys_select, ++ TP_PROTO(int n, fd_set * inp, fd_set * outp, fd_set * exp, struct timeval * tvp), ++ TP_ARGS(n, inp, outp, exp, tvp), ++ TP_STRUCT__entry(__field(int, n) __field_hex(fd_set *, inp) __field_hex(fd_set *, outp) __field_hex(fd_set *, exp) __field_hex(struct timeval *, tvp)), ++ TP_fast_assign(tp_assign(n, n) tp_assign(inp, inp) tp_assign(outp, outp) tp_assign(exp, exp) tp_assign(tvp, tvp)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setsockopt ++SC_TRACE_EVENT(sys_setsockopt, ++ TP_PROTO(int fd, int level, int optname, char * optval, int optlen), ++ TP_ARGS(fd, level, optname, optval, optlen), ++ TP_STRUCT__entry(__field(int, fd) __field(int, level) __field(int, optname) __field_hex(char *, optval) __field(int, optlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(level, level) tp_assign(optname, optname) tp_assign(optval, optval) tp_assign(optlen, optlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_getsockopt ++SC_TRACE_EVENT(sys_getsockopt, ++ TP_PROTO(int fd, int level, int optname, char * optval, int * optlen), ++ TP_ARGS(fd, level, optname, optval, optlen), ++ TP_STRUCT__entry(__field(int, fd) __field(int, level) __field(int, optname) __field_hex(char *, optval) __field_hex(int *, optlen)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(level, level) tp_assign(optname, optname) tp_assign(optval, optval) tp_assign(optlen, optlen)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_msgrcv ++SC_TRACE_EVENT(sys_msgrcv, ++ TP_PROTO(int msqid, struct msgbuf * msgp, size_t msgsz, long msgtyp, int msgflg), ++ TP_ARGS(msqid, msgp, msgsz, msgtyp, msgflg), ++ TP_STRUCT__entry(__field(int, msqid) __field_hex(struct msgbuf *, msgp) __field(size_t, msgsz) __field(long, msgtyp) __field(int, msgflg)), ++ TP_fast_assign(tp_assign(msqid, msqid) tp_assign(msgp, msgp) tp_assign(msgsz, msgsz) tp_assign(msgtyp, msgtyp) tp_assign(msgflg, msgflg)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mount ++SC_TRACE_EVENT(sys_mount, ++ TP_PROTO(char * dev_name, char * dir_name, char * type, unsigned long flags, void * data), ++ TP_ARGS(dev_name, dir_name, type, flags, data), ++ TP_STRUCT__entry(__string_from_user(dev_name, dev_name) __string_from_user(dir_name, dir_name) __string_from_user(type, type) __field(unsigned long, flags) __field_hex(void *, data)), ++ TP_fast_assign(tp_copy_string_from_user(dev_name, dev_name) tp_copy_string_from_user(dir_name, dir_name) tp_copy_string_from_user(type, type) tp_assign(flags, flags) tp_assign(data, data)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_setxattr ++SC_TRACE_EVENT(sys_setxattr, ++ TP_PROTO(const char * pathname, const char * name, const void * value, size_t size, int flags), ++ TP_ARGS(pathname, name, value, size, flags), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(const void *, value) __field(size_t, size) __field(int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_lsetxattr ++SC_TRACE_EVENT(sys_lsetxattr, ++ TP_PROTO(const char * pathname, const char * name, const void * value, size_t size, int flags), ++ TP_ARGS(pathname, name, value, size, flags), ++ TP_STRUCT__entry(__string_from_user(pathname, pathname) __string_from_user(name, name) __field_hex(const void *, value) __field(size_t, size) __field(int, flags)), ++ TP_fast_assign(tp_copy_string_from_user(pathname, pathname) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fsetxattr ++SC_TRACE_EVENT(sys_fsetxattr, ++ TP_PROTO(int fd, const char * name, const void * value, size_t size, int flags), ++ TP_ARGS(fd, name, value, size, flags), ++ TP_STRUCT__entry(__field(int, fd) __string_from_user(name, name) __field_hex(const void *, value) __field(size_t, size) __field(int, flags)), ++ TP_fast_assign(tp_assign(fd, fd) tp_copy_string_from_user(name, name) tp_assign(value, value) tp_assign(size, size) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_io_getevents ++SC_TRACE_EVENT(sys_io_getevents, ++ TP_PROTO(aio_context_t ctx_id, long min_nr, long nr, struct io_event * events, struct timespec * timeout), ++ TP_ARGS(ctx_id, min_nr, nr, events, timeout), ++ TP_STRUCT__entry(__field(aio_context_t, ctx_id) __field(long, min_nr) __field(long, nr) __field_hex(struct io_event *, events) __field_hex(struct timespec *, timeout)), ++ TP_fast_assign(tp_assign(ctx_id, ctx_id) tp_assign(min_nr, min_nr) tp_assign(nr, nr) tp_assign(events, events) tp_assign(timeout, timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mq_timedsend ++SC_TRACE_EVENT(sys_mq_timedsend, ++ TP_PROTO(mqd_t mqdes, const char * u_msg_ptr, size_t msg_len, unsigned int msg_prio, const struct timespec * u_abs_timeout), ++ TP_ARGS(mqdes, u_msg_ptr, msg_len, msg_prio, u_abs_timeout), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(const char *, u_msg_ptr) __field(size_t, msg_len) __field(unsigned int, msg_prio) __field_hex(const struct timespec *, u_abs_timeout)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_msg_ptr, u_msg_ptr) tp_assign(msg_len, msg_len) tp_assign(msg_prio, msg_prio) tp_assign(u_abs_timeout, u_abs_timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_mq_timedreceive ++SC_TRACE_EVENT(sys_mq_timedreceive, ++ TP_PROTO(mqd_t mqdes, char * u_msg_ptr, size_t msg_len, unsigned int * u_msg_prio, const struct timespec * u_abs_timeout), ++ TP_ARGS(mqdes, u_msg_ptr, msg_len, u_msg_prio, u_abs_timeout), ++ TP_STRUCT__entry(__field(mqd_t, mqdes) __field_hex(char *, u_msg_ptr) __field(size_t, msg_len) __field_hex(unsigned int *, u_msg_prio) __field_hex(const struct timespec *, u_abs_timeout)), ++ TP_fast_assign(tp_assign(mqdes, mqdes) tp_assign(u_msg_ptr, u_msg_ptr) tp_assign(msg_len, msg_len) tp_assign(u_msg_prio, u_msg_prio) tp_assign(u_abs_timeout, u_abs_timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_waitid ++SC_TRACE_EVENT(sys_waitid, ++ TP_PROTO(int which, pid_t upid, struct siginfo * infop, int options, struct rusage * ru), ++ TP_ARGS(which, upid, infop, options, ru), ++ TP_STRUCT__entry(__field(int, which) __field(pid_t, upid) __field_hex(struct siginfo *, infop) __field(int, options) __field_hex(struct rusage *, ru)), ++ TP_fast_assign(tp_assign(which, which) tp_assign(upid, upid) tp_assign(infop, infop) tp_assign(options, options) tp_assign(ru, ru)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_fchownat ++SC_TRACE_EVENT(sys_fchownat, ++ TP_PROTO(int dfd, const char * filename, uid_t user, gid_t group, int flag), ++ TP_ARGS(dfd, filename, user, group, flag), ++ TP_STRUCT__entry(__field(int, dfd) __string_from_user(filename, filename) __field(uid_t, user) __field(gid_t, group) __field(int, flag)), ++ TP_fast_assign(tp_assign(dfd, dfd) tp_copy_string_from_user(filename, filename) tp_assign(user, user) tp_assign(group, group) tp_assign(flag, flag)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_linkat ++SC_TRACE_EVENT(sys_linkat, ++ TP_PROTO(int olddfd, const char * oldname, int newdfd, const char * newname, int flags), ++ TP_ARGS(olddfd, oldname, newdfd, newname, flags), ++ TP_STRUCT__entry(__field(int, olddfd) __string_from_user(oldname, oldname) __field(int, newdfd) __string_from_user(newname, newname) __field(int, flags)), ++ TP_fast_assign(tp_assign(olddfd, olddfd) tp_copy_string_from_user(oldname, oldname) tp_assign(newdfd, newdfd) tp_copy_string_from_user(newname, newname) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_ppoll ++SC_TRACE_EVENT(sys_ppoll, ++ TP_PROTO(struct pollfd * ufds, unsigned int nfds, struct timespec * tsp, const sigset_t * sigmask, size_t sigsetsize), ++ TP_ARGS(ufds, nfds, tsp, sigmask, sigsetsize), ++ TP_STRUCT__entry(__field_hex(struct pollfd *, ufds) __field(unsigned int, nfds) __field_hex(struct timespec *, tsp) __field_hex(const sigset_t *, sigmask) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(ufds, ufds) tp_assign(nfds, nfds) tp_assign(tsp, tsp) tp_assign(sigmask, sigmask) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_preadv ++SC_TRACE_EVENT(sys_preadv, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h), ++ TP_ARGS(fd, vec, vlen, pos_l, pos_h), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen) __field(unsigned long, pos_l) __field(unsigned long, pos_h)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen) tp_assign(pos_l, pos_l) tp_assign(pos_h, pos_h)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_pwritev ++SC_TRACE_EVENT(sys_pwritev, ++ TP_PROTO(unsigned long fd, const struct iovec * vec, unsigned long vlen, unsigned long pos_l, unsigned long pos_h), ++ TP_ARGS(fd, vec, vlen, pos_l, pos_h), ++ TP_STRUCT__entry(__field(unsigned long, fd) __field_hex(const struct iovec *, vec) __field(unsigned long, vlen) __field(unsigned long, pos_l) __field(unsigned long, pos_h)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(vec, vec) tp_assign(vlen, vlen) tp_assign(pos_l, pos_l) tp_assign(pos_h, pos_h)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_perf_event_open ++SC_TRACE_EVENT(sys_perf_event_open, ++ TP_PROTO(struct perf_event_attr * attr_uptr, pid_t pid, int cpu, int group_fd, unsigned long flags), ++ TP_ARGS(attr_uptr, pid, cpu, group_fd, flags), ++ TP_STRUCT__entry(__field_hex(struct perf_event_attr *, attr_uptr) __field(pid_t, pid) __field(int, cpu) __field(int, group_fd) __field(unsigned long, flags)), ++ TP_fast_assign(tp_assign(attr_uptr, attr_uptr) tp_assign(pid, pid) tp_assign(cpu, cpu) tp_assign(group_fd, group_fd) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_recvmmsg ++SC_TRACE_EVENT(sys_recvmmsg, ++ TP_PROTO(int fd, struct mmsghdr * mmsg, unsigned int vlen, unsigned int flags, struct timespec * timeout), ++ TP_ARGS(fd, mmsg, vlen, flags, timeout), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(struct mmsghdr *, mmsg) __field(unsigned int, vlen) __field(unsigned int, flags) __field_hex(struct timespec *, timeout)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(mmsg, mmsg) tp_assign(vlen, vlen) tp_assign(flags, flags) tp_assign(timeout, timeout)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_sendto ++SC_TRACE_EVENT(sys_sendto, ++ TP_PROTO(int fd, void * buff, size_t len, unsigned flags, struct sockaddr * addr, int addr_len), ++ TP_ARGS(fd, buff, len, flags, addr, addr_len), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(void *, buff) __field(size_t, len) __field(unsigned, flags) __field_hex(struct sockaddr *, addr) __field_hex(int, addr_len)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(buff, buff) tp_assign(len, len) tp_assign(flags, flags) tp_assign(addr, addr) tp_assign(addr_len, addr_len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_recvfrom ++SC_TRACE_EVENT(sys_recvfrom, ++ TP_PROTO(int fd, void * ubuf, size_t size, unsigned flags, struct sockaddr * addr, int * addr_len), ++ TP_ARGS(fd, ubuf, size, flags, addr, addr_len), ++ TP_STRUCT__entry(__field(int, fd) __field_hex(void *, ubuf) __field(size_t, size) __field(unsigned, flags) __field_hex(struct sockaddr *, addr) __field_hex(int *, addr_len)), ++ TP_fast_assign(tp_assign(fd, fd) tp_assign(ubuf, ubuf) tp_assign(size, size) tp_assign(flags, flags) tp_assign(addr, addr) tp_assign(addr_len, addr_len)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_futex ++SC_TRACE_EVENT(sys_futex, ++ TP_PROTO(u32 * uaddr, int op, u32 val, struct timespec * utime, u32 * uaddr2, u32 val3), ++ TP_ARGS(uaddr, op, val, utime, uaddr2, val3), ++ TP_STRUCT__entry(__field_hex(u32 *, uaddr) __field(int, op) __field(u32, val) __field_hex(struct timespec *, utime) __field_hex(u32 *, uaddr2) __field(u32, val3)), ++ TP_fast_assign(tp_assign(uaddr, uaddr) tp_assign(op, op) tp_assign(val, val) tp_assign(utime, utime) tp_assign(uaddr2, uaddr2) tp_assign(val3, val3)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_pselect6 ++SC_TRACE_EVENT(sys_pselect6, ++ TP_PROTO(int n, fd_set * inp, fd_set * outp, fd_set * exp, struct timespec * tsp, void * sig), ++ TP_ARGS(n, inp, outp, exp, tsp, sig), ++ TP_STRUCT__entry(__field(int, n) __field_hex(fd_set *, inp) __field_hex(fd_set *, outp) __field_hex(fd_set *, exp) __field_hex(struct timespec *, tsp) __field_hex(void *, sig)), ++ TP_fast_assign(tp_assign(n, n) tp_assign(inp, inp) tp_assign(outp, outp) tp_assign(exp, exp) tp_assign(tsp, tsp) tp_assign(sig, sig)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_splice ++SC_TRACE_EVENT(sys_splice, ++ TP_PROTO(int fd_in, loff_t * off_in, int fd_out, loff_t * off_out, size_t len, unsigned int flags), ++ TP_ARGS(fd_in, off_in, fd_out, off_out, len, flags), ++ TP_STRUCT__entry(__field(int, fd_in) __field_hex(loff_t *, off_in) __field(int, fd_out) __field_hex(loff_t *, off_out) __field(size_t, len) __field(unsigned int, flags)), ++ TP_fast_assign(tp_assign(fd_in, fd_in) tp_assign(off_in, off_in) tp_assign(fd_out, fd_out) tp_assign(off_out, off_out) tp_assign(len, len) tp_assign(flags, flags)), ++ TP_printk() ++) ++#endif ++#ifndef OVERRIDE_64_sys_epoll_pwait ++SC_TRACE_EVENT(sys_epoll_pwait, ++ TP_PROTO(int epfd, struct epoll_event * events, int maxevents, int timeout, const sigset_t * sigmask, size_t sigsetsize), ++ TP_ARGS(epfd, events, maxevents, timeout, sigmask, sigsetsize), ++ TP_STRUCT__entry(__field(int, epfd) __field_hex(struct epoll_event *, events) __field(int, maxevents) __field(int, timeout) __field_hex(const sigset_t *, sigmask) __field(size_t, sigsetsize)), ++ TP_fast_assign(tp_assign(epfd, epfd) tp_assign(events, events) tp_assign(maxevents, maxevents) tp_assign(timeout, timeout) tp_assign(sigmask, sigmask) tp_assign(sigsetsize, sigsetsize)), ++ TP_printk() ++) ++#endif ++ ++#endif /* _TRACE_SYSCALLS_POINTERS_H */ ++ ++/* This part must be outside protection */ ++#include "../../../probes/define_trace.h" ++ ++#else /* CREATE_SYSCALL_TABLE */ ++ ++#include "x86-64-syscalls-3.0.4_pointers_override.h" ++#include "syscalls_pointers_override.h" ++ ++#ifndef OVERRIDE_TABLE_64_sys_read ++TRACE_SYSCALL_TABLE(sys_read, sys_read, 0, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_write ++TRACE_SYSCALL_TABLE(sys_write, sys_write, 1, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_open ++TRACE_SYSCALL_TABLE(sys_open, sys_open, 2, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_newstat ++TRACE_SYSCALL_TABLE(sys_newstat, sys_newstat, 4, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_newfstat ++TRACE_SYSCALL_TABLE(sys_newfstat, sys_newfstat, 5, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_newlstat ++TRACE_SYSCALL_TABLE(sys_newlstat, sys_newlstat, 6, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_poll ++TRACE_SYSCALL_TABLE(sys_poll, sys_poll, 7, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rt_sigaction ++TRACE_SYSCALL_TABLE(sys_rt_sigaction, sys_rt_sigaction, 13, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rt_sigprocmask ++TRACE_SYSCALL_TABLE(sys_rt_sigprocmask, sys_rt_sigprocmask, 14, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_readv ++TRACE_SYSCALL_TABLE(sys_readv, sys_readv, 19, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_writev ++TRACE_SYSCALL_TABLE(sys_writev, sys_writev, 20, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_access ++TRACE_SYSCALL_TABLE(sys_access, sys_access, 21, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_pipe ++TRACE_SYSCALL_TABLE(sys_pipe, sys_pipe, 22, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_select ++TRACE_SYSCALL_TABLE(sys_select, sys_select, 23, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mincore ++TRACE_SYSCALL_TABLE(sys_mincore, sys_mincore, 27, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_shmat ++TRACE_SYSCALL_TABLE(sys_shmat, sys_shmat, 30, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_shmctl ++TRACE_SYSCALL_TABLE(sys_shmctl, sys_shmctl, 31, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_nanosleep ++TRACE_SYSCALL_TABLE(sys_nanosleep, sys_nanosleep, 35, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getitimer ++TRACE_SYSCALL_TABLE(sys_getitimer, sys_getitimer, 36, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setitimer ++TRACE_SYSCALL_TABLE(sys_setitimer, sys_setitimer, 38, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sendfile64 ++TRACE_SYSCALL_TABLE(sys_sendfile64, sys_sendfile64, 40, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_connect ++TRACE_SYSCALL_TABLE(sys_connect, sys_connect, 42, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_accept ++TRACE_SYSCALL_TABLE(sys_accept, sys_accept, 43, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sendto ++TRACE_SYSCALL_TABLE(sys_sendto, sys_sendto, 44, 6) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_recvfrom ++TRACE_SYSCALL_TABLE(sys_recvfrom, sys_recvfrom, 45, 6) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sendmsg ++TRACE_SYSCALL_TABLE(sys_sendmsg, sys_sendmsg, 46, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_recvmsg ++TRACE_SYSCALL_TABLE(sys_recvmsg, sys_recvmsg, 47, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_bind ++TRACE_SYSCALL_TABLE(sys_bind, sys_bind, 49, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getsockname ++TRACE_SYSCALL_TABLE(sys_getsockname, sys_getsockname, 51, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getpeername ++TRACE_SYSCALL_TABLE(sys_getpeername, sys_getpeername, 52, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_socketpair ++TRACE_SYSCALL_TABLE(sys_socketpair, sys_socketpair, 53, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setsockopt ++TRACE_SYSCALL_TABLE(sys_setsockopt, sys_setsockopt, 54, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getsockopt ++TRACE_SYSCALL_TABLE(sys_getsockopt, sys_getsockopt, 55, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_wait4 ++TRACE_SYSCALL_TABLE(sys_wait4, sys_wait4, 61, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_newuname ++TRACE_SYSCALL_TABLE(sys_newuname, sys_newuname, 63, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_semop ++TRACE_SYSCALL_TABLE(sys_semop, sys_semop, 65, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_shmdt ++TRACE_SYSCALL_TABLE(sys_shmdt, sys_shmdt, 67, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_msgsnd ++TRACE_SYSCALL_TABLE(sys_msgsnd, sys_msgsnd, 69, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_msgrcv ++TRACE_SYSCALL_TABLE(sys_msgrcv, sys_msgrcv, 70, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_msgctl ++TRACE_SYSCALL_TABLE(sys_msgctl, sys_msgctl, 71, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_truncate ++TRACE_SYSCALL_TABLE(sys_truncate, sys_truncate, 76, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getdents ++TRACE_SYSCALL_TABLE(sys_getdents, sys_getdents, 78, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getcwd ++TRACE_SYSCALL_TABLE(sys_getcwd, sys_getcwd, 79, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_chdir ++TRACE_SYSCALL_TABLE(sys_chdir, sys_chdir, 80, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rename ++TRACE_SYSCALL_TABLE(sys_rename, sys_rename, 82, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mkdir ++TRACE_SYSCALL_TABLE(sys_mkdir, sys_mkdir, 83, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rmdir ++TRACE_SYSCALL_TABLE(sys_rmdir, sys_rmdir, 84, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_creat ++TRACE_SYSCALL_TABLE(sys_creat, sys_creat, 85, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_link ++TRACE_SYSCALL_TABLE(sys_link, sys_link, 86, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_unlink ++TRACE_SYSCALL_TABLE(sys_unlink, sys_unlink, 87, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_symlink ++TRACE_SYSCALL_TABLE(sys_symlink, sys_symlink, 88, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_readlink ++TRACE_SYSCALL_TABLE(sys_readlink, sys_readlink, 89, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_chmod ++TRACE_SYSCALL_TABLE(sys_chmod, sys_chmod, 90, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_chown ++TRACE_SYSCALL_TABLE(sys_chown, sys_chown, 92, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_lchown ++TRACE_SYSCALL_TABLE(sys_lchown, sys_lchown, 94, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_gettimeofday ++TRACE_SYSCALL_TABLE(sys_gettimeofday, sys_gettimeofday, 96, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getrlimit ++TRACE_SYSCALL_TABLE(sys_getrlimit, sys_getrlimit, 97, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getrusage ++TRACE_SYSCALL_TABLE(sys_getrusage, sys_getrusage, 98, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sysinfo ++TRACE_SYSCALL_TABLE(sys_sysinfo, sys_sysinfo, 99, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_times ++TRACE_SYSCALL_TABLE(sys_times, sys_times, 100, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_syslog ++TRACE_SYSCALL_TABLE(sys_syslog, sys_syslog, 103, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getgroups ++TRACE_SYSCALL_TABLE(sys_getgroups, sys_getgroups, 115, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setgroups ++TRACE_SYSCALL_TABLE(sys_setgroups, sys_setgroups, 116, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getresuid ++TRACE_SYSCALL_TABLE(sys_getresuid, sys_getresuid, 118, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getresgid ++TRACE_SYSCALL_TABLE(sys_getresgid, sys_getresgid, 120, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rt_sigpending ++TRACE_SYSCALL_TABLE(sys_rt_sigpending, sys_rt_sigpending, 127, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rt_sigtimedwait ++TRACE_SYSCALL_TABLE(sys_rt_sigtimedwait, sys_rt_sigtimedwait, 128, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rt_sigqueueinfo ++TRACE_SYSCALL_TABLE(sys_rt_sigqueueinfo, sys_rt_sigqueueinfo, 129, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rt_sigsuspend ++TRACE_SYSCALL_TABLE(sys_rt_sigsuspend, sys_rt_sigsuspend, 130, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_utime ++TRACE_SYSCALL_TABLE(sys_utime, sys_utime, 132, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mknod ++TRACE_SYSCALL_TABLE(sys_mknod, sys_mknod, 133, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_ustat ++TRACE_SYSCALL_TABLE(sys_ustat, sys_ustat, 136, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_statfs ++TRACE_SYSCALL_TABLE(sys_statfs, sys_statfs, 137, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fstatfs ++TRACE_SYSCALL_TABLE(sys_fstatfs, sys_fstatfs, 138, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_setparam ++TRACE_SYSCALL_TABLE(sys_sched_setparam, sys_sched_setparam, 142, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_getparam ++TRACE_SYSCALL_TABLE(sys_sched_getparam, sys_sched_getparam, 143, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_setscheduler ++TRACE_SYSCALL_TABLE(sys_sched_setscheduler, sys_sched_setscheduler, 144, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_rr_get_interval ++TRACE_SYSCALL_TABLE(sys_sched_rr_get_interval, sys_sched_rr_get_interval, 148, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_pivot_root ++TRACE_SYSCALL_TABLE(sys_pivot_root, sys_pivot_root, 155, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sysctl ++TRACE_SYSCALL_TABLE(sys_sysctl, sys_sysctl, 156, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_adjtimex ++TRACE_SYSCALL_TABLE(sys_adjtimex, sys_adjtimex, 159, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setrlimit ++TRACE_SYSCALL_TABLE(sys_setrlimit, sys_setrlimit, 160, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_chroot ++TRACE_SYSCALL_TABLE(sys_chroot, sys_chroot, 161, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_settimeofday ++TRACE_SYSCALL_TABLE(sys_settimeofday, sys_settimeofday, 164, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mount ++TRACE_SYSCALL_TABLE(sys_mount, sys_mount, 165, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_umount ++TRACE_SYSCALL_TABLE(sys_umount, sys_umount, 166, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_swapon ++TRACE_SYSCALL_TABLE(sys_swapon, sys_swapon, 167, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_swapoff ++TRACE_SYSCALL_TABLE(sys_swapoff, sys_swapoff, 168, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_reboot ++TRACE_SYSCALL_TABLE(sys_reboot, sys_reboot, 169, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sethostname ++TRACE_SYSCALL_TABLE(sys_sethostname, sys_sethostname, 170, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setdomainname ++TRACE_SYSCALL_TABLE(sys_setdomainname, sys_setdomainname, 171, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_init_module ++TRACE_SYSCALL_TABLE(sys_init_module, sys_init_module, 175, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_delete_module ++TRACE_SYSCALL_TABLE(sys_delete_module, sys_delete_module, 176, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_nfsservctl ++TRACE_SYSCALL_TABLE(sys_nfsservctl, sys_nfsservctl, 180, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_setxattr ++TRACE_SYSCALL_TABLE(sys_setxattr, sys_setxattr, 188, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_lsetxattr ++TRACE_SYSCALL_TABLE(sys_lsetxattr, sys_lsetxattr, 189, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fsetxattr ++TRACE_SYSCALL_TABLE(sys_fsetxattr, sys_fsetxattr, 190, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getxattr ++TRACE_SYSCALL_TABLE(sys_getxattr, sys_getxattr, 191, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_lgetxattr ++TRACE_SYSCALL_TABLE(sys_lgetxattr, sys_lgetxattr, 192, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fgetxattr ++TRACE_SYSCALL_TABLE(sys_fgetxattr, sys_fgetxattr, 193, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_listxattr ++TRACE_SYSCALL_TABLE(sys_listxattr, sys_listxattr, 194, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_llistxattr ++TRACE_SYSCALL_TABLE(sys_llistxattr, sys_llistxattr, 195, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_flistxattr ++TRACE_SYSCALL_TABLE(sys_flistxattr, sys_flistxattr, 196, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_removexattr ++TRACE_SYSCALL_TABLE(sys_removexattr, sys_removexattr, 197, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_lremovexattr ++TRACE_SYSCALL_TABLE(sys_lremovexattr, sys_lremovexattr, 198, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fremovexattr ++TRACE_SYSCALL_TABLE(sys_fremovexattr, sys_fremovexattr, 199, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_time ++TRACE_SYSCALL_TABLE(sys_time, sys_time, 201, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_futex ++TRACE_SYSCALL_TABLE(sys_futex, sys_futex, 202, 6) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_setaffinity ++TRACE_SYSCALL_TABLE(sys_sched_setaffinity, sys_sched_setaffinity, 203, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sched_getaffinity ++TRACE_SYSCALL_TABLE(sys_sched_getaffinity, sys_sched_getaffinity, 204, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_io_setup ++TRACE_SYSCALL_TABLE(sys_io_setup, sys_io_setup, 206, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_io_getevents ++TRACE_SYSCALL_TABLE(sys_io_getevents, sys_io_getevents, 208, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_io_submit ++TRACE_SYSCALL_TABLE(sys_io_submit, sys_io_submit, 209, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_io_cancel ++TRACE_SYSCALL_TABLE(sys_io_cancel, sys_io_cancel, 210, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_getdents64 ++TRACE_SYSCALL_TABLE(sys_getdents64, sys_getdents64, 217, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_set_tid_address ++TRACE_SYSCALL_TABLE(sys_set_tid_address, sys_set_tid_address, 218, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_semtimedop ++TRACE_SYSCALL_TABLE(sys_semtimedop, sys_semtimedop, 220, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timer_create ++TRACE_SYSCALL_TABLE(sys_timer_create, sys_timer_create, 222, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timer_settime ++TRACE_SYSCALL_TABLE(sys_timer_settime, sys_timer_settime, 223, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timer_gettime ++TRACE_SYSCALL_TABLE(sys_timer_gettime, sys_timer_gettime, 224, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_clock_settime ++TRACE_SYSCALL_TABLE(sys_clock_settime, sys_clock_settime, 227, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_clock_gettime ++TRACE_SYSCALL_TABLE(sys_clock_gettime, sys_clock_gettime, 228, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_clock_getres ++TRACE_SYSCALL_TABLE(sys_clock_getres, sys_clock_getres, 229, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_clock_nanosleep ++TRACE_SYSCALL_TABLE(sys_clock_nanosleep, sys_clock_nanosleep, 230, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_epoll_wait ++TRACE_SYSCALL_TABLE(sys_epoll_wait, sys_epoll_wait, 232, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_epoll_ctl ++TRACE_SYSCALL_TABLE(sys_epoll_ctl, sys_epoll_ctl, 233, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_utimes ++TRACE_SYSCALL_TABLE(sys_utimes, sys_utimes, 235, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mq_open ++TRACE_SYSCALL_TABLE(sys_mq_open, sys_mq_open, 240, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mq_unlink ++TRACE_SYSCALL_TABLE(sys_mq_unlink, sys_mq_unlink, 241, 1) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mq_timedsend ++TRACE_SYSCALL_TABLE(sys_mq_timedsend, sys_mq_timedsend, 242, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mq_timedreceive ++TRACE_SYSCALL_TABLE(sys_mq_timedreceive, sys_mq_timedreceive, 243, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mq_notify ++TRACE_SYSCALL_TABLE(sys_mq_notify, sys_mq_notify, 244, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mq_getsetattr ++TRACE_SYSCALL_TABLE(sys_mq_getsetattr, sys_mq_getsetattr, 245, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_kexec_load ++TRACE_SYSCALL_TABLE(sys_kexec_load, sys_kexec_load, 246, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_waitid ++TRACE_SYSCALL_TABLE(sys_waitid, sys_waitid, 247, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_inotify_add_watch ++TRACE_SYSCALL_TABLE(sys_inotify_add_watch, sys_inotify_add_watch, 254, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_openat ++TRACE_SYSCALL_TABLE(sys_openat, sys_openat, 257, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mkdirat ++TRACE_SYSCALL_TABLE(sys_mkdirat, sys_mkdirat, 258, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_mknodat ++TRACE_SYSCALL_TABLE(sys_mknodat, sys_mknodat, 259, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fchownat ++TRACE_SYSCALL_TABLE(sys_fchownat, sys_fchownat, 260, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_futimesat ++TRACE_SYSCALL_TABLE(sys_futimesat, sys_futimesat, 261, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_newfstatat ++TRACE_SYSCALL_TABLE(sys_newfstatat, sys_newfstatat, 262, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_unlinkat ++TRACE_SYSCALL_TABLE(sys_unlinkat, sys_unlinkat, 263, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_renameat ++TRACE_SYSCALL_TABLE(sys_renameat, sys_renameat, 264, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_linkat ++TRACE_SYSCALL_TABLE(sys_linkat, sys_linkat, 265, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_symlinkat ++TRACE_SYSCALL_TABLE(sys_symlinkat, sys_symlinkat, 266, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_readlinkat ++TRACE_SYSCALL_TABLE(sys_readlinkat, sys_readlinkat, 267, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_fchmodat ++TRACE_SYSCALL_TABLE(sys_fchmodat, sys_fchmodat, 268, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_faccessat ++TRACE_SYSCALL_TABLE(sys_faccessat, sys_faccessat, 269, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_pselect6 ++TRACE_SYSCALL_TABLE(sys_pselect6, sys_pselect6, 270, 6) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_ppoll ++TRACE_SYSCALL_TABLE(sys_ppoll, sys_ppoll, 271, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_set_robust_list ++TRACE_SYSCALL_TABLE(sys_set_robust_list, sys_set_robust_list, 273, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_get_robust_list ++TRACE_SYSCALL_TABLE(sys_get_robust_list, sys_get_robust_list, 274, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_splice ++TRACE_SYSCALL_TABLE(sys_splice, sys_splice, 275, 6) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_vmsplice ++TRACE_SYSCALL_TABLE(sys_vmsplice, sys_vmsplice, 278, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_utimensat ++TRACE_SYSCALL_TABLE(sys_utimensat, sys_utimensat, 280, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_epoll_pwait ++TRACE_SYSCALL_TABLE(sys_epoll_pwait, sys_epoll_pwait, 281, 6) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_signalfd ++TRACE_SYSCALL_TABLE(sys_signalfd, sys_signalfd, 282, 3) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timerfd_settime ++TRACE_SYSCALL_TABLE(sys_timerfd_settime, sys_timerfd_settime, 286, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_timerfd_gettime ++TRACE_SYSCALL_TABLE(sys_timerfd_gettime, sys_timerfd_gettime, 287, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_accept4 ++TRACE_SYSCALL_TABLE(sys_accept4, sys_accept4, 288, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_signalfd4 ++TRACE_SYSCALL_TABLE(sys_signalfd4, sys_signalfd4, 289, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_pipe2 ++TRACE_SYSCALL_TABLE(sys_pipe2, sys_pipe2, 293, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_preadv ++TRACE_SYSCALL_TABLE(sys_preadv, sys_preadv, 295, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_pwritev ++TRACE_SYSCALL_TABLE(sys_pwritev, sys_pwritev, 296, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_rt_tgsigqueueinfo ++TRACE_SYSCALL_TABLE(sys_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo, 297, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_perf_event_open ++TRACE_SYSCALL_TABLE(sys_perf_event_open, sys_perf_event_open, 298, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_recvmmsg ++TRACE_SYSCALL_TABLE(sys_recvmmsg, sys_recvmmsg, 299, 5) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_prlimit64 ++TRACE_SYSCALL_TABLE(sys_prlimit64, sys_prlimit64, 302, 4) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_clock_adjtime ++TRACE_SYSCALL_TABLE(sys_clock_adjtime, sys_clock_adjtime, 305, 2) ++#endif ++#ifndef OVERRIDE_TABLE_64_sys_sendmmsg ++TRACE_SYSCALL_TABLE(sys_sendmmsg, sys_sendmmsg, 307, 4) ++#endif ++ ++#endif /* CREATE_SYSCALL_TABLE */ +diff --git 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 +new file mode 100644 +index 0000000..0cdb32a +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/headers/x86-64-syscalls-3.0.4_pointers_override.h +@@ -0,0 +1,5 @@ ++#ifndef CREATE_SYSCALL_TABLE ++ ++#else /* CREATE_SYSCALL_TABLE */ ++ ++#endif /* CREATE_SYSCALL_TABLE */ +diff --git a/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/Makefile b/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/Makefile +new file mode 100644 +index 0000000..4beb88c +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/Makefile +@@ -0,0 +1 @@ ++obj-m += lttng-syscalls-extractor.o +diff --git 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 +new file mode 100644 +index 0000000..06c0da1 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-extractor/lttng-syscalls-extractor.c +@@ -0,0 +1,85 @@ ++/* ++ * Copyright 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * Copyright 2011 - Julien Desfossez <julien.desfossez@polymtl.ca> ++ * ++ * Dump syscall metadata to console. ++ * ++ * GPLv2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/types.h> ++#include <linux/list.h> ++#include <linux/err.h> ++#include <linux/slab.h> ++#include <linux/kallsyms.h> ++#include <linux/dcache.h> ++#include <linux/ftrace_event.h> ++#include <trace/syscall.h> ++ ++#ifndef CONFIG_FTRACE_SYSCALLS ++#error "You need to set CONFIG_FTRACE_SYSCALLS=y" ++#endif ++ ++#ifndef CONFIG_KALLSYMS_ALL ++#error "You need to set CONFIG_KALLSYMS_ALL=y" ++#endif ++ ++static struct syscall_metadata **__start_syscalls_metadata; ++static struct syscall_metadata **__stop_syscalls_metadata; ++ ++static __init ++struct syscall_metadata *find_syscall_meta(unsigned long syscall) ++{ ++ struct syscall_metadata **iter; ++ ++ for (iter = __start_syscalls_metadata; ++ iter < __stop_syscalls_metadata; iter++) { ++ if ((*iter)->syscall_nr == syscall) ++ return (*iter); ++ } ++ return NULL; ++} ++ ++int init_module(void) ++{ ++ struct syscall_metadata *meta; ++ int i; ++ ++ __start_syscalls_metadata = (void *) kallsyms_lookup_name("__start_syscalls_metadata"); ++ __stop_syscalls_metadata = (void *) kallsyms_lookup_name("__stop_syscalls_metadata"); ++ ++ for (i = 0; i < NR_syscalls; i++) { ++ int j; ++ ++ meta = find_syscall_meta(i); ++ if (!meta) ++ continue; ++ printk("syscall %s nr %d nbargs %d ", ++ meta->name, meta->syscall_nr, meta->nb_args); ++ printk("types: ("); ++ for (j = 0; j < meta->nb_args; j++) { ++ if (j > 0) ++ printk(", "); ++ printk("%s", meta->types[j]); ++ } ++ printk(") "); ++ printk("args: ("); ++ for (j = 0; j < meta->nb_args; j++) { ++ if (j > 0) ++ printk(", "); ++ printk("%s", meta->args[j]); ++ } ++ printk(")\n"); ++ } ++ printk("SUCCESS\n"); ++ ++ return -1; ++} ++ ++void cleanup_module(void) ++{ ++} ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-generate-headers.sh b/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-generate-headers.sh +new file mode 100644 +index 0000000..5eddb27 +--- /dev/null ++++ b/drivers/staging/lttng/instrumentation/syscalls/lttng-syscalls-generate-headers.sh +@@ -0,0 +1,275 @@ ++#!/bin/sh ++ ++# Generate system call probe description macros from syscall metadata dump file. ++# example usage: ++# ++# lttng-syscalls-generate-headers.sh integers 3.0.4 x86-64-syscalls-3.0.4 64 ++# lttng-syscalls-generate-headers.sh pointers 3.0.4 x86-64-syscalls-3.0.4 64 ++ ++CLASS=$1 ++INPUTDIR=$2 ++INPUTFILE=$3 ++BITNESS=$4 ++INPUT=${INPUTDIR}/${INPUTFILE} ++SRCFILE=gen.tmp.0 ++TMPFILE=gen.tmp.1 ++HEADER=headers/${INPUTFILE}_${CLASS}.h ++ ++cp ${INPUT} ${SRCFILE} ++ ++#Cleanup ++perl -p -e 's/^\[.*\] //g' ${SRCFILE} > ${TMPFILE} ++mv ${TMPFILE} ${SRCFILE} ++ ++perl -p -e 's/^syscall sys_([^ ]*)/syscall $1/g' ${SRCFILE} > ${TMPFILE} ++mv ${TMPFILE} ${SRCFILE} ++ ++#Filter ++ ++if [ "$CLASS" = integers ]; then ++ #select integers and no-args. ++ CLASSCAP=INTEGERS ++ grep -v "\\*\|cap_user_header_t" ${SRCFILE} > ${TMPFILE} ++ mv ${TMPFILE} ${SRCFILE} ++fi ++ ++ ++if [ "$CLASS" = pointers ]; then ++ #select system calls using pointers. ++ CLASSCAP=POINTERS ++ grep "\\*\|cap_#user_header_t" ${SRCFILE} > ${TMPFILE} ++ mv ${TMPFILE} ${SRCFILE} ++fi ++ ++echo "/* THIS FILE IS AUTO-GENERATED. DO NOT EDIT */" > ${HEADER} ++ ++echo \ ++"#ifndef CREATE_SYSCALL_TABLE ++ ++#if !defined(_TRACE_SYSCALLS_${CLASSCAP}_H) || defined(TRACE_HEADER_MULTI_READ) ++#define _TRACE_SYSCALLS_${CLASSCAP}_H ++ ++#include <linux/tracepoint.h> ++#include <linux/syscalls.h> ++#include \"${INPUTFILE}_${CLASS}_override.h\" ++#include \"syscalls_${CLASS}_override.h\" ++" >> ${HEADER} ++ ++if [ "$CLASS" = integers ]; then ++ ++NRARGS=0 ++ ++echo \ ++'SC_DECLARE_EVENT_CLASS_NOARGS(syscalls_noargs,\n'\ ++' TP_STRUCT__entry(),\n'\ ++' TP_fast_assign(),\n'\ ++' TP_printk()\n'\ ++')'\ ++ >> ${HEADER} ++ ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) '\ ++'types: \(([^)]*)\) '\ ++'args: \(([^)]*)\)/'\ ++'#ifndef OVERRIDE_'"${BITNESS}"'_sys_$1\n'\ ++'SC_DEFINE_EVENT_NOARGS(syscalls_noargs, sys_$1)\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++fi ++ ++ ++# types: 4 ++# args 5 ++ ++NRARGS=1 ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) '\ ++'types: \(([^)]*)\) '\ ++'args: \(([^)]*)\)/'\ ++'#ifndef OVERRIDE_'"${BITNESS}"'_sys_$1\n'\ ++'SC_TRACE_EVENT(sys_$1,\n'\ ++' TP_PROTO($4 $5),\n'\ ++' TP_ARGS($5),\n'\ ++' TP_STRUCT__entry(__field($4, $5)),\n'\ ++' TP_fast_assign(tp_assign($4, $5, $5)),\n'\ ++' TP_printk()\n'\ ++')\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++# types: 4 5 ++# args 6 7 ++ ++NRARGS=2 ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) '\ ++'types: \(([^,]*), ([^)]*)\) '\ ++'args: \(([^,]*), ([^)]*)\)/'\ ++'#ifndef OVERRIDE_'"${BITNESS}"'_sys_$1\n'\ ++'SC_TRACE_EVENT(sys_$1,\n'\ ++' TP_PROTO($4 $6, $5 $7),\n'\ ++' TP_ARGS($6, $7),\n'\ ++' TP_STRUCT__entry(__field($4, $6) __field($5, $7)),\n'\ ++' TP_fast_assign(tp_assign($4, $6, $6) tp_assign($5, $7, $7)),\n'\ ++' TP_printk()\n'\ ++')\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++# types: 4 5 6 ++# args 7 8 9 ++ ++NRARGS=3 ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) '\ ++'types: \(([^,]*), ([^,]*), ([^)]*)\) '\ ++'args: \(([^,]*), ([^,]*), ([^)]*)\)/'\ ++'#ifndef OVERRIDE_'"${BITNESS}"'_sys_$1\n'\ ++'SC_TRACE_EVENT(sys_$1,\n'\ ++' TP_PROTO($4 $7, $5 $8, $6 $9),\n'\ ++' TP_ARGS($7, $8, $9),\n'\ ++' TP_STRUCT__entry(__field($4, $7) __field($5, $8) __field($6, $9)),\n'\ ++' TP_fast_assign(tp_assign($4, $7, $7) tp_assign($5, $8, $8) tp_assign($6, $9, $9)),\n'\ ++' TP_printk()\n'\ ++')\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++ ++# types: 4 5 6 7 ++# args 8 9 10 11 ++ ++NRARGS=4 ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) '\ ++'types: \(([^,]*), ([^,]*), ([^,]*), ([^)]*)\) '\ ++'args: \(([^,]*), ([^,]*), ([^,]*), ([^)]*)\)/'\ ++'#ifndef OVERRIDE_'"${BITNESS}"'_sys_$1\n'\ ++'SC_TRACE_EVENT(sys_$1,\n'\ ++' TP_PROTO($4 $8, $5 $9, $6 $10, $7 $11),\n'\ ++' TP_ARGS($8, $9, $10, $11),\n'\ ++' TP_STRUCT__entry(__field($4, $8) __field($5, $9) __field($6, $10) __field($7, $11)),\n'\ ++' TP_fast_assign(tp_assign($4, $8, $8) tp_assign($5, $9, $9) tp_assign($6, $10, $10) tp_assign($7, $11, $11)),\n'\ ++' TP_printk()\n'\ ++')\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++# types: 4 5 6 7 8 ++# args 9 10 11 12 13 ++ ++NRARGS=5 ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) '\ ++'types: \(([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^)]*)\) '\ ++'args: \(([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^)]*)\)/'\ ++'#ifndef OVERRIDE_'"${BITNESS}"'_sys_$1\n'\ ++'SC_TRACE_EVENT(sys_$1,\n'\ ++' TP_PROTO($4 $9, $5 $10, $6 $11, $7 $12, $8 $13),\n'\ ++' TP_ARGS($9, $10, $11, $12, $13),\n'\ ++' TP_STRUCT__entry(__field($4, $9) __field($5, $10) __field($6, $11) __field($7, $12) __field($8, $13)),\n'\ ++' TP_fast_assign(tp_assign($4, $9, $9) tp_assign($5, $10, $10) tp_assign($6, $11, $11) tp_assign($7, $12, $12) tp_assign($8, $13, $13)),\n'\ ++' TP_printk()\n'\ ++')\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++ ++# types: 4 5 6 7 8 9 ++# args 10 11 12 13 14 15 ++ ++NRARGS=6 ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) '\ ++'types: \(([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^\)]*)\) '\ ++'args: \(([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^,]*), ([^\)]*)\)/'\ ++'#ifndef OVERRIDE_'"${BITNESS}"'_sys_$1\n'\ ++'SC_TRACE_EVENT(sys_$1,\n'\ ++' TP_PROTO($4 $10, $5 $11, $6 $12, $7 $13, $8 $14, $9 $15),\n'\ ++' TP_ARGS($10, $11, $12, $13, $14, $15),\n'\ ++' TP_STRUCT__entry(__field($4, $10) __field($5, $11) __field($6, $12) __field($7, $13) __field($8, $14) __field($9, $15)),\n'\ ++' TP_fast_assign(tp_assign($4, $10, $10) tp_assign($5, $11, $11) tp_assign($6, $12, $12) tp_assign($7, $13, $13) tp_assign($8, $14, $14) tp_assign($9, $15, $15)),\n'\ ++' TP_printk()\n'\ ++')\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++# Macro for tracing syscall table ++ ++rm -f ${TMPFILE} ++for NRARGS in $(seq 0 6); do ++ grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} >> ${TMPFILE} ++done ++ ++echo \ ++" ++#endif /* _TRACE_SYSCALLS_${CLASSCAP}_H */ ++ ++/* This part must be outside protection */ ++#include \"../../../probes/define_trace.h\" ++ ++#else /* CREATE_SYSCALL_TABLE */ ++ ++#include \"${INPUTFILE}_${CLASS}_override.h\" ++#include \"syscalls_${CLASS}_override.h\" ++" >> ${HEADER} ++ ++NRARGS=0 ++ ++if [ "$CLASS" = integers ]; then ++#noargs ++grep "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) .*$/'\ ++'#ifndef OVERRIDE_TABLE_'"${BITNESS}"'_sys_$1\n'\ ++'TRACE_SYSCALL_TABLE\(syscalls_noargs, sys_$1, $2, $3\)\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++fi ++ ++#others. ++grep -v "^syscall [^ ]* nr [^ ]* nbargs ${NRARGS} " ${SRCFILE} > ${TMPFILE} ++perl -p -e 's/^syscall ([^ ]*) nr ([^ ]*) nbargs ([^ ]*) .*$/'\ ++'#ifndef OVERRIDE_TABLE_'"${BITNESS}"'_sys_$1\n'\ ++'TRACE_SYSCALL_TABLE(sys_$1, sys_$1, $2, $3)\n'\ ++'#endif/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++echo -n \ ++" ++#endif /* CREATE_SYSCALL_TABLE */ ++" >> ${HEADER} ++ ++#fields names: ...char * type with *name* or *file* or *path* or *root* ++# or *put_old* or *type* ++cp -f ${HEADER} ${TMPFILE} ++rm -f ${HEADER} ++perl -p -e 's/__field\(([^,)]*char \*), ([^\)]*)(name|file|path|root|put_old|type)([^\)]*)\)/__string_from_user($2$3$4, $2$3$4)/g'\ ++ ${TMPFILE} >> ${HEADER} ++cp -f ${HEADER} ${TMPFILE} ++rm -f ${HEADER} ++perl -p -e 's/tp_assign\(([^,)]*char \*), ([^,]*)(name|file|path|root|put_old|type)([^,]*), ([^\)]*)\)/tp_copy_string_from_user($2$3$4, $5)/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++#prettify addresses heuristics. ++#field names with addr or ptr ++cp -f ${HEADER} ${TMPFILE} ++rm -f ${HEADER} ++perl -p -e 's/__field\(([^,)]*), ([^,)]*addr|[^,)]*ptr)([^),]*)\)/__field_hex($1, $2$3)/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++#field types ending with '*' ++cp -f ${HEADER} ${TMPFILE} ++rm -f ${HEADER} ++perl -p -e 's/__field\(([^,)]*\*), ([^),]*)\)/__field_hex($1, $2)/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++#strip the extra type information from tp_assign. ++cp -f ${HEADER} ${TMPFILE} ++rm -f ${HEADER} ++perl -p -e 's/tp_assign\(([^,)]*), ([^,]*), ([^\)]*)\)/tp_assign($2, $3)/g'\ ++ ${TMPFILE} >> ${HEADER} ++ ++rm -f ${INPUTFILE}.tmp ++rm -f ${TMPFILE} ++rm -f ${SRCFILE} +-- +1.7.9 + diff --git a/patches.lttng/0009-lttng-lib-ring-buffer-clients.patch b/patches.lttng/0009-lttng-lib-ring-buffer-clients.patch new file mode 100644 index 0000000000000..39826468e4988 --- /dev/null +++ b/patches.lttng/0009-lttng-lib-ring-buffer-clients.patch @@ -0,0 +1,1106 @@ +From 6857797120e99facc465a972026038199e4c2356 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:17 -0500 +Subject: lttng: lib ring buffer clients + +Each lttng buffer configuration (discard mode, overwrite mode, mmap +support, splice support, per-cpu buffers, global buffer for metadata) is +a lib ring buffer client. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + .../staging/lttng/ltt-ring-buffer-client-discard.c | 21 + + .../lttng/ltt-ring-buffer-client-mmap-discard.c | 21 + + .../lttng/ltt-ring-buffer-client-mmap-overwrite.c | 21 + + .../lttng/ltt-ring-buffer-client-overwrite.c | 21 + + drivers/staging/lttng/ltt-ring-buffer-client.h | 569 ++++++++++++++++++++ + .../lttng/ltt-ring-buffer-metadata-client.c | 21 + + .../lttng/ltt-ring-buffer-metadata-client.h | 330 ++++++++++++ + .../lttng/ltt-ring-buffer-metadata-mmap-client.c | 21 + + 8 files changed, 1025 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-client-discard.c + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-client-mmap-discard.c + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-client-mmap-overwrite.c + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-client-overwrite.c + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-client.h + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-metadata-client.c + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-metadata-client.h + create mode 100644 drivers/staging/lttng/ltt-ring-buffer-metadata-mmap-client.c + +diff --git a/drivers/staging/lttng/ltt-ring-buffer-client-discard.c b/drivers/staging/lttng/ltt-ring-buffer-client-discard.c +new file mode 100644 +index 0000000..eafcf45 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-client-discard.c +@@ -0,0 +1,21 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-ring-buffer-client-mmap-discard.c b/drivers/staging/lttng/ltt-ring-buffer-client-mmap-discard.c +new file mode 100644 +index 0000000..29819a7 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-client-mmap-discard.c +@@ -0,0 +1,21 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-ring-buffer-client-mmap-overwrite.c b/drivers/staging/lttng/ltt-ring-buffer-client-mmap-overwrite.c +new file mode 100644 +index 0000000..741aa7b +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-client-mmap-overwrite.c +@@ -0,0 +1,21 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-ring-buffer-client-overwrite.c b/drivers/staging/lttng/ltt-ring-buffer-client-overwrite.c +new file mode 100644 +index 0000000..9811941 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-client-overwrite.c +@@ -0,0 +1,21 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-ring-buffer-client.h b/drivers/staging/lttng/ltt-ring-buffer-client.h +new file mode 100644 +index 0000000..8df3790 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-client.h +@@ -0,0 +1,569 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-ring-buffer-metadata-client.c b/drivers/staging/lttng/ltt-ring-buffer-metadata-client.c +new file mode 100644 +index 0000000..ac6fe78 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-metadata-client.c +@@ -0,0 +1,21 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-ring-buffer-metadata-client.h b/drivers/staging/lttng/ltt-ring-buffer-metadata-client.h +new file mode 100644 +index 0000000..529bbb1 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-metadata-client.h +@@ -0,0 +1,330 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-ring-buffer-metadata-mmap-client.c b/drivers/staging/lttng/ltt-ring-buffer-metadata-mmap-client.c +new file mode 100644 +index 0000000..5cad3f9 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-ring-buffer-metadata-mmap-client.c +@@ -0,0 +1,21 @@ ++/* ++ * 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"); +-- +1.7.9 + diff --git a/patches.lttng/0010-lttng-tracer-control-and-core-structures.patch b/patches.lttng/0010-lttng-tracer-control-and-core-structures.patch new file mode 100644 index 0000000000000..7c3541e84d019 --- /dev/null +++ b/patches.lttng/0010-lttng-tracer-control-and-core-structures.patch @@ -0,0 +1,1812 @@ +From ccc7340a9415839763e872bceb626638c58174a1 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:18 -0500 +Subject: lttng: tracer control and core structures + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + 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-tracer-core.h | 28 + + drivers/staging/lttng/ltt-tracer.h | 67 ++ + 6 files changed, 1751 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/ltt-endian.h + create mode 100644 drivers/staging/lttng/ltt-events.c + create mode 100644 drivers/staging/lttng/ltt-events.h + create mode 100644 drivers/staging/lttng/ltt-probes.c + create mode 100644 drivers/staging/lttng/ltt-tracer-core.h + create mode 100644 drivers/staging/lttng/ltt-tracer.h + +diff --git a/drivers/staging/lttng/ltt-endian.h b/drivers/staging/lttng/ltt-endian.h +new file mode 100644 +index 0000000..9a0512d +--- /dev/null ++++ b/drivers/staging/lttng/ltt-endian.h +@@ -0,0 +1,31 @@ ++#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 */ +diff --git a/drivers/staging/lttng/ltt-events.c b/drivers/staging/lttng/ltt-events.c +new file mode 100644 +index 0000000..4229914 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-events.c +@@ -0,0 +1,1009 @@ ++/* ++ * 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"); +diff --git a/drivers/staging/lttng/ltt-events.h b/drivers/staging/lttng/ltt-events.h +new file mode 100644 +index 0000000..36b281a +--- /dev/null ++++ b/drivers/staging/lttng/ltt-events.h +@@ -0,0 +1,452 @@ ++#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 */ ++ unsigned int signedness:1; ++ unsigned int 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 */ ++ int 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 */ ++ int 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 */ ++ int 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 */ +diff --git a/drivers/staging/lttng/ltt-probes.c b/drivers/staging/lttng/ltt-probes.c +new file mode 100644 +index 0000000..81dcbd7 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-probes.c +@@ -0,0 +1,164 @@ ++/* ++ * 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, ++}; +diff --git a/drivers/staging/lttng/ltt-tracer-core.h b/drivers/staging/lttng/ltt-tracer-core.h +new file mode 100644 +index 0000000..5abc432 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-tracer-core.h +@@ -0,0 +1,28 @@ ++#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 */ +diff --git a/drivers/staging/lttng/ltt-tracer.h b/drivers/staging/lttng/ltt-tracer.h +new file mode 100644 +index 0000000..a21c38c +--- /dev/null ++++ b/drivers/staging/lttng/ltt-tracer.h +@@ -0,0 +1,67 @@ ++#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 */ +-- +1.7.9 + diff --git a/patches.lttng/0011-lttng-dynamically-selectable-context-information.patch b/patches.lttng/0011-lttng-dynamically-selectable-context-information.patch new file mode 100644 index 0000000000000..e10ed06438f23 --- /dev/null +++ b/patches.lttng/0011-lttng-dynamically-selectable-context-information.patch @@ -0,0 +1,1131 @@ +From 6c19da3578bc0ae0d3a65560b7ac7963a35ea79c Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:19 -0500 +Subject: lttng: dynamically selectable context information + +Events can be augmented with context information. This is dynamically +configurable from the command line. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/ltt-context.c | 93 +++++++ + drivers/staging/lttng/lttng-context-nice.c | 68 +++++ + .../staging/lttng/lttng-context-perf-counters.c | 271 ++++++++++++++++++++ + drivers/staging/lttng/lttng-context-pid.c | 68 +++++ + drivers/staging/lttng/lttng-context-ppid.c | 71 +++++ + drivers/staging/lttng/lttng-context-prio.c | 89 +++++++ + drivers/staging/lttng/lttng-context-procname.c | 72 +++++ + drivers/staging/lttng/lttng-context-tid.c | 68 +++++ + drivers/staging/lttng/lttng-context-vpid.c | 74 ++++++ + drivers/staging/lttng/lttng-context-vppid.c | 79 ++++++ + drivers/staging/lttng/lttng-context-vtid.c | 74 ++++++ + 11 files changed, 1027 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/ltt-context.c + create mode 100644 drivers/staging/lttng/lttng-context-nice.c + create mode 100644 drivers/staging/lttng/lttng-context-perf-counters.c + create mode 100644 drivers/staging/lttng/lttng-context-pid.c + create mode 100644 drivers/staging/lttng/lttng-context-ppid.c + create mode 100644 drivers/staging/lttng/lttng-context-prio.c + create mode 100644 drivers/staging/lttng/lttng-context-procname.c + create mode 100644 drivers/staging/lttng/lttng-context-tid.c + create mode 100644 drivers/staging/lttng/lttng-context-vpid.c + create mode 100644 drivers/staging/lttng/lttng-context-vppid.c + create mode 100644 drivers/staging/lttng/lttng-context-vtid.c + +diff --git a/drivers/staging/lttng/ltt-context.c b/drivers/staging/lttng/ltt-context.c +new file mode 100644 +index 0000000..60ea525 +--- /dev/null ++++ b/drivers/staging/lttng/ltt-context.c +@@ -0,0 +1,93 @@ ++/* ++ * 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); ++} +diff --git a/drivers/staging/lttng/lttng-context-nice.c b/drivers/staging/lttng/lttng-context-nice.c +new file mode 100644 +index 0000000..9b99b54 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-nice.c +@@ -0,0 +1,68 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng nice context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-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 += sizeof(int); ++ return size; ++} ++ ++static ++void nice_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ int nice; ++ ++ nice = task_nice(current); ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(nice)); ++ chan->ops->event_write(ctx, &nice, sizeof(nice)); ++} ++ ++int lttng_add_nice_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "nice")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = nice_get_size; ++ field->record = nice_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_nice_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit Nice Context"); +diff --git a/drivers/staging/lttng/lttng-context-perf-counters.c b/drivers/staging/lttng/lttng-context-perf-counters.c +new file mode 100644 +index 0000000..3ae2266 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-perf-counters.c +@@ -0,0 +1,271 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng performance monitoring counters (perf-counters) integration module. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/perf_event.h> ++#include <linux/list.h> ++#include <linux/string.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "wrapper/perf.h" ++#include "ltt-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 += sizeof(uint64_t); ++ return size; ++} ++ ++static ++void perf_counter_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ struct perf_event *event; ++ uint64_t value; ++ ++ event = field->u.perf_counter->e[ctx->cpu]; ++ if (likely(event)) { ++ if (unlikely(event->state == PERF_EVENT_STATE_ERROR)) { ++ value = 0; ++ } else { ++ event->pmu->read(event); ++ value = local64_read(&event->count); ++ } ++ } else { ++ /* ++ * Perf chooses not to be clever and not to support enabling a ++ * perf counter before the cpu is brought up. Therefore, we need ++ * to support having events coming (e.g. scheduler events) ++ * before the counter is setup. Write an arbitrary 0 in this ++ * case. ++ */ ++ value = 0; ++ } ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(value)); ++ chan->ops->event_write(ctx, &value, sizeof(value)); ++} ++ ++#if defined(CONFIG_PERF_EVENTS) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,99)) ++static ++void overflow_callback(struct perf_event *event, ++ struct perf_sample_data *data, ++ struct pt_regs *regs) ++{ ++} ++#else ++static ++void overflow_callback(struct perf_event *event, int nmi, ++ struct perf_sample_data *data, ++ struct pt_regs *regs) ++{ ++} ++#endif ++ ++static ++void lttng_destroy_perf_counter_field(struct lttng_ctx_field *field) ++{ ++ struct perf_event **events = field->u.perf_counter->e; ++ int cpu; ++ ++ get_online_cpus(); ++ for_each_online_cpu(cpu) ++ perf_event_release_kernel(events[cpu]); ++ put_online_cpus(); ++#ifdef CONFIG_HOTPLUG_CPU ++ unregister_cpu_notifier(&field->u.perf_counter->nb); ++#endif ++ kfree(field->event_field.name); ++ kfree(field->u.perf_counter->attr); ++ kfree(events); ++ kfree(field->u.perf_counter); ++} ++ ++#ifdef CONFIG_HOTPLUG_CPU ++ ++/** ++ * lttng_perf_counter_hp_callback - CPU hotplug callback ++ * @nb: notifier block ++ * @action: hotplug action to take ++ * @hcpu: CPU number ++ * ++ * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD) ++ * ++ * We can setup perf counters when the cpu is online (up prepare seems to be too ++ * soon). ++ */ ++static ++int __cpuinit lttng_perf_counter_cpu_hp_callback(struct notifier_block *nb, ++ unsigned long action, ++ void *hcpu) ++{ ++ unsigned int cpu = (unsigned long) hcpu; ++ struct lttng_perf_counter_field *perf_field = ++ container_of(nb, struct lttng_perf_counter_field, nb); ++ struct perf_event **events = perf_field->e; ++ struct perf_event_attr *attr = perf_field->attr; ++ struct perf_event *pevent; ++ ++ if (!perf_field->hp_enable) ++ return NOTIFY_OK; ++ ++ switch (action) { ++ case CPU_ONLINE: ++ case CPU_ONLINE_FROZEN: ++ pevent = wrapper_perf_event_create_kernel_counter(attr, ++ cpu, NULL, overflow_callback); ++ if (!pevent || IS_ERR(pevent)) ++ return NOTIFY_BAD; ++ if (pevent->state == PERF_EVENT_STATE_ERROR) { ++ perf_event_release_kernel(pevent); ++ return NOTIFY_BAD; ++ } ++ barrier(); /* Create perf counter before setting event */ ++ events[cpu] = pevent; ++ break; ++ case CPU_UP_CANCELED: ++ case CPU_UP_CANCELED_FROZEN: ++ case CPU_DEAD: ++ case CPU_DEAD_FROZEN: ++ pevent = events[cpu]; ++ events[cpu] = NULL; ++ barrier(); /* NULLify event before perf counter teardown */ ++ perf_event_release_kernel(pevent); ++ break; ++ } ++ return NOTIFY_OK; ++} ++ ++#endif ++ ++int lttng_add_perf_counter_to_ctx(uint32_t type, ++ uint64_t config, ++ const char *name, ++ struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ struct lttng_perf_counter_field *perf_field; ++ struct perf_event **events; ++ struct perf_event_attr *attr; ++ int ret; ++ int cpu; ++ char *name_alloc; ++ ++ events = kzalloc(num_possible_cpus() * sizeof(*events), GFP_KERNEL); ++ if (!events) ++ return -ENOMEM; ++ ++ attr = kzalloc(sizeof(struct perf_event_attr), GFP_KERNEL); ++ if (!attr) { ++ ret = -ENOMEM; ++ goto error_attr; ++ } ++ ++ attr->type = type; ++ attr->config = config; ++ attr->size = sizeof(struct perf_event_attr); ++ attr->pinned = 1; ++ attr->disabled = 0; ++ ++ perf_field = kzalloc(sizeof(struct lttng_perf_counter_field), GFP_KERNEL); ++ if (!perf_field) { ++ ret = -ENOMEM; ++ goto error_alloc_perf_field; ++ } ++ perf_field->e = events; ++ perf_field->attr = attr; ++ ++ name_alloc = kstrdup(name, GFP_KERNEL); ++ if (!name_alloc) { ++ ret = -ENOMEM; ++ goto name_alloc_error; ++ } ++ ++ field = lttng_append_context(ctx); ++ if (!field) { ++ ret = -ENOMEM; ++ goto append_context_error; ++ } ++ if (lttng_find_context(*ctx, name_alloc)) { ++ ret = -EEXIST; ++ goto find_error; ++ } ++ ++#ifdef CONFIG_HOTPLUG_CPU ++ perf_field->nb.notifier_call = ++ lttng_perf_counter_cpu_hp_callback; ++ perf_field->nb.priority = 0; ++ register_cpu_notifier(&perf_field->nb); ++#endif ++ ++ get_online_cpus(); ++ for_each_online_cpu(cpu) { ++ events[cpu] = wrapper_perf_event_create_kernel_counter(attr, ++ cpu, NULL, overflow_callback); ++ if (!events[cpu] || IS_ERR(events[cpu])) { ++ ret = -EINVAL; ++ goto counter_error; ++ } ++ if (events[cpu]->state == PERF_EVENT_STATE_ERROR) { ++ ret = -EBUSY; ++ goto counter_busy; ++ } ++ } ++ put_online_cpus(); ++ ++ field->destroy = lttng_destroy_perf_counter_field; ++ ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = perf_counter_get_size; ++ field->record = perf_counter_record; ++ field->u.perf_counter = perf_field; ++ perf_field->hp_enable = 1; ++ ++ wrapper_vmalloc_sync_all(); ++ return 0; ++ ++counter_busy: ++counter_error: ++ for_each_online_cpu(cpu) { ++ if (events[cpu] && !IS_ERR(events[cpu])) ++ perf_event_release_kernel(events[cpu]); ++ } ++ put_online_cpus(); ++#ifdef CONFIG_HOTPLUG_CPU ++ unregister_cpu_notifier(&perf_field->nb); ++#endif ++find_error: ++ lttng_remove_context_field(ctx, field); ++append_context_error: ++ kfree(name_alloc); ++name_alloc_error: ++ kfree(perf_field); ++error_alloc_perf_field: ++ kfree(attr); ++error_attr: ++ kfree(events); ++ return ret; ++} ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit Perf Support"); +diff --git a/drivers/staging/lttng/lttng-context-pid.c b/drivers/staging/lttng/lttng-context-pid.c +new file mode 100644 +index 0000000..698b242 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-pid.c +@@ -0,0 +1,68 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng PID context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-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 += sizeof(pid_t); ++ return size; ++} ++ ++static ++void pid_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ pid_t pid; ++ ++ pid = task_tgid_nr(current); ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(pid)); ++ chan->ops->event_write(ctx, &pid, sizeof(pid)); ++} ++ ++int lttng_add_pid_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "pid")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = pid_get_size; ++ field->record = pid_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_pid_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit PID Context"); +diff --git a/drivers/staging/lttng/lttng-context-ppid.c b/drivers/staging/lttng/lttng-context-ppid.c +new file mode 100644 +index 0000000..738f7e6 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-ppid.c +@@ -0,0 +1,71 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng PPID context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include <linux/syscalls.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-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 += sizeof(pid_t); ++ return size; ++} ++ ++static ++void ppid_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_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)); ++ chan->ops->event_write(ctx, &ppid, sizeof(ppid)); ++} ++ ++int lttng_add_ppid_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "ppid")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = ppid_get_size; ++ field->record = ppid_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_ppid_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit PPID Context"); +diff --git a/drivers/staging/lttng/lttng-context-prio.c b/drivers/staging/lttng/lttng-context-prio.c +new file mode 100644 +index 0000000..1ee3a54 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-prio.c +@@ -0,0 +1,89 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng priority context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "wrapper/kallsyms.h" ++#include "ltt-tracer.h" ++ ++static ++int (*wrapper_task_prio_sym)(struct task_struct *t); ++ ++int wrapper_task_prio_init(void) ++{ ++ wrapper_task_prio_sym = (void *) kallsyms_lookup_funcptr("task_prio"); ++ if (!wrapper_task_prio_sym) { ++ printk(KERN_WARNING "LTTng: task_prio symbol lookup failed.\n"); ++ return -EINVAL; ++ } ++ return 0; ++} ++ ++static ++size_t prio_get_size(size_t offset) ++{ ++ size_t size = 0; ++ ++ size += lib_ring_buffer_align(offset, ltt_alignof(int)); ++ size += sizeof(int); ++ return size; ++} ++ ++static ++void prio_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ int prio; ++ ++ prio = wrapper_task_prio_sym(current); ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(prio)); ++ chan->ops->event_write(ctx, &prio, sizeof(prio)); ++} ++ ++int lttng_add_prio_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ int ret; ++ ++ if (!wrapper_task_prio_sym) { ++ ret = wrapper_task_prio_init(); ++ if (ret) ++ return ret; ++ } ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "prio")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = prio_get_size; ++ field->record = prio_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_prio_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit Priority Context"); +diff --git a/drivers/staging/lttng/lttng-context-procname.c b/drivers/staging/lttng/lttng-context-procname.c +new file mode 100644 +index 0000000..c6bc646 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-procname.c +@@ -0,0 +1,72 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng procname context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-tracer.h" ++ ++static ++size_t procname_get_size(size_t offset) ++{ ++ size_t size = 0; ++ ++ size += sizeof(current->comm); ++ return size; ++} ++ ++/* ++ * Racy read of procname. We simply copy its whole array size. ++ * Races with /proc/<task>/procname write only. ++ * Otherwise having to take a mutex for each event is cumbersome and ++ * could lead to crash in IRQ context and deadlock of the lockdep tracer. ++ */ ++static ++void procname_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ chan->ops->event_write(ctx, current->comm, sizeof(current->comm)); ++} ++ ++int lttng_add_procname_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "procname")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ field->event_field.name = "procname"; ++ 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.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; ++ field->event_field.type.u.array.elem_type.u.basic.integer.encoding = lttng_encode_UTF8; ++ field->event_field.type.u.array.length = sizeof(current->comm); ++ ++ field->get_size = procname_get_size; ++ field->record = procname_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_procname_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit Perf Support"); +diff --git a/drivers/staging/lttng/lttng-context-tid.c b/drivers/staging/lttng/lttng-context-tid.c +new file mode 100644 +index 0000000..d5ccdb6 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-tid.c +@@ -0,0 +1,68 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng TID context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-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 += sizeof(pid_t); ++ return size; ++} ++ ++static ++void tid_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ pid_t tid; ++ ++ tid = task_pid_nr(current); ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(tid)); ++ chan->ops->event_write(ctx, &tid, sizeof(tid)); ++} ++ ++int lttng_add_tid_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "tid")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = tid_get_size; ++ field->record = tid_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_tid_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit TID Context"); +diff --git a/drivers/staging/lttng/lttng-context-vpid.c b/drivers/staging/lttng/lttng-context-vpid.c +new file mode 100644 +index 0000000..3f16e03 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-vpid.c +@@ -0,0 +1,74 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng vPID context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-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 += sizeof(pid_t); ++ return size; ++} ++ ++static ++void vpid_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ pid_t vpid; ++ ++ /* ++ * nsproxy can be NULL when scheduled out of exit. ++ */ ++ if (!current->nsproxy) ++ vpid = 0; ++ else ++ vpid = task_tgid_vnr(current); ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(vpid)); ++ chan->ops->event_write(ctx, &vpid, sizeof(vpid)); ++} ++ ++int lttng_add_vpid_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "vpid")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = vpid_get_size; ++ field->record = vpid_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_vpid_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit vPID Context"); +diff --git a/drivers/staging/lttng/lttng-context-vppid.c b/drivers/staging/lttng/lttng-context-vppid.c +new file mode 100644 +index 0000000..f01b020 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-vppid.c +@@ -0,0 +1,79 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng vPPID context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include <linux/syscalls.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-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 += sizeof(pid_t); ++ return size; ++} ++ ++static ++void vppid_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ struct task_struct *parent; ++ pid_t vppid; ++ ++ /* ++ * nsproxy can be NULL when scheduled out of exit. ++ */ ++ rcu_read_lock(); ++ parent = rcu_dereference(current->real_parent); ++ if (!parent->nsproxy) ++ vppid = 0; ++ else ++ vppid = task_tgid_vnr(parent); ++ rcu_read_unlock(); ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(vppid)); ++ chan->ops->event_write(ctx, &vppid, sizeof(vppid)); ++} ++ ++int lttng_add_vppid_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "vppid")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = vppid_get_size; ++ field->record = vppid_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_vppid_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit vPPID Context"); +diff --git a/drivers/staging/lttng/lttng-context-vtid.c b/drivers/staging/lttng/lttng-context-vtid.c +new file mode 100644 +index 0000000..264bbb3 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-context-vtid.c +@@ -0,0 +1,74 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng vTID context. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/sched.h> ++#include "ltt-events.h" ++#include "wrapper/ringbuffer/frontend_types.h" ++#include "wrapper/vmalloc.h" ++#include "ltt-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 += sizeof(pid_t); ++ return size; ++} ++ ++static ++void vtid_record(struct lttng_ctx_field *field, ++ struct lib_ring_buffer_ctx *ctx, ++ struct ltt_channel *chan) ++{ ++ pid_t vtid; ++ ++ /* ++ * nsproxy can be NULL when scheduled out of exit. ++ */ ++ if (!current->nsproxy) ++ vtid = 0; ++ else ++ vtid = task_pid_vnr(current); ++ lib_ring_buffer_align_ctx(ctx, ltt_alignof(vtid)); ++ chan->ops->event_write(ctx, &vtid, sizeof(vtid)); ++} ++ ++int lttng_add_vtid_to_ctx(struct lttng_ctx **ctx) ++{ ++ struct lttng_ctx_field *field; ++ ++ field = lttng_append_context(ctx); ++ if (!field) ++ return -ENOMEM; ++ if (lttng_find_context(*ctx, "vtid")) { ++ lttng_remove_context_field(ctx, field); ++ return -EEXIST; ++ } ++ 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.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; ++ field->event_field.type.u.basic.integer.encoding = lttng_encode_none; ++ field->get_size = vtid_get_size; ++ field->record = vtid_record; ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(lttng_add_vtid_to_ctx); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit vTID Context"); +-- +1.7.9 + diff --git a/patches.lttng/0012-lttng-timing-calibration-feature.patch b/patches.lttng/0012-lttng-timing-calibration-feature.patch new file mode 100644 index 0000000000000..7dffaf984ada0 --- /dev/null +++ b/patches.lttng/0012-lttng-timing-calibration-feature.patch @@ -0,0 +1,54 @@ +From da66e4e541b21b326a26a36de42f400975da60ac Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:20 -0500 +Subject: lttng: timing calibration feature + +This calibration feature is fairly limited for now, but provides an +example of how this can be performed. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/lttng-calibrate.c | 30 ++++++++++++++++++++++++++++++ + 1 files changed, 30 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/lttng-calibrate.c + +diff --git a/drivers/staging/lttng/lttng-calibrate.c b/drivers/staging/lttng/lttng-calibrate.c +new file mode 100644 +index 0000000..07e3c5b +--- /dev/null ++++ b/drivers/staging/lttng/lttng-calibrate.c +@@ -0,0 +1,30 @@ ++/* ++ * lttng-calibrate.c ++ * ++ * Copyright 2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng probe calibration. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include "ltt-debugfs-abi.h" ++#include "ltt-events.h" ++ ++noinline ++void lttng_calibrate_kretprobe(void) ++{ ++ asm volatile (""); ++} ++ ++int lttng_calibrate(struct lttng_kernel_calibrate *calibrate) ++{ ++ switch (calibrate->type) { ++ case LTTNG_KERNEL_CALIBRATE_KRETPROBE: ++ lttng_calibrate_kretprobe(); ++ break; ++ default: ++ return -EINVAL; ++ } ++ return 0; ++} +-- +1.7.9 + diff --git a/patches.lttng/0013-lttng-debugfs-and-procfs-ABI.patch b/patches.lttng/0013-lttng-debugfs-and-procfs-ABI.patch new file mode 100644 index 0000000000000..9142942f3a347 --- /dev/null +++ b/patches.lttng/0013-lttng-debugfs-and-procfs-ABI.patch @@ -0,0 +1,965 @@ +From c623c0a3493e87ba60a07eef89dc78274d2e1f4a Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:21 -0500 +Subject: lttng: debugfs and procfs ABI + +Add the "lttng" virtual file to debugfs and procfs. All operations are +performed through ioctls (LTTng ioctl range is already reserved +upstream) on this virtual file and on anonymous file descriptors +returned by these ioctls. Each file descriptor is associated with a +tracer "object" (session, channel, stream, event, context). + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/ltt-debugfs-abi.c | 777 +++++++++++++++++++++++++++++++ + drivers/staging/lttng/ltt-debugfs-abi.h | 153 ++++++ + 2 files changed, 930 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/ltt-debugfs-abi.c + create mode 100644 drivers/staging/lttng/ltt-debugfs-abi.h + +diff --git a/drivers/staging/lttng/ltt-debugfs-abi.c b/drivers/staging/lttng/ltt-debugfs-abi.c +new file mode 100644 +index 0000000..37cccfa +--- /dev/null ++++ b/drivers/staging/lttng/ltt-debugfs-abi.c +@@ -0,0 +1,777 @@ ++/* ++ * 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); ++} +diff --git a/drivers/staging/lttng/ltt-debugfs-abi.h b/drivers/staging/lttng/ltt-debugfs-abi.h +new file mode 100644 +index 0000000..42bc9fd +--- /dev/null ++++ b/drivers/staging/lttng/ltt-debugfs-abi.h +@@ -0,0 +1,153 @@ ++#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 128 ++ ++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 */ +-- +1.7.9 + diff --git a/patches.lttng/0014-lttng-Add-documentation-and-TODO-files.patch b/patches.lttng/0014-lttng-Add-documentation-and-TODO-files.patch new file mode 100644 index 0000000000000..1d3c7fe2b0aa7 --- /dev/null +++ b/patches.lttng/0014-lttng-Add-documentation-and-TODO-files.patch @@ -0,0 +1,249 @@ +From 18b2248a0dcc70284d68ecd095cd2e8451714966 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:22 -0500 +Subject: lttng: Add documentation and TODO files + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/LICENSE | 27 ++++++++ + drivers/staging/lttng/README | 48 ++++++++++++++ + drivers/staging/lttng/TODO | 137 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 212 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/LICENSE + create mode 100644 drivers/staging/lttng/README + create mode 100644 drivers/staging/lttng/TODO + +diff --git a/drivers/staging/lttng/LICENSE b/drivers/staging/lttng/LICENSE +new file mode 100644 +index 0000000..bb880bf +--- /dev/null ++++ b/drivers/staging/lttng/LICENSE +@@ -0,0 +1,27 @@ ++LTTng modules licensing ++Mathieu Desnoyers ++June 2, 2011 ++ ++* LGPLv2.1/GPLv2 dual-license ++ ++The files contained within this package are licensed under ++LGPLv2.1/GPLv2 dual-license (see lgpl-2.1.txt and gpl-2.0.txt for ++details), except for files identified by the following sections. ++ ++* GPLv2 license ++ ++These files are licensed exclusively under the GPLv2 license. See ++gpl-2.0.txt for details. ++ ++lib/ringbuffer/ring_buffer_splice.c ++lib/ringbuffer/ring_buffer_mmap.c ++instrumentation/events/mainline/*.h ++instrumentation/events/lttng-modules/*.h ++ ++* MIT-style license ++ ++These files are licensed under an MIT-style license: ++ ++lib/prio_heap/lttng_prio_heap.h ++lib/prio_heap/lttng_prio_heap.c ++lib/bitfield.h +diff --git a/drivers/staging/lttng/README b/drivers/staging/lttng/README +new file mode 100644 +index 0000000..a154d6e +--- /dev/null ++++ b/drivers/staging/lttng/README +@@ -0,0 +1,48 @@ ++LTTng 2.0 modules ++ ++Mathieu Desnoyers ++November 1st, 2011 ++ ++LTTng 2.0 kernel modules is currently part of the Linux kernel staging ++tree. It features (new features since LTTng 0.x): ++ ++- Produces CTF (Common Trace Format) natively, ++ (http://www.efficios.com/ctf) ++- Tracepoints, Function tracer, CPU Performance Monitoring Unit (PMU) ++ counters, kprobes, and kretprobes support, ++- Integrated interface for both kernel and userspace tracing, ++- Have the ability to attach "context" information to events in the ++ trace (e.g. any PMU counter, pid, ppid, tid, comm name, etc). ++ All the extra information fields to be collected with events are ++ 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. ++ ++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. ++ ++* Note about Perf PMU counters support ++ ++Each PMU counter has its zero value set when it is attached to a context with ++add-context. Therefore, it is normal that the same counters attached to both the ++stream context and event context show different values for a given event; what ++matters is that they increment at the same rate. +diff --git a/drivers/staging/lttng/TODO b/drivers/staging/lttng/TODO +new file mode 100644 +index 0000000..3fdc5e6 +--- /dev/null ++++ b/drivers/staging/lttng/TODO +@@ -0,0 +1,137 @@ ++Please contact Mathieu Desnoyers <mathieu.desnoyers@efficios.com> for ++questions about this TODO list. The "Cleanup/Testing" section would be ++good to go through before integration into mainline. The "Features" ++section is a wish list of features to complete before releasing the ++"LTTng 2.0" final version, but are not required to have LTTng working. ++These features are mostly performance enhancements and instrumentation ++enhancements. ++ ++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. ++ 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. ++ This means that although the usual case of pairs of ++ lib_ring_buffer_get_next_subbuf/lib_ring_buffer_put_next_subbuf ++ work fine, there is probably a problem that needs to be ++ investigated in ++ lib_ring_buffer_get_subbuf/lib_ring_buffer_put_subbuf, which ++ depend on the producer to push the reader position. ++ Contact: Julien Desfossez <julien.desfossez@polymtl.ca> ++ ++ 4) Test latest -rt kernel support. ++ There has been report of corrupted traces when tracing a ++ 3.0.10-rt27 in the area of access_ok() system call event. ++ Still has to be investigated. Cannot be reproduced with ++ mainline kernel. ++ Contact: Yannick Brosseau <yannick.brosseau@polymtl.ca> ++ ++B) Features ++ ++ 1) Integration of the LTTng 0.x trace clocks into ++ LTTng 2.0. ++ Currently using mainline kernel monotonic clock. NMIs can ++ therefore not be traced, and this causes a significant ++ performance degradation compared to the LTTng 0.x trace ++ clocks. Imply the creation of drivers/staging/lttng/arch to ++ contain the arch-specific clock support files. ++ * Dependency: addition of clock descriptions to CTF. ++ See: http://git.lttng.org/?p=linux-2.6-lttng.git;a=summary ++ for the LTTng 0.x git tree. ++ ++ 2) Port OMAP3 LTTng trace clocks to x86 to support systems ++ without constant TSC. ++ * Dependency: (B.1) ++ See: http://git.lttng.org/?p=linux-2.6-lttng.git;a=summary ++ for the LTTng 0.x git tree. ++ ++ 3) Implement mmap operation on an anonymous file created by a ++ LTTNG_KERNEL_CLOCK ioctl to export data to export ++ synchronized kernel and user-level LTTng trace clocks: ++ with: ++ - shared per-cpu data, ++ - read seqlock. ++ The content exported by this shared memory area will be ++ arch-specific. ++ * Dependency: (B.1) && (B.2) ++ See: http://git.lttng.org/?p=linux-2.6-lttng.git;a=summary ++ for the LTTng 0.x git tree, which has vDSO support for ++ LTTng trace clock on the x86 architecture. ++ ++ 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 ++ ++ 4) Generate system call TRACE_EVENT headers for all ++ architectures (currently done: x86 32/64). ++ ++ 5) Define "unknown" system calls into instrumentation/syscalls ++ override files / or do SYSCALL_DEFINE improvements to ++ mainline kernel to allow automatic generation of these ++ missing system call descriptions. ++ ++ 6) Create missing tracepoint event headers files into ++ instrumentation/events from headers located in ++ include/trace/events/. Choice: either do as currently done, ++ and copy those headers locally into the lttng driver and ++ perform the modifications locally, or push TRACE_EVENT API ++ modification into mainline headers, which would require ++ collaboration from Ftrace/Perf maintainers. ++ ++ 7) Poll: implement a poll and/or epoll exclusive wakeup scheme, ++ which contradicts POSIX, but protect multiple consumer ++ threads from thundering herd effect. ++ ++ 8) Re-integrate sample modules from libringbuffer into ++ lttng driver. Those modules can be used as example of how to ++ use libringbuffer in other contexts than LTTng, and are ++ useful to perform benchmarks of the ringbuffer library. ++ See: http://www.efficios.com/ringbuffer ++ ++ 9) NOHZ support for lib ring buffer. NOHZ infrastructure in the ++ Linux kernel does not support notifiers chains, which does ++ not let LTTng play nicely with low power consumption setups ++ for flight recorder (overwrite mode) live traces. One way to ++ 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 ++ hash table. Turns O(n^2) trace systems registration (cost ++ for n systems) into O(n). (O(1) per system) ++ ++ 11) drivers/staging/lttng/probes/lttng-ftrace.c: ++ LTTng currently uses kretprobes for per-function tracing, ++ not the function tracer. So lttng-ftrace.c should be used ++ for "all" function tracing. ++ ++ 12) drivers/staging/lttng/probes/lttng-types.c: ++ This is a currently unused placeholder to export entire C ++ type declarations into the trace metadata, e.g. for support ++ of describing the layout of structures/enumeration mapping ++ along with syscall entry events. The design of this support ++ will likely change though, and become integrated with the ++ TRACE_EVENT support within lttng, by adding new macros, and ++ support for generation of metadata from these macros, to ++ allow description of those compound types/enumerations. ++ ++Please send patches ++To: Greg Kroah-Hartman <greg@kroah.com> ++To: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +-- +1.7.9 + diff --git a/patches.lttng/0015-lttng-add-system-call-instrumentation-probe.patch b/patches.lttng/0015-lttng-add-system-call-instrumentation-probe.patch new file mode 100644 index 0000000000000..f38581e1a7f73 --- /dev/null +++ b/patches.lttng/0015-lttng-add-system-call-instrumentation-probe.patch @@ -0,0 +1,459 @@ +From 97104e24fbefa7081e4c9aa9bff3c4fa1a0212cf Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:23 -0500 +Subject: lttng: add system call instrumentation probe + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/lttng-syscalls.c | 438 ++++++++++++++++++++++++++++++++ + 1 files changed, 438 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/lttng-syscalls.c + +diff --git a/drivers/staging/lttng/lttng-syscalls.c b/drivers/staging/lttng/lttng-syscalls.c +new file mode 100644 +index 0000000..16624a7f7 +--- /dev/null ++++ b/drivers/staging/lttng/lttng-syscalls.c +@@ -0,0 +1,438 @@ ++/* ++ * lttng-syscalls.c ++ * ++ * Copyright 2010-2011 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng syscall probes. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/slab.h> ++#include <linux/compat.h> ++#include <asm/ptrace.h> ++#include <asm/syscall.h> ++ ++#include "ltt-events.h" ++ ++#ifndef CONFIG_COMPAT ++static inline int is_compat_task(void) ++{ ++ return 0; ++} ++#endif ++ ++static ++void syscall_entry_probe(void *__data, struct pt_regs *regs, long id); ++ ++/* ++ * Take care of NOARGS not supported by mainline. ++ */ ++#define DECLARE_EVENT_CLASS_NOARGS(name, tstruct, assign, print) ++#define DEFINE_EVENT_NOARGS(template, name) ++#define TRACE_EVENT_NOARGS(name, struct, assign, print) ++ ++/* ++ * Create LTTng tracepoint probes. ++ */ ++#define LTTNG_PACKAGE_BUILD ++#define CREATE_TRACE_POINTS ++#define TP_MODULE_OVERRIDE ++#define TRACE_INCLUDE_PATH ../instrumentation/syscalls/headers ++ ++#define PARAMS(args...) args ++ ++#undef TRACE_SYSTEM ++ ++/* Hijack probe callback for system calls */ ++#undef TP_PROBE_CB ++#define TP_PROBE_CB(_template) &syscall_entry_probe ++#define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ ++ TRACE_EVENT(_name, PARAMS(_proto), PARAMS(_args),\ ++ PARAMS(_struct), PARAMS(_assign), PARAMS(_printk)) ++#define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \ ++ DECLARE_EVENT_CLASS_NOARGS(_name, PARAMS(_struct), PARAMS(_assign),\ ++ PARAMS(_printk)) ++#define SC_DEFINE_EVENT_NOARGS(_template, _name) \ ++ DEFINE_EVENT_NOARGS(_template, _name) ++#define TRACE_SYSTEM syscalls_integers ++#include "instrumentation/syscalls/headers/syscalls_integers.h" ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM syscalls_pointers ++#include "instrumentation/syscalls/headers/syscalls_pointers.h" ++#undef TRACE_SYSTEM ++#undef SC_TRACE_EVENT ++#undef SC_DECLARE_EVENT_CLASS_NOARGS ++#undef SC_DEFINE_EVENT_NOARGS ++ ++#define TRACE_SYSTEM syscalls_unknown ++#include "instrumentation/syscalls/headers/syscalls_unknown.h" ++#undef TRACE_SYSTEM ++ ++/* For compat syscalls */ ++#undef _TRACE_SYSCALLS_integers_H ++#undef _TRACE_SYSCALLS_pointers_H ++ ++/* Hijack probe callback for system calls */ ++#undef TP_PROBE_CB ++#define TP_PROBE_CB(_template) &syscall_entry_probe ++#define SC_TRACE_EVENT(_name, _proto, _args, _struct, _assign, _printk) \ ++ TRACE_EVENT(compat_##_name, PARAMS(_proto), PARAMS(_args), \ ++ PARAMS(_struct), PARAMS(_assign), \ ++ PARAMS(_printk)) ++#define SC_DECLARE_EVENT_CLASS_NOARGS(_name, _struct, _assign, _printk) \ ++ DECLARE_EVENT_CLASS_NOARGS(compat_##_name, PARAMS(_struct), \ ++ PARAMS(_assign), PARAMS(_printk)) ++#define SC_DEFINE_EVENT_NOARGS(_template, _name) \ ++ DEFINE_EVENT_NOARGS(compat_##_template, compat_##_name) ++#define TRACE_SYSTEM compat_syscalls_integers ++#include "instrumentation/syscalls/headers/compat_syscalls_integers.h" ++#undef TRACE_SYSTEM ++#define TRACE_SYSTEM compat_syscalls_pointers ++#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h" ++#undef TRACE_SYSTEM ++#undef SC_TRACE_EVENT ++#undef SC_DECLARE_EVENT_CLASS_NOARGS ++#undef SC_DEFINE_EVENT_NOARGS ++#undef TP_PROBE_CB ++ ++#undef TP_MODULE_OVERRIDE ++#undef LTTNG_PACKAGE_BUILD ++#undef CREATE_TRACE_POINTS ++ ++struct trace_syscall_entry { ++ void *func; ++ const struct lttng_event_desc *desc; ++ const struct lttng_event_field *fields; ++ unsigned int nrargs; ++}; ++ ++#define CREATE_SYSCALL_TABLE ++ ++#undef TRACE_SYSCALL_TABLE ++#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \ ++ [ _nr ] = { \ ++ .func = __event_probe__##_template, \ ++ .nrargs = (_nrargs), \ ++ .fields = __event_fields___##_template, \ ++ .desc = &__event_desc___##_name, \ ++ }, ++ ++static const struct trace_syscall_entry sc_table[] = { ++#include "instrumentation/syscalls/headers/syscalls_integers.h" ++#include "instrumentation/syscalls/headers/syscalls_pointers.h" ++}; ++ ++#undef TRACE_SYSCALL_TABLE ++#define TRACE_SYSCALL_TABLE(_template, _name, _nr, _nrargs) \ ++ [ _nr ] = { \ ++ .func = __event_probe__##compat_##_template, \ ++ .nrargs = (_nrargs), \ ++ .fields = __event_fields___##compat_##_template,\ ++ .desc = &__event_desc___##compat_##_name, \ ++ }, ++ ++/* Create compatibility syscall table */ ++const struct trace_syscall_entry compat_sc_table[] = { ++#include "instrumentation/syscalls/headers/compat_syscalls_integers.h" ++#include "instrumentation/syscalls/headers/compat_syscalls_pointers.h" ++}; ++ ++#undef CREATE_SYSCALL_TABLE ++ ++static void syscall_entry_unknown(struct ltt_event *event, ++ struct pt_regs *regs, unsigned int id) ++{ ++ unsigned long args[UNKNOWN_SYSCALL_NRARGS]; ++ ++ syscall_get_arguments(current, regs, 0, UNKNOWN_SYSCALL_NRARGS, args); ++ if (unlikely(is_compat_task())) ++ __event_probe__compat_sys_unknown(event, id, args); ++ else ++ __event_probe__sys_unknown(event, id, args); ++} ++ ++void syscall_entry_probe(void *__data, struct pt_regs *regs, long id) ++{ ++ struct ltt_channel *chan = __data; ++ struct ltt_event *event, *unknown_event; ++ const struct trace_syscall_entry *table, *entry; ++ size_t table_len; ++ ++ if (unlikely(is_compat_task())) { ++ table = compat_sc_table; ++ table_len = ARRAY_SIZE(compat_sc_table); ++ unknown_event = chan->sc_compat_unknown; ++ } else { ++ table = sc_table; ++ table_len = ARRAY_SIZE(sc_table); ++ unknown_event = chan->sc_unknown; ++ } ++ if (unlikely(id >= table_len)) { ++ syscall_entry_unknown(unknown_event, regs, id); ++ return; ++ } ++ if (unlikely(is_compat_task())) ++ event = chan->compat_sc_table[id]; ++ else ++ event = chan->sc_table[id]; ++ if (unlikely(!event)) { ++ syscall_entry_unknown(unknown_event, regs, id); ++ return; ++ } ++ entry = &table[id]; ++ WARN_ON_ONCE(!entry); ++ ++ switch (entry->nrargs) { ++ case 0: ++ { ++ void (*fptr)(void *__data) = entry->func; ++ ++ fptr(event); ++ break; ++ } ++ case 1: ++ { ++ void (*fptr)(void *__data, unsigned long arg0) = entry->func; ++ unsigned long args[1]; ++ ++ syscall_get_arguments(current, regs, 0, entry->nrargs, args); ++ fptr(event, args[0]); ++ break; ++ } ++ case 2: ++ { ++ void (*fptr)(void *__data, ++ unsigned long arg0, ++ unsigned long arg1) = entry->func; ++ unsigned long args[2]; ++ ++ syscall_get_arguments(current, regs, 0, entry->nrargs, args); ++ fptr(event, args[0], args[1]); ++ break; ++ } ++ case 3: ++ { ++ void (*fptr)(void *__data, ++ unsigned long arg0, ++ unsigned long arg1, ++ unsigned long arg2) = entry->func; ++ unsigned long args[3]; ++ ++ syscall_get_arguments(current, regs, 0, entry->nrargs, args); ++ fptr(event, args[0], args[1], args[2]); ++ break; ++ } ++ case 4: ++ { ++ void (*fptr)(void *__data, ++ unsigned long arg0, ++ unsigned long arg1, ++ unsigned long arg2, ++ unsigned long arg3) = entry->func; ++ unsigned long args[4]; ++ ++ syscall_get_arguments(current, regs, 0, entry->nrargs, args); ++ fptr(event, args[0], args[1], args[2], args[3]); ++ break; ++ } ++ case 5: ++ { ++ void (*fptr)(void *__data, ++ unsigned long arg0, ++ unsigned long arg1, ++ unsigned long arg2, ++ unsigned long arg3, ++ unsigned long arg4) = entry->func; ++ unsigned long args[5]; ++ ++ syscall_get_arguments(current, regs, 0, entry->nrargs, args); ++ fptr(event, args[0], args[1], args[2], args[3], args[4]); ++ break; ++ } ++ case 6: ++ { ++ void (*fptr)(void *__data, ++ unsigned long arg0, ++ unsigned long arg1, ++ unsigned long arg2, ++ unsigned long arg3, ++ unsigned long arg4, ++ unsigned long arg5) = entry->func; ++ unsigned long args[6]; ++ ++ syscall_get_arguments(current, regs, 0, entry->nrargs, args); ++ fptr(event, args[0], args[1], args[2], ++ args[3], args[4], args[5]); ++ break; ++ } ++ default: ++ break; ++ } ++} ++ ++/* 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) ++{ ++ const struct lttng_event_desc *desc; ++ unsigned int i; ++ ++ /* Allocate events for each syscall, insert into table */ ++ for (i = 0; i < table_len; i++) { ++ struct lttng_kernel_event ev; ++ desc = table[i].desc; ++ ++ if (!desc) { ++ /* Unknown syscall */ ++ continue; ++ } ++ /* ++ * Skip those already populated by previous failed ++ * register for this channel. ++ */ ++ 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'; ++ ev.instrumentation = LTTNG_KERNEL_NOOP; ++ chan_table[i] = ltt_event_create(chan, &ev, filter, ++ desc); ++ if (!chan_table[i]) { ++ /* ++ * If something goes wrong in event registration ++ * after the first one, we have no choice but to ++ * leave the previous events in there, until ++ * deleted by session teardown. ++ */ ++ return -EINVAL; ++ } ++ } ++ return 0; ++} ++ ++int lttng_syscalls_register(struct ltt_channel *chan, void *filter) ++{ ++ struct lttng_kernel_event ev; ++ int ret; ++ ++ wrapper_vmalloc_sync_all(); ++ ++ if (!chan->sc_table) { ++ /* create syscall table mapping syscall to events */ ++ chan->sc_table = kzalloc(sizeof(struct ltt_event *) ++ * ARRAY_SIZE(sc_table), GFP_KERNEL); ++ if (!chan->sc_table) ++ return -ENOMEM; ++ } ++ ++#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 *) ++ * ARRAY_SIZE(compat_sc_table), GFP_KERNEL); ++ if (!chan->compat_sc_table) ++ return -ENOMEM; ++ } ++#endif ++ if (!chan->sc_unknown) { ++ const struct lttng_event_desc *desc = ++ &__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'; ++ ev.instrumentation = LTTNG_KERNEL_NOOP; ++ chan->sc_unknown = ltt_event_create(chan, &ev, filter, ++ desc); ++ if (!chan->sc_unknown) { ++ return -EINVAL; ++ } ++ } ++ ++ if (!chan->sc_compat_unknown) { ++ const struct lttng_event_desc *desc = ++ &__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'; ++ ev.instrumentation = LTTNG_KERNEL_NOOP; ++ chan->sc_compat_unknown = ltt_event_create(chan, &ev, filter, ++ desc); ++ if (!chan->sc_compat_unknown) { ++ return -EINVAL; ++ } ++ } ++ ++ if (!chan->sc_exit) { ++ const struct lttng_event_desc *desc = ++ &__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'; ++ ev.instrumentation = LTTNG_KERNEL_NOOP; ++ chan->sc_exit = ltt_event_create(chan, &ev, filter, ++ desc); ++ if (!chan->sc_exit) { ++ return -EINVAL; ++ } ++ } ++ ++ ret = fill_table(sc_table, ARRAY_SIZE(sc_table), ++ chan->sc_table, chan, filter); ++ if (ret) ++ return ret; ++#ifdef CONFIG_COMPAT ++ ret = fill_table(compat_sc_table, ARRAY_SIZE(compat_sc_table), ++ chan->compat_sc_table, chan, filter); ++ if (ret) ++ return ret; ++#endif ++ ret = tracepoint_probe_register("sys_enter", ++ (void *) syscall_entry_probe, chan); ++ if (ret) ++ return ret; ++ /* ++ * We change the name of sys_exit tracepoint due to namespace ++ * conflict with sys_exit syscall entry. ++ */ ++ ret = tracepoint_probe_register("sys_exit", ++ (void *) __event_probe__exit_syscall, ++ chan->sc_exit); ++ if (ret) { ++ WARN_ON_ONCE(tracepoint_probe_unregister("sys_enter", ++ (void *) syscall_entry_probe, chan)); ++ } ++ return ret; ++} ++ ++/* ++ * Only called at session destruction. ++ */ ++int lttng_syscalls_unregister(struct ltt_channel *chan) ++{ ++ int ret; ++ ++ if (!chan->sc_table) ++ return 0; ++ ret = tracepoint_probe_unregister("sys_exit", ++ (void *) __event_probe__exit_syscall, ++ chan->sc_exit); ++ if (ret) ++ return ret; ++ ret = tracepoint_probe_unregister("sys_enter", ++ (void *) syscall_entry_probe, chan); ++ if (ret) ++ return ret; ++ /* ltt_event destroy will be performed by ltt_session_destroy() */ ++ kfree(chan->sc_table); ++#ifdef CONFIG_COMPAT ++ kfree(chan->compat_sc_table); ++#endif ++ return 0; ++} +-- +1.7.9 + diff --git a/patches.lttng/0016-lttng-probe-callbacks.patch b/patches.lttng/0016-lttng-probe-callbacks.patch new file mode 100644 index 0000000000000..60ce75cd78d10 --- /dev/null +++ b/patches.lttng/0016-lttng-probe-callbacks.patch @@ -0,0 +1,2035 @@ +From 1e8ab70d74ed14bc287e2cb98145e860e2d95f6e Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:24 -0500 +Subject: lttng: probe callbacks + +Implement the LTTng probe callbacks. One notable file here is +lttng-events.h, which is the core implementation of the LTTng +TRACE_EVENT macros for generation of probes and tracepoint decription +from the TRACE_EVENT declarations. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/probes/Makefile | 37 ++ + drivers/staging/lttng/probes/define_trace.h | 132 ++++ + drivers/staging/lttng/probes/lttng-events-reset.h | 84 +++ + drivers/staging/lttng/probes/lttng-events.h | 703 +++++++++++++++++++++ + drivers/staging/lttng/probes/lttng-ftrace.c | 188 ++++++ + drivers/staging/lttng/probes/lttng-kprobes.c | 164 +++++ + drivers/staging/lttng/probes/lttng-kretprobes.c | 277 ++++++++ + drivers/staging/lttng/probes/lttng-probe-block.c | 31 + + drivers/staging/lttng/probes/lttng-probe-irq.c | 31 + + drivers/staging/lttng/probes/lttng-probe-kvm.c | 31 + + drivers/staging/lttng/probes/lttng-probe-lttng.c | 24 + + drivers/staging/lttng/probes/lttng-probe-sched.c | 30 + + drivers/staging/lttng/probes/lttng-type-list.h | 21 + + drivers/staging/lttng/probes/lttng-types.c | 49 ++ + drivers/staging/lttng/probes/lttng-types.h | 72 +++ + drivers/staging/lttng/probes/lttng.h | 15 + + 16 files changed, 1889 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/probes/Makefile + create mode 100644 drivers/staging/lttng/probes/define_trace.h + create mode 100644 drivers/staging/lttng/probes/lttng-events-reset.h + create mode 100644 drivers/staging/lttng/probes/lttng-events.h + create mode 100644 drivers/staging/lttng/probes/lttng-ftrace.c + create mode 100644 drivers/staging/lttng/probes/lttng-kprobes.c + create mode 100644 drivers/staging/lttng/probes/lttng-kretprobes.c + create mode 100644 drivers/staging/lttng/probes/lttng-probe-block.c + create mode 100644 drivers/staging/lttng/probes/lttng-probe-irq.c + create mode 100644 drivers/staging/lttng/probes/lttng-probe-kvm.c + create mode 100644 drivers/staging/lttng/probes/lttng-probe-lttng.c + create mode 100644 drivers/staging/lttng/probes/lttng-probe-sched.c + create mode 100644 drivers/staging/lttng/probes/lttng-type-list.h + create mode 100644 drivers/staging/lttng/probes/lttng-types.c + create mode 100644 drivers/staging/lttng/probes/lttng-types.h + create mode 100644 drivers/staging/lttng/probes/lttng.h + +diff --git a/drivers/staging/lttng/probes/Makefile b/drivers/staging/lttng/probes/Makefile +new file mode 100644 +index 0000000..bdc1179 +--- /dev/null ++++ b/drivers/staging/lttng/probes/Makefile +@@ -0,0 +1,37 @@ ++# ++# Makefile for the LTT probes. ++# ++ ++ccflags-y += -I$(PWD)/probes ++obj-m += lttng-types.o ++ ++obj-m += lttng-probe-lttng.o ++ ++obj-m += lttng-probe-sched.o ++obj-m += lttng-probe-irq.o ++ ++ifneq ($(CONFIG_KVM),) ++obj-m += lttng-probe-kvm.o ++endif ++ ++ifneq ($(CONFIG_BLOCK),) ++ifneq ($(CONFIG_EVENT_TRACING),) # need blk_cmd_buf_len ++obj-m += $(shell \ ++ if [ $(VERSION) -ge 3 \ ++ -o \( $(VERSION) -eq 2 -a $(PATCHLEVEL) -ge 6 -a $(SUBLEVEL) -ge 38 \) ] ; then \ ++ echo "lttng-probe-block.o" ; fi;) ++endif ++endif ++ ++ifneq ($(CONFIG_KPROBES),) ++obj-m += lttng-kprobes.o ++endif ++ ++ ++ifneq ($(CONFIG_KRETPROBES),) ++obj-m += lttng-kretprobes.o ++endif ++ ++ifneq ($(CONFIG_DYNAMIC_FTRACE),) ++obj-m += lttng-ftrace.o ++endif +diff --git a/drivers/staging/lttng/probes/define_trace.h b/drivers/staging/lttng/probes/define_trace.h +new file mode 100644 +index 0000000..3c9a467 +--- /dev/null ++++ b/drivers/staging/lttng/probes/define_trace.h +@@ -0,0 +1,132 @@ ++/* ++ * define_trace.h ++ * ++ * Copyright (C) 2009 Steven Rostedt <rostedt@goodmis.org> ++ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++/* ++ * Trace files that want to automate creationg of all tracepoints defined ++ * in their file should include this file. The following are macros that the ++ * trace file may define: ++ * ++ * TRACE_SYSTEM defines the system the tracepoint is for ++ * ++ * TRACE_INCLUDE_FILE if the file name is something other than TRACE_SYSTEM.h ++ * This macro may be defined to tell define_trace.h what file to include. ++ * Note, leave off the ".h". ++ * ++ * TRACE_INCLUDE_PATH if the path is something other than core kernel include/trace ++ * then this macro can define the path to use. Note, the path is relative to ++ * define_trace.h, not the file including it. Full path names for out of tree ++ * modules must be used. ++ */ ++ ++#ifdef CREATE_TRACE_POINTS ++ ++/* Prevent recursion */ ++#undef CREATE_TRACE_POINTS ++ ++#include <linux/stringify.h> ++/* ++ * module.h includes tracepoints, and because ftrace.h ++ * pulls in module.h: ++ * trace/ftrace.h -> linux/ftrace_event.h -> linux/perf_event.h -> ++ * linux/ftrace.h -> linux/module.h ++ * we must include module.h here before we play with any of ++ * the TRACE_EVENT() macros, otherwise the tracepoints included ++ * by module.h may break the build. ++ */ ++#include <linux/module.h> ++ ++#undef TRACE_EVENT ++#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \ ++ DEFINE_TRACE(name) ++ ++#undef TRACE_EVENT_CONDITION ++#define TRACE_EVENT_CONDITION(name, proto, args, cond, tstruct, assign, print) \ ++ TRACE_EVENT(name, \ ++ PARAMS(proto), \ ++ PARAMS(args), \ ++ PARAMS(tstruct), \ ++ PARAMS(assign), \ ++ PARAMS(print)) ++ ++#undef TRACE_EVENT_FN ++#define TRACE_EVENT_FN(name, proto, args, tstruct, \ ++ assign, print, reg, unreg) \ ++ DEFINE_TRACE_FN(name, reg, unreg) ++ ++#undef DEFINE_EVENT ++#define DEFINE_EVENT(template, name, proto, args) \ ++ DEFINE_TRACE(name) ++ ++#undef DEFINE_EVENT_PRINT ++#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ ++ DEFINE_TRACE(name) ++ ++#undef DEFINE_EVENT_CONDITION ++#define DEFINE_EVENT_CONDITION(template, name, proto, args, cond) \ ++ DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args)) ++ ++#undef DECLARE_TRACE ++#define DECLARE_TRACE(name, proto, args) \ ++ DEFINE_TRACE(name) ++ ++#undef TRACE_INCLUDE ++#undef __TRACE_INCLUDE ++ ++#ifndef TRACE_INCLUDE_FILE ++# define TRACE_INCLUDE_FILE TRACE_SYSTEM ++# define UNDEF_TRACE_INCLUDE_FILE ++#endif ++ ++#ifndef TRACE_INCLUDE_PATH ++# define __TRACE_INCLUDE(system) <trace/events/system.h> ++# define UNDEF_TRACE_INCLUDE_PATH ++#else ++# define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h) ++#endif ++ ++# define TRACE_INCLUDE(system) __TRACE_INCLUDE(system) ++ ++/* Let the trace headers be reread */ ++#define TRACE_HEADER_MULTI_READ ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++/* Make all open coded DECLARE_TRACE nops */ ++#undef DECLARE_TRACE ++#define DECLARE_TRACE(name, proto, args) ++ ++#ifdef LTTNG_PACKAGE_BUILD ++#include "lttng-events.h" ++#endif ++ ++#undef TRACE_EVENT ++#undef TRACE_EVENT_FN ++#undef TRACE_EVENT_CONDITION ++#undef DECLARE_EVENT_CLASS ++#undef DEFINE_EVENT ++#undef DEFINE_EVENT_PRINT ++#undef DEFINE_EVENT_CONDITION ++#undef TRACE_HEADER_MULTI_READ ++#undef DECLARE_TRACE ++ ++/* Only undef what we defined in this file */ ++#ifdef UNDEF_TRACE_INCLUDE_FILE ++# undef TRACE_INCLUDE_FILE ++# undef UNDEF_TRACE_INCLUDE_FILE ++#endif ++ ++#ifdef UNDEF_TRACE_INCLUDE_PATH ++# undef TRACE_INCLUDE_PATH ++# undef UNDEF_TRACE_INCLUDE_PATH ++#endif ++ ++/* We may be processing more files */ ++#define CREATE_TRACE_POINTS ++ ++#endif /* CREATE_TRACE_POINTS */ +diff --git a/drivers/staging/lttng/probes/lttng-events-reset.h b/drivers/staging/lttng/probes/lttng-events-reset.h +new file mode 100644 +index 0000000..c8a1046 +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-events-reset.h +@@ -0,0 +1,84 @@ ++/* ++ * lttng-events-reset.h ++ * ++ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++/* Reset macros used within TRACE_EVENT to "nothing" */ ++ ++#undef __field_full ++#define __field_full(_type, _item, _order, _base) ++ ++#undef __array_enc_ext ++#define __array_enc_ext(_type, _item, _length, _order, _base, _encoding) ++ ++#undef __dynamic_array_enc_ext ++#define __dynamic_array_enc_ext(_type, _item, _length, _order, _base, _encoding) ++ ++#undef __dynamic_array_len ++#define __dynamic_array_len(_type, _item, _length) ++ ++#undef __string ++#define __string(_item, _src) ++ ++#undef tp_assign ++#define tp_assign(dest, src) ++ ++#undef tp_memcpy ++#define tp_memcpy(dest, src, len) ++ ++#undef tp_memcpy_dyn ++#define tp_memcpy_dyn(dest, src, len) ++ ++#undef tp_strcpy ++#define tp_strcpy(dest, src) ++ ++#undef __get_str ++#define __get_str(field) ++ ++#undef __get_dynamic_array ++#define __get_dynamic_array(field) ++ ++#undef __get_dynamic_array_len ++#define __get_dynamic_array_len(field) ++ ++#undef TP_PROTO ++#define TP_PROTO(args...) ++ ++#undef TP_ARGS ++#define TP_ARGS(args...) ++ ++#undef TP_STRUCT__entry ++#define TP_STRUCT__entry(args...) ++ ++#undef TP_fast_assign ++#define TP_fast_assign(args...) ++ ++#undef __perf_count ++#define __perf_count(args...) ++ ++#undef __perf_addr ++#define __perf_addr(args...) ++ ++#undef TP_perf_assign ++#define TP_perf_assign(args...) ++ ++#undef TP_printk ++#define TP_printk(args...) ++ ++#undef DECLARE_EVENT_CLASS ++#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) ++ ++#undef DECLARE_EVENT_CLASS_NOARGS ++#define DECLARE_EVENT_CLASS_NOARGS(_name, _tstruct, _assign, _print) ++ ++#undef DEFINE_EVENT ++#define DEFINE_EVENT(_template, _name, _proto, _args) ++ ++#undef DEFINE_EVENT_NOARGS ++#define DEFINE_EVENT_NOARGS(_template, _name) ++ ++#undef TRACE_EVENT_FLAGS ++#define TRACE_EVENT_FLAGS(name, value) +diff --git a/drivers/staging/lttng/probes/lttng-events.h b/drivers/staging/lttng/probes/lttng-events.h +new file mode 100644 +index 0000000..ff6273f +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-events.h +@@ -0,0 +1,703 @@ ++/* ++ * lttng-events.h ++ * ++ * Copyright (C) 2009 Steven Rostedt <rostedt@goodmis.org> ++ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/debugfs.h> ++#include "lttng.h" ++#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" ++ ++/* ++ * Macro declarations used for all stages. ++ */ ++ ++/* ++ * DECLARE_EVENT_CLASS can be used to add a generic function ++ * handlers for events. That is, if all events have the same ++ * parameters and just have distinct trace points. ++ * Each tracepoint can be defined with DEFINE_EVENT and that ++ * will map the DECLARE_EVENT_CLASS to the tracepoint. ++ * ++ * TRACE_EVENT is a one to one mapping between tracepoint and template. ++ */ ++ ++#undef TRACE_EVENT ++#define TRACE_EVENT(name, proto, args, tstruct, assign, print) \ ++ DECLARE_EVENT_CLASS(name, \ ++ PARAMS(proto), \ ++ PARAMS(args), \ ++ PARAMS(tstruct), \ ++ PARAMS(assign), \ ++ PARAMS(print)) \ ++ DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args)) ++ ++#undef TRACE_EVENT_NOARGS ++#define TRACE_EVENT_NOARGS(name, tstruct, assign, print) \ ++ DECLARE_EVENT_CLASS_NOARGS(name, \ ++ PARAMS(tstruct), \ ++ PARAMS(assign), \ ++ PARAMS(print)) \ ++ DEFINE_EVENT_NOARGS(name, name) ++ ++ ++#undef DEFINE_EVENT_PRINT ++#define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ ++ DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args)) ++ ++/* Callbacks are meaningless to LTTng. */ ++#undef TRACE_EVENT_FN ++#define TRACE_EVENT_FN(name, proto, args, tstruct, \ ++ assign, print, reg, unreg) \ ++ TRACE_EVENT(name, PARAMS(proto), PARAMS(args), \ ++ PARAMS(tstruct), PARAMS(assign), PARAMS(print)) \ ++ ++/* ++ * Stage 1 of the trace events. ++ * ++ * Create dummy trace calls for each events, verifying that the LTTng module ++ * TRACE_EVENT headers match the kernel arguments. Will be optimized out by the ++ * compiler. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++#undef TP_PROTO ++#define TP_PROTO(args...) args ++ ++#undef TP_ARGS ++#define TP_ARGS(args...) args ++ ++#undef DEFINE_EVENT ++#define DEFINE_EVENT(_template, _name, _proto, _args) \ ++void trace_##_name(_proto); ++ ++#undef DEFINE_EVENT_NOARGS ++#define DEFINE_EVENT_NOARGS(_template, _name) \ ++void trace_##_name(void *__data); ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++/* ++ * Stage 2 of the trace events. ++ * ++ * Create event field type metadata section. ++ * Each event produce an array of fields. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++/* Named field types must be defined in lttng-types.h */ ++ ++#undef __field_full ++#define __field_full(_type, _item, _order, _base) \ ++ { \ ++ .name = #_item, \ ++ .type = __type_integer(_type, _order, _base, none), \ ++ }, ++ ++#undef __field ++#define __field(_type, _item) \ ++ __field_full(_type, _item, __BYTE_ORDER, 10) ++ ++#undef __field_ext ++#define __field_ext(_type, _item, _filter_type) \ ++ __field(_type, _item) ++ ++#undef __field_hex ++#define __field_hex(_type, _item) \ ++ __field_full(_type, _item, __BYTE_ORDER, 16) ++ ++#undef __field_network ++#define __field_network(_type, _item) \ ++ __field_full(_type, _item, __BIG_ENDIAN, 10) ++ ++#undef __field_network_hex ++#define __field_network_hex(_type, _item) \ ++ __field_full(_type, _item, __BIG_ENDIAN, 16) ++ ++#undef __array_enc_ext ++#define __array_enc_ext(_type, _item, _length, _order, _base, _encoding)\ ++ { \ ++ .name = #_item, \ ++ .type = \ ++ { \ ++ .atype = atype_array, \ ++ .u.array = \ ++ { \ ++ .length = _length, \ ++ .elem_type = __type_integer(_type, _order, _base, _encoding), \ ++ }, \ ++ }, \ ++ }, ++ ++#undef __array ++#define __array(_type, _item, _length) \ ++ __array_enc_ext(_type, _item, _length, __BYTE_ORDER, 10, none) ++ ++#undef __array_text ++#define __array_text(_type, _item, _length) \ ++ __array_enc_ext(_type, _item, _length, __BYTE_ORDER, 10, UTF8) ++ ++#undef __array_hex ++#define __array_hex(_type, _item, _length) \ ++ __array_enc_ext(_type, _item, _length, __BYTE_ORDER, 16, none) ++ ++#undef __dynamic_array_enc_ext ++#define __dynamic_array_enc_ext(_type, _item, _length, _order, _base, _encoding) \ ++ { \ ++ .name = #_item, \ ++ .type = \ ++ { \ ++ .atype = atype_sequence, \ ++ .u.sequence = \ ++ { \ ++ .length_type = __type_integer(u32, __BYTE_ORDER, 10, none), \ ++ .elem_type = __type_integer(_type, _order, _base, _encoding), \ ++ }, \ ++ }, \ ++ }, ++ ++#undef __dynamic_array ++#define __dynamic_array(_type, _item, _length) \ ++ __dynamic_array_enc_ext(_type, _item, _length, __BYTE_ORDER, 10, none) ++ ++#undef __dynamic_array_text ++#define __dynamic_array_text(_type, _item, _length) \ ++ __dynamic_array_enc_ext(_type, _item, _length, __BYTE_ORDER, 10, UTF8) ++ ++#undef __dynamic_array_hex ++#define __dynamic_array_hex(_type, _item, _length) \ ++ __dynamic_array_enc_ext(_type, _item, _length, __BYTE_ORDER, 16, none) ++ ++#undef __string ++#define __string(_item, _src) \ ++ { \ ++ .name = #_item, \ ++ .type = \ ++ { \ ++ .atype = atype_string, \ ++ .u.basic.string.encoding = lttng_encode_UTF8, \ ++ }, \ ++ }, ++ ++#undef __string_from_user ++#define __string_from_user(_item, _src) \ ++ __string(_item, _src) ++ ++#undef TP_STRUCT__entry ++#define TP_STRUCT__entry(args...) args /* Only one used in this phase */ ++ ++#undef DECLARE_EVENT_CLASS_NOARGS ++#define DECLARE_EVENT_CLASS_NOARGS(_name, _tstruct, _assign, _print) \ ++ static const struct lttng_event_field __event_fields___##_name[] = { \ ++ _tstruct \ ++ }; ++ ++#undef DECLARE_EVENT_CLASS ++#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ ++ DECLARE_EVENT_CLASS_NOARGS(_name, PARAMS(_tstruct), PARAMS(_assign), \ ++ PARAMS(_print)) ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++/* ++ * Stage 3 of the trace events. ++ * ++ * Create probe callback prototypes. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++#undef TP_PROTO ++#define TP_PROTO(args...) args ++ ++#undef DECLARE_EVENT_CLASS ++#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ ++static void __event_probe__##_name(void *__data, _proto); ++ ++#undef DECLARE_EVENT_CLASS_NOARGS ++#define DECLARE_EVENT_CLASS_NOARGS(_name, _tstruct, _assign, _print) \ ++static void __event_probe__##_name(void *__data); ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++/* ++ * Stage 3.9 of the trace events. ++ * ++ * Create event descriptions. ++ */ ++ ++/* Named field types must be defined in lttng-types.h */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++#ifndef TP_PROBE_CB ++#define TP_PROBE_CB(_template) &__event_probe__##_template ++#endif ++ ++#undef DEFINE_EVENT_NOARGS ++#define DEFINE_EVENT_NOARGS(_template, _name) \ ++static const struct lttng_event_desc __event_desc___##_name = { \ ++ .fields = __event_fields___##_template, \ ++ .name = #_name, \ ++ .probe_callback = (void *) TP_PROBE_CB(_template), \ ++ .nr_fields = ARRAY_SIZE(__event_fields___##_template), \ ++ .owner = THIS_MODULE, \ ++}; ++ ++#undef DEFINE_EVENT ++#define DEFINE_EVENT(_template, _name, _proto, _args) \ ++ DEFINE_EVENT_NOARGS(_template, _name) ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++ ++/* ++ * Stage 4 of the trace events. ++ * ++ * Create an array of event description pointers. ++ */ ++ ++/* Named field types must be defined in lttng-types.h */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++#undef DEFINE_EVENT_NOARGS ++#define DEFINE_EVENT_NOARGS(_template, _name) \ ++ &__event_desc___##_name, ++ ++#undef DEFINE_EVENT ++#define DEFINE_EVENT(_template, _name, _proto, _args) \ ++ DEFINE_EVENT_NOARGS(_template, _name) ++ ++#define TP_ID1(_token, _system) _token##_system ++#define TP_ID(_token, _system) TP_ID1(_token, _system) ++ ++static const struct lttng_event_desc *TP_ID(__event_desc___, TRACE_SYSTEM)[] = { ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++}; ++ ++#undef TP_ID1 ++#undef TP_ID ++ ++ ++/* ++ * Stage 5 of the trace events. ++ * ++ * Create a toplevel descriptor for the whole probe. ++ */ ++ ++#define TP_ID1(_token, _system) _token##_system ++#define TP_ID(_token, _system) TP_ID1(_token, _system) ++ ++/* non-const because list head will be modified when registered. */ ++static __used struct lttng_probe_desc TP_ID(__probe_desc___, TRACE_SYSTEM) = { ++ .event_desc = TP_ID(__event_desc___, TRACE_SYSTEM), ++ .nr_events = ARRAY_SIZE(TP_ID(__event_desc___, TRACE_SYSTEM)), ++}; ++ ++#undef TP_ID1 ++#undef TP_ID ++ ++/* ++ * Stage 6 of the trace events. ++ * ++ * Create static inline function that calculates event size. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++/* Named field types must be defined in lttng-types.h */ ++ ++#undef __field_full ++#define __field_full(_type, _item, _order, _base) \ ++ __event_len += lib_ring_buffer_align(__event_len, ltt_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 += 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 += sizeof(u32); \ ++ __event_len += lib_ring_buffer_align(__event_len, ltt_alignof(_type)); \ ++ __dynamic_len[__dynamic_len_idx] = (_length); \ ++ __event_len += sizeof(_type) * __dynamic_len[__dynamic_len_idx]; \ ++ __dynamic_len_idx++; ++ ++#undef __string ++#define __string(_item, _src) \ ++ __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 1; ++ ++/* ++ * strlen_user includes \0. If returns 0, it faulted, so we set size to ++ * 1 (\0 only). ++ */ ++#undef __string_from_user ++#define __string_from_user(_item, _src) \ ++ __event_len += __dynamic_len[__dynamic_len_idx++] = \ ++ min_t(size_t, strlen_user(_src), 1); ++ ++#undef TP_PROTO ++#define TP_PROTO(args...) args ++ ++#undef TP_STRUCT__entry ++#define TP_STRUCT__entry(args...) args ++ ++#undef DECLARE_EVENT_CLASS ++#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ ++static inline size_t __event_get_size__##_name(size_t *__dynamic_len, _proto) \ ++{ \ ++ size_t __event_len = 0; \ ++ unsigned int __dynamic_len_idx = 0; \ ++ \ ++ if (0) \ ++ (void) __dynamic_len_idx; /* don't warn if unused */ \ ++ _tstruct \ ++ return __event_len; \ ++} ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++/* ++ * Stage 7 of the trace events. ++ * ++ * Create static inline function that calculates event payload alignment. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++/* Named field types must be defined in lttng-types.h */ ++ ++#undef __field_full ++#define __field_full(_type, _item, _order, _base) \ ++ __event_align = max_t(size_t, __event_align, ltt_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)); ++ ++#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)); ++ ++#undef __string ++#define __string(_item, _src) ++ ++#undef __string_from_user ++#define __string_from_user(_item, _src) ++ ++#undef TP_PROTO ++#define TP_PROTO(args...) args ++ ++#undef TP_STRUCT__entry ++#define TP_STRUCT__entry(args...) args ++ ++#undef DECLARE_EVENT_CLASS ++#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ ++static inline size_t __event_get_align__##_name(_proto) \ ++{ \ ++ size_t __event_align = 1; \ ++ _tstruct \ ++ return __event_align; \ ++} ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++ ++/* ++ * Stage 8 of the trace events. ++ * ++ * Create structure declaration that allows the "assign" macros to access the ++ * field types. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++/* Named field types must be defined in lttng-types.h */ ++ ++#undef __field_full ++#define __field_full(_type, _item, _order, _base) _type _item; ++ ++#undef __array_enc_ext ++#define __array_enc_ext(_type, _item, _length, _order, _base, _encoding) \ ++ _type _item; ++ ++#undef __dynamic_array_enc_ext ++#define __dynamic_array_enc_ext(_type, _item, _length, _order, _base, _encoding)\ ++ _type _item; ++ ++#undef __string ++#define __string(_item, _src) char _item; ++ ++#undef __string_from_user ++#define __string_from_user(_item, _src) \ ++ __string(_item, _src) ++ ++#undef TP_STRUCT__entry ++#define TP_STRUCT__entry(args...) args ++ ++#undef DECLARE_EVENT_CLASS ++#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ ++struct __event_typemap__##_name { \ ++ _tstruct \ ++}; ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++ ++/* ++ * Stage 9 of the trace events. ++ * ++ * Create the probe function : call even size calculation and write event data ++ * into the buffer. ++ * ++ * We use both the field and assignment macros to write the fields in the order ++ * defined in the field declaration. The field declarations control the ++ * execution order, jumping to the appropriate assignment block. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++#undef __field_full ++#define __field_full(_type, _item, _order, _base) \ ++ goto __assign_##_item; \ ++__end_field_##_item: ++ ++#undef __array_enc_ext ++#define __array_enc_ext(_type, _item, _length, _order, _base, _encoding)\ ++ goto __assign_##_item; \ ++__end_field_##_item: ++ ++#undef __dynamic_array_enc_ext ++#define __dynamic_array_enc_ext(_type, _item, _length, _order, _base, _encoding)\ ++ goto __assign_##_item##_1; \ ++__end_field_##_item##_1: \ ++ goto __assign_##_item##_2; \ ++__end_field_##_item##_2: ++ ++#undef __string ++#define __string(_item, _src) \ ++ goto __assign_##_item; \ ++__end_field_##_item: ++ ++#undef __string_from_user ++#define __string_from_user(_item, _src) \ ++ __string(_item, _src) ++ ++/* ++ * Macros mapping tp_assign() to "=", tp_memcpy() to memcpy() and tp_strcpy() to ++ * strcpy(). ++ */ ++#undef tp_assign ++#define tp_assign(dest, src) \ ++__assign_##dest: \ ++ { \ ++ __typeof__(__typemap.dest) __tmp = (src); \ ++ lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__tmp)); \ ++ __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp));\ ++ } \ ++ goto __end_field_##dest; ++ ++#undef tp_memcpy ++#define tp_memcpy(dest, src, len) \ ++__assign_##dest: \ ++ if (0) \ ++ (void) __typemap.dest; \ ++ lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest)); \ ++ __chan->ops->event_write(&__ctx, src, len); \ ++ goto __end_field_##dest; ++ ++#undef tp_memcpy_dyn ++#define tp_memcpy_dyn(dest, src) \ ++__assign_##dest##_1: \ ++ { \ ++ u32 __tmpl = __dynamic_len[__dynamic_len_idx]; \ ++ lib_ring_buffer_align_ctx(&__ctx, ltt_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)); \ ++ __chan->ops->event_write(&__ctx, src, \ ++ sizeof(__typemap.dest) * __get_dynamic_array_len(dest));\ ++ goto __end_field_##dest##_2; ++ ++#undef tp_memcpy_from_user ++#define tp_memcpy_from_user(dest, src, len) \ ++ __assign_##dest: \ ++ if (0) \ ++ (void) __typemap.dest; \ ++ lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest)); \ ++ __chan->ops->event_write_from_user(&__ctx, src, len); \ ++ goto __end_field_##dest; ++ ++/* ++ * The string length including the final \0. ++ */ ++#undef tp_copy_string_from_user ++#define tp_copy_string_from_user(dest, src) \ ++ __assign_##dest: \ ++ { \ ++ size_t __ustrlen; \ ++ \ ++ if (0) \ ++ (void) __typemap.dest; \ ++ lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest));\ ++ __ustrlen = __get_dynamic_array_len(dest); \ ++ if (likely(__ustrlen) > 1) { \ ++ __chan->ops->event_write_from_user(&__ctx, src, \ ++ __ustrlen - 1); \ ++ } \ ++ __chan->ops->event_memset(&__ctx, 0, 1); \ ++ } \ ++ goto __end_field_##dest; ++#undef tp_strcpy ++#define tp_strcpy(dest, src) \ ++ tp_memcpy(dest, src, __get_dynamic_array_len(dest)) ++ ++/* Named field types must be defined in lttng-types.h */ ++ ++#undef __get_str ++#define __get_str(field) field ++ ++#undef __get_dynamic_array ++#define __get_dynamic_array(field) field ++ ++/* Beware: this get len actually consumes the len value */ ++#undef __get_dynamic_array_len ++#define __get_dynamic_array_len(field) __dynamic_len[__dynamic_len_idx++] ++ ++#undef TP_PROTO ++#define TP_PROTO(args...) args ++ ++#undef TP_ARGS ++#define TP_ARGS(args...) args ++ ++#undef TP_STRUCT__entry ++#define TP_STRUCT__entry(args...) args ++ ++#undef TP_fast_assign ++#define TP_fast_assign(args...) args ++ ++#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 lib_ring_buffer_ctx __ctx; \ ++ size_t __event_len, __event_align; \ ++ size_t __dynamic_len_idx = 0; \ ++ size_t __dynamic_len[ARRAY_SIZE(__event_fields___##_name)]; \ ++ struct __event_typemap__##_name __typemap; \ ++ int __ret; \ ++ \ ++ if (0) \ ++ (void) __dynamic_len_idx; /* don't warn if unused */ \ ++ if (unlikely(!ACCESS_ONCE(__chan->session->active))) \ ++ return; \ ++ if (unlikely(!ACCESS_ONCE(__chan->enabled))) \ ++ return; \ ++ if (unlikely(!ACCESS_ONCE(__event->enabled))) \ ++ return; \ ++ __event_len = __event_get_size__##_name(__dynamic_len, _args); \ ++ __event_align = __event_get_align__##_name(_args); \ ++ lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \ ++ __event_align, -1); \ ++ __ret = __chan->ops->event_reserve(&__ctx, __event->id); \ ++ if (__ret < 0) \ ++ return; \ ++ /* Control code (field ordering) */ \ ++ _tstruct \ ++ __chan->ops->event_commit(&__ctx); \ ++ return; \ ++ /* Copy code, steered by control code */ \ ++ _assign \ ++} ++ ++#undef DECLARE_EVENT_CLASS_NOARGS ++#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 lib_ring_buffer_ctx __ctx; \ ++ size_t __event_len, __event_align; \ ++ int __ret; \ ++ \ ++ if (unlikely(!ACCESS_ONCE(__chan->session->active))) \ ++ return; \ ++ if (unlikely(!ACCESS_ONCE(__chan->enabled))) \ ++ return; \ ++ if (unlikely(!ACCESS_ONCE(__event->enabled))) \ ++ return; \ ++ __event_len = 0; \ ++ __event_align = 1; \ ++ lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \ ++ __event_align, -1); \ ++ __ret = __chan->ops->event_reserve(&__ctx, __event->id); \ ++ if (__ret < 0) \ ++ return; \ ++ /* Control code (field ordering) */ \ ++ _tstruct \ ++ __chan->ops->event_commit(&__ctx); \ ++ return; \ ++ /* Copy code, steered by control code */ \ ++ _assign \ ++} ++ ++#include TRACE_INCLUDE(TRACE_INCLUDE_FILE) ++ ++/* ++ * Stage 10 of the trace events. ++ * ++ * Register/unregister probes at module load/unload. ++ */ ++ ++#include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ ++ ++#define TP_ID1(_token, _system) _token##_system ++#define TP_ID(_token, _system) TP_ID1(_token, _system) ++#define module_init_eval1(_token, _system) module_init(_token##_system) ++#define module_init_eval(_token, _system) module_init_eval1(_token, _system) ++#define module_exit_eval1(_token, _system) module_exit(_token##_system) ++#define module_exit_eval(_token, _system) module_exit_eval1(_token, _system) ++ ++#ifndef TP_MODULE_OVERRIDE ++static int TP_ID(__lttng_events_init__, TRACE_SYSTEM)(void) ++{ ++ wrapper_vmalloc_sync_all(); ++ return ltt_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)); ++} ++ ++module_exit_eval(__lttng_events_exit__, TRACE_SYSTEM); ++#endif ++ ++#undef module_init_eval ++#undef module_exit_eval ++#undef TP_ID1 ++#undef TP_ID ++ ++#undef TP_PROTO ++#undef TP_ARGS ++#undef TRACE_EVENT_FLAGS +diff --git a/drivers/staging/lttng/probes/lttng-ftrace.c b/drivers/staging/lttng/probes/lttng-ftrace.c +new file mode 100644 +index 0000000..1aa7183 +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-ftrace.c +@@ -0,0 +1,188 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng function tracer integration module. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++/* ++ * Ftrace function tracer does not seem to provide synchronization between probe ++ * teardown and callback execution. Therefore, we make this module permanently ++ * loaded (unloadable). ++ * ++ * TODO: Move to register_ftrace_function() (which is exported for ++ * modules) for Linux >= 3.0. It is faster (only enables the selected ++ * functions), and will stay there. ++ */ ++ ++#include <linux/module.h> ++#include <linux/ftrace.h> ++#include <linux/slab.h> ++#include "../ltt-events.h" ++#include "../wrapper/ringbuffer/frontend_types.h" ++#include "../wrapper/ftrace.h" ++#include "../wrapper/vmalloc.h" ++#include "../ltt-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 lib_ring_buffer_ctx ctx; ++ struct { ++ unsigned long ip; ++ unsigned long parent_ip; ++ } payload; ++ int ret; ++ ++ if (unlikely(!ACCESS_ONCE(chan->session->active))) ++ return; ++ if (unlikely(!ACCESS_ONCE(chan->enabled))) ++ return; ++ if (unlikely(!ACCESS_ONCE(event->enabled))) ++ return; ++ ++ lib_ring_buffer_ctx_init(&ctx, chan->chan, event, ++ sizeof(payload), ltt_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)); ++ chan->ops->event_write(&ctx, &payload, sizeof(payload)); ++ chan->ops->event_commit(&ctx); ++ return; ++} ++ ++/* ++ * Create event description ++ */ ++static ++int lttng_create_ftrace_event(const char *name, struct ltt_event *event) ++{ ++ struct lttng_event_field *fields; ++ struct lttng_event_desc *desc; ++ int ret; ++ ++ desc = kzalloc(sizeof(*event->desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ desc->name = kstrdup(name, GFP_KERNEL); ++ if (!desc->name) { ++ ret = -ENOMEM; ++ goto error_str; ++ } ++ desc->nr_fields = 2; ++ desc->fields = fields = ++ kzalloc(2 * sizeof(struct lttng_event_field), GFP_KERNEL); ++ if (!desc->fields) { ++ ret = -ENOMEM; ++ goto error_fields; ++ } ++ 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.signedness = is_signed_type(unsigned long); ++ fields[0].type.u.basic.integer.reverse_byte_order = 0; ++ fields[0].type.u.basic.integer.base = 16; ++ fields[0].type.u.basic.integer.encoding = lttng_encode_none; ++ ++ 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.signedness = is_signed_type(unsigned long); ++ fields[1].type.u.basic.integer.reverse_byte_order = 0; ++ fields[1].type.u.basic.integer.base = 16; ++ fields[1].type.u.basic.integer.encoding = lttng_encode_none; ++ ++ desc->owner = THIS_MODULE; ++ event->desc = desc; ++ ++ return 0; ++ ++error_fields: ++ kfree(desc->name); ++error_str: ++ kfree(desc); ++ return ret; ++} ++ ++static ++struct ftrace_probe_ops lttng_ftrace_ops = { ++ .func = lttng_ftrace_handler, ++}; ++ ++int lttng_ftrace_register(const char *name, ++ const char *symbol_name, ++ struct ltt_event *event) ++{ ++ int ret; ++ ++ ret = lttng_create_ftrace_event(name, event); ++ if (ret) ++ goto error; ++ ++ event->u.ftrace.symbol_name = kstrdup(symbol_name, GFP_KERNEL); ++ if (!event->u.ftrace.symbol_name) ++ goto name_error; ++ ++ /* Ensure the memory we just allocated don't trigger page faults */ ++ wrapper_vmalloc_sync_all(); ++ ++ ret = wrapper_register_ftrace_function_probe(event->u.ftrace.symbol_name, ++ <tng_ftrace_ops, event); ++ if (ret < 0) ++ goto register_error; ++ return 0; ++ ++register_error: ++ kfree(event->u.ftrace.symbol_name); ++name_error: ++ kfree(event->desc->name); ++ kfree(event->desc); ++error: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(lttng_ftrace_register); ++ ++void lttng_ftrace_unregister(struct ltt_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) ++{ ++ kfree(event->u.ftrace.symbol_name); ++ kfree(event->desc->fields); ++ kfree(event->desc->name); ++ kfree(event->desc); ++} ++EXPORT_SYMBOL_GPL(lttng_ftrace_destroy_private); ++ ++int lttng_ftrace_init(void) ++{ ++ wrapper_vmalloc_sync_all(); ++ return 0; ++} ++module_init(lttng_ftrace_init) ++ ++/* ++ * Ftrace takes care of waiting for a grace period (RCU sched) at probe ++ * unregistration, and disables preemption around probe call. ++ */ ++void lttng_ftrace_exit(void) ++{ ++} ++module_exit(lttng_ftrace_exit) ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit Ftrace Support"); +diff --git a/drivers/staging/lttng/probes/lttng-kprobes.c b/drivers/staging/lttng/probes/lttng-kprobes.c +new file mode 100644 +index 0000000..784002a +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-kprobes.c +@@ -0,0 +1,164 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng kprobes integration module. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kprobes.h> ++#include <linux/slab.h> ++#include "../ltt-events.h" ++#include "../wrapper/ringbuffer/frontend_types.h" ++#include "../wrapper/vmalloc.h" ++#include "../ltt-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 lib_ring_buffer_ctx ctx; ++ int ret; ++ unsigned long data = (unsigned long) p->addr; ++ ++ if (unlikely(!ACCESS_ONCE(chan->session->active))) ++ return 0; ++ if (unlikely(!ACCESS_ONCE(chan->enabled))) ++ return 0; ++ if (unlikely(!ACCESS_ONCE(event->enabled))) ++ return 0; ++ ++ lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(data), ++ ltt_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)); ++ chan->ops->event_write(&ctx, &data, sizeof(data)); ++ chan->ops->event_commit(&ctx); ++ return 0; ++} ++ ++/* ++ * Create event description ++ */ ++static ++int lttng_create_kprobe_event(const char *name, struct ltt_event *event) ++{ ++ struct lttng_event_field *field; ++ struct lttng_event_desc *desc; ++ int ret; ++ ++ desc = kzalloc(sizeof(*event->desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ desc->name = kstrdup(name, GFP_KERNEL); ++ if (!desc->name) { ++ ret = -ENOMEM; ++ goto error_str; ++ } ++ desc->nr_fields = 1; ++ desc->fields = field = ++ kzalloc(1 * sizeof(struct lttng_event_field), GFP_KERNEL); ++ if (!field) { ++ ret = -ENOMEM; ++ goto error_field; ++ } ++ 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.signedness = is_signed_type(unsigned long); ++ field->type.u.basic.integer.reverse_byte_order = 0; ++ field->type.u.basic.integer.base = 16; ++ field->type.u.basic.integer.encoding = lttng_encode_none; ++ desc->owner = THIS_MODULE; ++ event->desc = desc; ++ ++ return 0; ++ ++error_field: ++ kfree(desc->name); ++error_str: ++ kfree(desc); ++ return ret; ++} ++ ++int lttng_kprobes_register(const char *name, ++ const char *symbol_name, ++ uint64_t offset, ++ uint64_t addr, ++ struct ltt_event *event) ++{ ++ int ret; ++ ++ /* Kprobes expects a NULL symbol name if unused */ ++ if (symbol_name[0] == '\0') ++ symbol_name = NULL; ++ ++ ret = lttng_create_kprobe_event(name, event); ++ if (ret) ++ goto error; ++ memset(&event->u.kprobe.kp, 0, sizeof(event->u.kprobe.kp)); ++ 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), ++ 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)); ++ event->u.kprobe.kp.symbol_name = ++ event->u.kprobe.symbol_name; ++ } ++ event->u.kprobe.kp.offset = offset; ++ event->u.kprobe.kp.addr = (void *) (unsigned long) addr; ++ ++ /* ++ * Ensure the memory we just allocated don't trigger page faults. ++ * Well.. kprobes itself puts the page fault handler on the blacklist, ++ * but we can never be too careful. ++ */ ++ wrapper_vmalloc_sync_all(); ++ ++ ret = register_kprobe(&event->u.kprobe.kp); ++ if (ret) ++ goto register_error; ++ return 0; ++ ++register_error: ++ kfree(event->u.kprobe.symbol_name); ++name_error: ++ kfree(event->desc->fields); ++ kfree(event->desc->name); ++ kfree(event->desc); ++error: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(lttng_kprobes_register); ++ ++void lttng_kprobes_unregister(struct ltt_event *event) ++{ ++ unregister_kprobe(&event->u.kprobe.kp); ++} ++EXPORT_SYMBOL_GPL(lttng_kprobes_unregister); ++ ++void lttng_kprobes_destroy_private(struct ltt_event *event) ++{ ++ kfree(event->u.kprobe.symbol_name); ++ kfree(event->desc->fields); ++ kfree(event->desc->name); ++ kfree(event->desc); ++} ++EXPORT_SYMBOL_GPL(lttng_kprobes_destroy_private); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit Kprobes Support"); +diff --git a/drivers/staging/lttng/probes/lttng-kretprobes.c b/drivers/staging/lttng/probes/lttng-kretprobes.c +new file mode 100644 +index 0000000..6b29101 +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-kretprobes.c +@@ -0,0 +1,277 @@ ++/* ++ * (C) Copyright 2009-2011 - ++ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng kretprobes integration module. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kprobes.h> ++#include <linux/slab.h> ++#include <linux/kref.h> ++#include "../ltt-events.h" ++#include "../wrapper/ringbuffer/frontend_types.h" ++#include "../wrapper/vmalloc.h" ++#include "../ltt-tracer.h" ++ ++enum lttng_kretprobe_type { ++ EVENT_ENTRY = 0, ++ EVENT_RETURN = 1, ++}; ++ ++struct lttng_krp { ++ struct kretprobe krp; ++ struct ltt_event *event[2]; /* ENTRY and RETURN */ ++ struct kref kref_register; ++ struct kref kref_alloc; ++}; ++ ++static ++int _lttng_kretprobes_handler(struct kretprobe_instance *krpi, ++ struct pt_regs *regs, ++ enum lttng_kretprobe_type type) ++{ ++ struct lttng_krp *lttng_krp = ++ container_of(krpi->rp, struct lttng_krp, krp); ++ struct ltt_event *event = ++ lttng_krp->event[type]; ++ struct ltt_channel *chan = event->chan; ++ struct lib_ring_buffer_ctx ctx; ++ int ret; ++ struct { ++ unsigned long ip; ++ unsigned long parent_ip; ++ } payload; ++ ++ if (unlikely(!ACCESS_ONCE(chan->session->active))) ++ return 0; ++ if (unlikely(!ACCESS_ONCE(chan->enabled))) ++ return 0; ++ if (unlikely(!ACCESS_ONCE(event->enabled))) ++ return 0; ++ ++ payload.ip = (unsigned long) krpi->rp->kp.addr; ++ payload.parent_ip = (unsigned long) krpi->ret_addr; ++ ++ lib_ring_buffer_ctx_init(&ctx, chan->chan, event, sizeof(payload), ++ ltt_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)); ++ chan->ops->event_write(&ctx, &payload, sizeof(payload)); ++ chan->ops->event_commit(&ctx); ++ return 0; ++} ++ ++static ++int lttng_kretprobes_handler_entry(struct kretprobe_instance *krpi, ++ struct pt_regs *regs) ++{ ++ return _lttng_kretprobes_handler(krpi, regs, EVENT_ENTRY); ++} ++ ++static ++int lttng_kretprobes_handler_return(struct kretprobe_instance *krpi, ++ struct pt_regs *regs) ++{ ++ return _lttng_kretprobes_handler(krpi, regs, EVENT_RETURN); ++} ++ ++/* ++ * Create event description ++ */ ++static ++int lttng_create_kprobe_event(const char *name, struct ltt_event *event, ++ enum lttng_kretprobe_type type) ++{ ++ struct lttng_event_field *fields; ++ struct lttng_event_desc *desc; ++ int ret; ++ char *alloc_name; ++ size_t name_len; ++ const char *suffix = NULL; ++ ++ desc = kzalloc(sizeof(*event->desc), GFP_KERNEL); ++ if (!desc) ++ return -ENOMEM; ++ name_len = strlen(name); ++ switch (type) { ++ case EVENT_ENTRY: ++ suffix = "_entry"; ++ break; ++ case EVENT_RETURN: ++ suffix = "_return"; ++ break; ++ } ++ name_len += strlen(suffix); ++ alloc_name = kmalloc(name_len + 1, GFP_KERNEL); ++ if (!alloc_name) { ++ ret = -ENOMEM; ++ goto error_str; ++ } ++ strcpy(alloc_name, name); ++ strcat(alloc_name, suffix); ++ desc->name = alloc_name; ++ desc->nr_fields = 2; ++ desc->fields = fields = ++ kzalloc(2 * sizeof(struct lttng_event_field), GFP_KERNEL); ++ if (!desc->fields) { ++ ret = -ENOMEM; ++ goto error_fields; ++ } ++ 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.signedness = is_signed_type(unsigned long); ++ fields[0].type.u.basic.integer.reverse_byte_order = 0; ++ fields[0].type.u.basic.integer.base = 16; ++ fields[0].type.u.basic.integer.encoding = lttng_encode_none; ++ ++ 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.signedness = is_signed_type(unsigned long); ++ fields[1].type.u.basic.integer.reverse_byte_order = 0; ++ fields[1].type.u.basic.integer.base = 16; ++ fields[1].type.u.basic.integer.encoding = lttng_encode_none; ++ ++ desc->owner = THIS_MODULE; ++ event->desc = desc; ++ ++ return 0; ++ ++error_fields: ++ kfree(desc->name); ++error_str: ++ kfree(desc); ++ return ret; ++} ++ ++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_return) ++{ ++ int ret; ++ struct lttng_krp *lttng_krp; ++ ++ /* Kprobes expects a NULL symbol name if unused */ ++ if (symbol_name[0] == '\0') ++ symbol_name = NULL; ++ ++ ret = lttng_create_kprobe_event(name, event_entry, EVENT_ENTRY); ++ if (ret) ++ goto error; ++ ret = lttng_create_kprobe_event(name, event_return, EVENT_RETURN); ++ if (ret) ++ goto event_return_error; ++ lttng_krp = kzalloc(sizeof(*lttng_krp), GFP_KERNEL); ++ if (!lttng_krp) ++ goto krp_error; ++ lttng_krp->krp.entry_handler = lttng_kretprobes_handler_entry; ++ lttng_krp->krp.handler = lttng_kretprobes_handler_return; ++ if (symbol_name) { ++ char *alloc_symbol; ++ ++ alloc_symbol = kstrdup(symbol_name, GFP_KERNEL); ++ if (!alloc_symbol) { ++ ret = -ENOMEM; ++ goto name_error; ++ } ++ lttng_krp->krp.kp.symbol_name = ++ alloc_symbol; ++ event_entry->u.kretprobe.symbol_name = ++ alloc_symbol; ++ event_return->u.kretprobe.symbol_name = ++ alloc_symbol; ++ } ++ lttng_krp->krp.kp.offset = offset; ++ lttng_krp->krp.kp.addr = (void *) (unsigned long) addr; ++ ++ /* Allow probe handler to find event structures */ ++ lttng_krp->event[EVENT_ENTRY] = event_entry; ++ lttng_krp->event[EVENT_RETURN] = event_return; ++ event_entry->u.kretprobe.lttng_krp = lttng_krp; ++ event_return->u.kretprobe.lttng_krp = lttng_krp; ++ ++ /* ++ * Both events must be unregistered before the kretprobe is ++ * unregistered. Same for memory allocation. ++ */ ++ kref_init(<tng_krp->kref_alloc); ++ kref_get(<tng_krp->kref_alloc); /* inc refcount to 2 */ ++ kref_init(<tng_krp->kref_register); ++ kref_get(<tng_krp->kref_register); /* inc refcount to 2 */ ++ ++ /* ++ * Ensure the memory we just allocated don't trigger page faults. ++ * Well.. kprobes itself puts the page fault handler on the blacklist, ++ * but we can never be too careful. ++ */ ++ wrapper_vmalloc_sync_all(); ++ ++ ret = register_kretprobe(<tng_krp->krp); ++ if (ret) ++ goto register_error; ++ return 0; ++ ++register_error: ++ kfree(lttng_krp->krp.kp.symbol_name); ++name_error: ++ kfree(lttng_krp); ++krp_error: ++ kfree(event_return->desc->fields); ++ kfree(event_return->desc->name); ++ kfree(event_return->desc); ++event_return_error: ++ kfree(event_entry->desc->fields); ++ kfree(event_entry->desc->name); ++ kfree(event_entry->desc); ++error: ++ return ret; ++} ++EXPORT_SYMBOL_GPL(lttng_kretprobes_register); ++ ++static ++void _lttng_kretprobes_unregister_release(struct kref *kref) ++{ ++ struct lttng_krp *lttng_krp = ++ container_of(kref, struct lttng_krp, kref_register); ++ unregister_kretprobe(<tng_krp->krp); ++} ++ ++void lttng_kretprobes_unregister(struct ltt_event *event) ++{ ++ kref_put(&event->u.kretprobe.lttng_krp->kref_register, ++ _lttng_kretprobes_unregister_release); ++} ++EXPORT_SYMBOL_GPL(lttng_kretprobes_unregister); ++ ++static ++void _lttng_kretprobes_release(struct kref *kref) ++{ ++ struct lttng_krp *lttng_krp = ++ container_of(kref, struct lttng_krp, kref_alloc); ++ kfree(lttng_krp->krp.kp.symbol_name); ++} ++ ++void lttng_kretprobes_destroy_private(struct ltt_event *event) ++{ ++ kfree(event->desc->fields); ++ kfree(event->desc->name); ++ kfree(event->desc); ++ kref_put(&event->u.kretprobe.lttng_krp->kref_alloc, ++ _lttng_kretprobes_release); ++} ++EXPORT_SYMBOL_GPL(lttng_kretprobes_destroy_private); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers"); ++MODULE_DESCRIPTION("Linux Trace Toolkit Kretprobes Support"); +diff --git a/drivers/staging/lttng/probes/lttng-probe-block.c b/drivers/staging/lttng/probes/lttng-probe-block.c +new file mode 100644 +index 0000000..9eeebfc +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-probe-block.c +@@ -0,0 +1,31 @@ ++/* ++ * probes/lttng-probe-block.c ++ * ++ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng block probes. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/blktrace_api.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/block.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/block.h" ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); ++MODULE_DESCRIPTION("LTTng block probes"); +diff --git a/drivers/staging/lttng/probes/lttng-probe-irq.c b/drivers/staging/lttng/probes/lttng-probe-irq.c +new file mode 100644 +index 0000000..4a6a322 +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-probe-irq.c +@@ -0,0 +1,31 @@ ++/* ++ * probes/lttng-probe-irq.c ++ * ++ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng irq probes. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/interrupt.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/irq.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/irq.h" ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); ++MODULE_DESCRIPTION("LTTng irq probes"); +diff --git a/drivers/staging/lttng/probes/lttng-probe-kvm.c b/drivers/staging/lttng/probes/lttng-probe-kvm.c +new file mode 100644 +index 0000000..9efc6dd +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-probe-kvm.c +@@ -0,0 +1,31 @@ ++/* ++ * probes/lttng-probe-kvm.c ++ * ++ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng kvm probes. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.h> ++#include <linux/kvm_host.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/kvm.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/kvm.h" ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); ++MODULE_DESCRIPTION("LTTng kvm probes"); +diff --git a/drivers/staging/lttng/probes/lttng-probe-lttng.c b/drivers/staging/lttng/probes/lttng-probe-lttng.c +new file mode 100644 +index 0000000..62aab6c +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-probe-lttng.c +@@ -0,0 +1,24 @@ ++/* ++ * probes/lttng-probe-core.c ++ * ++ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng core probes. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/module.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/lttng.h" ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); ++MODULE_DESCRIPTION("LTTng core probes"); +diff --git a/drivers/staging/lttng/probes/lttng-probe-sched.c b/drivers/staging/lttng/probes/lttng-probe-sched.c +new file mode 100644 +index 0000000..18c1521 +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-probe-sched.c +@@ -0,0 +1,30 @@ ++/* ++ * probes/lttng-probe-sched.c ++ * ++ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng sched probes. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#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/sched.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/sched.h" ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); ++MODULE_DESCRIPTION("LTTng sched probes"); +diff --git a/drivers/staging/lttng/probes/lttng-type-list.h b/drivers/staging/lttng/probes/lttng-type-list.h +new file mode 100644 +index 0000000..7b953db +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-type-list.h +@@ -0,0 +1,21 @@ ++/* ++ * lttng-type-list.h ++ * ++ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++/* Type list, used to create metadata */ ++ ++/* Enumerations */ ++TRACE_EVENT_ENUM(hrtimer_mode, ++ V(HRTIMER_MODE_ABS), ++ V(HRTIMER_MODE_REL), ++ V(HRTIMER_MODE_PINNED), ++ V(HRTIMER_MODE_ABS_PINNED), ++ V(HRTIMER_MODE_REL_PINNED), ++ R(HRTIMER_MODE_UNDEFINED, 0x04, 0x20), /* Example (to remove) */ ++) ++ ++TRACE_EVENT_TYPE(hrtimer_mode, enum, unsigned char) +diff --git a/drivers/staging/lttng/probes/lttng-types.c b/drivers/staging/lttng/probes/lttng-types.c +new file mode 100644 +index 0000000..93a9ae5 +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-types.c +@@ -0,0 +1,49 @@ ++/* ++ * probes/lttng-types.c ++ * ++ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng types. ++ * ++ * 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 "lttng-types.h" ++#include <linux/hrtimer.h> ++ ++#define STAGE_EXPORT_ENUMS ++#include "lttng-types.h" ++#include "lttng-type-list.h" ++#undef STAGE_EXPORT_ENUMS ++ ++struct lttng_enum lttng_enums[] = { ++#define STAGE_EXPORT_TYPES ++#include "lttng-types.h" ++#include "lttng-type-list.h" ++#undef STAGE_EXPORT_TYPES ++}; ++ ++static int lttng_types_init(void) ++{ ++ int ret = 0; ++ ++ wrapper_vmalloc_sync_all(); ++ /* TODO */ ++ return ret; ++} ++ ++module_init(lttng_types_init); ++ ++static void lttng_types_exit(void) ++{ ++} ++ ++module_exit(lttng_types_exit); ++ ++MODULE_LICENSE("GPL and additional rights"); ++MODULE_AUTHOR("Mathieu Desnoyers <mathieu.desnoyers@efficios.com>"); ++MODULE_DESCRIPTION("LTTng types"); +diff --git a/drivers/staging/lttng/probes/lttng-types.h b/drivers/staging/lttng/probes/lttng-types.h +new file mode 100644 +index 0000000..1062028 +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng-types.h +@@ -0,0 +1,72 @@ ++/* ++ * Protect against multiple inclusion of structure declarations, but run the ++ * stages below each time. ++ */ ++#ifndef _LTTNG_PROBES_LTTNG_TYPES_H ++#define _LTTNG_PROBES_LTTNG_TYPES_H ++ ++/* ++ * probes/lttng-types.h ++ * ++ * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * LTTng types. ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#include <linux/seq_file.h> ++#include "lttng.h" ++#include "../ltt-events.h" ++#include "../ltt-tracer.h" ++#include "../ltt-endian.h" ++ ++#endif /* _LTTNG_PROBES_LTTNG_TYPES_H */ ++ ++/* Export enumerations */ ++ ++#ifdef STAGE_EXPORT_ENUMS ++ ++#undef TRACE_EVENT_TYPE ++#define TRACE_EVENT_TYPE(_name, _abstract_type, args...) ++ ++#undef TRACE_EVENT_ENUM ++#define TRACE_EVENT_ENUM(_name, _entries...) \ ++ const struct lttng_enum_entry __trace_event_enum_##_name[] = { \ ++ PARAMS(_entries) \ ++ }; ++ ++/* Enumeration entry (single value) */ ++#undef V ++#define V(_string) { _string, _string, #_string} ++ ++/* Enumeration entry (range) */ ++#undef R ++#define R(_string, _range_start, _range_end) \ ++ { _range_start, _range_end, #_string } ++ ++#endif /* STAGE_EXPORT_ENUMS */ ++ ++ ++/* Export named types */ ++ ++#ifdef STAGE_EXPORT_TYPES ++ ++#undef TRACE_EVENT_TYPE___enum ++#define TRACE_EVENT_TYPE___enum(_name, _container_type) \ ++ { \ ++ .name = #_name, \ ++ .container_type = __type_integer(_container_type, __BYTE_ORDER, 10, none), \ ++ .entries = __trace_event_enum_##_name, \ ++ .len = ARRAY_SIZE(__trace_event_enum_##_name), \ ++ }, ++ ++/* Local declaration */ ++#undef TRACE_EVENT_TYPE ++#define TRACE_EVENT_TYPE(_name, _abstract_type, args...) \ ++ TRACE_EVENT_TYPE___##_abstract_type(_name, args) ++ ++#undef TRACE_EVENT_ENUM ++#define TRACE_EVENT_ENUM(_name, _entries...) ++ ++#endif /* STAGE_EXPORT_TYPES */ +diff --git a/drivers/staging/lttng/probes/lttng.h b/drivers/staging/lttng/probes/lttng.h +new file mode 100644 +index 0000000..e16fc2d +--- /dev/null ++++ b/drivers/staging/lttng/probes/lttng.h +@@ -0,0 +1,15 @@ ++#ifndef _LTTNG_PROBES_LTTNG_H ++#define _LTTNG_PROBES_LTTNG_H ++ ++/* ++ * lttng.h ++ * ++ * Copyright (C) 2010-2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++ * ++ * Dual LGPL v2.1/GPL v2 license. ++ */ ++ ++#undef PARAMS ++#define PARAMS(args...) args ++ ++#endif /* _LTTNG_PROBES_LTTNG_H */ +-- +1.7.9 + diff --git a/patches.lttng/0017-lttng-toplevel-Makefile-and-Kconfig.patch b/patches.lttng/0017-lttng-toplevel-Makefile-and-Kconfig.patch new file mode 100644 index 0000000000000..aad46b07ea99a --- /dev/null +++ b/patches.lttng/0017-lttng-toplevel-Makefile-and-Kconfig.patch @@ -0,0 +1,97 @@ +From 3c46c44027a86fc8a008a6096b0e5b8f5a4afcb5 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:25 -0500 +Subject: lttng: toplevel Makefile and Kconfig + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/Kconfig | 35 +++++++++++++++++++++++++++++++++++ + drivers/staging/lttng/Makefile | 33 +++++++++++++++++++++++++++++++++ + 2 files changed, 68 insertions(+), 0 deletions(-) + create mode 100644 drivers/staging/lttng/Kconfig + create mode 100644 drivers/staging/lttng/Makefile + +diff --git a/drivers/staging/lttng/Kconfig b/drivers/staging/lttng/Kconfig +new file mode 100644 +index 0000000..34c4a4f +--- /dev/null ++++ b/drivers/staging/lttng/Kconfig +@@ -0,0 +1,35 @@ ++config LTTNG ++ tristate "LTTng kernel tracer" ++ depends on TRACEPOINTS ++ help ++ The LTTng 2.0 Tracer Toolchain allows integrated kernel and ++ user-space tracing from a single user interface: the "lttng" ++ command. See http://lttng.org website for the "lttng-tools" ++ user-space tracer control tools package and the "babeltrace" ++ package for conversion of trace data to a human-readable ++ format. ++ ++ LTTng features: ++ - System-wide tracing across kernel, libraries and ++ applications, ++ - Tracepoints, detailed syscall tracing (fast strace replacement), ++ Function tracer, CPU Performance Monitoring Unit (PMU) counters ++ and kprobes support, ++ - Have the ability to attach "context" information to events in the ++ trace (e.g. any PMU counter, pid, ppid, tid, comm name, etc). All ++ the extra information fields to be collected with events are ++ optional, specified on a per-tracing-session basis (except for ++ timestamp and event id, which are mandatory). ++ - Precise and fast clock sources with near cycle-level ++ timestamps, ++ - Efficient trace data transport: ++ - Compact Binary format with CTF, ++ - Per-core buffers ensures scalability, ++ - Fast-paths in caller context, amortized synchronization, ++ - Zero-copy using splice and mmap system calls, over disk, ++ network or consumed in-place, ++ - Multiple concurrent tracing sessions are supported, ++ - Designed to meet hard real-time constraints, ++ - Supports live streaming of the trace data, ++ - Produces CTF (Common Trace Format) natively (see ++ http://www.efficios.com/ctf). +diff --git a/drivers/staging/lttng/Makefile b/drivers/staging/lttng/Makefile +new file mode 100644 +index 0000000..9ad4eb0 +--- /dev/null ++++ b/drivers/staging/lttng/Makefile +@@ -0,0 +1,33 @@ ++# ++# 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 += ltt-relay.o ++ltt-relay-objs := ltt-events.o ltt-debugfs-abi.o \ ++ ltt-probes.o ltt-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 ++ ++ifneq ($(CONFIG_HAVE_SYSCALL_TRACEPOINTS),) ++ltt-relay-objs += lttng-syscalls.o ++endif ++ ++ifneq ($(CONFIG_PERF_EVENTS),) ++ltt-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;) ++endif ++ ++obj-m += probes/ ++obj-m += lib/ +-- +1.7.9 + diff --git a/patches.lttng/0018-staging-add-LTTng-to-build.patch b/patches.lttng/0018-staging-add-LTTng-to-build.patch new file mode 100644 index 0000000000000..11da1a29e36cd --- /dev/null +++ b/patches.lttng/0018-staging-add-LTTng-to-build.patch @@ -0,0 +1,33 @@ +From 9b6d12198448aa51979b81aa68651cb49c0c5a02 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:26 -0500 +Subject: staging: add LTTng to build + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/Kconfig | 2 ++ + drivers/staging/Makefile | 1 + + 2 files changed, 3 insertions(+) + +--- a/drivers/staging/Kconfig ++++ b/drivers/staging/Kconfig +@@ -78,6 +78,8 @@ source "drivers/staging/line6/Kconfig" + + source "drivers/gpu/drm/vmwgfx/Kconfig" + ++source "drivers/staging/lttng/Kconfig" ++ + source "drivers/gpu/drm/nouveau/Kconfig" + + source "drivers/staging/octeon/Kconfig" +--- a/drivers/staging/Makefile ++++ b/drivers/staging/Makefile +@@ -32,6 +32,7 @@ obj-$(CONFIG_TRANZPORT) += frontier/ + obj-$(CONFIG_POHMELFS) += pohmelfs/ + obj-$(CONFIG_IDE_PHISON) += phison/ + obj-$(CONFIG_LINE6_USB) += line6/ ++obj-$(CONFIG_LTTNG) += lttng/ + obj-$(CONFIG_USB_SERIAL_QUATECH2) += serqt_usb2/ + obj-$(CONFIG_USB_SERIAL_QUATECH_USB2) += quatech_usb2/ + obj-$(CONFIG_OCTEON_ETHERNET) += octeon/ diff --git a/patches.lttng/0019-staging-Add-LTTng-entry-to-MAINTAINERS-file.patch b/patches.lttng/0019-staging-Add-LTTng-entry-to-MAINTAINERS-file.patch new file mode 100644 index 0000000000000..23ee572006d6d --- /dev/null +++ b/patches.lttng/0019-staging-Add-LTTng-entry-to-MAINTAINERS-file.patch @@ -0,0 +1,27 @@ +From 70bd4399bbdd4dd35697664af00fcd48cb2008a2 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 28 Nov 2011 07:42:27 -0500 +Subject: staging: Add LTTng entry to MAINTAINERS file + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + MAINTAINERS | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -4022,6 +4022,13 @@ W: http://ltp.sourceforge.net/ + T: git git://ltp.git.sourceforge.net/gitroot/ltp/ltp-dev + S: Maintained + ++LTTng (Linux Trace Toolkit Next Generation) ++M: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> ++L: lttng-dev@lists.lttng.org (moderated for non-subscribers) ++W: http://lttng.org ++S: Maintained ++F: drivers/staging/lttng/ ++ + M32R ARCHITECTURE + M: Hirokazu Takata <takata@linux-m32r.org> + L: linux-m32r@ml.linux-m32r.org diff --git a/patches.lttng/0069-lttng-lib-ring-buffer-remove-stale-null-pointer.patch b/patches.lttng/0069-lttng-lib-ring-buffer-remove-stale-null-pointer.patch new file mode 100644 index 0000000000000..bb268aca581ca --- /dev/null +++ b/patches.lttng/0069-lttng-lib-ring-buffer-remove-stale-null-pointer.patch @@ -0,0 +1,63 @@ +From 2f8e0b31ad257bca9ff5dda9fdfdcc98d38d97f8 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Wed, 30 Nov 2011 13:34:14 -0500 +Subject: lttng lib: ring buffer: remove stale null-pointer + +* Dan Carpenter <dan.carpenter@oracle.com> wrote: +[...] +> The patch c844b2f5cfea: "lttng lib: ring buffer" from Nov 28, 2011, +> leads to the following Smatch complaint: +> +> drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +1150 +> +lib_ring_buffer_print_buffer_errors() +> warn: variable dereferenced before check 'chan' (see line 1143) +> +> drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +> 1142 { +> 1143 const struct lib_ring_buffer_config *config = +> +chan->backend.config; +> +> +^^^^^^^^^^^^^^^^^^^^ +> Dereference. +> +> 1144 unsigned long write_offset, cons_offset; +> 1145 +> 1146 /* +> 1147 * Can be called in the error path of allocation when +> 1148 * trans_channel_data is not yet set. +> 1149 */ +> 1150 if (!chan) +> ^^^^^^^^^ +> Check. At first glance the comment seems out of date, I think check can +> be removed safely. +> +> 1151 return; +> 1152 /* + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + .../lttng/lib/ringbuffer/ring_buffer_frontend.c | 6 ------ + 1 files changed, 0 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +index 802f5cd..957d7f3 100644 +--- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +@@ -1144,12 +1144,6 @@ void lib_ring_buffer_print_buffer_errors(struct lib_ring_buffer *buf, + unsigned long write_offset, cons_offset; + + /* +- * Can be called in the error path of allocation when +- * trans_channel_data is not yet set. +- */ +- if (!chan) +- return; +- /* + * No need to order commit_count, write_offset and cons_offset reads + * because we execute at teardown when no more writer nor reader + * references are left. +-- +1.7.9 + diff --git a/patches.lttng/0070-lttng-lib-ring-buffer-remove-duplicate-null-pointer.patch b/patches.lttng/0070-lttng-lib-ring-buffer-remove-duplicate-null-pointer.patch new file mode 100644 index 0000000000000..dccc66032ad1a --- /dev/null +++ b/patches.lttng/0070-lttng-lib-ring-buffer-remove-duplicate-null-pointer.patch @@ -0,0 +1,60 @@ +From e5f7787388da7562b955a36b46e909e500a5974b Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Wed, 30 Nov 2011 13:34:15 -0500 +Subject: lttng lib: ring buffer remove duplicate null pointer + +* Dan Carpenter <dan.carpenter@oracle.com> wrote: +> The patch c844b2f5cfea: "lttng lib: ring buffer" from Nov 28, 2011, +> leads to the following Smatch complaint: +> +> drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +33 +> +lib_ring_buffer_fault() +> warn: variable dereferenced before check 'buf' (see line 26) +> +> drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +> 25 struct lib_ring_buffer *buf = vma->vm_private_data; +> 26 struct channel *chan = buf->backend.chan; +> ^^^^^^^^^^^^^^^^^ +> Dereference. +> +> 27 const struct lib_ring_buffer_config *config = chan->backend.config; +> 28 pgoff_t pgoff = vmf->pgoff; +> 29 struct page **page; +> 30 void **virt; +> 31 unsigned long offset, sb_bindex; +> 32 +> 33 if (!buf) +> ^^^^ +> Check. +> +> 34 return VM_FAULT_OOM; +> 35 + +This check is performed at mapping setup time in +lib_ring_buffer_mmap_buf() already, so we can safely remove this +duplicata. + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + .../lttng/lib/ringbuffer/ring_buffer_mmap.c | 3 --- + 1 files changed, 0 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +index 68221ee..cf37434 100644 +--- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +@@ -30,9 +30,6 @@ static int lib_ring_buffer_fault(struct vm_area_struct *vma, struct vm_fault *vm + 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. +-- +1.7.9 + diff --git a/patches.lttng/0071-lttng-lib-ring-buffer-move-null-pointer-check-to-ope.patch b/patches.lttng/0071-lttng-lib-ring-buffer-move-null-pointer-check-to-ope.patch new file mode 100644 index 0000000000000..6d6d98bbf79a5 --- /dev/null +++ b/patches.lttng/0071-lttng-lib-ring-buffer-move-null-pointer-check-to-ope.patch @@ -0,0 +1,75 @@ +From eeb34e2113576aea782094d1e30f22b445355fe8 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Wed, 30 Nov 2011 13:34:16 -0500 +Subject: lttng lib: ring buffer move null pointer check to open + +* Dan Carpenter <dan.carpenter@oracle.com> wrote: +> The patch c844b2f5cfea: "lttng lib: ring buffer" from Nov 28, 2011, +> leads to the following Smatch complaint: +> +> drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +86 +> +lib_ring_buffer_mmap_buf() +> warn: variable dereferenced before check 'buf' (see line 79) +> +> drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +> 78 unsigned long length = vma->vm_end - vma->vm_start; +> 79 struct channel *chan = buf->backend.chan; +> ^^^^^^^^^^^^^^^^^ +> Dereference. +> +> 80 const struct lib_ring_buffer_config *config = chan->backend.config; +> 81 unsigned long mmap_buf_len; +> 82 +> 83 if (config->output != RING_BUFFER_MMAP) +> 84 return -EINVAL; +> 85 +> 86 if (!buf) +> ^^^^ +> Check. +> +> 87 return -EBADF; +> 88 + +Let's move the NULL buf check to the file "open", where it belongs. The +"open" file operation is the actual interface between lib ring buffer +and the modules using it. + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + .../lttng/lib/ringbuffer/ring_buffer_mmap.c | 3 --- + .../staging/lttng/lib/ringbuffer/ring_buffer_vfs.c | 3 +++ + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +index cf37434..c9d6e89 100644 +--- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_mmap.c +@@ -80,9 +80,6 @@ static int lib_ring_buffer_mmap_buf(struct lib_ring_buffer *buf, + 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; +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c +index 1708ffd..8b78305 100644 +--- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_vfs.c +@@ -42,6 +42,9 @@ int lib_ring_buffer_open(struct inode *inode, struct file *file) + struct lib_ring_buffer *buf = inode->i_private; + int ret; + ++ if (!buf) ++ return -EINVAL; ++ + ret = lib_ring_buffer_open_read(buf); + if (ret) + return ret; +-- +1.7.9 + diff --git a/patches.lttng/0072-lttng-wrapper-add-missing-include-to-kallsyms-wrappe.patch b/patches.lttng/0072-lttng-wrapper-add-missing-include-to-kallsyms-wrappe.patch new file mode 100644 index 0000000000000..8f2d8fb21b1f3 --- /dev/null +++ b/patches.lttng/0072-lttng-wrapper-add-missing-include-to-kallsyms-wrappe.patch @@ -0,0 +1,29 @@ +From 91c0a213f10aa6637f680848e474fb107dd41ecf Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Wed, 30 Nov 2011 13:34:18 -0500 +Subject: lttng wrapper: add missing include to kallsyms wrapper + +Needed to keep bissectability. + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/wrapper/kallsyms.h | 2 ++ + 1 files changed, 2 insertions(+), 0 deletions(-) + +diff --git a/drivers/staging/lttng/wrapper/kallsyms.h b/drivers/staging/lttng/wrapper/kallsyms.h +index bb45f38..a7b8ab1 100644 +--- a/drivers/staging/lttng/wrapper/kallsyms.h ++++ b/drivers/staging/lttng/wrapper/kallsyms.h +@@ -1,6 +1,8 @@ + #ifndef _LTT_WRAPPER_KALLSYMS_H + #define _LTT_WRAPPER_KALLSYMS_H + ++#include <linux/kallsyms.h> ++ + /* + * Copyright (C) 2011 Avik Sil (avik.sil@linaro.org) + * +-- +1.7.9 + diff --git a/patches.lttng/0073-staging-lttng-cleanup-one-bit-signed-bitfields.patch b/patches.lttng/0073-staging-lttng-cleanup-one-bit-signed-bitfields.patch new file mode 100644 index 0000000000000..c85c46619e126 --- /dev/null +++ b/patches.lttng/0073-staging-lttng-cleanup-one-bit-signed-bitfields.patch @@ -0,0 +1,209 @@ +From 0dcbcbb49e3e8636e2f9d8cbcbeea827c5c951d9 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Thu, 1 Dec 2011 09:31:18 -0500 +Subject: staging: lttng: cleanup one-bit signed bitfields + +* Dan Carpenter <dan.carpenter@oracle.com> wrote: +> Sparse complains that these signed bitfields look "dubious". The +> problem is that instead of being either 0 or 1 like people would expect, +> signed one bit variables like this are either 0 or -1. It doesn't cause +> a problem in this case but it's ugly so lets fix them. + +* walter harms (wharms@bfs.de) wrote: +> hi, +> This patch looks ok to me but this design is ugly by itself. +> It should be replaced by an uchar uint whatever or use a +> real bool (obviously not preferred by this programmes). + +bool :1, uchar :1 or uint :1 could make sense. uchar:1/bool:1 won't save +any space here, because the surrounding fields are either uint or +pointers, so alignment will just add padding. + +I try to use int/uint whenever possible because x86 CPUs tend to get +less register false-dependencies when using instructions modifying the +whole register (generated by using int/uint types) rather than only part +of it (uchar/char/bool). I only use char/uchar/bool when there is a +clear wanted space gain. + +The reason why I never use the bool type within a structure when I want +a compact representation is that bool takes a whole byte just to +represent one bit: + +struct usebitfield { + int a; + unsigned int f:1, g:1, h:1, i:1, j:1; + int b; +}; + +struct usebool { + int a; + bool f, g, h, i, j; + int b; +}; + +struct useboolbf { + int a; + bool f:1, g:1, h:1, i:1, j:1; + int b; +}; + +int main() +{ + printf("bitfield %d bytes, bool %d bytes, boolbitfield %d bytes\n", + sizeof(struct usebitfield), sizeof(struct usebool), + sizeof(struct useboolbf)); +} + +result: + +bitfield 12 bytes, bool 16 bytes, boolbitfield 12 bytes + +This is because each bool takes one byte, while the bitfields are put in +units of "unsigned int" (or bool for the 3rd struct). So in this +example, we need 5 bytes + 3 bytes alignment for the bool, but only 4 +bytes to hold the "unsigned int" unit for the bitfields. + +The choice between bool and bitfields must also take into account the +frequency of access to the variable, because bitfields require mask +operations to access the selected bit(s). You will notice that none of +these bitfields are accessed on the tracing fast-path: only in +slow-paths. Therefore, space gain is more important than speed here. + +One might argue that I have so few of these fields here that it does not +make an actual difference to go for bitfield or bool. I am just trying +to choose types best suited for their intended purpose, ensuring they +are future-proof and will allow simply adding more fields using the same +type, as needed. + +So I guess I'll go for uint :1. + +Reported-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Acked-by: Dan Carpenter <dan.carpenter@oracle.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + .../staging/lttng/lib/ringbuffer/backend_types.h | 4 ++-- + .../staging/lttng/lib/ringbuffer/frontend_types.h | 14 +++++++------- + .../lttng/lib/ringbuffer/ring_buffer_frontend.c | 2 +- + drivers/staging/lttng/ltt-events.h | 10 +++++----- + 4 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/drivers/staging/lttng/lib/ringbuffer/backend_types.h b/drivers/staging/lttng/lib/ringbuffer/backend_types.h +index 1d301de..25c41bc 100644 +--- a/drivers/staging/lttng/lib/ringbuffer/backend_types.h ++++ b/drivers/staging/lttng/lib/ringbuffer/backend_types.h +@@ -53,7 +53,7 @@ struct lib_ring_buffer_backend { + struct channel *chan; /* Associated channel */ + int cpu; /* This buffer's cpu. -1 if global. */ + union v_atomic records_read; /* Number of records read */ +- unsigned int allocated:1; /* Bool: is buffer allocated ? */ ++ uint allocated:1; /* is buffer allocated ? */ + }; + + struct channel_backend { +@@ -65,7 +65,7 @@ struct channel_backend { + * for writer. + */ + unsigned int buf_size_order; /* Order of buffer size */ +- int extra_reader_sb:1; /* Bool: has extra reader subbuffer */ ++ uint extra_reader_sb:1; /* has extra reader subbuffer ? */ + struct lib_ring_buffer *buf; /* Channel per-cpu buffers */ + + unsigned long num_subbuf; /* Number of sub-buffers for writer */ +diff --git a/drivers/staging/lttng/lib/ringbuffer/frontend_types.h b/drivers/staging/lttng/lib/ringbuffer/frontend_types.h +index 5c7437f..eced7be 100644 +--- a/drivers/staging/lttng/lib/ringbuffer/frontend_types.h ++++ b/drivers/staging/lttng/lib/ringbuffer/frontend_types.h +@@ -60,8 +60,8 @@ struct channel { + struct notifier_block cpu_hp_notifier; /* CPU hotplug notifier */ + struct notifier_block tick_nohz_notifier; /* CPU nohz notifier */ + struct notifier_block hp_iter_notifier; /* hotplug iterator notifier */ +- int cpu_hp_enable:1; /* Enable CPU hotplug notif. */ +- int hp_iter_enable:1; /* Enable hp iter notif. */ ++ uint cpu_hp_enable:1; /* Enable CPU hotplug notif. */ ++ uint hp_iter_enable:1; /* Enable hp iter notif. */ + wait_queue_head_t read_wait; /* reader wait queue */ + wait_queue_head_t hp_wait; /* CPU hotplug wait queue */ + int finalized; /* Has channel been finalized */ +@@ -94,8 +94,8 @@ struct lib_ring_buffer_iter { + ITER_NEXT_RECORD, + ITER_PUT_SUBBUF, + } state; +- int allocated:1; +- int read_open:1; /* Opened for reading ? */ ++ uint allocated:1; ++ uint read_open:1; /* Opened for reading ? */ + }; + + /* ring buffer state */ +@@ -138,9 +138,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 */ +- int get_subbuf:1; /* Sub-buffer being held by reader */ +- int switch_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ +- int read_timer_enabled:1; /* Protected by ring_buffer_nohz_lock */ ++ 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 */ + }; + + static inline +diff --git a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +index 957d7f3..348c05e 100644 +--- a/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c ++++ b/drivers/staging/lttng/lib/ringbuffer/ring_buffer_frontend.c +@@ -54,7 +54,7 @@ + struct switch_offsets { + unsigned long begin, end, old; + size_t pre_header_padding, size; +- unsigned int switch_new_start:1, switch_new_end:1, switch_old_start:1, ++ uint switch_new_start:1, switch_new_end:1, switch_old_start:1, + switch_old_end:1; + }; + +diff --git a/drivers/staging/lttng/ltt-events.h b/drivers/staging/lttng/ltt-events.h +index 36b281a..c370ca6 100644 +--- a/drivers/staging/lttng/ltt-events.h ++++ b/drivers/staging/lttng/ltt-events.h +@@ -67,8 +67,8 @@ struct lttng_enum_entry { + struct lttng_integer_type { + unsigned int size; /* in bits */ + unsigned short alignment; /* in bits */ +- unsigned int signedness:1; +- unsigned int reverse_byte_order:1; ++ uint signedness:1; ++ uint reverse_byte_order:1; + unsigned int base; /* 2, 8, 10, 16, for pretty print */ + enum lttng_string_encodings encoding; + }; +@@ -191,7 +191,7 @@ struct ltt_event { + } ftrace; + } u; + struct list_head list; /* Event list */ +- int metadata_dumped:1; ++ uint metadata_dumped:1; + }; + + struct ltt_channel_ops { +@@ -251,7 +251,7 @@ struct ltt_channel { + struct ltt_event *sc_compat_unknown; + struct ltt_event *sc_exit; /* for syscall exit */ + int header_type; /* 0: unset, 1: compact, 2: large */ +- int metadata_dumped:1; ++ uint metadata_dumped:1; + }; + + struct ltt_session { +@@ -264,7 +264,7 @@ struct ltt_session { + struct list_head list; /* Session list */ + unsigned int free_chan_id; /* Next chan ID to allocate */ + uuid_le uuid; /* Trace session unique ID */ +- int metadata_dumped:1; ++ uint metadata_dumped:1; + }; + + struct ltt_session *ltt_session_create(void); +-- +1.7.9 + diff --git a/patches.lttng/0172-staging-lttng-Fix-recent-modifications-to-string_fro.patch b/patches.lttng/0172-staging-lttng-Fix-recent-modifications-to-string_fro.patch new file mode 100644 index 0000000000000..9b0ccef77278f --- /dev/null +++ b/patches.lttng/0172-staging-lttng-Fix-recent-modifications-to-string_fro.patch @@ -0,0 +1,42 @@ +From 643167423858052c26b2dfaf332c1ec0b472ea7a Mon Sep 17 00:00:00 2001 +From: Yannick Brosseau <yannick.brosseau@gmail.com> +Date: Fri, 2 Dec 2011 21:13:32 -0500 +Subject: staging: lttng: Fix recent modifications to string_from_user + operation + +Include: a fix for a recently introduced change: obviously max_t should +be used instead of min_t here. Also, a likely should apply to the result +of the comparison, not the variable per se. + +Signed-off-by: Yannick Brosseau <yannick.brosseau@gmail.com> +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/probes/lttng-events.h | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/staging/lttng/probes/lttng-events.h b/drivers/staging/lttng/probes/lttng-events.h +index ff6273f..d486994 100644 +--- a/drivers/staging/lttng/probes/lttng-events.h ++++ b/drivers/staging/lttng/probes/lttng-events.h +@@ -347,7 +347,7 @@ static __used struct lttng_probe_desc TP_ID(__probe_desc___, TRACE_SYSTEM) = { + #undef __string_from_user + #define __string_from_user(_item, _src) \ + __event_len += __dynamic_len[__dynamic_len_idx++] = \ +- min_t(size_t, strlen_user(_src), 1); ++ max_t(size_t, strlen_user(_src), 1); + + #undef TP_PROTO + #define TP_PROTO(args...) args +@@ -557,7 +557,7 @@ __assign_##dest##_2: \ + (void) __typemap.dest; \ + lib_ring_buffer_align_ctx(&__ctx, ltt_alignof(__typemap.dest));\ + __ustrlen = __get_dynamic_array_len(dest); \ +- if (likely(__ustrlen) > 1) { \ ++ if (likely(__ustrlen > 1)) { \ + __chan->ops->event_write_from_user(&__ctx, src, \ + __ustrlen - 1); \ + } \ +-- +1.7.9 + diff --git a/patches.lttng/0173-staging-lttng-TODO-update-lttng-reported-to-work-fin.patch b/patches.lttng/0173-staging-lttng-TODO-update-lttng-reported-to-work-fin.patch new file mode 100644 index 0000000000000..e3a98e3f332f0 --- /dev/null +++ b/patches.lttng/0173-staging-lttng-TODO-update-lttng-reported-to-work-fin.patch @@ -0,0 +1,37 @@ +From 4ee778a44cc353ee201e933e45f493453cde3dfb Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Sat, 3 Dec 2011 13:05:37 -0500 +Subject: staging: lttng: TODO update: lttng reported to work fine on -rt now + +The patch "lttng: Fix recent modifications to string_from_user +operation" has been confirmed to fix the corrupted trace problem +experienced on -rt kernel by the original bug reporter. Remove the +entry from the LTTng TODO list. + +Reported-by: Yannick Brosseau <yannick.brosseau@gmail.com> +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/TODO | 6 ------ + 1 files changed, 0 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/lttng/TODO b/drivers/staging/lttng/TODO +index 3fdc5e6..5e3a581 100644 +--- a/drivers/staging/lttng/TODO ++++ b/drivers/staging/lttng/TODO +@@ -35,12 +35,6 @@ A) Cleanup/Testing + depend on the producer to push the reader position. + Contact: Julien Desfossez <julien.desfossez@polymtl.ca> + +- 4) Test latest -rt kernel support. +- There has been report of corrupted traces when tracing a +- 3.0.10-rt27 in the area of access_ok() system call event. +- Still has to be investigated. Cannot be reproduced with +- mainline kernel. +- Contact: Yannick Brosseau <yannick.brosseau@polymtl.ca> + + B) Features + +-- +1.7.9 + diff --git a/patches.lttng/0174-staging-lttng-Update-max-symbol-length-to-256.patch b/patches.lttng/0174-staging-lttng-Update-max-symbol-length-to-256.patch new file mode 100644 index 0000000000000..289b02bd8dc93 --- /dev/null +++ b/patches.lttng/0174-staging-lttng-Update-max-symbol-length-to-256.patch @@ -0,0 +1,30 @@ +From 4588d6d4087bfcd3663e9dc26d0fffacb38c4df6 Mon Sep 17 00:00:00 2001 +From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Date: Mon, 5 Dec 2011 20:07:35 -0500 +Subject: staging: lttng: Update max symbol length to 256 + +The user-space tracer, along with the control tools, now support longer +event name strings (up to 256 chars, including \0). + +Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> +--- + drivers/staging/lttng/ltt-debugfs-abi.h | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/drivers/staging/lttng/ltt-debugfs-abi.h b/drivers/staging/lttng/ltt-debugfs-abi.h +index 42bc9fd..a018297 100644 +--- a/drivers/staging/lttng/ltt-debugfs-abi.h ++++ b/drivers/staging/lttng/ltt-debugfs-abi.h +@@ -13,7 +13,7 @@ + + #include <linux/fs.h> + +-#define LTTNG_SYM_NAME_LEN 128 ++#define LTTNG_SYM_NAME_LEN 256 + + enum lttng_kernel_instrumentation { + LTTNG_KERNEL_TRACEPOINT = 0, +-- +1.7.9 + @@ -50,3 +50,37 @@ patches.android/android-0038-Staging-android-binder-Fix-crashes-when-sharing-a-b patches.android/android-0039-staging-android-lowmemorykiller-Don-t-wait-more-than-one-sec.patch patches.android/android-0040-staging-android-ram_console-Don-t-build-on-arches-w-o-iorema.patch + +# +# LTTNG +# Patches came from short-lived experiment when they were added to the staging +# tree for a week or so. +# +patches.lttng/0001-lttng-lib-ring-buffer.patch +patches.lttng/0002-lttng-lib-portable-bitfield-read-write-header.patch +patches.lttng/0003-lttng-BUILD_RUNTIME_BUG_ON.patch +patches.lttng/0004-lttng-offset-alignment-header.patch +patches.lttng/0005-lttng-libs-add-Makefile.patch +patches.lttng/0006-lttng-wrappers.patch +patches.lttng/0007-lttng-instrumentation-tracepoint-events.patch +patches.lttng/0008-lttng-syscall-instrumentation.patch +patches.lttng/0009-lttng-lib-ring-buffer-clients.patch +patches.lttng/0010-lttng-tracer-control-and-core-structures.patch +patches.lttng/0011-lttng-dynamically-selectable-context-information.patch +patches.lttng/0012-lttng-timing-calibration-feature.patch +patches.lttng/0013-lttng-debugfs-and-procfs-ABI.patch +patches.lttng/0014-lttng-Add-documentation-and-TODO-files.patch +patches.lttng/0015-lttng-add-system-call-instrumentation-probe.patch +patches.lttng/0016-lttng-probe-callbacks.patch +patches.lttng/0017-lttng-toplevel-Makefile-and-Kconfig.patch +patches.lttng/0018-staging-add-LTTng-to-build.patch +patches.lttng/0019-staging-Add-LTTng-entry-to-MAINTAINERS-file.patch +patches.lttng/0069-lttng-lib-ring-buffer-remove-stale-null-pointer.patch +patches.lttng/0070-lttng-lib-ring-buffer-remove-duplicate-null-pointer.patch +patches.lttng/0071-lttng-lib-ring-buffer-move-null-pointer-check-to-ope.patch +patches.lttng/0072-lttng-wrapper-add-missing-include-to-kallsyms-wrappe.patch +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 + |