History

ring-buffer: add counters for commit overrun and nmi dropped entries

The WARN_ON in the ring buffer when a commit is preempted and the buffer is filled by preceding writes can happen in normal operations. The WARN_ON makes it look like a bug, not to mention, because it does not stop tracing and calls printk which can also recurse, this is prone to deadlock (the WARN_ON is not in a position to recurse). This patch removes the WARN_ON and replaces it with a counter that can be retrieved by a tracer. This counter is called commit_overrun. While at it, I added a nmi_dropped counter to count any time an NMI entry is dropped because the NMI could not take the spinlock. [ Impact: prevent deadlock by printing normal case warning ]

Steven Rostedt committed 17 years ago

Commit f0d2c681 parent d6ce96d2 files · +51 −3Browse files

Unified · Split

2 files
  1. include/linux/ring_buffer.h +2 −0
  2. kernel/trace/ring_buffer.c +49 −3
include/linux/ring_buffer.h+2−0
@@ -153,6 +153,8 @@ unsigned long ring_buffer_entries(struct ring_buffer *buffer); · 152 unmodified lines
153153 unsigned long ring_buffer_overruns(struct ring_buffer *buffer);
154154 unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu);
155155 unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu);
156+unsigned long ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu);
157+unsigned long ring_buffer_nmi_dropped_cpu(struct ring_buffer *buffer, int cpu);
156158
157159 u64 ring_buffer_time_stamp(struct ring_buffer *buffer, int cpu);
158160 void ring_buffer_normalize_time_stamp(struct ring_buffer *buffer,
kernel/trace/ring_buffer.c+49−3
@@ -402,6 +402,8 @@ struct ring_buffer_per_cpu { · 401 unmodified lines
402402 struct buffer_page *tail_page; /* write to tail */
403403 struct buffer_page *commit_page; /* committed pages */
404404 struct buffer_page *reader_page;
405+ unsigned long nmi_dropped;
406+ unsigned long commit_overrun;
405407 unsigned long overrun;
406408 unsigned long entries;
407409 u64 write_stamp;
@@ -1216,8 +1218,10 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, · 808 unmodified lines
12161218 * simply fail.
12171219 */
12181220 if (unlikely(in_nmi())) {
1219− if (!__raw_spin_trylock(&cpu_buffer->lock))
1221+ if (!__raw_spin_trylock(&cpu_buffer->lock)) {
1222+ cpu_buffer->nmi_dropped++;
12201223 goto out_reset;
1224+ }
12211225 } else
12221226 __raw_spin_lock(&cpu_buffer->lock);
12231227
@@ -1238,8 +1242,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, · 14 unmodified lines
12381242 * about it.
12391243 */
12401244 if (unlikely(next_page == commit_page)) {
1241− /* This can easily happen on small ring buffers */
1242− WARN_ON_ONCE(buffer->pages > 2);
1245+ cpu_buffer->commit_overrun++;
12431246 goto out_reset;
12441247 }
12451248
@@ -1925,6 +1928,47 @@ unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu) · 679 unmodified lines
19251928 }
19261929 EXPORT_SYMBOL_GPL(ring_buffer_overrun_cpu);
19271930
1931+/**
1932+ * ring_buffer_nmi_dropped_cpu - get the number of nmis that were dropped
1933+ * @buffer: The ring buffer
1934+ * @cpu: The per CPU buffer to get the number of overruns from
1935+ */
1936+unsigned long ring_buffer_nmi_dropped_cpu(struct ring_buffer *buffer, int cpu)
1937+{
1938+ struct ring_buffer_per_cpu *cpu_buffer;
1939+ unsigned long ret;
1940+
1941+ if (!cpumask_test_cpu(cpu, buffer->cpumask))
1942+ return 0;
1943+
1944+ cpu_buffer = buffer->buffers[cpu];
1945+ ret = cpu_buffer->nmi_dropped;
1946+
1947+ return ret;
1948+}
1949+EXPORT_SYMBOL_GPL(ring_buffer_nmi_dropped_cpu);
1950+
1951+/**
1952+ * ring_buffer_commit_overrun_cpu - get the number of overruns caused by commits
1953+ * @buffer: The ring buffer
1954+ * @cpu: The per CPU buffer to get the number of overruns from
1955+ */
1956+unsigned long
1957+ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu)
1958+{
1959+ struct ring_buffer_per_cpu *cpu_buffer;
1960+ unsigned long ret;
1961+
1962+ if (!cpumask_test_cpu(cpu, buffer->cpumask))
1963+ return 0;
1964+
1965+ cpu_buffer = buffer->buffers[cpu];
1966+ ret = cpu_buffer->commit_overrun;
1967+
1968+ return ret;
1969+}
1970+EXPORT_SYMBOL_GPL(ring_buffer_commit_overrun_cpu);
1971+
19281972 /**
19291973 * ring_buffer_entries - get the number of entries in a buffer
19301974 * @buffer: The ring buffer
@@ -2595,6 +2639,8 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) · 664 unmodified lines
25952639 local_set(&cpu_buffer->reader_page->page->commit, 0);
25962640 cpu_buffer->reader_page->read = 0;
25972641
2642+ cpu_buffer->nmi_dropped = 0;
2643+ cpu_buffer->commit_overrun = 0;
25982644 cpu_buffer->overrun = 0;
25992645 cpu_buffer->entries = 0;
26002646