diff options
Diffstat (limited to 'kernel/trace/blktrace.c')
| -rw-r--r-- | kernel/trace/blktrace.c | 285 |
1 files changed, 234 insertions, 51 deletions
diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 921ef5d1f0ba..39af8af6fc30 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; |
| @@ -642,12 +669,12 @@ static void blk_add_trace_rq(struct request_queue *q, struct request *rq, | |||
| 642 | 669 | ||
| 643 | if (blk_pc_request(rq)) { | 670 | if (blk_pc_request(rq)) { |
| 644 | what |= BLK_TC_ACT(BLK_TC_PC); | 671 | what |= BLK_TC_ACT(BLK_TC_PC); |
| 645 | __blk_add_trace(bt, 0, rq->data_len, rw, what, rq->errors, | 672 | __blk_add_trace(bt, 0, blk_rq_bytes(rq), rw, |
| 646 | rq->cmd_len, rq->cmd); | 673 | what, rq->errors, rq->cmd_len, rq->cmd); |
| 647 | } else { | 674 | } else { |
| 648 | what |= BLK_TC_ACT(BLK_TC_FS); | 675 | what |= BLK_TC_ACT(BLK_TC_FS); |
| 649 | __blk_add_trace(bt, rq->hard_sector, rq->hard_nr_sectors << 9, | 676 | __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), rw, |
| 650 | rw, what, rq->errors, 0, NULL); | 677 | what, rq->errors, 0, NULL); |
| 651 | } | 678 | } |
| 652 | } | 679 | } |
| 653 | 680 | ||
| @@ -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 | /** |
| @@ -854,11 +881,11 @@ void blk_add_driver_data(struct request_queue *q, | |||
| 854 | return; | 881 | return; |
| 855 | 882 | ||
| 856 | if (blk_pc_request(rq)) | 883 | if (blk_pc_request(rq)) |
| 857 | __blk_add_trace(bt, 0, rq->data_len, 0, BLK_TA_DRV_DATA, | 884 | __blk_add_trace(bt, 0, blk_rq_bytes(rq), 0, |
| 858 | rq->errors, len, data); | 885 | BLK_TA_DRV_DATA, rq->errors, len, data); |
| 859 | else | 886 | else |
| 860 | __blk_add_trace(bt, rq->hard_sector, rq->hard_nr_sectors << 9, | 887 | __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0, |
| 861 | 0, BLK_TA_DRV_DATA, rq->errors, len, data); | 888 | BLK_TA_DRV_DATA, rq->errors, len, data); |
| 862 | } | 889 | } |
| 863 | EXPORT_SYMBOL_GPL(blk_add_driver_data); | 890 | EXPORT_SYMBOL_GPL(blk_add_driver_data); |
| 864 | 891 | ||
| @@ -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,77 @@ 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 | bytes = blk_rq_bytes(rq); | ||
| 1728 | |||
| 1729 | blk_fill_rwbs(rwbs, rw, bytes); | ||
| 1730 | } | ||
| 1731 | |||
| 1732 | #endif /* CONFIG_EVENT_TRACING */ | ||
| 1733 | |||
