On Thu, 2014-06-19 at 21:54 -0700, Paul E. McKenney wrote: > On Thu, Jun 19, 2014 at 08:13:22PM -0400, Pranith Kumar wrote: > > On 06/19/2014 07:49 PM, Paul E. McKenney wrote: > > > On Thu, Jun 19, 2014 at 07:24:48PM -0400, Pranith Kumar wrote: > > >> (dropping some CCs) > > >> > > >> On 06/19/2014 05:00 PM, Paul E. McKenney wrote: > > >>> On Wed, Jun 18, 2014 at 12:49:42PM -0700, Joe Perches wrote: > > >>>> > > >>>> I believe the function doesn't work well. > > >>>> > > >>>> static void > > >>>> rcu_torture_stats_print(void) > > >>>> { > > >>>> int size = nr_cpu_ids * 200 + 8192; > > >>>> char *buf; > > >>>> > > >>>> buf = kmalloc(size, GFP_KERNEL); > > >>>> if (!buf) { > > >>>> pr_err("rcu-torture: Out of memory, need: %d\n", size); > > >>>> return; > > >>>> } > > >>>> rcu_torture_printk(buf); > > >>>> pr_alert("%s", buf); > > >>>> kfree(buf); > > >>>> } > > >>>> > > >>>> rcu_torture_printk simply fills buf > > >>>> > > >>>> btw: I believe the arguments should pass size and > > >>>> rcu_torture_printk should use snprintf/size > > >>>> > > >>>> but all printks are limited to a maximum of 1024 > > >>>> bytes so the large allocation is senseless and > > >>>> would even if it worked, would likely need to be > > >>>> vmalloc/vfree > > >>> > > >>> Fair point! > > >>> > > >>> Pranith, Romanov, if you would like part of RCU that is less touchy > > >>> about random hacking, this would be a good place to start. Scripts in > > >>> tools/testing/selftests/rcutorture/bin do care about some of the format, > > >>> but the variable-length portion generated by cur_ops->stats() is as far > > >>> as I know only parsed by human eyes. > > >>> > > >> > > >> Here is a first run of the change. Please let me know if I am totally > > >> off. RFC. :) > > > > > > Thank you for taking this on! > > > > You are most welcome :) > > > > > > > >> Three things on Todo list: > > >> > > >> * We need to check that we are using less than the allocated size of the > > >> buffer (used > size). (we are allocating a big buffer, so not sure if > > >> necessary) > > >> * Need to check with the scripts if they are working. > > >> * I used a loop for pr_alert(). I am not sure this is right, there > > >> should be a better way for printing large buffers > > >> > > >> If the overall structure is ok I will go ahead and check how the scripts > > >> are handling these changes. > > > > > > One other thing... Convince this function (and a few others that it > > > calls) that the system really has 4096 CPUs, run this code, and see wshat > > > actually happens both before and after. Just to get a bit of practice > > > mixed in with the theory. ;-) > > > > > > > OK. I think to do this I need to use 4096 instead of nr_cpu_ids. I will try > > this and see how it goes :) > > That's the spirit! You will probably have to adjust a few other things > as well.
Perhaps this should not use the allocation / page buffer and instead call pr_alert and pr_cont directly like this: include/linux/torture.h | 2 +- kernel/rcu/rcutorture.c | 110 +++++++++++++++++++++++------------------------- kernel/torture.c | 16 +++---- 3 files changed, 60 insertions(+), 68 deletions(-) diff --git a/include/linux/torture.h b/include/linux/torture.h index 5ca58fc..fec46f8 100644 --- a/include/linux/torture.h +++ b/include/linux/torture.h @@ -51,7 +51,7 @@ /* Definitions for online/offline exerciser. */ int torture_onoff_init(long ooholdoff, long oointerval); -char *torture_onoff_stats(char *page); +void torture_onoff_stats(void); bool torture_onoff_failures(void); /* Low-rider random number generator. */ diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 7fa34f8..bb6db08 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -242,7 +242,7 @@ struct rcu_torture_ops { void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu)); void (*cb_barrier)(void); void (*fqs)(void); - void (*stats)(char *page); + void (*stats)(void); int irq_capable; int can_boost; const char *name; @@ -525,21 +525,21 @@ static void srcu_torture_barrier(void) srcu_barrier(&srcu_ctl); } -static void srcu_torture_stats(char *page) +static void srcu_torture_stats(void) { int cpu; int idx = srcu_ctl.completed & 0x1; - page += sprintf(page, "%s%s per-CPU(idx=%d):", - torture_type, TORTURE_FLAG, idx); + pr_alert("%s%s per-CPU(idx=%d):", + torture_type, TORTURE_FLAG, idx); for_each_possible_cpu(cpu) { long c0, c1; c0 = (long)per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx]; c1 = (long)per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]; - page += sprintf(page, " %d(%ld,%ld)", cpu, c0, c1); + pr_cont(" %d(%ld,%ld)", cpu, c0, c1); } - sprintf(page, "\n"); + pr_cont("\n"); } static void srcu_torture_synchronize_expedited(void) @@ -1031,10 +1031,10 @@ rcu_torture_reader(void *arg) } /* - * Create an RCU-torture statistics message in the specified buffer. + * Print RCU-torture statistics */ static void -rcu_torture_printk(char *page) +rcu_torture_printk(void) { int cpu; int i; @@ -1052,55 +1052,60 @@ rcu_torture_printk(char *page) if (pipesummary[i] != 0) break; } - page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG); - page += sprintf(page, - "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ", - rcu_torture_current, - rcu_torture_current_version, - list_empty(&rcu_torture_freelist), - atomic_read(&n_rcu_torture_alloc), - atomic_read(&n_rcu_torture_alloc_fail), - atomic_read(&n_rcu_torture_free)); - page += sprintf(page, "rtmbe: %d rtbke: %ld rtbre: %ld ", - atomic_read(&n_rcu_torture_mberror), - n_rcu_torture_boost_ktrerror, - n_rcu_torture_boost_rterror); - page += sprintf(page, "rtbf: %ld rtb: %ld nt: %ld ", - n_rcu_torture_boost_failure, - n_rcu_torture_boosts, - n_rcu_torture_timers); - page = torture_onoff_stats(page); - page += sprintf(page, "barrier: %ld/%ld:%ld", - n_barrier_successes, - n_barrier_attempts, - n_rcu_torture_barrier_error); - page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG); + + pr_alert("%s%s ", torture_type, TORTURE_FLAG); + pr_cont("rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ", + rcu_torture_current, + rcu_torture_current_version, + list_empty(&rcu_torture_freelist), + atomic_read(&n_rcu_torture_alloc), + atomic_read(&n_rcu_torture_alloc_fail), + atomic_read(&n_rcu_torture_free)); + pr_cont("rtmbe: %d rtbke: %ld rtbre: %ld ", + atomic_read(&n_rcu_torture_mberror), + n_rcu_torture_boost_ktrerror, + n_rcu_torture_boost_rterror); + pr_cont("rtbf: %ld rtb: %ld nt: %ld ", + n_rcu_torture_boost_failure, + n_rcu_torture_boosts, + n_rcu_torture_timers); + torture_onoff_stats(); + pr_cont("barrier: %ld/%ld:%ld\n", + n_barrier_successes, + n_barrier_attempts, + n_rcu_torture_barrier_error); + + pr_alert("%s%s ", torture_type, TORTURE_FLAG); if (atomic_read(&n_rcu_torture_mberror) != 0 || n_rcu_torture_barrier_error != 0 || n_rcu_torture_boost_ktrerror != 0 || n_rcu_torture_boost_rterror != 0 || n_rcu_torture_boost_failure != 0 || i > 1) { - page += sprintf(page, "!!! "); + pr_cont("%s", "!!! "); atomic_inc(&n_rcu_torture_error); WARN_ON_ONCE(1); } - page += sprintf(page, "Reader Pipe: "); + pr_cont("Reader Pipe: "); for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) - page += sprintf(page, " %ld", pipesummary[i]); - page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG); - page += sprintf(page, "Reader Batch: "); + pr_cont(" %ld", pipesummary[i]); + pr_cont("\n"); + + pr_alert("%s%s ", torture_type, TORTURE_FLAG); + pr_cont("Reader Batch: "); for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) - page += sprintf(page, " %ld", batchsummary[i]); - page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG); - page += sprintf(page, "Free-Block Circulation: "); + pr_cont(" %ld", batchsummary[i]); + pr_cont("\n"); + + pr_alert("%s%s ", torture_type, TORTURE_FLAG); + pr_cont("Free-Block Circulation: "); for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) { - page += sprintf(page, " %d", - atomic_read(&rcu_torture_wcount[i])); + pr_cont(" %d", atomic_read(&rcu_torture_wcount[i])); } - page += sprintf(page, "\n"); + pr_cont("\n"); + if (cur_ops->stats) - cur_ops->stats(page); + cur_ops->stats(); if (rtcv_snap == rcu_torture_current_version && rcu_torture_current != NULL) { int __maybe_unused flags; @@ -1109,10 +1114,9 @@ rcu_torture_printk(char *page) rcutorture_get_gp_data(cur_ops->ttype, &flags, &gpnum, &completed); - page += sprintf(page, - "??? Writer stall state %d g%lu c%lu f%#x\n", - rcu_torture_writer_state, - gpnum, completed, flags); + pr_alert("??? Writer stall state %d g%lu c%lu f%#x\n", + rcu_torture_writer_state, + gpnum, completed, flags); show_rcu_gp_kthreads(); rcutorture_trace_dump(); } @@ -1130,17 +1134,7 @@ rcu_torture_printk(char *page) static void rcu_torture_stats_print(void) { - int size = nr_cpu_ids * 200 + 8192; - char *buf; - - buf = kmalloc(size, GFP_KERNEL); - if (!buf) { - pr_err("rcu-torture: Out of memory, need: %d", size); - return; - } - rcu_torture_printk(buf); - pr_alert("%s", buf); - kfree(buf); + rcu_torture_printk(); } /* diff --git a/kernel/torture.c b/kernel/torture.c index 40bb511..a98d3c1 100644 --- a/kernel/torture.c +++ b/kernel/torture.c @@ -211,18 +211,16 @@ EXPORT_SYMBOL_GPL(torture_onoff_cleanup); /* * Print online/offline testing statistics. */ -char *torture_onoff_stats(char *page) +void torture_onoff_stats(void) { #ifdef CONFIG_HOTPLUG_CPU - page += sprintf(page, - "onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ", - n_online_successes, n_online_attempts, - n_offline_successes, n_offline_attempts, - min_online, max_online, - min_offline, max_offline, - sum_online, sum_offline, HZ); + pr_cont("onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ", + n_online_successes, n_online_attempts, + n_offline_successes, n_offline_attempts, + min_online, max_online, + min_offline, max_offline, + sum_online, sum_offline, HZ); #endif /* #ifdef CONFIG_HOTPLUG_CPU */ - return page; } EXPORT_SYMBOL_GPL(torture_onoff_stats); -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/