Skip to content

Commit

Permalink
rcu: Add failure tracing to rcutorture
Browse files Browse the repository at this point in the history
Trace the rcutorture RCU accesses and dump the trace buffer when the
first failure is detected.

Signed-off-by: Paul E. McKenney <[email protected]>
Signed-off-by: Paul E. McKenney <[email protected]>
Reviewed-by: Josh Triplett <[email protected]>
  • Loading branch information
Paul E. McKenney authored and paulmck committed Dec 11, 2011
1 parent a8eecf2 commit 91afaf3
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/linux/rcupdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,21 @@ extern int rcutorture_runnable; /* for sysctl */
#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
extern void rcutorture_record_test_transition(void);
extern void rcutorture_record_progress(unsigned long vernum);
extern void do_trace_rcu_torture_read(char *rcutorturename,
struct rcu_head *rhp);
#else
static inline void rcutorture_record_test_transition(void)
{
}
static inline void rcutorture_record_progress(unsigned long vernum)
{
}
#ifdef CONFIG_RCU_TRACE
extern void do_trace_rcu_torture_read(char *rcutorturename,
struct rcu_head *rhp);
#else
#define do_trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
#endif
#endif

#define UINT_CMP_GE(a, b) (UINT_MAX / 2 >= (a) - (b))
Expand Down
26 changes: 26 additions & 0 deletions include/trace/events/rcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,31 @@ TRACE_EVENT(rcu_batch_end,
__entry->rcuname, __entry->callbacks_invoked)
);

/*
* Tracepoint for rcutorture readers. The first argument is the name
* of the RCU flavor from rcutorture's viewpoint and the second argument
* is the callback address.
*/
TRACE_EVENT(rcu_torture_read,

TP_PROTO(char *rcutorturename, struct rcu_head *rhp),

TP_ARGS(rcutorturename, rhp),

TP_STRUCT__entry(
__field(char *, rcutorturename)
__field(struct rcu_head *, rhp)
),

TP_fast_assign(
__entry->rcutorturename = rcutorturename;
__entry->rhp = rhp;
),

TP_printk("%s torture read %p",
__entry->rcutorturename, __entry->rhp)
);

#else /* #ifdef CONFIG_RCU_TRACE */

#define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0)
Expand All @@ -452,6 +477,7 @@ TRACE_EVENT(rcu_batch_end,
#define trace_rcu_invoke_callback(rcuname, rhp) do { } while (0)
#define trace_rcu_invoke_kfree_callback(rcuname, rhp, offset) do { } while (0)
#define trace_rcu_batch_end(rcuname, callbacks_invoked) do { } while (0)
#define trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)

#endif /* #else #ifdef CONFIG_RCU_TRACE */

Expand Down
10 changes: 10 additions & 0 deletions kernel/rcupdate.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,13 @@ struct debug_obj_descr rcuhead_debug_descr = {
};
EXPORT_SYMBOL_GPL(rcuhead_debug_descr);
#endif /* #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD */

#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU) || defined(CONFIG_RCU_TRACE)
void do_trace_rcu_torture_read(char *rcutorturename, struct rcu_head *rhp)
{
trace_rcu_torture_read(rcutorturename, rhp);
}
EXPORT_SYMBOL_GPL(do_trace_rcu_torture_read);
#else
#define do_trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
#endif
18 changes: 18 additions & 0 deletions kernel/rcutorture.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,6 +913,18 @@ rcu_torture_fakewriter(void *arg)
return 0;
}

void rcutorture_trace_dump(void)
{
static atomic_t beenhere = ATOMIC_INIT(0);

if (atomic_read(&beenhere))
return;
if (atomic_xchg(&beenhere, 1) != 0)
return;
do_trace_rcu_torture_read(cur_ops->name, (struct rcu_head *)~0UL);
ftrace_dump(DUMP_ALL);
}

/*
* RCU torture reader from timer handler. Dereferences rcu_torture_current,
* incrementing the corresponding element of the pipeline array. The
Expand All @@ -934,6 +946,7 @@ static void rcu_torture_timer(unsigned long unused)
rcu_read_lock_bh_held() ||
rcu_read_lock_sched_held() ||
srcu_read_lock_held(&srcu_ctl));
do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu);
if (p == NULL) {
/* Leave because rcu_torture_writer is not yet underway */
cur_ops->readunlock(idx);
Expand All @@ -951,6 +964,8 @@ static void rcu_torture_timer(unsigned long unused)
/* Should not happen, but... */
pipe_count = RCU_TORTURE_PIPE_LEN;
}
if (pipe_count > 1)
rcutorture_trace_dump();
__this_cpu_inc(rcu_torture_count[pipe_count]);
completed = cur_ops->completed() - completed;
if (completed > RCU_TORTURE_PIPE_LEN) {
Expand Down Expand Up @@ -994,6 +1009,7 @@ rcu_torture_reader(void *arg)
rcu_read_lock_bh_held() ||
rcu_read_lock_sched_held() ||
srcu_read_lock_held(&srcu_ctl));
do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu);
if (p == NULL) {
/* Wait for rcu_torture_writer to get underway */
cur_ops->readunlock(idx);
Expand All @@ -1009,6 +1025,8 @@ rcu_torture_reader(void *arg)
/* Should not happen, but... */
pipe_count = RCU_TORTURE_PIPE_LEN;
}
if (pipe_count > 1)
rcutorture_trace_dump();
__this_cpu_inc(rcu_torture_count[pipe_count]);
completed = cur_ops->completed() - completed;
if (completed > RCU_TORTURE_PIPE_LEN) {
Expand Down

0 comments on commit 91afaf3

Please sign in to comment.