diff options
author | Frederic Weisbecker <fweisbec@gmail.com> | 2009-03-12 13:24:49 -0400 |
---|---|---|
committer | Steven Rostedt <srostedt@redhat.com> | 2009-03-12 21:15:00 -0400 |
commit | 48ead02030f849d011259244bb4ea9b985479006 (patch) | |
tree | 4500f27dc7eb6567ca79dd03fa94fe9e56fbc316 /kernel/trace/trace.c | |
parent | db526ca329f855510e8ce672332eba3304aed590 (diff) |
tracing/core: bring back raw trace_printk for dynamic formats strings
Impact: fix callsites with dynamic format strings
Since its new binary implementation, trace_printk() internally uses static
containers for the format strings on each callsites. But the value is
assigned once at build time, which means that it can't take dynamic
formats.
So this patch unearthes the raw trace_printk implementation for the callers
that will need trace_printk to be able to carry these dynamic format
strings. The trace_printk() macro will use the appropriate implementation
for each callsite. Most of the time however, the binary implementation will
still be used.
The other impact of this patch is that mmiotrace_printk() will use the old
implementation because it calls the low level trace_vprintk and we can't
guess here whether the format passed in it is dynamic or not.
Some parts of this patch have been written by Steven Rostedt (most notably
the part that chooses the appropriate implementation for each callsites).
Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Signed-off-by: Steven Rostedt <srostedt@redhat.com>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 85 |
1 files changed, 80 insertions, 5 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 62a63b2b33dd..dbb077d8a172 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1179,10 +1179,10 @@ void trace_graph_return(struct ftrace_graph_ret *trace) | |||
1179 | 1179 | ||
1180 | 1180 | ||
1181 | /** | 1181 | /** |
1182 | * trace_vprintk - write binary msg to tracing buffer | 1182 | * trace_vbprintk - write binary msg to tracing buffer |
1183 | * | 1183 | * |
1184 | */ | 1184 | */ |
1185 | int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | 1185 | int trace_vbprintk(unsigned long ip, int depth, const char *fmt, va_list args) |
1186 | { | 1186 | { |
1187 | static raw_spinlock_t trace_buf_lock = | 1187 | static raw_spinlock_t trace_buf_lock = |
1188 | (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; | 1188 | (raw_spinlock_t)__RAW_SPIN_LOCK_UNLOCKED; |
@@ -1191,7 +1191,7 @@ int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | |||
1191 | struct ring_buffer_event *event; | 1191 | struct ring_buffer_event *event; |
1192 | struct trace_array *tr = &global_trace; | 1192 | struct trace_array *tr = &global_trace; |
1193 | struct trace_array_cpu *data; | 1193 | struct trace_array_cpu *data; |
1194 | struct print_entry *entry; | 1194 | struct bprint_entry *entry; |
1195 | unsigned long flags; | 1195 | unsigned long flags; |
1196 | int resched; | 1196 | int resched; |
1197 | int cpu, len = 0, size, pc; | 1197 | int cpu, len = 0, size, pc; |
@@ -1219,7 +1219,7 @@ int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | |||
1219 | goto out_unlock; | 1219 | goto out_unlock; |
1220 | 1220 | ||
1221 | size = sizeof(*entry) + sizeof(u32) * len; | 1221 | size = sizeof(*entry) + sizeof(u32) * len; |
1222 | event = trace_buffer_lock_reserve(tr, TRACE_PRINT, size, flags, pc); | 1222 | event = trace_buffer_lock_reserve(tr, TRACE_BPRINT, size, flags, pc); |
1223 | if (!event) | 1223 | if (!event) |
1224 | goto out_unlock; | 1224 | goto out_unlock; |
1225 | entry = ring_buffer_event_data(event); | 1225 | entry = ring_buffer_event_data(event); |
@@ -1240,6 +1240,60 @@ out: | |||
1240 | 1240 | ||
1241 | return len; | 1241 | return len; |
1242 | } | 1242 | } |
1243 | EXPORT_SYMBOL_GPL(trace_vbprintk); | ||
1244 | |||
1245 | int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) | ||
1246 | { | ||
1247 | static raw_spinlock_t trace_buf_lock = __RAW_SPIN_LOCK_UNLOCKED; | ||
1248 | static char trace_buf[TRACE_BUF_SIZE]; | ||
1249 | |||
1250 | struct ring_buffer_event *event; | ||
1251 | struct trace_array *tr = &global_trace; | ||
1252 | struct trace_array_cpu *data; | ||
1253 | int cpu, len = 0, size, pc; | ||
1254 | struct print_entry *entry; | ||
1255 | unsigned long irq_flags; | ||
1256 | |||
1257 | if (tracing_disabled || tracing_selftest_running) | ||
1258 | return 0; | ||
1259 | |||
1260 | pc = preempt_count(); | ||
1261 | preempt_disable_notrace(); | ||
1262 | cpu = raw_smp_processor_id(); | ||
1263 | data = tr->data[cpu]; | ||
1264 | |||
1265 | if (unlikely(atomic_read(&data->disabled))) | ||
1266 | goto out; | ||
1267 | |||
1268 | pause_graph_tracing(); | ||
1269 | raw_local_irq_save(irq_flags); | ||
1270 | __raw_spin_lock(&trace_buf_lock); | ||
1271 | len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args); | ||
1272 | |||
1273 | len = min(len, TRACE_BUF_SIZE-1); | ||
1274 | trace_buf[len] = 0; | ||
1275 | |||
1276 | size = sizeof(*entry) + len + 1; | ||
1277 | event = trace_buffer_lock_reserve(tr, TRACE_PRINT, size, irq_flags, pc); | ||
1278 | if (!event) | ||
1279 | goto out_unlock; | ||
1280 | entry = ring_buffer_event_data(event); | ||
1281 | entry->ip = ip; | ||
1282 | entry->depth = depth; | ||
1283 | |||
1284 | memcpy(&entry->buf, trace_buf, len); | ||
1285 | entry->buf[len] = 0; | ||
1286 | ring_buffer_unlock_commit(tr->buffer, event); | ||
1287 | |||
1288 | out_unlock: | ||
1289 | __raw_spin_unlock(&trace_buf_lock); | ||
1290 | raw_local_irq_restore(irq_flags); | ||
1291 | unpause_graph_tracing(); | ||
1292 | out: | ||
1293 | preempt_enable_notrace(); | ||
1294 | |||
1295 | return len; | ||
1296 | } | ||
1243 | EXPORT_SYMBOL_GPL(trace_vprintk); | 1297 | EXPORT_SYMBOL_GPL(trace_vprintk); |
1244 | 1298 | ||
1245 | enum trace_file_type { | 1299 | enum trace_file_type { |
@@ -1628,6 +1682,22 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
1628 | return TRACE_TYPE_HANDLED; | 1682 | return TRACE_TYPE_HANDLED; |
1629 | } | 1683 | } |
1630 | 1684 | ||
1685 | static enum print_line_t print_bprintk_msg_only(struct trace_iterator *iter) | ||
1686 | { | ||
1687 | struct trace_seq *s = &iter->seq; | ||
1688 | struct trace_entry *entry = iter->ent; | ||
1689 | struct bprint_entry *field; | ||
1690 | int ret; | ||
1691 | |||
1692 | trace_assign_type(field, entry); | ||
1693 | |||
1694 | ret = trace_seq_bprintf(s, field->fmt, field->buf); | ||
1695 | if (!ret) | ||
1696 | return TRACE_TYPE_PARTIAL_LINE; | ||
1697 | |||
1698 | return TRACE_TYPE_HANDLED; | ||
1699 | } | ||
1700 | |||
1631 | static enum print_line_t print_printk_msg_only(struct trace_iterator *iter) | 1701 | static enum print_line_t print_printk_msg_only(struct trace_iterator *iter) |
1632 | { | 1702 | { |
1633 | struct trace_seq *s = &iter->seq; | 1703 | struct trace_seq *s = &iter->seq; |
@@ -1637,7 +1707,7 @@ static enum print_line_t print_printk_msg_only(struct trace_iterator *iter) | |||
1637 | 1707 | ||
1638 | trace_assign_type(field, entry); | 1708 | trace_assign_type(field, entry); |
1639 | 1709 | ||
1640 | ret = trace_seq_bprintf(s, field->fmt, field->buf); | 1710 | ret = trace_seq_printf(s, "%s", field->buf); |
1641 | if (!ret) | 1711 | if (!ret) |
1642 | return TRACE_TYPE_PARTIAL_LINE; | 1712 | return TRACE_TYPE_PARTIAL_LINE; |
1643 | 1713 | ||
@@ -1702,6 +1772,11 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) | |||
1702 | return ret; | 1772 | return ret; |
1703 | } | 1773 | } |
1704 | 1774 | ||
1775 | if (iter->ent->type == TRACE_BPRINT && | ||
1776 | trace_flags & TRACE_ITER_PRINTK && | ||
1777 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) | ||
1778 | return print_bprintk_msg_only(iter); | ||
1779 | |||
1705 | if (iter->ent->type == TRACE_PRINT && | 1780 | if (iter->ent->type == TRACE_PRINT && |
1706 | trace_flags & TRACE_ITER_PRINTK && | 1781 | trace_flags & TRACE_ITER_PRINTK && |
1707 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) | 1782 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) |