diff options
-rw-r--r-- | kernel/trace/blktrace.c | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index c103b0c20022..947c5b3f90c4 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -59,22 +59,39 @@ static void trace_note(struct blk_trace *bt, pid_t pid, int action, | |||
59 | const void *data, size_t len) | 59 | const void *data, size_t len) |
60 | { | 60 | { |
61 | struct blk_io_trace *t; | 61 | struct blk_io_trace *t; |
62 | struct ring_buffer_event *event = NULL; | ||
63 | int pc = 0; | ||
64 | int cpu = smp_processor_id(); | ||
65 | bool blk_tracer = blk_tracer_enabled; | ||
66 | |||
67 | if (blk_tracer) { | ||
68 | pc = preempt_count(); | ||
69 | event = trace_buffer_lock_reserve(blk_tr, TRACE_BLK, | ||
70 | sizeof(*t) + len, | ||
71 | 0, pc); | ||
72 | if (!event) | ||
73 | return; | ||
74 | t = ring_buffer_event_data(event); | ||
75 | goto record_it; | ||
76 | } | ||
62 | 77 | ||
63 | if (!bt->rchan) | 78 | if (!bt->rchan) |
64 | return; | 79 | return; |
65 | 80 | ||
66 | t = relay_reserve(bt->rchan, sizeof(*t) + len); | 81 | t = relay_reserve(bt->rchan, sizeof(*t) + len); |
67 | if (t) { | 82 | if (t) { |
68 | const int cpu = smp_processor_id(); | ||
69 | |||
70 | t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; | 83 | t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; |
71 | t->time = ktime_to_ns(ktime_get()); | 84 | t->time = ktime_to_ns(ktime_get()); |
85 | record_it: | ||
72 | t->device = bt->dev; | 86 | t->device = bt->dev; |
73 | t->action = action; | 87 | t->action = action; |
74 | t->pid = pid; | 88 | t->pid = pid; |
75 | t->cpu = cpu; | 89 | t->cpu = cpu; |
76 | t->pdu_len = len; | 90 | t->pdu_len = len; |
77 | memcpy((void *) t + sizeof(*t), data, len); | 91 | memcpy((void *) t + sizeof(*t), data, len); |
92 | |||
93 | if (blk_tracer) | ||
94 | trace_buffer_unlock_commit(blk_tr, event, 0, pc); | ||
78 | } | 95 | } |
79 | } | 96 | } |
80 | 97 | ||
@@ -110,14 +127,8 @@ void __trace_note_message(struct blk_trace *bt, const char *fmt, ...) | |||
110 | unsigned long flags; | 127 | unsigned long flags; |
111 | char *buf; | 128 | char *buf; |
112 | 129 | ||
113 | if (blk_tracer_enabled) { | 130 | if (unlikely(bt->trace_state != Blktrace_running && |
114 | va_start(args, fmt); | 131 | !blk_tracer_enabled)) |
115 | ftrace_vprintk(fmt, args); | ||
116 | va_end(args); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | if (!bt->msg_data) | ||
121 | return; | 132 | return; |
122 | 133 | ||
123 | local_irq_save(flags); | 134 | local_irq_save(flags); |
@@ -168,9 +179,9 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, | |||
168 | unsigned long *sequence; | 179 | unsigned long *sequence; |
169 | pid_t pid; | 180 | pid_t pid; |
170 | int cpu, pc = 0; | 181 | int cpu, pc = 0; |
182 | bool blk_tracer = blk_tracer_enabled; | ||
171 | 183 | ||
172 | if (unlikely(bt->trace_state != Blktrace_running && | 184 | if (unlikely(bt->trace_state != Blktrace_running && !blk_tracer)) |
173 | !blk_tracer_enabled)) | ||
174 | return; | 185 | return; |
175 | 186 | ||
176 | what |= ddir_act[rw & WRITE]; | 187 | what |= ddir_act[rw & WRITE]; |
@@ -185,7 +196,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, | |||
185 | return; | 196 | return; |
186 | cpu = raw_smp_processor_id(); | 197 | cpu = raw_smp_processor_id(); |
187 | 198 | ||
188 | if (blk_tracer_enabled) { | 199 | if (blk_tracer) { |
189 | tracing_record_cmdline(current); | 200 | tracing_record_cmdline(current); |
190 | 201 | ||
191 | pc = preempt_count(); | 202 | pc = preempt_count(); |
@@ -235,7 +246,7 @@ record_it: | |||
235 | if (pdu_len) | 246 | if (pdu_len) |
236 | memcpy((void *) t + sizeof(*t), pdu_data, pdu_len); | 247 | memcpy((void *) t + sizeof(*t), pdu_data, pdu_len); |
237 | 248 | ||
238 | if (blk_tracer_enabled) { | 249 | if (blk_tracer) { |
239 | trace_buffer_unlock_commit(blk_tr, event, 0, pc); | 250 | trace_buffer_unlock_commit(blk_tr, event, 0, pc); |
240 | return; | 251 | return; |
241 | } | 252 | } |
@@ -922,6 +933,11 @@ static void fill_rwbs(char *rwbs, const struct blk_io_trace *t) | |||
922 | int i = 0; | 933 | int i = 0; |
923 | int tc = t->action >> BLK_TC_SHIFT; | 934 | int tc = t->action >> BLK_TC_SHIFT; |
924 | 935 | ||
936 | if (t->action == BLK_TN_MESSAGE) { | ||
937 | rwbs[i++] = 'N'; | ||
938 | goto out; | ||
939 | } | ||
940 | |||
925 | if (tc & BLK_TC_DISCARD) | 941 | if (tc & BLK_TC_DISCARD) |
926 | rwbs[i++] = 'D'; | 942 | rwbs[i++] = 'D'; |
927 | else if (tc & BLK_TC_WRITE) | 943 | else if (tc & BLK_TC_WRITE) |
@@ -939,7 +955,7 @@ static void fill_rwbs(char *rwbs, const struct blk_io_trace *t) | |||
939 | rwbs[i++] = 'S'; | 955 | rwbs[i++] = 'S'; |
940 | if (tc & BLK_TC_META) | 956 | if (tc & BLK_TC_META) |
941 | rwbs[i++] = 'M'; | 957 | rwbs[i++] = 'M'; |
942 | 958 | out: | |
943 | rwbs[i] = '\0'; | 959 | rwbs[i] = '\0'; |
944 | } | 960 | } |
945 | 961 | ||
@@ -1074,6 +1090,17 @@ static int blk_log_split(struct trace_seq *s, const struct trace_entry *ent) | |||
1074 | get_pdu_int(ent), cmd); | 1090 | get_pdu_int(ent), cmd); |
1075 | } | 1091 | } |
1076 | 1092 | ||
1093 | static int blk_log_msg(struct trace_seq *s, const struct trace_entry *ent) | ||
1094 | { | ||
1095 | int ret; | ||
1096 | const struct blk_io_trace *t = te_blk_io_trace(ent); | ||
1097 | |||
1098 | ret = trace_seq_putmem(s, t + 1, t->pdu_len); | ||
1099 | if (ret) | ||
1100 | return trace_seq_putc(s, '\n'); | ||
1101 | return ret; | ||
1102 | } | ||
1103 | |||
1077 | /* | 1104 | /* |
1078 | * struct tracer operations | 1105 | * struct tracer operations |
1079 | */ | 1106 | */ |
@@ -1146,6 +1173,13 @@ static enum print_line_t print_one_line(struct trace_iterator *iter, | |||
1146 | long_act = !!(trace_flags & TRACE_ITER_VERBOSE); | 1173 | long_act = !!(trace_flags & TRACE_ITER_VERBOSE); |
1147 | log_action = classic ? &blk_log_action_classic : &blk_log_action; | 1174 | log_action = classic ? &blk_log_action_classic : &blk_log_action; |
1148 | 1175 | ||
1176 | if (t->action == BLK_TN_MESSAGE) { | ||
1177 | ret = log_action(iter, long_act ? "message" : "m"); | ||
1178 | if (ret) | ||
1179 | ret = blk_log_msg(s, iter->ent); | ||
1180 | goto out; | ||
1181 | } | ||
1182 | |||
1149 | if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act))) | 1183 | if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act))) |
1150 | ret = trace_seq_printf(s, "Bad pc action %x\n", what); | 1184 | ret = trace_seq_printf(s, "Bad pc action %x\n", what); |
1151 | else { | 1185 | else { |
@@ -1153,7 +1187,7 @@ static enum print_line_t print_one_line(struct trace_iterator *iter, | |||
1153 | if (ret) | 1187 | if (ret) |
1154 | ret = what2act[what].print(s, iter->ent); | 1188 | ret = what2act[what].print(s, iter->ent); |
1155 | } | 1189 | } |
1156 | 1190 | out: | |
1157 | return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; | 1191 | return ret ? TRACE_TYPE_HANDLED : TRACE_TYPE_PARTIAL_LINE; |
1158 | } | 1192 | } |
1159 | 1193 | ||
@@ -1253,11 +1287,16 @@ static int blk_trace_remove_queue(struct request_queue *q) | |||
1253 | static int blk_trace_setup_queue(struct request_queue *q, dev_t dev) | 1287 | static int blk_trace_setup_queue(struct request_queue *q, dev_t dev) |
1254 | { | 1288 | { |
1255 | struct blk_trace *old_bt, *bt = NULL; | 1289 | struct blk_trace *old_bt, *bt = NULL; |
1290 | int ret = -ENOMEM; | ||
1256 | 1291 | ||
1257 | bt = kzalloc(sizeof(*bt), GFP_KERNEL); | 1292 | bt = kzalloc(sizeof(*bt), GFP_KERNEL); |
1258 | if (!bt) | 1293 | if (!bt) |
1259 | return -ENOMEM; | 1294 | return -ENOMEM; |
1260 | 1295 | ||
1296 | bt->msg_data = __alloc_percpu(BLK_TN_MAX_MSG, __alignof__(char)); | ||
1297 | if (!bt->msg_data) | ||
1298 | goto free_bt; | ||
1299 | |||
1261 | bt->dev = dev; | 1300 | bt->dev = dev; |
1262 | bt->act_mask = (u16)-1; | 1301 | bt->act_mask = (u16)-1; |
1263 | bt->end_lba = -1ULL; | 1302 | bt->end_lba = -1ULL; |
@@ -1265,14 +1304,17 @@ static int blk_trace_setup_queue(struct request_queue *q, dev_t dev) | |||
1265 | old_bt = xchg(&q->blk_trace, bt); | 1304 | old_bt = xchg(&q->blk_trace, bt); |
1266 | if (old_bt != NULL) { | 1305 | if (old_bt != NULL) { |
1267 | (void)xchg(&q->blk_trace, old_bt); | 1306 | (void)xchg(&q->blk_trace, old_bt); |
1268 | kfree(bt); | 1307 | ret = -EBUSY; |
1269 | return -EBUSY; | 1308 | goto free_bt; |
1270 | } | 1309 | } |
1271 | 1310 | ||
1272 | if (atomic_inc_return(&blk_probes_ref) == 1) | 1311 | if (atomic_inc_return(&blk_probes_ref) == 1) |
1273 | blk_register_tracepoints(); | 1312 | blk_register_tracepoints(); |
1274 | |||
1275 | return 0; | 1313 | return 0; |
1314 | |||
1315 | free_bt: | ||
1316 | blk_trace_free(bt); | ||
1317 | return ret; | ||
1276 | } | 1318 | } |
1277 | 1319 | ||
1278 | /* | 1320 | /* |