Skip to content

Commit d100895

Browse files
Chen Gangpaulmck
authored andcommitted
rcu/torture: Dynamically allocate SRCU output buffer to avoid overflow
If the rcutorture SRCU output exceeds 4096 bytes, for example, if you have more than about 75 CPUs, it will overflow the current statically allocated buffer. This commit therefore replaces this static buffer with a dynamically buffer whose size is based on the number of CPUs. Benefits: - Avoids both buffer overflow and output truncation. - Handles an arbitrarily large number of CPUs. - Straightforward implementation. Shortcomings: - Some memory is wasted: 1 cpu now comsumes 50 - 60 bytes, and this patch provides 200 bytes. Therefore, for 1K CPUs, roughly 100KB of memory will be wasted. However, the memory is freed immediately after printing, so this wastage should not be a problem in practice. Testing (Fedora16 2 CPUs, 2GB RAM x86_64): - as module, with/without "torture_type=srcu". - build-in not boot runnable, with/without "torture_type=srcu". - build-in let boot runnable, with/without "torture_type=srcu". Signed-off-by: Chen Gang <gang.chen@asianux.com> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
1 parent a096932 commit d100895

File tree

1 file changed

+34
-33
lines changed

1 file changed

+34
-33
lines changed

kernel/rcu/torture.c

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,6 @@ MODULE_PARM_DESC(verbose, "Enable verbose debugging printk()s");
139139
#define VERBOSE_PRINTK_ERRSTRING(s) \
140140
do { if (verbose) pr_alert("%s" TORTURE_FLAG "!!! " s "\n", torture_type); } while (0)
141141

