rcu: make rcutorture version numbers available through debugfs
It is not possible to accurately correlate rcutorture output with that of debugfs. This patch therefore adds a debugfs file that prints out the rcutorture version number, permitting easy correlation. Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
This commit is contained in:
parent
d71df90ead
commit
4a29865689
5 changed files with 85 additions and 4 deletions
|
@ -47,6 +47,18 @@
|
||||||
extern int rcutorture_runnable; /* for sysctl */
|
extern int rcutorture_runnable; /* for sysctl */
|
||||||
#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
|
#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
|
||||||
|
|
||||||
|
#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);
|
||||||
|
#else
|
||||||
|
static inline void rcutorture_record_test_transition(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void rcutorture_record_progress(unsigned long vernum)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define UINT_CMP_GE(a, b) (UINT_MAX / 2 >= (a) - (b))
|
#define UINT_CMP_GE(a, b) (UINT_MAX / 2 >= (a) - (b))
|
||||||
#define UINT_CMP_LT(a, b) (UINT_MAX / 2 < (a) - (b))
|
#define UINT_CMP_LT(a, b) (UINT_MAX / 2 < (a) - (b))
|
||||||
#define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
|
#define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
|
||||||
|
@ -68,7 +80,6 @@ extern void call_rcu_sched(struct rcu_head *head,
|
||||||
extern void synchronize_sched(void);
|
extern void synchronize_sched(void);
|
||||||
extern void rcu_barrier_bh(void);
|
extern void rcu_barrier_bh(void);
|
||||||
extern void rcu_barrier_sched(void);
|
extern void rcu_barrier_sched(void);
|
||||||
extern int sched_expedited_torture_stats(char *page);
|
|
||||||
|
|
||||||
static inline void __rcu_read_lock_bh(void)
|
static inline void __rcu_read_lock_bh(void)
|
||||||
{
|
{
|
||||||
|
|
|
@ -58,9 +58,12 @@ static inline void synchronize_rcu_bh_expedited(void)
|
||||||
|
|
||||||
extern void rcu_barrier(void);
|
extern void rcu_barrier(void);
|
||||||
|
|
||||||
|
extern unsigned long rcutorture_testseq;
|
||||||
|
extern unsigned long rcutorture_vernum;
|
||||||
extern long rcu_batches_completed(void);
|
extern long rcu_batches_completed(void);
|
||||||
extern long rcu_batches_completed_bh(void);
|
extern long rcu_batches_completed_bh(void);
|
||||||
extern long rcu_batches_completed_sched(void);
|
extern long rcu_batches_completed_sched(void);
|
||||||
|
|
||||||
extern void rcu_force_quiescent_state(void);
|
extern void rcu_force_quiescent_state(void);
|
||||||
extern void rcu_bh_force_quiescent_state(void);
|
extern void rcu_bh_force_quiescent_state(void);
|
||||||
extern void rcu_sched_force_quiescent_state(void);
|
extern void rcu_sched_force_quiescent_state(void);
|
||||||
|
|
|
@ -131,7 +131,7 @@ struct rcu_torture {
|
||||||
|
|
||||||
static LIST_HEAD(rcu_torture_freelist);
|
static LIST_HEAD(rcu_torture_freelist);
|
||||||
static struct rcu_torture __rcu *rcu_torture_current;
|
static struct rcu_torture __rcu *rcu_torture_current;
|
||||||
static long rcu_torture_current_version;
|
static unsigned long rcu_torture_current_version;
|
||||||
static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
|
static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
|
||||||
static DEFINE_SPINLOCK(rcu_torture_lock);
|
static DEFINE_SPINLOCK(rcu_torture_lock);
|
||||||
static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
|
static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
|
||||||
|
@ -884,7 +884,7 @@ rcu_torture_writer(void *arg)
|
||||||
old_rp->rtort_pipe_count++;
|
old_rp->rtort_pipe_count++;
|
||||||
cur_ops->deferred_free(old_rp);
|
cur_ops->deferred_free(old_rp);
|
||||||
}
|
}
|
||||||
rcu_torture_current_version++;
|
rcutorture_record_progress(++rcu_torture_current_version);
|
||||||
oldbatch = cur_ops->completed();
|
oldbatch = cur_ops->completed();
|
||||||
rcu_stutter_wait("rcu_torture_writer");
|
rcu_stutter_wait("rcu_torture_writer");
|
||||||
} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
|
} while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
|
||||||
|
@ -1064,7 +1064,7 @@ rcu_torture_printk(char *page)
|
||||||
}
|
}
|
||||||
cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
|
cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
|
||||||
cnt += sprintf(&page[cnt],
|
cnt += sprintf(&page[cnt],
|
||||||
"rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d "
|
"rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
|
||||||
"rtmbe: %d rtbke: %ld rtbre: %ld "
|
"rtmbe: %d rtbke: %ld rtbre: %ld "
|
||||||
"rtbf: %ld rtb: %ld nt: %ld",
|
"rtbf: %ld rtb: %ld nt: %ld",
|
||||||
rcu_torture_current,
|
rcu_torture_current,
|
||||||
|
@ -1325,6 +1325,7 @@ rcu_torture_cleanup(void)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
mutex_lock(&fullstop_mutex);
|
mutex_lock(&fullstop_mutex);
|
||||||
|
rcutorture_record_test_transition();
|
||||||
if (fullstop == FULLSTOP_SHUTDOWN) {
|
if (fullstop == FULLSTOP_SHUTDOWN) {
|
||||||
printk(KERN_WARNING /* but going down anyway, so... */
|
printk(KERN_WARNING /* but going down anyway, so... */
|
||||||
"Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
|
"Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
|
||||||
|
@ -1616,6 +1617,7 @@ rcu_torture_init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
register_reboot_notifier(&rcutorture_shutdown_nb);
|
register_reboot_notifier(&rcutorture_shutdown_nb);
|
||||||
|
rcutorture_record_test_transition();
|
||||||
mutex_unlock(&fullstop_mutex);
|
mutex_unlock(&fullstop_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,18 @@ static void invoke_rcu_cpu_kthread(void);
|
||||||
|
|
||||||
#define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */
|
#define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Track the rcutorture test sequence number and the update version
|
||||||
|
* number within a given test. The rcutorture_testseq is incremented
|
||||||
|
* on every rcutorture module load and unload, so has an odd value
|
||||||
|
* when a test is running. The rcutorture_vernum is set to zero
|
||||||
|
* when rcutorture starts and is incremented on each rcutorture update.
|
||||||
|
* These variables enable correlating rcutorture output with the
|
||||||
|
* RCU tracing information.
|
||||||
|
*/
|
||||||
|
unsigned long rcutorture_testseq;
|
||||||
|
unsigned long rcutorture_vernum;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Return true if an RCU grace period is in progress. The ACCESS_ONCE()s
|
* Return true if an RCU grace period is in progress. The ACCESS_ONCE()s
|
||||||
* permit this function to be invoked without holding the root rcu_node
|
* permit this function to be invoked without holding the root rcu_node
|
||||||
|
@ -192,6 +204,31 @@ void rcu_bh_force_quiescent_state(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
|
EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the number of times rcutorture tests have been initiated and
|
||||||
|
* terminated. This information allows the debugfs tracing stats to be
|
||||||
|
* correlated to the rcutorture messages, even when the rcutorture module
|
||||||
|
* is being repeatedly loaded and unloaded. In other words, we cannot
|
||||||
|
* store this state in rcutorture itself.
|
||||||
|
*/
|
||||||
|
void rcutorture_record_test_transition(void)
|
||||||
|
{
|
||||||
|
rcutorture_testseq++;
|
||||||
|
rcutorture_vernum = 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rcutorture_record_test_transition);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the number of writer passes through the current rcutorture test.
|
||||||
|
* This is also used to correlate debugfs tracing stats with the rcutorture
|
||||||
|
* messages.
|
||||||
|
*/
|
||||||
|
void rcutorture_record_progress(unsigned long vernum)
|
||||||
|
{
|
||||||
|
rcutorture_vernum++;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(rcutorture_record_progress);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Force a quiescent state for RCU-sched.
|
* Force a quiescent state for RCU-sched.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -394,6 +394,29 @@ static const struct file_operations rcu_pending_fops = {
|
||||||
.release = single_release,
|
.release = single_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int show_rcutorture(struct seq_file *m, void *unused)
|
||||||
|
{
|
||||||
|
seq_printf(m, "rcutorture test sequence: %lu %s\n",
|
||||||
|
rcutorture_testseq >> 1,
|
||||||
|
(rcutorture_testseq & 0x1) ? "(test in progress)" : "");
|
||||||
|
seq_printf(m, "rcutorture update version number: %lu\n",
|
||||||
|
rcutorture_vernum);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rcutorture_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, show_rcutorture, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations rcutorture_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = rcutorture_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release,
|
||||||
|
};
|
||||||
|
|
||||||
static struct dentry *rcudir;
|
static struct dentry *rcudir;
|
||||||
|
|
||||||
static int __init rcutree_trace_init(void)
|
static int __init rcutree_trace_init(void)
|
||||||
|
@ -430,6 +453,11 @@ static int __init rcutree_trace_init(void)
|
||||||
NULL, &rcu_pending_fops);
|
NULL, &rcu_pending_fops);
|
||||||
if (!retval)
|
if (!retval)
|
||||||
goto free_out;
|
goto free_out;
|
||||||
|
|
||||||
|
retval = debugfs_create_file("rcutorture", 0444, rcudir,
|
||||||
|
NULL, &rcutorture_fops);
|
||||||
|
if (!retval)
|
||||||
|
goto free_out;
|
||||||
return 0;
|
return 0;
|
||||||
free_out:
|
free_out:
|
||||||
debugfs_remove_recursive(rcudir);
|
debugfs_remove_recursive(rcudir);
|
||||||
|
|
Loading…
Reference in a new issue