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
153unsigned long ring_buffer_overruns(struct ring_buffer *buffer);153unsigned long ring_buffer_overruns(struct ring_buffer *buffer);
154unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu);154unsigned long ring_buffer_entries_cpu(struct ring_buffer *buffer, int cpu);
155unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu);155unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu);
156unsigned long ring_buffer_commit_overrun_cpu(struct ring_buffer *buffer, int cpu);
157unsigned long ring_buffer_nmi_dropped_cpu(struct ring_buffer *buffer, int cpu);
156 158
157u64 ring_buffer_time_stamp(struct ring_buffer *buffer, int cpu);159u64 ring_buffer_time_stamp(struct ring_buffer *buffer, int cpu);
158void ring_buffer_normalize_time_stamp(struct ring_buffer *buffer,160void 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
402 struct buffer_page *tail_page; /* write to tail */402 struct buffer_page *tail_page; /* write to tail */
403 struct buffer_page *commit_page; /* committed pages */403 struct buffer_page *commit_page; /* committed pages */
404 struct buffer_page *reader_page;404 struct buffer_page *reader_page;
405 unsigned long nmi_dropped;
406 unsigned long commit_overrun;
405 unsigned long overrun;407 unsigned long overrun;
406 unsigned long entries;408 unsigned long entries;
407 u64 write_stamp;409 u64 write_stamp;
@@ -1216,8 +1218,10 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, · 808 unmodified lines
1216 * simply fail.1218 * simply fail.
1217 */1219 */
1218 if (unlikely(in_nmi())) {1220 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++;
1220 goto out_reset;1223 goto out_reset;
1224 }
1221 } else1225 } else
1222 __raw_spin_lock(&cpu_buffer->lock);1226 __raw_spin_lock(&cpu_buffer->lock);
1223 1227
@@ -1238,8 +1242,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, · 14 unmodified lines
1238 * about it.1242 * about it.
1239 */1243 */
1240 if (unlikely(next_page == commit_page)) {1244 if (unlikely(next_page == commit_page)) {
1241 /* This can easily happen on small ring buffers */1245 cpu_buffer->commit_overrun++;
1242 WARN_ON_ONCE(buffer->pages > 2);
1243 goto out_reset;1246 goto out_reset;
1244 }1247 }
1245 1248
@@ -1925,6 +1928,47 @@ unsigned long ring_buffer_overrun_cpu(struct ring_buffer *buffer, int cpu) · 679 unmodified lines
1925}1928}
1926EXPORT_SYMBOL_GPL(ring_buffer_overrun_cpu);1929EXPORT_SYMBOL_GPL(ring_buffer_overrun_cpu);
1927 1930
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 */
1936unsigned 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}
1949EXPORT_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 */
1956unsigned long
1957ring_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}
1970EXPORT_SYMBOL_GPL(ring_buffer_commit_overrun_cpu);
1971
1928/**1972/**
1929 * ring_buffer_entries - get the number of entries in a buffer1973 * ring_buffer_entries - get the number of entries in a buffer
1930 * @buffer: The ring buffer1974 * @buffer: The ring buffer
@@ -2595,6 +2639,8 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer) · 664 unmodified lines
2595 local_set(&cpu_buffer->reader_page->page->commit, 0);2639 local_set(&cpu_buffer->reader_page->page->commit, 0);
2596 cpu_buffer->reader_page->read = 0;2640 cpu_buffer->reader_page->read = 0;
2597 2641
2642 cpu_buffer->nmi_dropped = 0;
2643 cpu_buffer->commit_overrun = 0;
2598 cpu_buffer->overrun = 0;2644 cpu_buffer->overrun = 0;
2599 cpu_buffer->entries = 0;2645 cpu_buffer->entries = 0;
2600 2646