aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paul.mckenney@linaro.org>2011-04-04 00:33:51 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2011-05-06 02:16:56 -0400
commit4a29865689dbb87a02e3b0fff4a4ae5041273173 (patch)
tree72c9f1641a9fb05e3ae4d8cc068f62f9c566bae9
parentd71df90eadfc35aa549ff9a850842673febca71f (diff)
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>
-rw-r--r--include/linux/rcupdate.h13
-rw-r--r--include/linux/rcutree.h3
-rw-r--r--kernel/rcutorture.c8
-rw-r--r--kernel/rcutree.c37
-rw-r--r--kernel/rcutree_trace.c28
5 files changed, 85 insertions, 4 deletions
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index ff422d2b7f90..9e169c2ba91f 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -47,6 +47,18 @@
47extern int rcutorture_runnable; /* for sysctl */ 47extern int rcutorture_runnable; /* for sysctl */
48#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */ 48#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */
49 49
50#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
51extern void rcutorture_record_test_transition(void);
52extern void rcutorture_record_progress(unsigned long vernum);
53#else
54static inline void rcutorture_record_test_transition(void)
55{
56}
57static inline void rcutorture_record_progress(unsigned long vernum)
58{
59}
60#endif
61
50#define UINT_CMP_GE(a, b) (UINT_MAX / 2 >= (a) - (b)) 62#define UINT_CMP_GE(a, b) (UINT_MAX / 2 >= (a) - (b))
51#define UINT_CMP_LT(a, b) (UINT_MAX / 2 < (a) - (b)) 63#define UINT_CMP_LT(a, b) (UINT_MAX / 2 < (a) - (b))
52#define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b)) 64#define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
@@ -68,7 +80,6 @@ extern void call_rcu_sched(struct rcu_head *head,
68extern void synchronize_sched(void); 80extern void synchronize_sched(void);
69extern void rcu_barrier_bh(void); 81extern void rcu_barrier_bh(void);
70extern void rcu_barrier_sched(void); 82extern void rcu_barrier_sched(void);
71extern int sched_expedited_torture_stats(char *page);
72 83
73static inline void __rcu_read_lock_bh(void) 84static inline void __rcu_read_lock_bh(void)
74{ 85{
diff --git a/include/linux/rcutree.h b/include/linux/rcutree.h
index 3a933482734a..284dad10c55b 100644
--- a/include/linux/rcutree.h
+++ b/include/linux/rcutree.h
@@ -58,9 +58,12 @@ static inline void synchronize_rcu_bh_expedited(void)
58 58
59extern void rcu_barrier(void); 59extern void rcu_barrier(void);
60 60
61extern unsigned long rcutorture_testseq;
62extern unsigned long rcutorture_vernum;
61extern long rcu_batches_completed(void); 63extern long rcu_batches_completed(void);
62extern long rcu_batches_completed_bh(void); 64extern long rcu_batches_completed_bh(void);
63extern long rcu_batches_completed_sched(void); 65extern long rcu_batches_completed_sched(void);
66
64extern void rcu_force_quiescent_state(void); 67extern void rcu_force_quiescent_state(void);
65extern void rcu_bh_force_quiescent_state(void); 68extern void rcu_bh_force_quiescent_state(void);
66extern void rcu_sched_force_quiescent_state(void); 69extern void rcu_sched_force_quiescent_state(void);
diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c
index 22b0e74e7d99..c2f58ec24751 100644
--- a/kernel/rcutorture.c
+++ b/kernel/rcutorture.c
@@ -131,7 +131,7 @@ struct rcu_torture {
131 131
132static LIST_HEAD(rcu_torture_freelist); 132static LIST_HEAD(rcu_torture_freelist);
133static struct rcu_torture __rcu *rcu_torture_current; 133static struct rcu_torture __rcu *rcu_torture_current;
134static long rcu_torture_current_version; 134static unsigned long rcu_torture_current_version;
135static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN]; 135static struct rcu_torture rcu_tortures[10 * RCU_TORTURE_PIPE_LEN];
136static DEFINE_SPINLOCK(rcu_torture_lock); 136static DEFINE_SPINLOCK(rcu_torture_lock);
137static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) = 137static DEFINE_PER_CPU(long [RCU_TORTURE_PIPE_LEN + 1], rcu_torture_count) =
@@ -884,7 +884,7 @@ rcu_torture_writer(void *arg)
884 old_rp->rtort_pipe_count++; 884 old_rp->rtort_pipe_count++;
885 cur_ops->deferred_free(old_rp); 885 cur_ops->deferred_free(old_rp);
886 } 886 }
887 rcu_torture_current_version++; 887 rcutorture_record_progress(++rcu_torture_current_version);
888 oldbatch = cur_ops->completed(); 888 oldbatch = cur_ops->completed();
889 rcu_stutter_wait("rcu_torture_writer"); 889 rcu_stutter_wait("rcu_torture_writer");
890 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP); 890 } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
@@ -1064,7 +1064,7 @@ rcu_torture_printk(char *page)
1064 } 1064 }
1065 cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG); 1065 cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
1066 cnt += sprintf(&page[cnt], 1066 cnt += sprintf(&page[cnt],
1067 "rtc: %p ver: %ld tfle: %d rta: %d rtaf: %d rtf: %d " 1067 "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
1068 "rtmbe: %d rtbke: %ld rtbre: %ld " 1068 "rtmbe: %d rtbke: %ld rtbre: %ld "
1069 "rtbf: %ld rtb: %ld nt: %ld", 1069 "rtbf: %ld rtb: %ld nt: %ld",
1070 rcu_torture_current, 1070 rcu_torture_current,
@@ -1325,6 +1325,7 @@ rcu_torture_cleanup(void)
1325 int i; 1325 int i;
1326 1326
1327 mutex_lock(&fullstop_mutex); 1327 mutex_lock(&fullstop_mutex);
1328 rcutorture_record_test_transition();
1328 if (fullstop == FULLSTOP_SHUTDOWN) { 1329 if (fullstop == FULLSTOP_SHUTDOWN) {
1329 printk(KERN_WARNING /* but going down anyway, so... */ 1330 printk(KERN_WARNING /* but going down anyway, so... */
1330 "Concurrent 'rmmod rcutorture' and shutdown illegal!\n"); 1331 "Concurrent 'rmmod rcutorture' and shutdown illegal!\n");
@@ -1616,6 +1617,7 @@ rcu_torture_init(void)
1616 } 1617 }
1617 } 1618 }
1618 register_reboot_notifier(&rcutorture_shutdown_nb); 1619 register_reboot_notifier(&rcutorture_shutdown_nb);
1620 rcutorture_record_test_transition();
1619 mutex_unlock(&fullstop_mutex); 1621 mutex_unlock(&fullstop_mutex);
1620 return 0; 1622 return 0;
1621 1623
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index d8917401cbbc..bb84deca3319 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -102,6 +102,18 @@ static void invoke_rcu_cpu_kthread(void);
102#define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */ 102#define RCU_KTHREAD_PRIO 1 /* RT priority for per-CPU kthreads. */
103 103
104/* 104/*
105 * Track the rcutorture test sequence number and the update version
106 * number within a given test. The rcutorture_testseq is incremented
107 * on every rcutorture module load and unload, so has an odd value
108 * when a test is running. The rcutorture_vernum is set to zero
109 * when rcutorture starts and is incremented on each rcutorture update.
110 * These variables enable correlating rcutorture output with the
111 * RCU tracing information.
112 */
113unsigned long rcutorture_testseq;
114unsigned long rcutorture_vernum;
115
116/*
105 * Return true if an RCU grace period is in progress. The ACCESS_ONCE()s 117 * Return true if an RCU grace period is in progress. The ACCESS_ONCE()s
106 * permit this function to be invoked without holding the root rcu_node 118 * permit this function to be invoked without holding the root rcu_node
107 * structure's ->lock, but of course results can be subject to change. 119 * structure's ->lock, but of course results can be subject to change.
@@ -193,6 +205,31 @@ void rcu_bh_force_quiescent_state(void)
193EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state); 205EXPORT_SYMBOL_GPL(rcu_bh_force_quiescent_state);
194 206
195/* 207/*
208 * Record the number of times rcutorture tests have been initiated and
209 * terminated. This information allows the debugfs tracing stats to be
210 * correlated to the rcutorture messages, even when the rcutorture module
211 * is being repeatedly loaded and unloaded. In other words, we cannot
212 * store this state in rcutorture itself.
213 */
214void rcutorture_record_test_transition(void)
215{
216 rcutorture_testseq++;
217 rcutorture_vernum = 0;
218}
219EXPORT_SYMBOL_GPL(rcutorture_record_test_transition);
220
221/*
222 * Record the number of writer passes through the current rcutorture test.
223 * This is also used to correlate debugfs tracing stats with the rcutorture
224 * messages.
225 */
226void rcutorture_record_progress(unsigned long vernum)
227{
228 rcutorture_vernum++;
229}
230EXPORT_SYMBOL_GPL(rcutorture_record_progress);
231
232/*
196 * Force a quiescent state for RCU-sched. 233 * Force a quiescent state for RCU-sched.
197 */ 234 */
198void rcu_sched_force_quiescent_state(void) 235void rcu_sched_force_quiescent_state(void)
diff --git a/kernel/rcutree_trace.c b/kernel/rcutree_trace.c
index fc40e89a028c..3baa235786b5 100644
--- a/kernel/rcutree_trace.c
+++ b/kernel/rcutree_trace.c
@@ -394,6 +394,29 @@ static const struct file_operations rcu_pending_fops = {
394 .release = single_release, 394 .release = single_release,
395}; 395};
396 396
397static int show_rcutorture(struct seq_file *m, void *unused)
398{
399 seq_printf(m, "rcutorture test sequence: %lu %s\n",
400 rcutorture_testseq >> 1,
401 (rcutorture_testseq & 0x1) ? "(test in progress)" : "");
402 seq_printf(m, "rcutorture update version number: %lu\n",
403 rcutorture_vernum);
404 return 0;
405}
406
407static int rcutorture_open(struct inode *inode, struct file *file)
408{
409 return single_open(file, show_rcutorture, NULL);
410}
411
412static const struct file_operations rcutorture_fops = {
413 .owner = THIS_MODULE,
414 .open = rcutorture_open,
415 .read = seq_read,
416 .llseek = seq_lseek,
417 .release = single_release,
418};
419
397static struct dentry *rcudir; 420static struct dentry *rcudir;
398 421
399static int __init rcutree_trace_init(void) 422static int __init rcutree_trace_init(void)
@@ -430,6 +453,11 @@ static int __init rcutree_trace_init(void)
430 NULL, &rcu_pending_fops); 453 NULL, &rcu_pending_fops);
431 if (!retval) 454 if (!retval)
432 goto free_out; 455 goto free_out;
456
457 retval = debugfs_create_file("rcutorture", 0444, rcudir,
458 NULL, &rcutorture_fops);
459 if (!retval)
460 goto free_out;
433 return 0; 461 return 0;
434free_out: 462free_out:
435 debugfs_remove_recursive(rcudir); 463 debugfs_remove_recursive(rcudir);