20 Nov, 2014

4 commits

  • As the seq_buf->len will soon be +1 size when there's an overflow, we
    must use trace_seq_used() or seq_buf_used() methods to get the real
    length. This will prevent buffer overflow issues if just the len
    of the seq_buf descriptor is used to copy memory.

    Link: http://lkml.kernel.org/r/20141114121911.09ba3d38@gandalf.local.home

    Reported-by: Petr Mladek
    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     
  • Create a seq_buf layer that trace_seq sits on. The seq_buf will not
    be limited to page size. This will allow other usages of seq_buf
    instead of a hard set PAGE_SIZE one that trace_seq has.

    Link: http://lkml.kernel.org/r/20141104160221.864997179@goodmis.org
    Link: http://lkml.kernel.org/r/20141114011412.170377300@goodmis.org

    Tested-by: Jiri Kosina
    Acked-by: Jiri Kosina
    Reviewed-by: Petr Mladek
    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     
  • The trace_seq_printf() and friends are used to store strings into a buffer
    that can be passed around from function to function. If the trace_seq buffer
    fills up, it will not print any more. The return values were somewhat
    inconsistant and using trace_seq_has_overflowed() was a better way to know
    if the write to the trace_seq buffer succeeded or not.

    Now that all users have removed reading the return value of the printf()
    type functions, they can safely return void and keep future users of them
    from reading the inconsistent values as well.

    Link: http://lkml.kernel.org/r/20141114011411.992510720@goodmis.org

    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     
  • Adding a trace_seq_has_overflowed() which returns true if the trace_seq
    had too much written into it allows us to simplify the code.

    Instead of checking the return value of every call to trace_seq_printf()
    and friends, they can all be called normally, and at the end we can
    return !trace_seq_has_overflowed() instead.

    Several functions also return TRACE_TYPE_PARTIAL_LINE when the trace_seq
    overflowed and TRACE_TYPE_HANDLED otherwise. Another helper function
    was created called trace_handle_return() which takes a trace_seq and
    returns these enums. Using this helper function also simplifies the
    code.

    This change also makes it possible to remove the return values of
    trace_seq_printf() and friends. They should instead just be
    void functions.

    Link: http://lkml.kernel.org/r/20141114011410.365183157@goodmis.org

    Reviewed-by: Petr Mladek
    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     

01 Jul, 2014

5 commits

  • There's several locations in the kernel that open code the calculation
    of the next location in the trace_seq buffer. This is usually done with

    p->buffer + p->len

    Instead of having this open coded, supply a helper function in the
    header to do it for them. This function is called trace_seq_buffer_ptr().

    Link: http://lkml.kernel.org/p/20140626220129.452783019@goodmis.org

    Acked-by: Paolo Bonzini
    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     
  • trace_seq_reserve() has no users in the kernel, it just wastes space.
    Remove it.

    Cc: Eduard - Gabriel Munteanu
    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     
  • Currently trace_seq_putmem_hex() can only take as a parameter a pointer
    to something that is 8 bytes or less, otherwise it will overflow the
    buffer. This is protected by a macro that encompasses the call to
    trace_seq_putmem_hex() that has a BUILD_BUG_ON() for the variable before
    it is passed in. This is not very robust and if trace_seq_putmem_hex() ever
    gets used outside that macro it will cause issues.

    Instead of only being able to produce a hex output of memory that is for
    a single word, change it to be more robust and allow any size input.

    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     
  • For using trace_seq_*() functions in NMI context, I posted a patch to move
    it to the lib/ directory. This caused Andrew Morton to take a look at the code.
    He went through and gave a lot of comments about missing kernel doc,
    inconsistent types for the save variable, mix match of EXPORT_SYMBOL_GPL()
    and EXPORT_SYMBOL() as well as missing EXPORT_SYMBOL*()s. There were
    a few comments about the way variables were being compared (int vs uint).

    All these were good review comments and should be implemented regardless of
    if trace_seq.c should be moved to lib/ or not.

    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     
  • The trace_seq_*() functions are a nice utility that allows users to manipulate
    buffers with printf() like formats. It has its own trace_seq.h header in
    include/linux and should be in its own file. Being tied with trace_output.c
    is rather awkward.

    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     

