aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c273
1 files changed, 244 insertions, 29 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 76dfe6d2466c..a917bea82715 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -197,12 +197,14 @@ unsigned long nsecs_to_usecs(unsigned long nsecs)
197 * NEED_RESCED - reschedule is requested 197 * NEED_RESCED - reschedule is requested
198 * HARDIRQ - inside an interrupt handler 198 * HARDIRQ - inside an interrupt handler
199 * SOFTIRQ - inside a softirq handler 199 * SOFTIRQ - inside a softirq handler
200 * CONT - multiple entries hold the trace item
200 */ 201 */
201enum trace_flag_type { 202enum trace_flag_type {
202 TRACE_FLAG_IRQS_OFF = 0x01, 203 TRACE_FLAG_IRQS_OFF = 0x01,
203 TRACE_FLAG_NEED_RESCHED = 0x02, 204 TRACE_FLAG_NEED_RESCHED = 0x02,
204 TRACE_FLAG_HARDIRQ = 0x04, 205 TRACE_FLAG_HARDIRQ = 0x04,
205 TRACE_FLAG_SOFTIRQ = 0x08, 206 TRACE_FLAG_SOFTIRQ = 0x08,
207 TRACE_FLAG_CONT = 0x10,
206}; 208};
207 209
208/* 210/*
@@ -1074,6 +1076,7 @@ enum trace_file_type {
1074 TRACE_FILE_LAT_FMT = 1, 1076 TRACE_FILE_LAT_FMT = 1,
1075}; 1077};
1076 1078
1079/* Return the current entry. */
1077static struct trace_entry * 1080static struct trace_entry *
1078trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data, 1081trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data,
1079 struct trace_iterator *iter, int cpu) 1082 struct trace_iterator *iter, int cpu)
@@ -1104,8 +1107,58 @@ trace_entry_idx(struct trace_array *tr, struct trace_array_cpu *data,
1104 return &array[iter->next_page_idx[cpu]]; 1107 return &array[iter->next_page_idx[cpu]];
1105} 1108}
1106 1109
1110/* Increment the index counter of an iterator by one */
1111static void trace_iterator_increment(struct trace_iterator *iter, int cpu)
1112{
1113 iter->idx++;
1114 iter->next_idx[cpu]++;
1115 iter->next_page_idx[cpu]++;
1116
1117 if (iter->next_page_idx[cpu] >= ENTRIES_PER_PAGE) {
1118 struct trace_array_cpu *data = iter->tr->data[cpu];
1119
1120 iter->next_page_idx[cpu] = 0;
1121 iter->next_page[cpu] =
1122 trace_next_list(data, iter->next_page[cpu]);
1123 }
1124}
1125
1107static struct trace_entry * 1126static struct trace_entry *
1108find_next_entry(struct trace_iterator *iter, int *ent_cpu) 1127trace_entry_next(struct trace_array *tr, struct trace_array_cpu *data,
1128 struct trace_iterator *iter, int cpu)
1129{
1130 struct list_head *next_page;
1131 struct trace_entry *ent;
1132 int idx, next_idx, next_page_idx;
1133
1134 ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu);
1135
1136 if (likely(!ent || ent->type != TRACE_CONT))
1137 return ent;
1138
1139 /* save the iterator details */
1140 idx = iter->idx;
1141 next_idx = iter->next_idx[cpu];
1142 next_page_idx = iter->next_page_idx[cpu];
1143 next_page = iter->next_page[cpu];
1144
1145 /* find a real entry */
1146 do {
1147 trace_iterator_increment(iter, cpu);
1148 ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu);
1149 } while (ent && ent->type != TRACE_CONT);
1150
1151 /* reset the iterator */
1152 iter->idx = idx;
1153 iter->next_idx[cpu] = next_idx;
1154 iter->next_page_idx[cpu] = next_page_idx;
1155 iter->next_page[cpu] = next_page;
1156
1157 return ent;
1158}
1159
1160static struct trace_entry *
1161__find_next_entry(struct trace_iterator *iter, int *ent_cpu, int inc)
1109{ 1162{
1110 struct trace_array *tr = iter->tr; 1163 struct trace_array *tr = iter->tr;
1111 struct trace_entry *ent, *next = NULL; 1164 struct trace_entry *ent, *next = NULL;
@@ -1115,7 +1168,23 @@ find_next_entry(struct trace_iterator *iter, int *ent_cpu)
1115 for_each_tracing_cpu(cpu) { 1168 for_each_tracing_cpu(cpu) {
1116 if (!head_page(tr->data[cpu])) 1169 if (!head_page(tr->data[cpu]))
1117 continue; 1170 continue;
1171
1118 ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu); 1172 ent = trace_entry_idx(tr, tr->data[cpu], iter, cpu);
1173
1174 if (ent && ent->type == TRACE_CONT) {
1175 struct trace_array_cpu *data = tr->data[cpu];
1176
1177 if (!inc)
1178 ent = trace_entry_next(tr, data, iter, cpu);
1179 else {
1180 while (ent && ent->type == TRACE_CONT) {
1181 trace_iterator_increment(iter, cpu);
1182 ent = trace_entry_idx(tr, tr->data[cpu],
1183 iter, cpu);
1184 }
1185 }
1186 }
1187
1119 /* 1188 /*
1120 * Pick the entry with the smallest timestamp: 1189 * Pick the entry with the smallest timestamp:
1121 */ 1190 */
@@ -1131,25 +1200,39 @@ find_next_entry(struct trace_iterator *iter, int *ent_cpu)
1131 return next; 1200 return next;
1132} 1201}
1133 1202
1134static void trace_iterator_increment(struct trace_iterator *iter) 1203/* Find the next real entry, without updating the iterator itself */
1204static struct trace_entry *
1205find_next_entry(struct trace_iterator *iter, int *ent_cpu)
1135{ 1206{
1136 iter->idx++; 1207 return __find_next_entry(iter, ent_cpu, 0);
1137 iter->next_idx[iter->cpu]++; 1208}
1138 iter->next_page_idx[iter->cpu]++; 1209
1210/* Find the next real entry, and increment the iterator to the next entry */
1211static void *find_next_entry_inc(struct trace_iterator *iter)
1212{
1213 struct trace_entry *next;
1214 int next_cpu = -1;
1139 1215
1140 if (iter->next_page_idx[iter->cpu] >= ENTRIES_PER_PAGE) { 1216 next = __find_next_entry(iter, &next_cpu, 1);
1141 struct trace_array_cpu *data = iter->tr->data[iter->cpu];
1142 1217
1143 iter->next_page_idx[iter->cpu] = 0; 1218 iter->prev_ent = iter->ent;
1144 iter->next_page[iter->cpu] = 1219 iter->prev_cpu = iter->cpu;
1145 trace_next_list(data, iter->next_page[iter->cpu]); 1220
1146 } 1221 iter->ent = next;
1222 iter->cpu = next_cpu;
1223
1224 if (next)
1225 trace_iterator_increment(iter, iter->cpu);
1226
1227 return next ? iter : NULL;
1147} 1228}
1148 1229
1149static void trace_consume(struct trace_iterator *iter) 1230static void trace_consume(struct trace_iterator *iter)
1150{ 1231{
1151 struct trace_array_cpu *data = iter->tr->data[iter->cpu]; 1232 struct trace_array_cpu *data = iter->tr->data[iter->cpu];
1233 struct trace_entry *ent;
1152 1234
1235 again:
1153 data->trace_tail_idx++; 1236 data->trace_tail_idx++;
1154 if (data->trace_tail_idx >= ENTRIES_PER_PAGE) { 1237 if (data->trace_tail_idx >= ENTRIES_PER_PAGE) {
1155 data->trace_tail = trace_next_page(data, data->trace_tail); 1238 data->trace_tail = trace_next_page(data, data->trace_tail);
@@ -1160,25 +1243,11 @@ static void trace_consume(struct trace_iterator *iter)
1160 if (data->trace_head == data->trace_tail && 1243 if (data->trace_head == data->trace_tail &&
1161 data->trace_head_idx == data->trace_tail_idx) 1244 data->trace_head_idx == data->trace_tail_idx)
1162 data->trace_idx = 0; 1245 data->trace_idx = 0;
1163}
1164
1165static void *find_next_entry_inc(struct trace_iterator *iter)
1166{
1167 struct trace_entry *next;
1168 int next_cpu = -1;
1169
1170 next = find_next_entry(iter, &next_cpu);
1171
1172 iter->prev_ent = iter->ent;
1173 iter->prev_cpu = iter->cpu;
1174
1175 iter->ent = next;
1176 iter->cpu = next_cpu;
1177
1178 if (next)
1179 trace_iterator_increment(iter);
1180 1246
1181 return next ? iter : NULL; 1247 ent = trace_entry_idx(iter->tr, iter->tr->data[iter->cpu],
1248 iter, iter->cpu);
1249 if (ent && ent->type == TRACE_CONT)
1250 goto again;
1182} 1251}
1183 1252
1184static void *s_next(struct seq_file *m, void *v, loff_t *pos) 1253static void *s_next(struct seq_file *m, void *v, loff_t *pos)
@@ -1473,6 +1542,26 @@ lat_print_timestamp(struct trace_seq *s, unsigned long long abs_usecs,
1473 1542
1474static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; 1543static const char state_to_char[] = TASK_STATE_TO_CHAR_STR;
1475 1544
1545static void
1546trace_seq_print_cont(struct trace_seq *s, struct trace_iterator *iter)
1547{
1548 struct trace_array *tr = iter->tr;
1549 struct trace_array_cpu *data = tr->data[iter->cpu];
1550 struct trace_entry *ent;
1551
1552 ent = trace_entry_idx(tr, data, iter, iter->cpu);
1553 if (!ent || ent->type != TRACE_CONT) {
1554 trace_seq_putc(s, '\n');
1555 return;
1556 }
1557
1558 do {
1559 trace_seq_printf(s, "%s", ent->cont.buf);
1560 trace_iterator_increment(iter, iter->cpu);
1561 ent = trace_entry_idx(tr, data, iter, iter->cpu);
1562 } while (ent && ent->type == TRACE_CONT);
1563}
1564
1476static int 1565static int
1477print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) 1566print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1478{ 1567{
@@ -1491,6 +1580,10 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1491 1580
1492 if (!next_entry) 1581 if (!next_entry)
1493 next_entry = entry; 1582 next_entry = entry;
1583
1584 if (entry->type == TRACE_CONT)
1585 return 1;
1586
1494 rel_usecs = ns2usecs(next_entry->field.t - entry->field.t); 1587 rel_usecs = ns2usecs(next_entry->field.t - entry->field.t);
1495 abs_usecs = ns2usecs(entry->field.t - iter->tr->time_start); 1588 abs_usecs = ns2usecs(entry->field.t - iter->tr->time_start);
1496 1589
@@ -1550,6 +1643,12 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu)
1550 } 1643 }
1551 trace_seq_puts(s, "\n"); 1644 trace_seq_puts(s, "\n");
1552 break; 1645 break;
1646 case TRACE_PRINT:
1647 seq_print_ip_sym(s, field->print.ip, sym_flags);
1648 trace_seq_printf(s, ": %s", field->print.buf);
1649 if (field->flags && TRACE_FLAG_CONT)
1650 trace_seq_print_cont(s, iter);
1651 break;
1553 default: 1652 default:
1554 trace_seq_printf(s, "Unknown type %d\n", entry->type); 1653 trace_seq_printf(s, "Unknown type %d\n", entry->type);
1555 } 1654 }
@@ -1571,6 +1670,10 @@ static int print_trace_fmt(struct trace_iterator *iter)
1571 int i; 1670 int i;
1572 1671
1573 entry = iter->ent; 1672 entry = iter->ent;
1673
1674 if (entry->type == TRACE_CONT)
1675 return 1;
1676
1574 field = &entry->field; 1677 field = &entry->field;
1575 1678
1576 comm = trace_find_cmdline(iter->ent->field.pid); 1679 comm = trace_find_cmdline(iter->ent->field.pid);
@@ -1653,6 +1756,12 @@ static int print_trace_fmt(struct trace_iterator *iter)
1653 if (!ret) 1756 if (!ret)
1654 return 0; 1757 return 0;
1655 break; 1758 break;
1759 case TRACE_PRINT:
1760 seq_print_ip_sym(s, field->print.ip, sym_flags);
1761 trace_seq_printf(s, ": %s", field->print.buf);
1762 if (field->flags && TRACE_FLAG_CONT)
1763 trace_seq_print_cont(s, iter);
1764 break;
1656 } 1765 }
1657 return 1; 1766 return 1;
1658} 1767}
@@ -1666,6 +1775,10 @@ static int print_raw_fmt(struct trace_iterator *iter)
1666 int S, T; 1775 int S, T;
1667 1776
1668 entry = iter->ent; 1777 entry = iter->ent;
1778
1779 if (entry->type == TRACE_CONT)
1780 return 1;
1781
1669 field = &entry->field; 1782 field = &entry->field;
1670 1783
1671 ret = trace_seq_printf(s, "%d %d %llu ", 1784 ret = trace_seq_printf(s, "%d %d %llu ",
@@ -1708,6 +1821,12 @@ static int print_raw_fmt(struct trace_iterator *iter)
1708 if (!ret) 1821 if (!ret)
1709 return 0; 1822 return 0;
1710 break; 1823 break;
1824 case TRACE_PRINT:
1825 trace_seq_printf(s, "# %lx %s",
1826 field->print.ip, field->print.buf);
1827 if (field->flags && TRACE_FLAG_CONT)
1828 trace_seq_print_cont(s, iter);
1829 break;
1711 } 1830 }
1712 return 1; 1831 return 1;
1713} 1832}
@@ -1733,6 +1852,10 @@ static int print_hex_fmt(struct trace_iterator *iter)
1733 int S, T; 1852 int S, T;
1734 1853
1735 entry = iter->ent; 1854 entry = iter->ent;
1855
1856 if (entry->type == TRACE_CONT)
1857 return 1;
1858
1736 field = &entry->field; 1859 field = &entry->field;
1737 1860
1738 SEQ_PUT_HEX_FIELD_RET(s, field->pid); 1861 SEQ_PUT_HEX_FIELD_RET(s, field->pid);
@@ -1778,6 +1901,10 @@ static int print_bin_fmt(struct trace_iterator *iter)
1778 struct trace_field *field; 1901 struct trace_field *field;
1779 1902
1780 entry = iter->ent; 1903 entry = iter->ent;
1904
1905 if (entry->type == TRACE_CONT)
1906 return 1;
1907
1781 field = &entry->field; 1908 field = &entry->field;
1782 1909
1783 SEQ_PUT_FIELD_RET(s, field->pid); 1910 SEQ_PUT_FIELD_RET(s, field->pid);
@@ -2943,6 +3070,94 @@ static __init void tracer_init_debugfs(void)
2943#endif 3070#endif
2944} 3071}
2945 3072
3073#define TRACE_BUF_SIZE 1024
3074#define TRACE_PRINT_BUF_SIZE \
3075 (sizeof(struct trace_field) - offsetof(struct trace_field, print.buf))
3076#define TRACE_CONT_BUF_SIZE sizeof(struct trace_field)
3077
3078/**
3079 * ftrace_printk - printf formatting in the ftrace buffer
3080 * @fmt - the printf format for printing.
3081 *
3082 * Note: __ftrace_printk is an internal function for ftrace_printk and
3083 * the @ip is passed in via the ftrace_printk macro.
3084 *
3085 * This function allows a kernel developer to debug fast path sections
3086 * that printk is not appropriate for. By scattering in various
3087 * printk like tracing in the code, a developer can quickly see
3088 * where problems are occurring.
3089 *
3090 * This is intended as a debugging tool for the developer only.
3091 * Please reframe from leaving ftrace_printks scattered around in
3092 * your code.
3093 */
3094int __ftrace_printk(unsigned long ip, const char *fmt, ...)
3095{
3096 struct trace_array *tr = &global_trace;
3097 static DEFINE_SPINLOCK(trace_buf_lock);
3098 static char trace_buf[TRACE_BUF_SIZE];
3099 struct trace_array_cpu *data;
3100 struct trace_entry *entry;
3101 unsigned long flags;
3102 long disabled;
3103 va_list ap;
3104 int cpu, len = 0, write, written = 0;
3105
3106 if (likely(!ftrace_function_enabled))
3107 return 0;
3108
3109 local_irq_save(flags);
3110 cpu = raw_smp_processor_id();
3111 data = tr->data[cpu];
3112 disabled = atomic_inc_return(&data->disabled);
3113
3114 if (unlikely(disabled != 1 || !ftrace_function_enabled))
3115 goto out;
3116
3117 spin_lock(&trace_buf_lock);
3118 va_start(ap, fmt);
3119 len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, ap);
3120 va_end(ap);
3121
3122 len = min(len, TRACE_BUF_SIZE-1);
3123 trace_buf[len] = 0;
3124
3125 __raw_spin_lock(&data->lock);
3126 entry = tracing_get_trace_entry(tr, data);
3127 tracing_generic_entry_update(entry, flags);
3128 entry->type = TRACE_PRINT;
3129 entry->field.print.ip = ip;
3130
3131 write = min(len, (int)(TRACE_PRINT_BUF_SIZE-1));
3132
3133 memcpy(&entry->field.print.buf, trace_buf, write);
3134 entry->field.print.buf[write] = 0;
3135 written = write;
3136
3137 if (written != len)
3138 entry->field.flags |= TRACE_FLAG_CONT;
3139
3140 while (written != len) {
3141 entry = tracing_get_trace_entry(tr, data);
3142
3143 entry->type = TRACE_CONT;
3144 write = min(len - written, (int)(TRACE_CONT_BUF_SIZE-1));
3145 memcpy(&entry->cont.buf, trace_buf+written, write);
3146 entry->cont.buf[write] = 0;
3147 written += write;
3148 }
3149 __raw_spin_unlock(&data->lock);
3150
3151 spin_unlock(&trace_buf_lock);
3152
3153 out:
3154 atomic_dec(&data->disabled);
3155 local_irq_restore(flags);
3156
3157 return len;
3158}
3159EXPORT_SYMBOL_GPL(__ftrace_printk);
3160
2946static int trace_alloc_page(void) 3161static int trace_alloc_page(void)
2947{ 3162{
2948 struct trace_array_cpu *data; 3163 struct trace_array_cpu *data;