Skip to content

Commit b3772c8

Browse files
Nathan Zimmergregkh
Nathan Zimmer
authored andcommitted
timer_list: correct the iterator for timer_list
commit 84a78a6 upstream. Correct an issue with /proc/timer_list reported by Holger. When reading from the proc file with a sufficiently small buffer, 2k so not really that small, there was one could get hung trying to read the file a chunk at a time. The timer_list_start function failed to account for the possibility that the offset was adjusted outside the timer_list_next. Signed-off-by: Nathan Zimmer <[email protected]> Reported-by: Holger Hans Peter Freyther <[email protected]> Cc: John Stultz <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Berke Durak <[email protected]> Cc: Jeff Layton <[email protected]> Tested-by: Al Viro <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent f1179e0 commit b3772c8

File tree

1 file changed

+24
-17
lines changed

1 file changed

+24
-17
lines changed

kernel/time/timer_list.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -265,10 +265,9 @@ static inline void timer_list_header(struct seq_file *m, u64 now)
265265
static int timer_list_show(struct seq_file *m, void *v)
266266
{
267267
struct timer_list_iter *iter = v;
268-
u64 now = ktime_to_ns(ktime_get());
269268

270269
if (iter->cpu == -1 && !iter->second_pass)
271-
timer_list_header(m, now);
270+
timer_list_header(m, iter->now);
272271
else if (!iter->second_pass)
273272
print_cpu(m, iter->cpu, iter->now);
274273
#ifdef CONFIG_GENERIC_CLOCKEVENTS
@@ -298,33 +297,41 @@ void sysrq_timer_list_show(void)
298297
return;
299298
}
300299

301-
static void *timer_list_start(struct seq_file *file, loff_t *offset)
300+
static void *move_iter(struct timer_list_iter *iter, loff_t offset)
302301
{
303-
struct timer_list_iter *iter = file->private;
304-
305-
if (!*offset) {
306-
iter->cpu = -1;
307-
iter->now = ktime_to_ns(ktime_get());
308-
} else if (iter->cpu >= nr_cpu_ids) {
302+
for (; offset; offset--) {
303+
iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
304+
if (iter->cpu >= nr_cpu_ids) {
309305
#ifdef CONFIG_GENERIC_CLOCKEVENTS
310-
if (!iter->second_pass) {
311-
iter->cpu = -1;
312-
iter->second_pass = true;
313-
} else
314-
return NULL;
306+
if (!iter->second_pass) {
307+
iter->cpu = -1;
308+
iter->second_pass = true;
309+
} else
310+
return NULL;
315311
#else
316-
return NULL;
312+
return NULL;
317313
#endif
314+
}
318315
}
319316
return iter;
320317
}
321318

319+
static void *timer_list_start(struct seq_file *file, loff_t *offset)
320+
{
321+
struct timer_list_iter *iter = file->private;
322+
323+
if (!*offset)
324+
iter->now = ktime_to_ns(ktime_get());
325+
iter->cpu = -1;
326+
iter->second_pass = false;
327+
return move_iter(iter, *offset);
328+
}
329+
322330
static void *timer_list_next(struct seq_file *file, void *v, loff_t *offset)
323331
{
324332
struct timer_list_iter *iter = file->private;
325-
iter->cpu = cpumask_next(iter->cpu, cpu_online_mask);
326333
++*offset;
327-
return timer_list_start(file, offset);
334+
return move_iter(iter, 1);
328335
}
329336

330337
static void timer_list_stop(struct seq_file *seq, void *v)

0 commit comments

Comments
 (0)