aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/blktrace.c80
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());
85record_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 958out:
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
1093static 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 1190out:
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)
1253static int blk_trace_setup_queue(struct request_queue *q, dev_t dev) 1287static 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
1315free_bt:
1316 blk_trace_free(bt);
1317 return ret;
1276} 1318}
1277 1319
1278/* 1320/*