diff options
author | Olaf Kirch <okir@suse.de> | 2006-12-01 04:39:12 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2006-12-01 04:39:12 -0500 |
commit | be1c63411addba3ad750eb4fdfc50b97bc82825e (patch) | |
tree | d00c889873310a5c6ee0caf79f2b70e64a382796 | |
parent | 0215ffb08ce99e2bb59eca114a99499a4d06e704 (diff) |
[PATCH] blktrace: add timestamp message
This adds a new timestamp message to blktrace, giving the timeofday when
we starting tracing. This helps user space correlate block trace events
with eg an application strace.
This requires a (compatible) update to blkparse. The changed blkparse
is still able to process traces generated by older kernels, and older
versions of blkparse should silently ignore the new records (because
they have a pid of 0).
Signed-off-by: Olaf Kirch <okir@suse.de>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | block/blktrace.c | 57 | ||||
-rw-r--r-- | include/linux/blktrace_api.h | 12 |
2 files changed, 57 insertions, 12 deletions
diff --git a/block/blktrace.c b/block/blktrace.c index 135593c8e45b..562ca7cbf858 100644 --- a/block/blktrace.c +++ b/block/blktrace.c | |||
@@ -22,30 +22,61 @@ | |||
22 | #include <linux/init.h> | 22 | #include <linux/init.h> |
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 <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | 27 | ||
27 | static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, }; | 28 | static DEFINE_PER_CPU(unsigned long long, blk_trace_cpu_offset) = { 0, }; |
28 | static unsigned int blktrace_seq __read_mostly = 1; | 29 | static unsigned int blktrace_seq __read_mostly = 1; |
29 | 30 | ||
30 | /* | 31 | /* |
32 | * Send out a notify message. | ||
33 | */ | ||
34 | static inline unsigned int trace_note(struct blk_trace *bt, | ||
35 | pid_t pid, int action, | ||
36 | const void *data, size_t len) | ||
37 | { | ||
38 | struct blk_io_trace *t; | ||
39 | int cpu = smp_processor_id(); | ||
40 | |||
41 | t = relay_reserve(bt->rchan, sizeof(*t) + len); | ||
42 | if (t == NULL) | ||
43 | return 0; | ||
44 | |||
45 | t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; | ||
46 | t->time = sched_clock() - per_cpu(blk_trace_cpu_offset, cpu); | ||
47 | t->device = bt->dev; | ||
48 | t->action = action; | ||
49 | t->pid = pid; | ||
50 | t->cpu = cpu; | ||
51 | t->pdu_len = len; | ||
52 | memcpy((void *) t + sizeof(*t), data, len); | ||
53 | return blktrace_seq; | ||
54 | } | ||
55 | |||
56 | /* | ||
31 | * Send out a notify for this process, if we haven't done so since a trace | 57 | * Send out a notify for this process, if we haven't done so since a trace |
32 | * started | 58 | * started |
33 | */ | 59 | */ |
34 | static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk) | 60 | static void trace_note_tsk(struct blk_trace *bt, struct task_struct *tsk) |
35 | { | 61 | { |
36 | struct blk_io_trace *t; | 62 | tsk->btrace_seq = trace_note(bt, tsk->pid, |
63 | BLK_TN_PROCESS, | ||
64 | tsk->comm, sizeof(tsk->comm)); | ||
65 | } | ||
37 | 66 | ||
38 | t = relay_reserve(bt->rchan, sizeof(*t) + sizeof(tsk->comm)); | 67 | static void trace_note_time(struct blk_trace *bt) |
39 | if (t) { | 68 | { |
40 | t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; | 69 | struct timespec now; |
41 | t->device = bt->dev; | 70 | unsigned long flags; |
42 | t->action = BLK_TC_ACT(BLK_TC_NOTIFY); | 71 | u32 words[2]; |
43 | t->pid = tsk->pid; | 72 | |
44 | t->cpu = smp_processor_id(); | 73 | getnstimeofday(&now); |
45 | t->pdu_len = sizeof(tsk->comm); | 74 | words[0] = now.tv_sec; |
46 | memcpy((void *) t + sizeof(*t), tsk->comm, t->pdu_len); | 75 | words[1] = now.tv_nsec; |
47 | tsk->btrace_seq = blktrace_seq; | 76 | |
48 | } | 77 | local_irq_save(flags); |
78 | trace_note(bt, 0, BLK_TN_TIMESTAMP, words, sizeof(words)); | ||
79 | local_irq_restore(flags); | ||
49 | } | 80 | } |
50 | 81 | ||
51 | static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, | 82 | static int act_log_check(struct blk_trace *bt, u32 what, sector_t sector, |
@@ -394,6 +425,8 @@ static int blk_trace_startstop(request_queue_t *q, int start) | |||
394 | blktrace_seq++; | 425 | blktrace_seq++; |
395 | smp_mb(); | 426 | smp_mb(); |
396 | bt->trace_state = Blktrace_running; | 427 | bt->trace_state = Blktrace_running; |
428 | |||
429 | trace_note_time(bt); | ||
397 | ret = 0; | 430 | ret = 0; |
398 | } | 431 | } |
399 | } else { | 432 | } else { |
diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index b99a714fcac6..3680ff9a30ed 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h | |||
@@ -50,6 +50,15 @@ enum blktrace_act { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Notify events. | ||
54 | */ | ||
55 | enum blktrace_notify { | ||
56 | __BLK_TN_PROCESS = 0, /* establish pid/name mapping */ | ||
57 | __BLK_TN_TIMESTAMP, /* include system clock */ | ||
58 | }; | ||
59 | |||
60 | |||
61 | /* | ||
53 | * Trace actions in full. Additionally, read or write is masked | 62 | * Trace actions in full. Additionally, read or write is masked |
54 | */ | 63 | */ |
55 | #define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE)) | 64 | #define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE)) |
@@ -68,6 +77,9 @@ enum blktrace_act { | |||
68 | #define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) | 77 | #define BLK_TA_BOUNCE (__BLK_TA_BOUNCE) |
69 | #define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) | 78 | #define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE)) |
70 | 79 | ||
80 | #define BLK_TN_PROCESS (__BLK_TN_PROCESS | BLK_TC_ACT(BLK_TC_NOTIFY)) | ||
81 | #define BLK_TN_TIMESTAMP (__BLK_TN_TIMESTAMP | BLK_TC_ACT(BLK_TC_NOTIFY)) | ||
82 | |||
71 | #define BLK_IO_TRACE_MAGIC 0x65617400 | 83 | #define BLK_IO_TRACE_MAGIC 0x65617400 |
72 | #define BLK_IO_TRACE_VERSION 0x07 | 84 | #define BLK_IO_TRACE_VERSION 0x07 |
73 | 85 | ||