142-
static char printk_buf[4096];
143-
144142
static int nrealreaders;
145143
static struct task_struct *writer_task;
146144
static struct task_struct **fakewriter_tasks;
@@ -376,7 +374,7 @@ struct rcu_torture_ops {
376374
void (*call)(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
377375
void (*cb_barrier)(void);
378376
void (*fqs)(void);
379-
int (*stats)(char *page);
377+
void (*stats)(char *page);
380378
int irq_capable;
381379
int can_boost;
382380
const char *name;
@@ -578,21 +576,19 @@ static void srcu_torture_barrier(void)
578576
srcu_barrier(&srcu_ctl);
579577
}
580578

581-
static int srcu_torture_stats(char *page)
579+
static void srcu_torture_stats(char *page)
582580
{
583-
int cnt = 0;
584581
int cpu;
585582
int idx = srcu_ctl.completed & 0x1;
586583

587-
cnt += sprintf(&page[cnt], "%s%s per-CPU(idx=%d):",
584+
page += sprintf(page, "%s%s per-CPU(idx=%d):",
588585
torture_type, TORTURE_FLAG, idx);
589586
for_each_possible_cpu(cpu) {
590-
cnt += sprintf(&page[cnt], " %d(%lu,%lu)", cpu,
587+
page += sprintf(page, " %d(%lu,%lu)", cpu,
591588
per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[!idx],
592589
per_cpu_ptr(srcu_ctl.per_cpu_ref, cpu)->c[idx]);
593590
}
594-
cnt += sprintf(&page[cnt], "\n");
595-
return cnt;
591+
sprintf(page, "\n");
596592
}
597593

598594
static void srcu_torture_synchronize_expedited(void)
@@ -1052,10 +1048,9 @@ rcu_torture_reader(void *arg)
10521048
/*
10531049
* Create an RCU-torture statistics message in the specified buffer.
10541050
*/
1055-
static int
1051+
static void
10561052
rcu_torture_printk(char *page)
10571053
{
1058-
int cnt = 0;
10591054
int cpu;
10601055
int i;
10611056
long pipesummary[RCU_TORTURE_PIPE_LEN + 1] = { 0 };
@@ -1071,62 +1066,61 @@ rcu_torture_printk(char *page)
10711066
if (pipesummary[i] != 0)
10721067
break;
10731068
}
1074-
cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
1075-
cnt += sprintf(&page[cnt],
1069+
page += sprintf(page, "%s%s ", torture_type, TORTURE_FLAG);
1070+
page += sprintf(page,
10761071
"rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
10771072
rcu_torture_current,
10781073
rcu_torture_current_version,
10791074
list_empty(&rcu_torture_freelist),
10801075
atomic_read(&n_rcu_torture_alloc),
10811076
atomic_read(&n_rcu_torture_alloc_fail),
10821077
atomic_read(&n_rcu_torture_free));
1083-
cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ",
1078+
page += sprintf(page, "rtmbe: %d rtbke: %ld rtbre: %ld ",
10841079
atomic_read(&n_rcu_torture_mberror),
10851080
n_rcu_torture_boost_ktrerror,
10861081
n_rcu_torture_boost_rterror);
1087-
cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ",
1082+
page += sprintf(page, "rtbf: %ld rtb: %ld nt: %ld ",
10881083
n_rcu_torture_boost_failure,
10891084
n_rcu_torture_boosts,
10901085
n_rcu_torture_timers);
1091-
cnt += sprintf(&page[cnt],
1086+
page += sprintf(page,
10921087
"onoff: %ld/%ld:%ld/%ld %d,%d:%d,%d %lu:%lu (HZ=%d) ",
10931088
n_online_successes, n_online_attempts,
10941089
n_offline_successes, n_offline_attempts,
10951090
min_online, max_online,
10961091
min_offline, max_offline,
10971092
sum_online, sum_offline, HZ);
1098-
cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld",
1093+
page += sprintf(page, "barrier: %ld/%ld:%ld",
10991094
n_barrier_successes,
11001095
n_barrier_attempts,
11011096
n_rcu_torture_barrier_error);
1102-
cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
1097+
page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
11031098
if (atomic_read(&n_rcu_torture_mberror) != 0 ||
11041099
n_rcu_torture_barrier_error != 0 ||
11051100
n_rcu_torture_boost_ktrerror != 0 ||
11061101
n_rcu_torture_boost_rterror != 0 ||
11071102
n_rcu_torture_boost_failure != 0 ||
11081103
i > 1) {
1109-
cnt += sprintf(&page[cnt], "!!! ");
1104+
page += sprintf(page, "!!! ");
11101105
atomic_inc(&n_rcu_torture_error);
11111106
WARN_ON_ONCE(1);
11121107
}
1113-
cnt += sprintf(&page[cnt], "Reader Pipe: ");
1108+
page += sprintf(page, "Reader Pipe: ");
11141109
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
1115-
cnt += sprintf(&page[cnt], " %ld", pipesummary[i]);
1116-
cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
1117-
cnt += sprintf(&page[cnt], "Reader Batch: ");
1110+
page += sprintf(page, " %ld", pipesummary[i]);
1111+
page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
1112+
page += sprintf(page, "Reader Batch: ");
11181113
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++)
1119-
cnt += sprintf(&page[cnt], " %ld", batchsummary[i]);
1120-
cnt += sprintf(&page[cnt], "\n%s%s ", torture_type, TORTURE_FLAG);
1121-
cnt += sprintf(&page[cnt], "Free-Block Circulation: ");
1114+
page += sprintf(page, " %ld", batchsummary[i]);
1115+
page += sprintf(page, "\n%s%s ", torture_type, TORTURE_FLAG);
1116+
page += sprintf(page, "Free-Block Circulation: ");
11221117
for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) {
1123-
cnt += sprintf(&page[cnt], " %d",
1118+
page += sprintf(page, " %d",
11241119
atomic_read(&rcu_torture_wcount[i]));
11251120
}
1126-
cnt += sprintf(&page[cnt], "\n");
1121+
page += sprintf(page, "\n");
11271122
if (cur_ops->stats)
1128-
cnt += cur_ops->stats(&page[cnt]);
1129-
return cnt;
1123+
cur_ops->stats(page);
11301124
}
11311125

11321126
/*
@@ -1140,10 +1134,17 @@ rcu_torture_printk(char *page)
11401134
static void
11411135
rcu_torture_stats_print(void)
11421136
{
1143-
int cnt;
1137+
int size = nr_cpu_ids * 200 + 8192;
1138+
char *buf;
11441139

1145-
cnt = rcu_torture_printk(printk_buf);
1146-
pr_alert("%s", printk_buf);
1140+
buf = kmalloc(size, GFP_KERNEL);
1141+
if (!buf) {
1142+
pr_err("rcu-torture: Out of memory, need: %d", size);
1143+
return;
1144+
}
1145+
rcu_torture_printk(buf);
1146+
pr_alert("%s", buf);
1147+
kfree(buf);
11471148
}
11481149

11491150
/*

0 commit comments

Comments
 (0)