15 May, 2014

1 commit

  • Being able to show a cpumask of events can be useful as some events
    may affect only some CPUs. There is no standard way to record the
    cpumask and converting it to a string is rather expensive during
    the trace as traces happen in hotpaths. It would be better to record
    the raw event mask and be able to parse it at print time.

    The following macros were added for use with the TRACE_EVENT() macro:

    __bitmask()
    __assign_bitmask()
    __get_bitmask()

    To test this, I added this to the sched_migrate_task event, which
    looked like this:

    TRACE_EVENT(sched_migrate_task,

    TP_PROTO(struct task_struct *p, int dest_cpu, const struct cpumask *cpus),

    TP_ARGS(p, dest_cpu, cpus),

    TP_STRUCT__entry(
    __array( char, comm, TASK_COMM_LEN )
    __field( pid_t, pid )
    __field( int, prio )
    __field( int, orig_cpu )
    __field( int, dest_cpu )
    __bitmask( cpumask, num_possible_cpus() )
    ),

    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;
    __assign_bitmask(cpumask, cpumask_bits(cpus), num_possible_cpus());
    ),

    TP_printk("comm=%s pid=%d prio=%d orig_cpu=%d dest_cpu=%d cpumask=%s",
    __entry->comm, __entry->pid, __entry->prio,
    __entry->orig_cpu, __entry->dest_cpu,
    __get_bitmask(cpumask))
    );

    With the output of:

    ksmtuned-3613 [003] d..2 485.220508: sched_migrate_task: comm=ksmtuned pid=3615 prio=120 orig_cpu=3 dest_cpu=2 cpumask=00000000,0000000f
    migration/1-13 [001] d..5 485.221202: sched_migrate_task: comm=ksmtuned pid=3614 prio=120 orig_cpu=1 dest_cpu=0 cpumask=00000000,0000000f
    awk-3615 [002] d.H5 485.221747: sched_migrate_task: comm=rcu_preempt pid=7 prio=120 orig_cpu=0 dest_cpu=1 cpumask=00000000,000000ff
    migration/2-18 [002] d..5 485.222062: sched_migrate_task: comm=ksmtuned pid=3615 prio=120 orig_cpu=2 dest_cpu=3 cpumask=00000000,0000000f

    Link: http://lkml.kernel.org/r/1399377998-14870-6-git-send-email-javi.merino@arm.com
    Link: http://lkml.kernel.org/r/20140506132238.22e136d1@gandalf.local.home

    Suggested-by: Javi Merino
    Tested-by: Javi Merino
    Signed-off-by: Steven Rostedt

    Steven Rostedt (Red Hat)
     

21 Mar, 2012

1 commit


01 Nov, 2011

1 commit

  • Standardize the style for compiler based printf format verification.
    Standardized the location of __printf too.

    Done via script and a little typing.

    $ grep -rPl --include=*.[ch] -w "__attribute__" * | \
    grep -vP "^(tools|scripts|include/linux/compiler-gcc.h)" | \
    xargs perl -n -i -e 'local $/; while (<>) { s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.+)\s*,\s*(.+)\s*\)\s*\)\s*\)/__printf($1, $2)/g ; print; }'

    [akpm@linux-foundation.org: revert arch bits]
    Signed-off-by: Joe Perches
    Cc: "Kirill A. Shutemov"
    Signed-off-by: Andrew Morton
    Signed-off-by: Linus Torvalds

    Joe Perches
     

10 Dec, 2009

