diff options
Diffstat (limited to 'kernel/trace/blktrace.c')
-rw-r--r-- | kernel/trace/blktrace.c | 272 |
1 files changed, 229 insertions, 43 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 921ef5d1f0b..7bd6a9893c2 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c | |||
@@ -23,10 +23,14 @@ | |||
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
26 | #include <trace/block.h> | ||
27 | #include <linux/uaccess.h> | 26 | #include <linux/uaccess.h> |
27 | |||
28 | #include <trace/events/block.h> | ||
29 | |||
28 | #include "trace_output.h" | 30 | #include "trace_output.h" |
29 | 31 | ||
32 | #ifdef CONFIG_BLK_DEV_IO_TRACE | ||
33 | |||
30 | static unsigned int blktrace_seq __read_mostly = 1; | 34 | static unsigned int blktrace_seq __read_mostly = 1; |
31 | 35 | ||
32 | static struct trace_array *blk_tr; | 36 | static struct trace_array *blk_tr; |
@@ -147,7 +151,7 @@ static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, | |||
147 | { | 151 | { |
148 | if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0) | 152 | if (((bt->act_mask << BLK_TC_SHIFT) & what) == 0) |
149 | return 1; | 153 | return 1; |
150 | if (sector < bt->start_lba || sector > bt->end_lba) | 154 | if (sector && (sector < bt->start_lba || sector > bt->end_lba)) |
151 | return 1; | 155 | return 1; |
152 | if (bt->pid && pid != bt->pid) | 156 | if (bt->pid && pid != bt->pid) |
153 | return 1; | 157 | return 1; |
@@ -192,7 +196,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, | |||
192 | what |= MASK_TC_BIT(rw, DISCARD); | 196 | what |= MASK_TC_BIT(rw, DISCARD); |
193 | 197 | ||
194 | pid = tsk->pid; | 198 | pid = tsk->pid; |
195 | if (unlikely(act_log_check(bt, what, sector, pid))) | 199 | if (act_log_check(bt, what, sector, pid)) |
196 | return; | 200 | return; |
197 | cpu = raw_smp_processor_id(); | 201 | cpu = raw_smp_processor_id(); |
198 | 202 | ||
@@ -262,6 +266,7 @@ static void blk_trace_free(struct blk_trace *bt) | |||
262 | { | 266 | { |
263 | debugfs_remove(bt->msg_file); | 267 | debugfs_remove(bt->msg_file); |
264 | debugfs_remove(bt->dropped_file); | 268 | debugfs_remove(bt->dropped_file); |
269 | debugfs_remove(bt->dir); | ||
265 | relay_close(bt->rchan); | 270 | relay_close(bt->rchan); |
266 | free_percpu(bt->sequence); | 271 | free_percpu(bt->sequence); |
267 | free_percpu(bt->msg_data); | 272 | free_percpu(bt->msg_data); |
@@ -403,11 +408,29 @@ static struct rchan_callbacks blk_relay_callbacks = { | |||
403 | .remove_buf_file = blk_remove_buf_file_callback, | 408 | .remove_buf_file = blk_remove_buf_file_callback, |
404 | }; | 409 | }; |
405 | 410 | ||
411 | static void blk_trace_setup_lba(struct blk_trace *bt, | ||
412 | struct block_device *bdev) | ||
413 | { | ||
414 | struct hd_struct *part = NULL; | ||
415 | |||
416 | if (bdev) | ||
417 | part = bdev->bd_part; | ||
418 | |||
419 | if (part) { | ||
420 | bt->start_lba = part->start_sect; | ||
421 | bt->end_lba = part->start_sect + part->nr_sects; | ||
422 | } else { | ||
423 | bt->start_lba = 0; | ||
424 | bt->end_lba = -1ULL; | ||
425 | } | ||
426 | } | ||
427 | |||
406 | /* | 428 | /* |
407 | * Setup everything required to start tracing | 429 | * Setup everything required to start tracing |
408 | */ | 430 | */ |
409 | int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | 431 | int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, |
410 | struct blk_user_trace_setup *buts) | 432 | struct block_device *bdev, |
433 | struct blk_user_trace_setup *buts) | ||
411 | { | 434 | { |
412 | struct blk_trace *old_bt, *bt = NULL; | 435 | struct blk_trace *old_bt, *bt = NULL; |
413 | struct dentry *dir = NULL; | 436 | struct dentry *dir = NULL; |
@@ -480,10 +503,13 @@ int do_blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |||
480 | if (!bt->act_mask) | 503 | if (!bt->act_mask) |
481 | bt->act_mask = (u16) -1; | 504 | bt->act_mask = (u16) -1; |
482 | 505 | ||
483 | bt->start_lba = buts->start_lba; | 506 | blk_trace_setup_lba(bt, bdev); |
484 | bt->end_lba = buts->end_lba; | 507 | |
485 | if (!bt->end_lba) | 508 | /* overwrite with user settings */ |
486 | bt->end_lba = -1ULL; | 509 | if (buts->start_lba) |
510 | bt->start_lba = buts->start_lba; | ||
511 | if (buts->end_lba) | ||
512 | bt->end_lba = buts->end_lba; | ||
487 | 513 | ||
488 | bt->pid = buts->pid; | 514 | bt->pid = buts->pid; |
489 | bt->trace_state = Blktrace_setup; | 515 | bt->trace_state = Blktrace_setup; |
@@ -505,6 +531,7 @@ err: | |||
505 | } | 531 | } |
506 | 532 | ||
507 | int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | 533 | int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, |
534 | struct block_device *bdev, | ||
508 | char __user *arg) | 535 | char __user *arg) |
509 | { | 536 | { |
510 | struct blk_user_trace_setup buts; | 537 | struct blk_user_trace_setup buts; |
@@ -514,7 +541,7 @@ int blk_trace_setup(struct request_queue *q, char *name, dev_t dev, | |||
514 | if (ret) | 541 | if (ret) |
515 | return -EFAULT; | 542 | return -EFAULT; |
516 | 543 | ||
517 | ret = do_blk_trace_setup(q, name, dev, &buts); | 544 | ret = do_blk_trace_setup(q, name, dev, bdev, &buts); |
518 | if (ret) | 545 | if (ret) |
519 | return ret; | 546 | return ret; |
520 | 547 | ||
@@ -582,7 +609,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) | |||
582 | switch (cmd) { | 609 | switch (cmd) { |
583 | case BLKTRACESETUP: | 610 | case BLKTRACESETUP: |
584 | bdevname(bdev, b); | 611 | bdevname(bdev, b); |
585 | ret = blk_trace_setup(q, b, bdev->bd_dev, arg); | 612 | ret = blk_trace_setup(q, b, bdev->bd_dev, bdev, arg); |
586 | break; | 613 | break; |
587 | case BLKTRACESTART: | 614 | case BLKTRACESTART: |
588 | start = 1; | 615 | start = 1; |
@@ -809,7 +836,6 @@ static void blk_add_trace_split(struct request_queue *q, struct bio *bio, | |||
809 | * @bio: the source bio | 836 | * @bio: the source bio |
810 | * @dev: target device | 837 | * @dev: target device |
811 | * @from: source sector | 838 | * @from: source sector |
812 | * @to: target sector | ||
813 | * | 839 | * |
814 | * Description: | 840 | * Description: |
815 | * Device mapper or raid target sometimes need to split a bio because | 841 | * Device mapper or raid target sometimes need to split a bio because |
@@ -817,7 +843,7 @@ static void blk_add_trace_split(struct request_queue *q, struct bio *bio, | |||
817 | * | 843 | * |
818 | **/ | 844 | **/ |
819 | static void blk_add_trace_remap(struct request_queue *q, struct bio *bio, | 845 | static void blk_add_trace_remap(struct request_queue *q, struct bio *bio, |
820 | dev_t dev, sector_t from, sector_t to) | 846 | dev_t dev, sector_t from) |
821 | { | 847 | { |
822 | struct blk_trace *bt = q->blk_trace; | 848 | struct blk_trace *bt = q->blk_trace; |
823 | struct blk_io_trace_remap r; | 849 | struct blk_io_trace_remap r; |
@@ -825,12 +851,13 @@ static void blk_add_trace_remap(struct request_queue *q, struct bio *bio, | |||
825 | if (likely(!bt)) | 851 | if (likely(!bt)) |
826 | return; | 852 | return; |
827 | 853 | ||
828 | r.device = cpu_to_be32(dev); | 854 | r.device_from = cpu_to_be32(dev); |
829 | r.device_from = cpu_to_be32(bio->bi_bdev->bd_dev); | 855 | r.device_to = cpu_to_be32(bio->bi_bdev->bd_dev); |
830 | r.sector = cpu_to_be64(to); | 856 | r.sector_from = cpu_to_be64(from); |
831 | 857 | ||
832 | __blk_add_trace(bt, from, bio->bi_size, bio->bi_rw, BLK_TA_REMAP, | 858 | __blk_add_trace(bt, bio->bi_sector, bio->bi_size, bio->bi_rw, |
833 | !bio_flagged(bio, BIO_UPTODATE), sizeof(r), &r); | 859 | BLK_TA_REMAP, !bio_flagged(bio, BIO_UPTODATE), |
860 | sizeof(r), &r); | ||
834 | } | 861 | } |
835 | 862 | ||
836 | /** | 863 | /** |
@@ -971,6 +998,16 @@ static inline const void *pdu_start(const struct trace_entry *ent) | |||
971 | return te_blk_io_trace(ent) + 1; | 998 | return te_blk_io_trace(ent) + 1; |
972 | } | 999 | } |
973 | 1000 | ||
1001 | static inline u32 t_action(const struct trace_entry *ent) | ||
1002 | { | ||
1003 | return te_blk_io_trace(ent)->action; | ||
1004 | } | ||
1005 | |||
1006 | static inline u32 t_bytes(const struct trace_entry *ent) | ||
1007 | { | ||
1008 | return te_blk_io_trace(ent)->bytes; | ||
1009 | } | ||
1010 | |||
974 | static inline u32 t_sec(const struct trace_entry *ent) | 1011 | static inline u32 t_sec(const struct trace_entry *ent) |
975 | { | 1012 | { |
976 | return te_blk_io_trace(ent)->bytes >> 9; | 1013 | return te_blk_io_trace(ent)->bytes >> 9; |
@@ -996,11 +1033,11 @@ static void get_pdu_remap(const struct trace_entry *ent, | |||
996 | struct blk_io_trace_remap *r) | 1033 | struct blk_io_trace_remap *r) |
997 | { | 1034 | { |
998 | const struct blk_io_trace_remap *__r = pdu_start(ent); | 1035 | const struct blk_io_trace_remap *__r = pdu_start(ent); |
999 | __u64 sector = __r->sector; | 1036 | __u64 sector_from = __r->sector_from; |
1000 | 1037 | ||
1001 | r->device = be32_to_cpu(__r->device); | ||
1002 | r->device_from = be32_to_cpu(__r->device_from); | 1038 | r->device_from = be32_to_cpu(__r->device_from); |
1003 | r->sector = be64_to_cpu(sector); | 1039 | r->device_to = be32_to_cpu(__r->device_to); |
1040 | r->sector_from = be64_to_cpu(sector_from); | ||
1004 | } | 1041 | } |
1005 | 1042 | ||
1006 | typedef int (blk_log_action_t) (struct trace_iterator *iter, const char *act); | 1043 | typedef int (blk_log_action_t) (struct trace_iterator *iter, const char *act); |
@@ -1031,36 +1068,98 @@ static int blk_log_action(struct trace_iterator *iter, const char *act) | |||
1031 | MAJOR(t->device), MINOR(t->device), act, rwbs); | 1068 | MAJOR(t->device), MINOR(t->device), act, rwbs); |
1032 | } | 1069 | } |
1033 | 1070 | ||
1071 | static int blk_log_dump_pdu(struct trace_seq *s, const struct trace_entry *ent) | ||
1072 | { | ||
1073 | const unsigned char *pdu_buf; | ||
1074 | int pdu_len; | ||
1075 | int i, end, ret; | ||
1076 | |||
1077 | pdu_buf = pdu_start(ent); | ||
1078 | pdu_len = te_blk_io_trace(ent)->pdu_len; | ||
1079 | |||
1080 | if (!pdu_len) | ||
1081 | return 1; | ||
1082 | |||
1083 | /* find the last zero that needs to be printed */ | ||
1084 | for (end = pdu_len - 1; end >= 0; end--) | ||
1085 | if (pdu_buf[end]) | ||
1086 | break; | ||
1087 | end++; | ||
1088 | |||
1089 | if (!trace_seq_putc(s, '(')) | ||
1090 | return 0; | ||
1091 | |||
1092 | for (i = 0; i < pdu_len; i++) { | ||
1093 | |||
1094 | ret = trace_seq_printf(s, "%s%02x", | ||
1095 | i == 0 ? "" : " ", pdu_buf[i]); | ||
1096 | if (!ret) | ||
1097 | return ret; | ||
1098 | |||
1099 | /* | ||
1100 | * stop when the rest is just zeroes and indicate so | ||
1101 | * with a ".." appended | ||
1102 | */ | ||
1103 | if (i == end && end != pdu_len - 1) | ||
1104 | return trace_seq_puts(s, " ..) "); | ||
1105 | } | ||
1106 | |||
1107 | return trace_seq_puts(s, ") "); | ||
1108 | } | ||
1109 | |||
1034 | static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent) | 1110 | static int blk_log_generic(struct trace_seq *s, const struct trace_entry *ent) |
1035 | { | 1111 | { |
1036 | char cmd[TASK_COMM_LEN]; | 1112 | char cmd[TASK_COMM_LEN]; |
1037 | 1113 | ||
1038 | trace_find_cmdline(ent->pid, cmd); | 1114 | trace_find_cmdline(ent->pid, cmd); |
1039 | 1115 | ||
1040 | if (t_sec(ent)) | 1116 | if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) { |
1041 | return trace_seq_printf(s, "%llu + %u [%s]\n", | 1117 | int ret; |
1042 | t_sector(ent), t_sec(ent), cmd); | 1118 | |
1043 | return trace_seq_printf(s, "[%s]\n", cmd); | 1119 | ret = trace_seq_printf(s, "%u ", t_bytes(ent)); |
1120 | if (!ret) | ||
1121 | return 0; | ||
1122 | ret = blk_log_dump_pdu(s, ent); | ||
1123 | if (!ret) | ||
1124 | return 0; | ||
1125 | return trace_seq_printf(s, "[%s]\n", cmd); | ||
1126 | } else { | ||
1127 | if (t_sec(ent)) | ||
1128 | return trace_seq_printf(s, "%llu + %u [%s]\n", | ||
1129 | t_sector(ent), t_sec(ent), cmd); | ||
1130 | return trace_seq_printf(s, "[%s]\n", cmd); | ||
1131 | } | ||
1044 | } | 1132 | } |
1045 | 1133 | ||
1046 | static int blk_log_with_error(struct trace_seq *s, | 1134 | static int blk_log_with_error(struct trace_seq *s, |
1047 | const struct trace_entry *ent) | 1135 | const struct trace_entry *ent) |
1048 | { | 1136 | { |
1049 | if (t_sec(ent)) | 1137 | if (t_action(ent) & BLK_TC_ACT(BLK_TC_PC)) { |
1050 | return trace_seq_printf(s, "%llu + %u [%d]\n", t_sector(ent), | 1138 | int ret; |
1051 | t_sec(ent), t_error(ent)); | 1139 | |
1052 | return trace_seq_printf(s, "%llu [%d]\n", t_sector(ent), t_error(ent)); | 1140 | ret = blk_log_dump_pdu(s, ent); |
1141 | if (ret) | ||
1142 | return trace_seq_printf(s, "[%d]\n", t_error(ent)); | ||
1143 | return 0; | ||
1144 | } else { | ||
1145 | if (t_sec(ent)) | ||
1146 | return trace_seq_printf(s, "%llu + %u [%d]\n", | ||
1147 | t_sector(ent), | ||
1148 | t_sec(ent), t_error(ent)); | ||
1149 | return trace_seq_printf(s, "%llu [%d]\n", | ||
1150 | t_sector(ent), t_error(ent)); | ||
1151 | } | ||
1053 | } | 1152 | } |
1054 | 1153 | ||
1055 | static int blk_log_remap(struct trace_seq *s, const struct trace_entry *ent) | 1154 | static int blk_log_remap(struct trace_seq *s, const struct trace_entry *ent) |
1056 | { | 1155 | { |
1057 | struct blk_io_trace_remap r = { .device = 0, }; | 1156 | struct blk_io_trace_remap r = { .device_from = 0, }; |
1058 | 1157 | ||
1059 | get_pdu_remap(ent, &r); | 1158 | get_pdu_remap(ent, &r); |
1060 | return trace_seq_printf(s, "%llu + %u <- (%d,%d) %llu\n", | 1159 | return trace_seq_printf(s, "%llu + %u <- (%d,%d) %llu\n", |
1061 | t_sector(ent), | 1160 | t_sector(ent), t_sec(ent), |
1062 | t_sec(ent), MAJOR(r.device), MINOR(r.device), | 1161 | MAJOR(r.device_from), MINOR(r.device_from), |
1063 | (unsigned long long)r.sector); | 1162 | (unsigned long long)r.sector_from); |
1064 | } | 1163 | } |
1065 | 1164 | ||
1066 | static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent) | 1165 | static int blk_log_plug(struct trace_seq *s, const struct trace_entry *ent) |
@@ -1117,7 +1216,6 @@ static void blk_tracer_print_header(struct seq_file *m) | |||
1117 | static void blk_tracer_start(struct trace_array *tr) | 1216 | static void blk_tracer_start(struct trace_array *tr) |
1118 | { | 1217 | { |
1119 | blk_tracer_enabled = true; | 1218 | blk_tracer_enabled = true; |
1120 | trace_flags &= ~TRACE_ITER_CONTEXT_INFO; | ||
1121 | } | 1219 | } |
1122 | 1220 | ||
1123 | static int blk_tracer_init(struct trace_array *tr) | 1221 | static int blk_tracer_init(struct trace_array *tr) |
@@ -1130,7 +1228,6 @@ static int blk_tracer_init(struct trace_array *tr) | |||
1130 | static void blk_tracer_stop(struct trace_array *tr) | 1228 | static void blk_tracer_stop(struct trace_array *tr) |
1131 | { | 1229 | { |
1132 | blk_tracer_enabled = false; | 1230 | blk_tracer_enabled = false; |
1133 | trace_flags |= TRACE_ITER_CONTEXT_INFO; | ||
1134 | } | 1231 | } |
1135 | 1232 | ||
1136 | static void blk_tracer_reset(struct trace_array *tr) | 1233 | static void blk_tracer_reset(struct trace_array *tr) |
@@ -1182,7 +1279,7 @@ static enum print_line_t print_one_line(struct trace_iterator *iter, | |||
1182 | } | 1279 | } |
1183 | 1280 | ||
1184 | if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act))) | 1281 | if (unlikely(what == 0 || what >= ARRAY_SIZE(what2act))) |
1185 | ret = trace_seq_printf(s, "Bad pc action %x\n", what); | 1282 | ret = trace_seq_printf(s, "Unknown action %x\n", what); |
1186 | else { | 1283 | else { |
1187 | ret = log_action(iter, what2act[what].act[long_act]); | 1284 | ret = log_action(iter, what2act[what].act[long_act]); |
1188 | if (ret) | 1285 | if (ret) |
@@ -1195,9 +1292,6 @@ out: | |||
1195 | static enum print_line_t blk_trace_event_print(struct trace_iterator *iter, | 1292 | static enum print_line_t blk_trace_event_print(struct trace_iterator *iter, |
1196 | int flags) | 1293 | int flags) |
1197 | { | 1294 | { |
1198 | if (!trace_print_context(iter)) | ||
1199 | return TRACE_TYPE_PARTIAL_LINE; | ||
1200 | |||
1201 | return print_one_line(iter, false); | 1295 | return print_one_line(iter, false); |
1202 | } | 1296 | } |
1203 | 1297 | ||
@@ -1232,6 +1326,18 @@ static enum print_line_t blk_tracer_print_line(struct trace_iterator *iter) | |||
1232 | return print_one_line(iter, true); | 1326 | return print_one_line(iter, true); |
1233 | } | 1327 | } |
1234 | 1328 | ||
1329 | static int blk_tracer_set_flag(u32 old_flags, u32 bit, int set) | ||
1330 | { | ||
1331 | /* don't output context-info for blk_classic output */ | ||
1332 | if (bit == TRACE_BLK_OPT_CLASSIC) { | ||
1333 | if (set) | ||
1334 | trace_flags &= ~TRACE_ITER_CONTEXT_INFO; | ||
1335 | else | ||
1336 | trace_flags |= TRACE_ITER_CONTEXT_INFO; | ||
1337 | } | ||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1235 | static struct tracer blk_tracer __read_mostly = { | 1341 | static struct tracer blk_tracer __read_mostly = { |
1236 | .name = "blk", | 1342 | .name = "blk", |
1237 | .init = blk_tracer_init, | 1343 | .init = blk_tracer_init, |
@@ -1241,6 +1347,7 @@ static struct tracer blk_tracer __read_mostly = { | |||
1241 | .print_header = blk_tracer_print_header, | 1347 | .print_header = blk_tracer_print_header, |
1242 | .print_line = blk_tracer_print_line, | 1348 | .print_line = blk_tracer_print_line, |
1243 | .flags = &blk_tracer_flags, | 1349 | .flags = &blk_tracer_flags, |
1350 | .set_flag = blk_tracer_set_flag, | ||
1244 | }; | 1351 | }; |
1245 | 1352 | ||
1246 | static struct trace_event trace_blk_event = { | 1353 | static struct trace_event trace_blk_event = { |
@@ -1285,7 +1392,8 @@ static int blk_trace_remove_queue(struct request_queue *q) | |||
1285 | /* | 1392 | /* |
1286 | * Setup everything required to start tracing | 1393 | * Setup everything required to start tracing |
1287 | */ | 1394 | */ |
1288 | static int blk_trace_setup_queue(struct request_queue *q, dev_t dev) | 1395 | static int blk_trace_setup_queue(struct request_queue *q, |
1396 | struct block_device *bdev) | ||
1289 | { | 1397 | { |
1290 | struct blk_trace *old_bt, *bt = NULL; | 1398 | struct blk_trace *old_bt, *bt = NULL; |
1291 | int ret = -ENOMEM; | 1399 | int ret = -ENOMEM; |
@@ -1298,9 +1406,10 @@ static int blk_trace_setup_queue(struct request_queue *q, dev_t dev) | |||
1298 | if (!bt->msg_data) | 1406 | if (!bt->msg_data) |
1299 | goto free_bt; | 1407 | goto free_bt; |
1300 | 1408 | ||
1301 | bt->dev = dev; | 1409 | bt->dev = bdev->bd_dev; |
1302 | bt->act_mask = (u16)-1; | 1410 | bt->act_mask = (u16)-1; |
1303 | bt->end_lba = -1ULL; | 1411 | |
1412 | blk_trace_setup_lba(bt, bdev); | ||
1304 | 1413 | ||
1305 | old_bt = xchg(&q->blk_trace, bt); | 1414 | old_bt = xchg(&q->blk_trace, bt); |
1306 | if (old_bt != NULL) { | 1415 | if (old_bt != NULL) { |
@@ -1517,7 +1626,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, | |||
1517 | 1626 | ||
1518 | if (attr == &dev_attr_enable) { | 1627 | if (attr == &dev_attr_enable) { |
1519 | if (value) | 1628 | if (value) |
1520 | ret = blk_trace_setup_queue(q, bdev->bd_dev); | 1629 | ret = blk_trace_setup_queue(q, bdev); |
1521 | else | 1630 | else |
1522 | ret = blk_trace_remove_queue(q); | 1631 | ret = blk_trace_remove_queue(q); |
1523 | goto out_unlock_bdev; | 1632 | goto out_unlock_bdev; |
@@ -1525,7 +1634,7 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, | |||
1525 | 1634 | ||
1526 | ret = 0; | 1635 | ret = 0; |
1527 | if (q->blk_trace == NULL) | 1636 | if (q->blk_trace == NULL) |
1528 | ret = blk_trace_setup_queue(q, bdev->bd_dev); | 1637 | ret = blk_trace_setup_queue(q, bdev); |
1529 | 1638 | ||
1530 | if (ret == 0) { | 1639 | if (ret == 0) { |
1531 | if (attr == &dev_attr_act_mask) | 1640 | if (attr == &dev_attr_act_mask) |
@@ -1548,3 +1657,80 @@ out: | |||
1548 | return ret ? ret : count; | 1657 | return ret ? ret : count; |
1549 | } | 1658 | } |
1550 | 1659 | ||
1660 | int blk_trace_init_sysfs(struct device *dev) | ||
1661 | { | ||
1662 | return sysfs_create_group(&dev->kobj, &blk_trace_attr_group); | ||
1663 | } | ||
1664 | |||
1665 | #endif /* CONFIG_BLK_DEV_IO_TRACE */ | ||
1666 | |||
1667 | #ifdef CONFIG_EVENT_TRACING | ||
1668 | |||
1669 | void blk_dump_cmd(char *buf, struct request *rq) | ||
1670 | { | ||
1671 | int i, end; | ||
1672 | int len = rq->cmd_len; | ||
1673 | unsigned char *cmd = rq->cmd; | ||
1674 | |||
1675 | if (!blk_pc_request(rq)) { | ||
1676 | buf[0] = '\0'; | ||
1677 | return; | ||
1678 | } | ||
1679 | |||
1680 | for (end = len - 1; end >= 0; end--) | ||
1681 | if (cmd[end]) | ||
1682 | break; | ||
1683 | end++; | ||
1684 | |||
1685 | for (i = 0; i < len; i++) { | ||
1686 | buf += sprintf(buf, "%s%02x", i == 0 ? "" : " ", cmd[i]); | ||
1687 | if (i == end && end != len - 1) { | ||
1688 | sprintf(buf, " .."); | ||
1689 | break; | ||
1690 | } | ||
1691 | } | ||
1692 | } | ||
1693 | |||
1694 | void blk_fill_rwbs(char *rwbs, u32 rw, int bytes) | ||
1695 | { | ||
1696 | int i = 0; | ||
1697 | |||
1698 | if (rw & WRITE) | ||
1699 | rwbs[i++] = 'W'; | ||
1700 | else if (rw & 1 << BIO_RW_DISCARD) | ||
1701 | rwbs[i++] = 'D'; | ||
1702 | else if (bytes) | ||
1703 | rwbs[i++] = 'R'; | ||
1704 | else | ||
1705 | rwbs[i++] = 'N'; | ||
1706 | |||
1707 | if (rw & 1 << BIO_RW_AHEAD) | ||
1708 | rwbs[i++] = 'A'; | ||
1709 | if (rw & 1 << BIO_RW_BARRIER) | ||
1710 | rwbs[i++] = 'B'; | ||
1711 | if (rw & 1 << BIO_RW_SYNCIO) | ||
1712 | rwbs[i++] = 'S'; | ||
1713 | if (rw & 1 << BIO_RW_META) | ||
1714 | rwbs[i++] = 'M'; | ||
1715 | |||
1716 | rwbs[i] = '\0'; | ||
1717 | } | ||
1718 | |||
1719 | void blk_fill_rwbs_rq(char *rwbs, struct request *rq) | ||
1720 | { | ||
1721 | int rw = rq->cmd_flags & 0x03; | ||
1722 | int bytes; | ||
1723 | |||
1724 | if (blk_discard_rq(rq)) | ||
1725 | rw |= (1 << BIO_RW_DISCARD); | ||
1726 | |||
1727 | if (blk_pc_request(rq)) | ||
1728 | bytes = rq->data_len; | ||
1729 | else | ||
1730 | bytes = rq->hard_nr_sectors << 9; | ||
1731 | |||
1732 | blk_fill_rwbs(rwbs, rw, bytes); | ||
1733 | } | ||
1734 | |||
1735 | #endif /* CONFIG_EVENT_TRACING */ | ||
1736 | |||