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 | /* | 