2 commits

  • The trace_seq buffer might fill up, and right now one needs to check the
    return value of each printf into the buffer to check for that.

    Instead, have the buffer keep track of whether it is full or not, and
    reject more input if it is full or would have overflowed with an input
    that wasn't added.

    Cc: Lai Jiangshan
    Signed-off-by: Johannes Berg
    Signed-off-by: Steven Rostedt

    Johannes Berg
     
  • If the seq_read fills the buffer it will call s_start again on the next
    itertation with the same position. This causes a problem with the
    function_graph tracer because it consumes the iteration in order to
    determine leaf functions.

    What happens is that the iterator stores the entry, and the function
    graph plugin will look at the next entry. If that next entry is a return
    of the same function and task, then the function is a leaf and the
    function_graph plugin calls ring_buffer_read which moves the ring buffer
    iterator forward (the trace iterator still points to the function start
    entry).

    The copying of the trace_seq to the seq_file buffer will fail if the
    seq_file buffer is full. The seq_read will not show this entry.
    The next read by userspace will cause seq_read to again call s_start
    which will reuse the trace iterator entry (the function start entry).
    But the function return entry was already consumed. The function graph
    plugin will think that this entry is a nested function and not a leaf.

    To solve this, the trace code now checks the return status of the
    seq_printf (trace_print_seq). If the writing to the seq_file buffer
    fails, we set a flag in the iterator (leftover) and we do not reset
    the trace_seq buffer. On the next call to s_start, we check the leftover
    flag, and if it is set, we just reuse the trace_seq buffer and do not
    call into the plugin print functions.

    Before this patch:

    2) | fput() {
    2) | __fput() {
    2) 0.550 us | inotify_inode_queue_event();
    2) | __fsnotify_parent() {
    2) 0.540 us | inotify_dentry_parent_queue_event();

    After the patch:

    2) | fput() {
    2) | __fput() {
    2) 0.550 us | inotify_inode_queue_event();
    2) 0.548 us | __fsnotify_parent();
    2) 0.540 us | inotify_dentry_parent_queue_event();

    [
    Updated the patch to fix a missing return 0 from the trace_print_seq()
    stub when CONFIG_TRACING is disabled.

    Reported-by: Ingo Molnar
    ]

    Reported-by: Jiri Olsa
    Cc: Frederic Weisbecker
    Signed-off-by: Steven Rostedt

    Steven Rostedt
     

24 Oct, 2009

1 commit


15 Jun, 2009

1 commit

  • when compiling linux-mips with kmemtrace enabled, there will be an
    error:

    include/linux/trace_seq.h:12: error: 'PAGE_SIZE' undeclared here (not in
    a function)

    I checked the source code and found trace_seq.h used PAGE_SIZE but not
    included the relative header file, so, fix it via adding the header file

    Acked-by: Frederic Weisbecker
    Acked-by: Pekka Enberg
    Signed-off-by: Wu Zhangjin
    LKML-Reference:
    Signed-off-by: Steven Rostedt

    Wu Zhangjin
     

10 Jun, 2009

1 commit


21 Apr, 2009

1 commit


18 Apr, 2009

1 commit

  • Due to a cut and paste error, I added the gcc attribute for printf
    format to the static inline stub of trace_seq_printf.

    This will cause a compile failure.

    [ Impact: fix compiler error when CONFIG_TRACING is off ]

    Reported-by: Ingo Molnar
    Signed-off-by: Steven Rostedt
    Cc: Andrew Morton
    Cc: =?ISO-8859-15?Q?Fr=E9d=E9ric_Weisbecker?=
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Steven Rostedt
     

15 Apr, 2009

2 commits

  • Impact: allow modules to add TRACE_EVENTS on load

    This patch adds the final hooks to allow modules to use the TRACE_EVENT
    macro. A notifier and a data structure are used to link the TRACE_EVENTs
    defined in the module to connect them with the ftrace event tracing system.

    It also adds the necessary automated clean ups to the trace events when a
    module is removed.

    Cc: Rusty Russell
    Signed-off-by: Steven Rostedt

    Steven Rostedt
     
  • In the process to make TRACE_EVENT macro work for modules, the trace_seq
    operations must be available for core kernel code.

    These operations are quite useful and can be used for other implementations.

    The main idea is that we create a trace_seq handle that acts very much
    like the seq_file handle.

    struct trace_seq *s = kmalloc(sizeof(*s, GFP_KERNEL);

    trace_seq_init(s);
    trace_seq_printf(s, "some data %d\n", variable);

    printk("%s", s->buffer);

    The main use is to allow a top level function call several other functions
    that may store printf like data into the buffer. Then at the end, the top
    level function can process all the data with any method it would like to.
    It could be passed to userspace, output via printk or even use seq_file:

    trace_seq_to_user(s, ubuf, cnt);
    seq_puts(m, s->buffer);

    Signed-off-by: Steven Rostedt

    Steven Rostedt