1*1a3d31e3SAndroid Build Coastguard Worker /*
2*1a3d31e3SAndroid Build Coastguard Worker * Copyright (C) 2012 Fusion-io
3*1a3d31e3SAndroid Build Coastguard Worker *
4*1a3d31e3SAndroid Build Coastguard Worker * This program is free software; you can redistribute it and/or
5*1a3d31e3SAndroid Build Coastguard Worker * modify it under the terms of the GNU General Public
6*1a3d31e3SAndroid Build Coastguard Worker * License v2 as published by the Free Software Foundation.
7*1a3d31e3SAndroid Build Coastguard Worker *
8*1a3d31e3SAndroid Build Coastguard Worker * This program is distributed in the hope that it will be useful,
9*1a3d31e3SAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
10*1a3d31e3SAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11*1a3d31e3SAndroid Build Coastguard Worker * GNU General Public License for more details.
12*1a3d31e3SAndroid Build Coastguard Worker *
13*1a3d31e3SAndroid Build Coastguard Worker * You should have received a copy of the GNU General Public License
14*1a3d31e3SAndroid Build Coastguard Worker * along with this program; if not, write to the Free Software
15*1a3d31e3SAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16*1a3d31e3SAndroid Build Coastguard Worker *
17*1a3d31e3SAndroid Build Coastguard Worker * Parts of this file were imported from Jens Axboe's blktrace sources (also GPL)
18*1a3d31e3SAndroid Build Coastguard Worker */
19*1a3d31e3SAndroid Build Coastguard Worker #include <sys/types.h>
20*1a3d31e3SAndroid Build Coastguard Worker #include <sys/stat.h>
21*1a3d31e3SAndroid Build Coastguard Worker #include <fcntl.h>
22*1a3d31e3SAndroid Build Coastguard Worker #include <unistd.h>
23*1a3d31e3SAndroid Build Coastguard Worker #include <stdlib.h>
24*1a3d31e3SAndroid Build Coastguard Worker #include <stdio.h>
25*1a3d31e3SAndroid Build Coastguard Worker #include <math.h>
26*1a3d31e3SAndroid Build Coastguard Worker #include <inttypes.h>
27*1a3d31e3SAndroid Build Coastguard Worker #include <string.h>
28*1a3d31e3SAndroid Build Coastguard Worker #include <asm/types.h>
29*1a3d31e3SAndroid Build Coastguard Worker #include <errno.h>
30*1a3d31e3SAndroid Build Coastguard Worker #include <sys/mman.h>
31*1a3d31e3SAndroid Build Coastguard Worker #include <time.h>
32*1a3d31e3SAndroid Build Coastguard Worker #include <math.h>
33*1a3d31e3SAndroid Build Coastguard Worker #include <dirent.h>
34*1a3d31e3SAndroid Build Coastguard Worker
35*1a3d31e3SAndroid Build Coastguard Worker #include "plot.h"
36*1a3d31e3SAndroid Build Coastguard Worker #include "blkparse.h"
37*1a3d31e3SAndroid Build Coastguard Worker #include "list.h"
38*1a3d31e3SAndroid Build Coastguard Worker #include "tracers.h"
39*1a3d31e3SAndroid Build Coastguard Worker
40*1a3d31e3SAndroid Build Coastguard Worker #define IO_HASH_TABLE_BITS 11
41*1a3d31e3SAndroid Build Coastguard Worker #define IO_HASH_TABLE_SIZE (1 << IO_HASH_TABLE_BITS)
42*1a3d31e3SAndroid Build Coastguard Worker static struct list_head io_hash_table[IO_HASH_TABLE_SIZE];
43*1a3d31e3SAndroid Build Coastguard Worker static u64 ios_in_flight = 0;
44*1a3d31e3SAndroid Build Coastguard Worker
45*1a3d31e3SAndroid Build Coastguard Worker #define PROCESS_HASH_TABLE_BITS 7
46*1a3d31e3SAndroid Build Coastguard Worker #define PROCESS_HASH_TABLE_SIZE (1 << PROCESS_HASH_TABLE_BITS)
47*1a3d31e3SAndroid Build Coastguard Worker static struct list_head process_hash_table[PROCESS_HASH_TABLE_SIZE];
48*1a3d31e3SAndroid Build Coastguard Worker
49*1a3d31e3SAndroid Build Coastguard Worker extern int plot_io_action;
50*1a3d31e3SAndroid Build Coastguard Worker extern int io_per_process;
51*1a3d31e3SAndroid Build Coastguard Worker
52*1a3d31e3SAndroid Build Coastguard Worker /*
53*1a3d31e3SAndroid Build Coastguard Worker * Trace categories
54*1a3d31e3SAndroid Build Coastguard Worker */
55*1a3d31e3SAndroid Build Coastguard Worker enum {
56*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_READ = 1 << 0, /* reads */
57*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_WRITE = 1 << 1, /* writes */
58*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_FLUSH = 1 << 2, /* flush */
59*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_SYNC = 1 << 3, /* sync */
60*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_QUEUE = 1 << 4, /* queueing/merging */
61*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_REQUEUE = 1 << 5, /* requeueing */
62*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_ISSUE = 1 << 6, /* issue */
63*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_COMPLETE = 1 << 7, /* completions */
64*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_FS = 1 << 8, /* fs requests */
65*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_PC = 1 << 9, /* pc requests */
66*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_NOTIFY = 1 << 10, /* special message */
67*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_AHEAD = 1 << 11, /* readahead */
68*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_META = 1 << 12, /* metadata */
69*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_DISCARD = 1 << 13, /* discard requests */
70*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_DRV_DATA = 1 << 14, /* binary driver data */
71*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_FUA = 1 << 15, /* fua requests */
72*1a3d31e3SAndroid Build Coastguard Worker
73*1a3d31e3SAndroid Build Coastguard Worker BLK_TC_END = 1 << 15, /* we've run out of bits! */
74*1a3d31e3SAndroid Build Coastguard Worker };
75*1a3d31e3SAndroid Build Coastguard Worker
76*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TC_SHIFT (16)
77*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TC_ACT(act) ((act) << BLK_TC_SHIFT)
78*1a3d31e3SAndroid Build Coastguard Worker #define BLK_DATADIR(a) (((a) >> BLK_TC_SHIFT) & (BLK_TC_READ | BLK_TC_WRITE))
79*1a3d31e3SAndroid Build Coastguard Worker
80*1a3d31e3SAndroid Build Coastguard Worker /*
81*1a3d31e3SAndroid Build Coastguard Worker * Basic trace actions
82*1a3d31e3SAndroid Build Coastguard Worker */
83*1a3d31e3SAndroid Build Coastguard Worker enum {
84*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_QUEUE = 1, /* queued */
85*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_BACKMERGE, /* back merged to existing rq */
86*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_FRONTMERGE, /* front merge to existing rq */
87*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_GETRQ, /* allocated new request */
88*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_SLEEPRQ, /* sleeping on rq allocation */
89*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_REQUEUE, /* request requeued */
90*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_ISSUE, /* sent to driver */
91*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_COMPLETE, /* completed by driver */
92*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_PLUG, /* queue was plugged */
93*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_UNPLUG_IO, /* queue was unplugged by io */
94*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_UNPLUG_TIMER, /* queue was unplugged by timer */
95*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_INSERT, /* insert request */
96*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_SPLIT, /* bio was split */
97*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_BOUNCE, /* bio was bounced */
98*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_REMAP, /* bio was remapped */
99*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_ABORT, /* request aborted */
100*1a3d31e3SAndroid Build Coastguard Worker __BLK_TA_DRV_DATA, /* binary driver data */
101*1a3d31e3SAndroid Build Coastguard Worker };
102*1a3d31e3SAndroid Build Coastguard Worker
103*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_MASK ((1 << BLK_TC_SHIFT) - 1)
104*1a3d31e3SAndroid Build Coastguard Worker
105*1a3d31e3SAndroid Build Coastguard Worker /*
106*1a3d31e3SAndroid Build Coastguard Worker * Notify events.
107*1a3d31e3SAndroid Build Coastguard Worker */
108*1a3d31e3SAndroid Build Coastguard Worker enum blktrace_notify {
109*1a3d31e3SAndroid Build Coastguard Worker __BLK_TN_PROCESS = 0, /* establish pid/name mapping */
110*1a3d31e3SAndroid Build Coastguard Worker __BLK_TN_TIMESTAMP, /* include system clock */
111*1a3d31e3SAndroid Build Coastguard Worker __BLK_TN_MESSAGE, /* Character string message */
112*1a3d31e3SAndroid Build Coastguard Worker };
113*1a3d31e3SAndroid Build Coastguard Worker
114*1a3d31e3SAndroid Build Coastguard Worker /*
115*1a3d31e3SAndroid Build Coastguard Worker * Trace actions in full. Additionally, read or write is masked
116*1a3d31e3SAndroid Build Coastguard Worker */
117*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_QUEUE (__BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_QUEUE))
118*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_BACKMERGE (__BLK_TA_BACKMERGE | BLK_TC_ACT(BLK_TC_QUEUE))
119*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_FRONTMERGE (__BLK_TA_FRONTMERGE | BLK_TC_ACT(BLK_TC_QUEUE))
120*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_GETRQ (__BLK_TA_GETRQ | BLK_TC_ACT(BLK_TC_QUEUE))
121*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_SLEEPRQ (__BLK_TA_SLEEPRQ | BLK_TC_ACT(BLK_TC_QUEUE))
122*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_REQUEUE (__BLK_TA_REQUEUE | BLK_TC_ACT(BLK_TC_REQUEUE))
123*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_ISSUE (__BLK_TA_ISSUE | BLK_TC_ACT(BLK_TC_ISSUE))
124*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_COMPLETE (__BLK_TA_COMPLETE| BLK_TC_ACT(BLK_TC_COMPLETE))
125*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_PLUG (__BLK_TA_PLUG | BLK_TC_ACT(BLK_TC_QUEUE))
126*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_UNPLUG_IO (__BLK_TA_UNPLUG_IO | BLK_TC_ACT(BLK_TC_QUEUE))
127*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_UNPLUG_TIMER (__BLK_TA_UNPLUG_TIMER | BLK_TC_ACT(BLK_TC_QUEUE))
128*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_INSERT (__BLK_TA_INSERT | BLK_TC_ACT(BLK_TC_QUEUE))
129*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_SPLIT (__BLK_TA_SPLIT)
130*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_BOUNCE (__BLK_TA_BOUNCE)
131*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_REMAP (__BLK_TA_REMAP | BLK_TC_ACT(BLK_TC_QUEUE))
132*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_ABORT (__BLK_TA_ABORT | BLK_TC_ACT(BLK_TC_QUEUE))
133*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TA_DRV_DATA (__BLK_TA_DRV_DATA | BLK_TC_ACT(BLK_TC_DRV_DATA))
134*1a3d31e3SAndroid Build Coastguard Worker
135*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TN_PROCESS (__BLK_TN_PROCESS | BLK_TC_ACT(BLK_TC_NOTIFY))
136*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TN_TIMESTAMP (__BLK_TN_TIMESTAMP | BLK_TC_ACT(BLK_TC_NOTIFY))
137*1a3d31e3SAndroid Build Coastguard Worker #define BLK_TN_MESSAGE (__BLK_TN_MESSAGE | BLK_TC_ACT(BLK_TC_NOTIFY))
138*1a3d31e3SAndroid Build Coastguard Worker
139*1a3d31e3SAndroid Build Coastguard Worker #define BLK_IO_TRACE_MAGIC 0x65617400
140*1a3d31e3SAndroid Build Coastguard Worker #define BLK_IO_TRACE_VERSION 0x07
141*1a3d31e3SAndroid Build Coastguard Worker /*
142*1a3d31e3SAndroid Build Coastguard Worker * The trace itself
143*1a3d31e3SAndroid Build Coastguard Worker */
144*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace {
145*1a3d31e3SAndroid Build Coastguard Worker __u32 magic; /* MAGIC << 8 | version */
146*1a3d31e3SAndroid Build Coastguard Worker __u32 sequence; /* event number */
147*1a3d31e3SAndroid Build Coastguard Worker __u64 time; /* in nanoseconds */
148*1a3d31e3SAndroid Build Coastguard Worker __u64 sector; /* disk offset */
149*1a3d31e3SAndroid Build Coastguard Worker __u32 bytes; /* transfer length */
150*1a3d31e3SAndroid Build Coastguard Worker __u32 action; /* what happened */
151*1a3d31e3SAndroid Build Coastguard Worker __u32 pid; /* who did it */
152*1a3d31e3SAndroid Build Coastguard Worker __u32 device; /* device identifier (dev_t) */
153*1a3d31e3SAndroid Build Coastguard Worker __u32 cpu; /* on what cpu did it happen */
154*1a3d31e3SAndroid Build Coastguard Worker __u16 error; /* completion error */
155*1a3d31e3SAndroid Build Coastguard Worker __u16 pdu_len; /* length of data after this trace */
156*1a3d31e3SAndroid Build Coastguard Worker };
157*1a3d31e3SAndroid Build Coastguard Worker
158*1a3d31e3SAndroid Build Coastguard Worker struct pending_io {
159*1a3d31e3SAndroid Build Coastguard Worker /* sector offset of this IO */
160*1a3d31e3SAndroid Build Coastguard Worker u64 sector;
161*1a3d31e3SAndroid Build Coastguard Worker
162*1a3d31e3SAndroid Build Coastguard Worker /* dev_t for this IO */
163*1a3d31e3SAndroid Build Coastguard Worker u32 device;
164*1a3d31e3SAndroid Build Coastguard Worker
165*1a3d31e3SAndroid Build Coastguard Worker /* time this IO was dispatched */
166*1a3d31e3SAndroid Build Coastguard Worker u64 dispatch_time;
167*1a3d31e3SAndroid Build Coastguard Worker /* time this IO was finished */
168*1a3d31e3SAndroid Build Coastguard Worker u64 completion_time;
169*1a3d31e3SAndroid Build Coastguard Worker struct list_head hash_list;
170*1a3d31e3SAndroid Build Coastguard Worker /* process which queued this IO */
171*1a3d31e3SAndroid Build Coastguard Worker u32 pid;
172*1a3d31e3SAndroid Build Coastguard Worker };
173*1a3d31e3SAndroid Build Coastguard Worker
174*1a3d31e3SAndroid Build Coastguard Worker struct pid_map {
175*1a3d31e3SAndroid Build Coastguard Worker struct list_head hash_list;
176*1a3d31e3SAndroid Build Coastguard Worker u32 pid;
177*1a3d31e3SAndroid Build Coastguard Worker int index;
178*1a3d31e3SAndroid Build Coastguard Worker char name[0];
179*1a3d31e3SAndroid Build Coastguard Worker };
180*1a3d31e3SAndroid Build Coastguard Worker
get_record_time(struct trace * trace)181*1a3d31e3SAndroid Build Coastguard Worker u64 get_record_time(struct trace *trace)
182*1a3d31e3SAndroid Build Coastguard Worker {
183*1a3d31e3SAndroid Build Coastguard Worker return trace->io->time;
184*1a3d31e3SAndroid Build Coastguard Worker }
185*1a3d31e3SAndroid Build Coastguard Worker
init_io_hash_table(void)186*1a3d31e3SAndroid Build Coastguard Worker void init_io_hash_table(void)
187*1a3d31e3SAndroid Build Coastguard Worker {
188*1a3d31e3SAndroid Build Coastguard Worker int i;
189*1a3d31e3SAndroid Build Coastguard Worker struct list_head *head;
190*1a3d31e3SAndroid Build Coastguard Worker
191*1a3d31e3SAndroid Build Coastguard Worker for (i = 0; i < IO_HASH_TABLE_SIZE; i++) {
192*1a3d31e3SAndroid Build Coastguard Worker head = io_hash_table + i;
193*1a3d31e3SAndroid Build Coastguard Worker INIT_LIST_HEAD(head);
194*1a3d31e3SAndroid Build Coastguard Worker }
195*1a3d31e3SAndroid Build Coastguard Worker }
196*1a3d31e3SAndroid Build Coastguard Worker
197*1a3d31e3SAndroid Build Coastguard Worker /* taken from the kernel hash.h */
hash_sector(u64 val)198*1a3d31e3SAndroid Build Coastguard Worker static inline u64 hash_sector(u64 val)
199*1a3d31e3SAndroid Build Coastguard Worker {
200*1a3d31e3SAndroid Build Coastguard Worker u64 hash = val;
201*1a3d31e3SAndroid Build Coastguard Worker
202*1a3d31e3SAndroid Build Coastguard Worker /* Sigh, gcc can't optimise this alone like it does for 32 bits. */
203*1a3d31e3SAndroid Build Coastguard Worker u64 n = hash;
204*1a3d31e3SAndroid Build Coastguard Worker n <<= 18;
205*1a3d31e3SAndroid Build Coastguard Worker hash -= n;
206*1a3d31e3SAndroid Build Coastguard Worker n <<= 33;
207*1a3d31e3SAndroid Build Coastguard Worker hash -= n;
208*1a3d31e3SAndroid Build Coastguard Worker n <<= 3;
209*1a3d31e3SAndroid Build Coastguard Worker hash += n;
210*1a3d31e3SAndroid Build Coastguard Worker n <<= 3;
211*1a3d31e3SAndroid Build Coastguard Worker hash -= n;
212*1a3d31e3SAndroid Build Coastguard Worker n <<= 4;
213*1a3d31e3SAndroid Build Coastguard Worker hash += n;
214*1a3d31e3SAndroid Build Coastguard Worker n <<= 2;
215*1a3d31e3SAndroid Build Coastguard Worker hash += n;
216*1a3d31e3SAndroid Build Coastguard Worker
217*1a3d31e3SAndroid Build Coastguard Worker /* High bits are more random, so use them. */
218*1a3d31e3SAndroid Build Coastguard Worker return hash >> (64 - IO_HASH_TABLE_BITS);
219*1a3d31e3SAndroid Build Coastguard Worker }
220*1a3d31e3SAndroid Build Coastguard Worker
io_hash_table_insert(struct pending_io * ins_pio)221*1a3d31e3SAndroid Build Coastguard Worker static int io_hash_table_insert(struct pending_io *ins_pio)
222*1a3d31e3SAndroid Build Coastguard Worker {
223*1a3d31e3SAndroid Build Coastguard Worker u64 sector = ins_pio->sector;
224*1a3d31e3SAndroid Build Coastguard Worker u32 dev = ins_pio->device;
225*1a3d31e3SAndroid Build Coastguard Worker int slot = hash_sector(sector);
226*1a3d31e3SAndroid Build Coastguard Worker struct list_head *head;
227*1a3d31e3SAndroid Build Coastguard Worker struct pending_io *pio;
228*1a3d31e3SAndroid Build Coastguard Worker
229*1a3d31e3SAndroid Build Coastguard Worker head = io_hash_table + slot;
230*1a3d31e3SAndroid Build Coastguard Worker list_for_each_entry(pio, head, hash_list) {
231*1a3d31e3SAndroid Build Coastguard Worker if (pio->sector == sector && pio->device == dev)
232*1a3d31e3SAndroid Build Coastguard Worker return -EEXIST;
233*1a3d31e3SAndroid Build Coastguard Worker }
234*1a3d31e3SAndroid Build Coastguard Worker list_add_tail(&ins_pio->hash_list, head);
235*1a3d31e3SAndroid Build Coastguard Worker return 0;
236*1a3d31e3SAndroid Build Coastguard Worker }
237*1a3d31e3SAndroid Build Coastguard Worker
io_hash_table_search(u64 sector,u32 dev)238*1a3d31e3SAndroid Build Coastguard Worker static struct pending_io *io_hash_table_search(u64 sector, u32 dev)
239*1a3d31e3SAndroid Build Coastguard Worker {
240*1a3d31e3SAndroid Build Coastguard Worker int slot = hash_sector(sector);
241*1a3d31e3SAndroid Build Coastguard Worker struct list_head *head;
242*1a3d31e3SAndroid Build Coastguard Worker struct pending_io *pio;
243*1a3d31e3SAndroid Build Coastguard Worker
244*1a3d31e3SAndroid Build Coastguard Worker head = io_hash_table + slot;
245*1a3d31e3SAndroid Build Coastguard Worker list_for_each_entry(pio, head, hash_list) {
246*1a3d31e3SAndroid Build Coastguard Worker if (pio->sector == sector && pio->device == dev)
247*1a3d31e3SAndroid Build Coastguard Worker return pio;
248*1a3d31e3SAndroid Build Coastguard Worker }
249*1a3d31e3SAndroid Build Coastguard Worker return NULL;
250*1a3d31e3SAndroid Build Coastguard Worker }
251*1a3d31e3SAndroid Build Coastguard Worker
hash_queued_io(struct blk_io_trace * io)252*1a3d31e3SAndroid Build Coastguard Worker static struct pending_io *hash_queued_io(struct blk_io_trace *io)
253*1a3d31e3SAndroid Build Coastguard Worker {
254*1a3d31e3SAndroid Build Coastguard Worker struct pending_io *pio;
255*1a3d31e3SAndroid Build Coastguard Worker int ret;
256*1a3d31e3SAndroid Build Coastguard Worker
257*1a3d31e3SAndroid Build Coastguard Worker pio = calloc(1, sizeof(*pio));
258*1a3d31e3SAndroid Build Coastguard Worker pio->sector = io->sector;
259*1a3d31e3SAndroid Build Coastguard Worker pio->device = io->device;
260*1a3d31e3SAndroid Build Coastguard Worker pio->pid = io->pid;
261*1a3d31e3SAndroid Build Coastguard Worker
262*1a3d31e3SAndroid Build Coastguard Worker ret = io_hash_table_insert(pio);
263*1a3d31e3SAndroid Build Coastguard Worker if (ret < 0) {
264*1a3d31e3SAndroid Build Coastguard Worker /* crud, the IO is there already */
265*1a3d31e3SAndroid Build Coastguard Worker free(pio);
266*1a3d31e3SAndroid Build Coastguard Worker return NULL;
267*1a3d31e3SAndroid Build Coastguard Worker }
268*1a3d31e3SAndroid Build Coastguard Worker return pio;
269*1a3d31e3SAndroid Build Coastguard Worker }
270*1a3d31e3SAndroid Build Coastguard Worker
hash_dispatched_io(struct blk_io_trace * io)271*1a3d31e3SAndroid Build Coastguard Worker static struct pending_io *hash_dispatched_io(struct blk_io_trace *io)
272*1a3d31e3SAndroid Build Coastguard Worker {
273*1a3d31e3SAndroid Build Coastguard Worker struct pending_io *pio;
274*1a3d31e3SAndroid Build Coastguard Worker
275*1a3d31e3SAndroid Build Coastguard Worker pio = io_hash_table_search(io->sector, io->device);
276*1a3d31e3SAndroid Build Coastguard Worker if (!pio) {
277*1a3d31e3SAndroid Build Coastguard Worker pio = hash_queued_io(io);
278*1a3d31e3SAndroid Build Coastguard Worker if (!pio)
279*1a3d31e3SAndroid Build Coastguard Worker return NULL;
280*1a3d31e3SAndroid Build Coastguard Worker }
281*1a3d31e3SAndroid Build Coastguard Worker pio->dispatch_time = io->time;
282*1a3d31e3SAndroid Build Coastguard Worker return pio;
283*1a3d31e3SAndroid Build Coastguard Worker }
284*1a3d31e3SAndroid Build Coastguard Worker
hash_completed_io(struct blk_io_trace * io)285*1a3d31e3SAndroid Build Coastguard Worker static struct pending_io *hash_completed_io(struct blk_io_trace *io)
286*1a3d31e3SAndroid Build Coastguard Worker {
287*1a3d31e3SAndroid Build Coastguard Worker struct pending_io *pio;
288*1a3d31e3SAndroid Build Coastguard Worker
289*1a3d31e3SAndroid Build Coastguard Worker pio = io_hash_table_search(io->sector, io->device);
290*1a3d31e3SAndroid Build Coastguard Worker
291*1a3d31e3SAndroid Build Coastguard Worker if (!pio)
292*1a3d31e3SAndroid Build Coastguard Worker return NULL;
293*1a3d31e3SAndroid Build Coastguard Worker return pio;
294*1a3d31e3SAndroid Build Coastguard Worker }
295*1a3d31e3SAndroid Build Coastguard Worker
init_process_hash_table(void)296*1a3d31e3SAndroid Build Coastguard Worker void init_process_hash_table(void)
297*1a3d31e3SAndroid Build Coastguard Worker {
298*1a3d31e3SAndroid Build Coastguard Worker int i;
299*1a3d31e3SAndroid Build Coastguard Worker struct list_head *head;
300*1a3d31e3SAndroid Build Coastguard Worker
301*1a3d31e3SAndroid Build Coastguard Worker for (i = 0; i < PROCESS_HASH_TABLE_SIZE; i++) {
302*1a3d31e3SAndroid Build Coastguard Worker head = process_hash_table + i;
303*1a3d31e3SAndroid Build Coastguard Worker INIT_LIST_HEAD(head);
304*1a3d31e3SAndroid Build Coastguard Worker }
305*1a3d31e3SAndroid Build Coastguard Worker }
306*1a3d31e3SAndroid Build Coastguard Worker
hash_pid(u32 pid)307*1a3d31e3SAndroid Build Coastguard Worker static u32 hash_pid(u32 pid)
308*1a3d31e3SAndroid Build Coastguard Worker {
309*1a3d31e3SAndroid Build Coastguard Worker u32 hash = pid;
310*1a3d31e3SAndroid Build Coastguard Worker
311*1a3d31e3SAndroid Build Coastguard Worker hash ^= pid >> 3;
312*1a3d31e3SAndroid Build Coastguard Worker hash ^= pid >> 3;
313*1a3d31e3SAndroid Build Coastguard Worker hash ^= pid >> 4;
314*1a3d31e3SAndroid Build Coastguard Worker hash ^= pid >> 6;
315*1a3d31e3SAndroid Build Coastguard Worker return (hash & (PROCESS_HASH_TABLE_SIZE - 1));
316*1a3d31e3SAndroid Build Coastguard Worker }
317*1a3d31e3SAndroid Build Coastguard Worker
process_hash_search(u32 pid)318*1a3d31e3SAndroid Build Coastguard Worker static struct pid_map *process_hash_search(u32 pid)
319*1a3d31e3SAndroid Build Coastguard Worker {
320*1a3d31e3SAndroid Build Coastguard Worker int slot = hash_pid(pid);
321*1a3d31e3SAndroid Build Coastguard Worker struct list_head *head;
322*1a3d31e3SAndroid Build Coastguard Worker struct pid_map *pm;
323*1a3d31e3SAndroid Build Coastguard Worker
324*1a3d31e3SAndroid Build Coastguard Worker head = process_hash_table + slot;
325*1a3d31e3SAndroid Build Coastguard Worker list_for_each_entry(pm, head, hash_list) {
326*1a3d31e3SAndroid Build Coastguard Worker if (pm->pid == pid)
327*1a3d31e3SAndroid Build Coastguard Worker return pm;
328*1a3d31e3SAndroid Build Coastguard Worker }
329*1a3d31e3SAndroid Build Coastguard Worker return NULL;
330*1a3d31e3SAndroid Build Coastguard Worker }
331*1a3d31e3SAndroid Build Coastguard Worker
process_hash_insert(u32 pid,char * name)332*1a3d31e3SAndroid Build Coastguard Worker static struct pid_map *process_hash_insert(u32 pid, char *name)
333*1a3d31e3SAndroid Build Coastguard Worker {
334*1a3d31e3SAndroid Build Coastguard Worker int slot = hash_pid(pid);
335*1a3d31e3SAndroid Build Coastguard Worker struct pid_map *pm;
336*1a3d31e3SAndroid Build Coastguard Worker int old_index = 0;
337*1a3d31e3SAndroid Build Coastguard Worker char buf[16];
338*1a3d31e3SAndroid Build Coastguard Worker
339*1a3d31e3SAndroid Build Coastguard Worker pm = process_hash_search(pid);
340*1a3d31e3SAndroid Build Coastguard Worker if (pm) {
341*1a3d31e3SAndroid Build Coastguard Worker /* Entry exists and name shouldn't be changed? */
342*1a3d31e3SAndroid Build Coastguard Worker if (!name || !strcmp(name, pm->name))
343*1a3d31e3SAndroid Build Coastguard Worker return pm;
344*1a3d31e3SAndroid Build Coastguard Worker list_del(&pm->hash_list);
345*1a3d31e3SAndroid Build Coastguard Worker old_index = pm->index;
346*1a3d31e3SAndroid Build Coastguard Worker free(pm);
347*1a3d31e3SAndroid Build Coastguard Worker }
348*1a3d31e3SAndroid Build Coastguard Worker if (!name) {
349*1a3d31e3SAndroid Build Coastguard Worker sprintf(buf, "[%u]", pid);
350*1a3d31e3SAndroid Build Coastguard Worker name = buf;
351*1a3d31e3SAndroid Build Coastguard Worker }
352*1a3d31e3SAndroid Build Coastguard Worker pm = malloc(sizeof(struct pid_map) + strlen(name) + 1);
353*1a3d31e3SAndroid Build Coastguard Worker pm->pid = pid;
354*1a3d31e3SAndroid Build Coastguard Worker pm->index = old_index;
355*1a3d31e3SAndroid Build Coastguard Worker strcpy(pm->name, name);
356*1a3d31e3SAndroid Build Coastguard Worker list_add_tail(&pm->hash_list, process_hash_table + slot);
357*1a3d31e3SAndroid Build Coastguard Worker
358*1a3d31e3SAndroid Build Coastguard Worker return pm;
359*1a3d31e3SAndroid Build Coastguard Worker }
360*1a3d31e3SAndroid Build Coastguard Worker
handle_notify(struct trace * trace)361*1a3d31e3SAndroid Build Coastguard Worker static void handle_notify(struct trace *trace)
362*1a3d31e3SAndroid Build Coastguard Worker {
363*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *io = trace->io;
364*1a3d31e3SAndroid Build Coastguard Worker void *payload = (char *)io + sizeof(*io);
365*1a3d31e3SAndroid Build Coastguard Worker u32 two32[2];
366*1a3d31e3SAndroid Build Coastguard Worker
367*1a3d31e3SAndroid Build Coastguard Worker if (io->action == BLK_TN_PROCESS) {
368*1a3d31e3SAndroid Build Coastguard Worker if (io_per_process)
369*1a3d31e3SAndroid Build Coastguard Worker process_hash_insert(io->pid, payload);
370*1a3d31e3SAndroid Build Coastguard Worker return;
371*1a3d31e3SAndroid Build Coastguard Worker }
372*1a3d31e3SAndroid Build Coastguard Worker
373*1a3d31e3SAndroid Build Coastguard Worker if (io->action != BLK_TN_TIMESTAMP)
374*1a3d31e3SAndroid Build Coastguard Worker return;
375*1a3d31e3SAndroid Build Coastguard Worker
376*1a3d31e3SAndroid Build Coastguard Worker if (io->pdu_len != sizeof(two32))
377*1a3d31e3SAndroid Build Coastguard Worker return;
378*1a3d31e3SAndroid Build Coastguard Worker
379*1a3d31e3SAndroid Build Coastguard Worker memcpy(two32, payload, sizeof(two32));
380*1a3d31e3SAndroid Build Coastguard Worker trace->start_timestamp = io->time;
381*1a3d31e3SAndroid Build Coastguard Worker trace->abs_start_time.tv_sec = two32[0];
382*1a3d31e3SAndroid Build Coastguard Worker trace->abs_start_time.tv_nsec = two32[1];
383*1a3d31e3SAndroid Build Coastguard Worker if (trace->abs_start_time.tv_nsec < 0) {
384*1a3d31e3SAndroid Build Coastguard Worker trace->abs_start_time.tv_sec--;
385*1a3d31e3SAndroid Build Coastguard Worker trace->abs_start_time.tv_nsec += 1000000000;
386*1a3d31e3SAndroid Build Coastguard Worker }
387*1a3d31e3SAndroid Build Coastguard Worker }
388*1a3d31e3SAndroid Build Coastguard Worker
next_record(struct trace * trace)389*1a3d31e3SAndroid Build Coastguard Worker int next_record(struct trace *trace)
390*1a3d31e3SAndroid Build Coastguard Worker {
391*1a3d31e3SAndroid Build Coastguard Worker int skip = trace->io->pdu_len;
392*1a3d31e3SAndroid Build Coastguard Worker u64 offset;
393*1a3d31e3SAndroid Build Coastguard Worker
394*1a3d31e3SAndroid Build Coastguard Worker trace->cur += sizeof(*trace->io) + skip;
395*1a3d31e3SAndroid Build Coastguard Worker offset = trace->cur - trace->start;
396*1a3d31e3SAndroid Build Coastguard Worker if (offset >= trace->len)
397*1a3d31e3SAndroid Build Coastguard Worker return 1;
398*1a3d31e3SAndroid Build Coastguard Worker
399*1a3d31e3SAndroid Build Coastguard Worker trace->io = (struct blk_io_trace *)trace->cur;
400*1a3d31e3SAndroid Build Coastguard Worker return 0;
401*1a3d31e3SAndroid Build Coastguard Worker }
402*1a3d31e3SAndroid Build Coastguard Worker
first_record(struct trace * trace)403*1a3d31e3SAndroid Build Coastguard Worker void first_record(struct trace *trace)
404*1a3d31e3SAndroid Build Coastguard Worker {
405*1a3d31e3SAndroid Build Coastguard Worker trace->cur = trace->start;
406*1a3d31e3SAndroid Build Coastguard Worker trace->io = (struct blk_io_trace *)trace->cur;
407*1a3d31e3SAndroid Build Coastguard Worker }
408*1a3d31e3SAndroid Build Coastguard Worker
is_io_event(struct blk_io_trace * test)409*1a3d31e3SAndroid Build Coastguard Worker static int is_io_event(struct blk_io_trace *test)
410*1a3d31e3SAndroid Build Coastguard Worker {
411*1a3d31e3SAndroid Build Coastguard Worker char *message;
412*1a3d31e3SAndroid Build Coastguard Worker if (!(test->action & BLK_TC_ACT(BLK_TC_NOTIFY)))
413*1a3d31e3SAndroid Build Coastguard Worker return 1;
414*1a3d31e3SAndroid Build Coastguard Worker if (test->action == BLK_TN_MESSAGE) {
415*1a3d31e3SAndroid Build Coastguard Worker int len = test->pdu_len;
416*1a3d31e3SAndroid Build Coastguard Worker if (len < 3)
417*1a3d31e3SAndroid Build Coastguard Worker return 0;
418*1a3d31e3SAndroid Build Coastguard Worker message = (char *)(test + 1);
419*1a3d31e3SAndroid Build Coastguard Worker if (strncmp(message, "fio ", 4) == 0) {
420*1a3d31e3SAndroid Build Coastguard Worker return 1;
421*1a3d31e3SAndroid Build Coastguard Worker }
422*1a3d31e3SAndroid Build Coastguard Worker }
423*1a3d31e3SAndroid Build Coastguard Worker return 0;
424*1a3d31e3SAndroid Build Coastguard Worker }
425*1a3d31e3SAndroid Build Coastguard Worker
find_last_time(struct trace * trace)426*1a3d31e3SAndroid Build Coastguard Worker u64 find_last_time(struct trace *trace)
427*1a3d31e3SAndroid Build Coastguard Worker {
428*1a3d31e3SAndroid Build Coastguard Worker char *p = trace->start + trace->len;
429*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *test;
430*1a3d31e3SAndroid Build Coastguard Worker int search_len = 0;
431*1a3d31e3SAndroid Build Coastguard Worker u64 found = 0;
432*1a3d31e3SAndroid Build Coastguard Worker
433*1a3d31e3SAndroid Build Coastguard Worker if (trace->len < sizeof(*trace->io))
434*1a3d31e3SAndroid Build Coastguard Worker return 0;
435*1a3d31e3SAndroid Build Coastguard Worker p -= sizeof(*trace->io);
436*1a3d31e3SAndroid Build Coastguard Worker while (p >= trace->start) {
437*1a3d31e3SAndroid Build Coastguard Worker test = (struct blk_io_trace *)p;
438*1a3d31e3SAndroid Build Coastguard Worker if (CHECK_MAGIC(test) && is_io_event(test)) {
439*1a3d31e3SAndroid Build Coastguard Worker u64 offset = p - trace->start;
440*1a3d31e3SAndroid Build Coastguard Worker if (offset + sizeof(*test) + test->pdu_len == trace->len) {
441*1a3d31e3SAndroid Build Coastguard Worker return test->time;
442*1a3d31e3SAndroid Build Coastguard Worker }
443*1a3d31e3SAndroid Build Coastguard Worker }
444*1a3d31e3SAndroid Build Coastguard Worker p--;
445*1a3d31e3SAndroid Build Coastguard Worker search_len++;
446*1a3d31e3SAndroid Build Coastguard Worker if (search_len > 8192) {
447*1a3d31e3SAndroid Build Coastguard Worker break;
448*1a3d31e3SAndroid Build Coastguard Worker }
449*1a3d31e3SAndroid Build Coastguard Worker }
450*1a3d31e3SAndroid Build Coastguard Worker
451*1a3d31e3SAndroid Build Coastguard Worker /* searching backwards didn't work out, we'll have to scan the file */
452*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
453*1a3d31e3SAndroid Build Coastguard Worker while (1) {
454*1a3d31e3SAndroid Build Coastguard Worker if (is_io_event(trace->io))
455*1a3d31e3SAndroid Build Coastguard Worker found = trace->io->time;
456*1a3d31e3SAndroid Build Coastguard Worker if (next_record(trace))
457*1a3d31e3SAndroid Build Coastguard Worker break;
458*1a3d31e3SAndroid Build Coastguard Worker }
459*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
460*1a3d31e3SAndroid Build Coastguard Worker return found;
461*1a3d31e3SAndroid Build Coastguard Worker }
462*1a3d31e3SAndroid Build Coastguard Worker
parse_fio_bank_message(struct trace * trace,u64 * bank_ret,u64 * offset_ret,u64 * num_banks_ret)463*1a3d31e3SAndroid Build Coastguard Worker static int parse_fio_bank_message(struct trace *trace, u64 *bank_ret, u64 *offset_ret,
464*1a3d31e3SAndroid Build Coastguard Worker u64 *num_banks_ret)
465*1a3d31e3SAndroid Build Coastguard Worker {
466*1a3d31e3SAndroid Build Coastguard Worker char *s;
467*1a3d31e3SAndroid Build Coastguard Worker char *next;
468*1a3d31e3SAndroid Build Coastguard Worker char *message;
469*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *test = trace->io;
470*1a3d31e3SAndroid Build Coastguard Worker int len = test->pdu_len;
471*1a3d31e3SAndroid Build Coastguard Worker u64 bank;
472*1a3d31e3SAndroid Build Coastguard Worker u64 offset;
473*1a3d31e3SAndroid Build Coastguard Worker u64 num_banks;
474*1a3d31e3SAndroid Build Coastguard Worker
475*1a3d31e3SAndroid Build Coastguard Worker if (!(test->action & BLK_TC_ACT(BLK_TC_NOTIFY)))
476*1a3d31e3SAndroid Build Coastguard Worker return -1;
477*1a3d31e3SAndroid Build Coastguard Worker if (test->action != BLK_TN_MESSAGE)
478*1a3d31e3SAndroid Build Coastguard Worker return -1;
479*1a3d31e3SAndroid Build Coastguard Worker
480*1a3d31e3SAndroid Build Coastguard Worker /* the message is fio rw bank offset num_banks */
481*1a3d31e3SAndroid Build Coastguard Worker if (len < 3)
482*1a3d31e3SAndroid Build Coastguard Worker return -1;
483*1a3d31e3SAndroid Build Coastguard Worker message = (char *)(test + 1);
484*1a3d31e3SAndroid Build Coastguard Worker if (strncmp(message, "fio r ", 6) != 0)
485*1a3d31e3SAndroid Build Coastguard Worker return -1;
486*1a3d31e3SAndroid Build Coastguard Worker
487*1a3d31e3SAndroid Build Coastguard Worker message = strndup(message, len);
488*1a3d31e3SAndroid Build Coastguard Worker s = strchr(message, ' ');
489*1a3d31e3SAndroid Build Coastguard Worker if (!s)
490*1a3d31e3SAndroid Build Coastguard Worker goto out;
491*1a3d31e3SAndroid Build Coastguard Worker s++;
492*1a3d31e3SAndroid Build Coastguard Worker s = strchr(s, ' ');
493*1a3d31e3SAndroid Build Coastguard Worker if (!s)
494*1a3d31e3SAndroid Build Coastguard Worker goto out;
495*1a3d31e3SAndroid Build Coastguard Worker
496*1a3d31e3SAndroid Build Coastguard Worker bank = strtoll(s, &next, 10);
497*1a3d31e3SAndroid Build Coastguard Worker if (s == next)
498*1a3d31e3SAndroid Build Coastguard Worker goto out;
499*1a3d31e3SAndroid Build Coastguard Worker s = next;
500*1a3d31e3SAndroid Build Coastguard Worker
501*1a3d31e3SAndroid Build Coastguard Worker offset = strtoll(s, &next, 10);
502*1a3d31e3SAndroid Build Coastguard Worker if (s == next)
503*1a3d31e3SAndroid Build Coastguard Worker goto out;
504*1a3d31e3SAndroid Build Coastguard Worker s = next;
505*1a3d31e3SAndroid Build Coastguard Worker
506*1a3d31e3SAndroid Build Coastguard Worker num_banks = strtoll(s, &next, 10);
507*1a3d31e3SAndroid Build Coastguard Worker if (s == next)
508*1a3d31e3SAndroid Build Coastguard Worker goto out;
509*1a3d31e3SAndroid Build Coastguard Worker
510*1a3d31e3SAndroid Build Coastguard Worker *bank_ret = bank;
511*1a3d31e3SAndroid Build Coastguard Worker *offset_ret = offset;
512*1a3d31e3SAndroid Build Coastguard Worker *num_banks_ret = num_banks;
513*1a3d31e3SAndroid Build Coastguard Worker
514*1a3d31e3SAndroid Build Coastguard Worker return 0;
515*1a3d31e3SAndroid Build Coastguard Worker out:
516*1a3d31e3SAndroid Build Coastguard Worker free(message);
517*1a3d31e3SAndroid Build Coastguard Worker return -1;
518*1a3d31e3SAndroid Build Coastguard Worker }
519*1a3d31e3SAndroid Build Coastguard Worker
lookup_dev(struct trace * trace,struct blk_io_trace * io)520*1a3d31e3SAndroid Build Coastguard Worker static struct dev_info *lookup_dev(struct trace *trace, struct blk_io_trace *io)
521*1a3d31e3SAndroid Build Coastguard Worker {
522*1a3d31e3SAndroid Build Coastguard Worker u32 dev = io->device;
523*1a3d31e3SAndroid Build Coastguard Worker int i;
524*1a3d31e3SAndroid Build Coastguard Worker struct dev_info *di = NULL;
525*1a3d31e3SAndroid Build Coastguard Worker
526*1a3d31e3SAndroid Build Coastguard Worker for (i = 0; i < trace->num_devices; i++) {
527*1a3d31e3SAndroid Build Coastguard Worker if (trace->devices[i].device == dev) {
528*1a3d31e3SAndroid Build Coastguard Worker di = trace->devices + i;
529*1a3d31e3SAndroid Build Coastguard Worker goto found;
530*1a3d31e3SAndroid Build Coastguard Worker }
531*1a3d31e3SAndroid Build Coastguard Worker }
532*1a3d31e3SAndroid Build Coastguard Worker i = trace->num_devices++;
533*1a3d31e3SAndroid Build Coastguard Worker if (i >= MAX_DEVICES_PER_TRACE) {
534*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "Trace contains too many devices (%d)\n", i);
535*1a3d31e3SAndroid Build Coastguard Worker exit(1);
536*1a3d31e3SAndroid Build Coastguard Worker }
537*1a3d31e3SAndroid Build Coastguard Worker di = trace->devices + i;
538*1a3d31e3SAndroid Build Coastguard Worker di->device = dev;
539*1a3d31e3SAndroid Build Coastguard Worker found:
540*1a3d31e3SAndroid Build Coastguard Worker return di;
541*1a3d31e3SAndroid Build Coastguard Worker }
542*1a3d31e3SAndroid Build Coastguard Worker
map_devices(struct trace * trace)543*1a3d31e3SAndroid Build Coastguard Worker static void map_devices(struct trace *trace)
544*1a3d31e3SAndroid Build Coastguard Worker {
545*1a3d31e3SAndroid Build Coastguard Worker struct dev_info *di;
546*1a3d31e3SAndroid Build Coastguard Worker u64 found;
547*1a3d31e3SAndroid Build Coastguard Worker u64 map_start = 0;
548*1a3d31e3SAndroid Build Coastguard Worker int i;
549*1a3d31e3SAndroid Build Coastguard Worker
550*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
551*1a3d31e3SAndroid Build Coastguard Worker while (1) {
552*1a3d31e3SAndroid Build Coastguard Worker if (!(trace->io->action & BLK_TC_ACT(BLK_TC_NOTIFY))) {
553*1a3d31e3SAndroid Build Coastguard Worker di = lookup_dev(trace, trace->io);
554*1a3d31e3SAndroid Build Coastguard Worker found = trace->io->sector << 9;
555*1a3d31e3SAndroid Build Coastguard Worker if (found < di->min)
556*1a3d31e3SAndroid Build Coastguard Worker di->min = found;
557*1a3d31e3SAndroid Build Coastguard Worker
558*1a3d31e3SAndroid Build Coastguard Worker found += trace->io->bytes;
559*1a3d31e3SAndroid Build Coastguard Worker if (di->max < found)
560*1a3d31e3SAndroid Build Coastguard Worker di->max = found;
561*1a3d31e3SAndroid Build Coastguard Worker }
562*1a3d31e3SAndroid Build Coastguard Worker if (next_record(trace))
563*1a3d31e3SAndroid Build Coastguard Worker break;
564*1a3d31e3SAndroid Build Coastguard Worker }
565*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
566*1a3d31e3SAndroid Build Coastguard Worker for (i = 0; i < trace->num_devices; i++) {
567*1a3d31e3SAndroid Build Coastguard Worker di = trace->devices + i;
568*1a3d31e3SAndroid Build Coastguard Worker di->map = map_start;
569*1a3d31e3SAndroid Build Coastguard Worker map_start += di->max - di->min;
570*1a3d31e3SAndroid Build Coastguard Worker }
571*1a3d31e3SAndroid Build Coastguard Worker }
572*1a3d31e3SAndroid Build Coastguard Worker
map_io(struct trace * trace,struct blk_io_trace * io)573*1a3d31e3SAndroid Build Coastguard Worker static u64 map_io(struct trace *trace, struct blk_io_trace *io)
574*1a3d31e3SAndroid Build Coastguard Worker {
575*1a3d31e3SAndroid Build Coastguard Worker struct dev_info *di = lookup_dev(trace, io);
576*1a3d31e3SAndroid Build Coastguard Worker u64 val = trace->io->sector << 9;
577*1a3d31e3SAndroid Build Coastguard Worker return di->map + val - di->min;
578*1a3d31e3SAndroid Build Coastguard Worker }
579*1a3d31e3SAndroid Build Coastguard Worker
find_extreme_offsets(struct trace * trace,u64 * min_ret,u64 * max_ret,u64 * max_bank_ret,u64 * max_offset_ret)580*1a3d31e3SAndroid Build Coastguard Worker void find_extreme_offsets(struct trace *trace, u64 *min_ret, u64 *max_ret, u64 *max_bank_ret,
581*1a3d31e3SAndroid Build Coastguard Worker u64 *max_offset_ret)
582*1a3d31e3SAndroid Build Coastguard Worker {
583*1a3d31e3SAndroid Build Coastguard Worker u64 found = 0;
584*1a3d31e3SAndroid Build Coastguard Worker u64 max = 0, min = ~(u64)0;
585*1a3d31e3SAndroid Build Coastguard Worker u64 max_bank = 0;
586*1a3d31e3SAndroid Build Coastguard Worker u64 max_bank_offset = 0;
587*1a3d31e3SAndroid Build Coastguard Worker u64 num_banks = 0;
588*1a3d31e3SAndroid Build Coastguard Worker
589*1a3d31e3SAndroid Build Coastguard Worker map_devices(trace);
590*1a3d31e3SAndroid Build Coastguard Worker
591*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
592*1a3d31e3SAndroid Build Coastguard Worker while (1) {
593*1a3d31e3SAndroid Build Coastguard Worker if (!(trace->io->action & BLK_TC_ACT(BLK_TC_NOTIFY))) {
594*1a3d31e3SAndroid Build Coastguard Worker found = map_io(trace, trace->io);
595*1a3d31e3SAndroid Build Coastguard Worker if (found < min)
596*1a3d31e3SAndroid Build Coastguard Worker min = found;
597*1a3d31e3SAndroid Build Coastguard Worker
598*1a3d31e3SAndroid Build Coastguard Worker found += trace->io->bytes;
599*1a3d31e3SAndroid Build Coastguard Worker if (max < found)
600*1a3d31e3SAndroid Build Coastguard Worker max = found;
601*1a3d31e3SAndroid Build Coastguard Worker } else {
602*1a3d31e3SAndroid Build Coastguard Worker u64 bank;
603*1a3d31e3SAndroid Build Coastguard Worker u64 offset;
604*1a3d31e3SAndroid Build Coastguard Worker if (!parse_fio_bank_message(trace, &bank,
605*1a3d31e3SAndroid Build Coastguard Worker &offset, &num_banks)) {
606*1a3d31e3SAndroid Build Coastguard Worker if (bank > max_bank)
607*1a3d31e3SAndroid Build Coastguard Worker max_bank = bank;
608*1a3d31e3SAndroid Build Coastguard Worker if (offset > max_bank_offset)
609*1a3d31e3SAndroid Build Coastguard Worker max_bank_offset = offset;
610*1a3d31e3SAndroid Build Coastguard Worker }
611*1a3d31e3SAndroid Build Coastguard Worker }
612*1a3d31e3SAndroid Build Coastguard Worker if (next_record(trace))
613*1a3d31e3SAndroid Build Coastguard Worker break;
614*1a3d31e3SAndroid Build Coastguard Worker }
615*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
616*1a3d31e3SAndroid Build Coastguard Worker *min_ret = min;
617*1a3d31e3SAndroid Build Coastguard Worker *max_ret = max;
618*1a3d31e3SAndroid Build Coastguard Worker *max_bank_ret = max_bank;
619*1a3d31e3SAndroid Build Coastguard Worker *max_offset_ret = max_bank_offset;
620*1a3d31e3SAndroid Build Coastguard Worker }
621*1a3d31e3SAndroid Build Coastguard Worker
check_io_types(struct trace * trace)622*1a3d31e3SAndroid Build Coastguard Worker static void check_io_types(struct trace *trace)
623*1a3d31e3SAndroid Build Coastguard Worker {
624*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *io = trace->io;
625*1a3d31e3SAndroid Build Coastguard Worker int action = io->action & BLK_TA_MASK;
626*1a3d31e3SAndroid Build Coastguard Worker
627*1a3d31e3SAndroid Build Coastguard Worker if (!(io->action & BLK_TC_ACT(BLK_TC_NOTIFY))) {
628*1a3d31e3SAndroid Build Coastguard Worker switch (action) {
629*1a3d31e3SAndroid Build Coastguard Worker case __BLK_TA_COMPLETE:
630*1a3d31e3SAndroid Build Coastguard Worker trace->found_completion = 1;
631*1a3d31e3SAndroid Build Coastguard Worker break;
632*1a3d31e3SAndroid Build Coastguard Worker case __BLK_TA_ISSUE:
633*1a3d31e3SAndroid Build Coastguard Worker trace->found_issue = 1;
634*1a3d31e3SAndroid Build Coastguard Worker break;
635*1a3d31e3SAndroid Build Coastguard Worker case __BLK_TA_QUEUE:
636*1a3d31e3SAndroid Build Coastguard Worker trace->found_queue = 1;
637*1a3d31e3SAndroid Build Coastguard Worker break;
638*1a3d31e3SAndroid Build Coastguard Worker };
639*1a3d31e3SAndroid Build Coastguard Worker }
640*1a3d31e3SAndroid Build Coastguard Worker }
641*1a3d31e3SAndroid Build Coastguard Worker
642*1a3d31e3SAndroid Build Coastguard Worker
filter_outliers(struct trace * trace,u64 min_offset,u64 max_offset,u64 * yzoom_min,u64 * yzoom_max)643*1a3d31e3SAndroid Build Coastguard Worker int filter_outliers(struct trace *trace, u64 min_offset, u64 max_offset,
644*1a3d31e3SAndroid Build Coastguard Worker u64 *yzoom_min, u64 *yzoom_max)
645*1a3d31e3SAndroid Build Coastguard Worker {
646*1a3d31e3SAndroid Build Coastguard Worker int hits[11];
647*1a3d31e3SAndroid Build Coastguard Worker u64 max_per_bucket[11];
648*1a3d31e3SAndroid Build Coastguard Worker u64 min_per_bucket[11];
649*1a3d31e3SAndroid Build Coastguard Worker u64 bytes_per_bucket = (max_offset - min_offset + 1) / 10;
650*1a3d31e3SAndroid Build Coastguard Worker int slot;
651*1a3d31e3SAndroid Build Coastguard Worker int fat_count = 0;
652*1a3d31e3SAndroid Build Coastguard Worker
653*1a3d31e3SAndroid Build Coastguard Worker memset(hits, 0, sizeof(int) * 11);
654*1a3d31e3SAndroid Build Coastguard Worker memset(max_per_bucket, 0, sizeof(u64) * 11);
655*1a3d31e3SAndroid Build Coastguard Worker memset(min_per_bucket, 0xff, sizeof(u64) * 11);
656*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
657*1a3d31e3SAndroid Build Coastguard Worker while (1) {
658*1a3d31e3SAndroid Build Coastguard Worker check_io_types(trace);
659*1a3d31e3SAndroid Build Coastguard Worker if (!(trace->io->action & BLK_TC_ACT(BLK_TC_NOTIFY)) &&
660*1a3d31e3SAndroid Build Coastguard Worker (trace->io->action & BLK_TA_MASK) == __BLK_TA_QUEUE) {
661*1a3d31e3SAndroid Build Coastguard Worker u64 off = map_io(trace, trace->io) - min_offset;
662*1a3d31e3SAndroid Build Coastguard Worker
663*1a3d31e3SAndroid Build Coastguard Worker slot = (int)(off / bytes_per_bucket);
664*1a3d31e3SAndroid Build Coastguard Worker hits[slot]++;
665*1a3d31e3SAndroid Build Coastguard Worker if (off < min_per_bucket[slot])
666*1a3d31e3SAndroid Build Coastguard Worker min_per_bucket[slot] = off;
667*1a3d31e3SAndroid Build Coastguard Worker
668*1a3d31e3SAndroid Build Coastguard Worker off += trace->io->bytes;
669*1a3d31e3SAndroid Build Coastguard Worker slot = (int)(off / bytes_per_bucket);
670*1a3d31e3SAndroid Build Coastguard Worker hits[slot]++;
671*1a3d31e3SAndroid Build Coastguard Worker if (off > max_per_bucket[slot])
672*1a3d31e3SAndroid Build Coastguard Worker max_per_bucket[slot] = off;
673*1a3d31e3SAndroid Build Coastguard Worker }
674*1a3d31e3SAndroid Build Coastguard Worker if (next_record(trace))
675*1a3d31e3SAndroid Build Coastguard Worker break;
676*1a3d31e3SAndroid Build Coastguard Worker }
677*1a3d31e3SAndroid Build Coastguard Worker first_record(trace);
678*1a3d31e3SAndroid Build Coastguard Worker for (slot = 0; slot < 11; slot++) {
679*1a3d31e3SAndroid Build Coastguard Worker if (hits[slot] > fat_count) {
680*1a3d31e3SAndroid Build Coastguard Worker fat_count = hits[slot];
681*1a3d31e3SAndroid Build Coastguard Worker }
682*1a3d31e3SAndroid Build Coastguard Worker }
683*1a3d31e3SAndroid Build Coastguard Worker
684*1a3d31e3SAndroid Build Coastguard Worker *yzoom_max = max_offset;
685*1a3d31e3SAndroid Build Coastguard Worker for (slot = 10; slot >= 0; slot--) {
686*1a3d31e3SAndroid Build Coastguard Worker double d = hits[slot];
687*1a3d31e3SAndroid Build Coastguard Worker
688*1a3d31e3SAndroid Build Coastguard Worker if (d >= (double)fat_count * .05) {
689*1a3d31e3SAndroid Build Coastguard Worker *yzoom_max = max_per_bucket[slot] + min_offset;
690*1a3d31e3SAndroid Build Coastguard Worker break;
691*1a3d31e3SAndroid Build Coastguard Worker }
692*1a3d31e3SAndroid Build Coastguard Worker }
693*1a3d31e3SAndroid Build Coastguard Worker
694*1a3d31e3SAndroid Build Coastguard Worker *yzoom_min = min_offset;
695*1a3d31e3SAndroid Build Coastguard Worker for (slot = 0; slot < 10; slot++) {
696*1a3d31e3SAndroid Build Coastguard Worker double d = hits[slot];
697*1a3d31e3SAndroid Build Coastguard Worker
698*1a3d31e3SAndroid Build Coastguard Worker if (d >= (double)fat_count * .05) {
699*1a3d31e3SAndroid Build Coastguard Worker *yzoom_min = min_per_bucket[slot] + min_offset;
700*1a3d31e3SAndroid Build Coastguard Worker break;
701*1a3d31e3SAndroid Build Coastguard Worker }
702*1a3d31e3SAndroid Build Coastguard Worker }
703*1a3d31e3SAndroid Build Coastguard Worker return 0;
704*1a3d31e3SAndroid Build Coastguard Worker }
705*1a3d31e3SAndroid Build Coastguard Worker
706*1a3d31e3SAndroid Build Coastguard Worker static char footer[] = ".blktrace.0";
707*1a3d31e3SAndroid Build Coastguard Worker static int footer_len = sizeof(footer) - 1;
708*1a3d31e3SAndroid Build Coastguard Worker
match_trace(char * name,int * len)709*1a3d31e3SAndroid Build Coastguard Worker static int match_trace(char *name, int *len)
710*1a3d31e3SAndroid Build Coastguard Worker {
711*1a3d31e3SAndroid Build Coastguard Worker int match_len;
712*1a3d31e3SAndroid Build Coastguard Worker int footer_start;
713*1a3d31e3SAndroid Build Coastguard Worker
714*1a3d31e3SAndroid Build Coastguard Worker match_len = strlen(name);
715*1a3d31e3SAndroid Build Coastguard Worker if (match_len <= footer_len)
716*1a3d31e3SAndroid Build Coastguard Worker return 0;
717*1a3d31e3SAndroid Build Coastguard Worker
718*1a3d31e3SAndroid Build Coastguard Worker footer_start = match_len - footer_len;
719*1a3d31e3SAndroid Build Coastguard Worker if (strcmp(name + footer_start, footer) != 0)
720*1a3d31e3SAndroid Build Coastguard Worker return 0;
721*1a3d31e3SAndroid Build Coastguard Worker
722*1a3d31e3SAndroid Build Coastguard Worker if (len)
723*1a3d31e3SAndroid Build Coastguard Worker *len = match_len;
724*1a3d31e3SAndroid Build Coastguard Worker return 1;
725*1a3d31e3SAndroid Build Coastguard Worker }
726*1a3d31e3SAndroid Build Coastguard Worker
727*1a3d31e3SAndroid Build Coastguard Worker struct tracelist {
728*1a3d31e3SAndroid Build Coastguard Worker struct tracelist *next;
729*1a3d31e3SAndroid Build Coastguard Worker char *name;
730*1a3d31e3SAndroid Build Coastguard Worker };
731*1a3d31e3SAndroid Build Coastguard Worker
traces_list(char * dir_name,int * len)732*1a3d31e3SAndroid Build Coastguard Worker static struct tracelist *traces_list(char *dir_name, int *len)
733*1a3d31e3SAndroid Build Coastguard Worker {
734*1a3d31e3SAndroid Build Coastguard Worker int count = 0;
735*1a3d31e3SAndroid Build Coastguard Worker struct tracelist *traces = NULL;
736*1a3d31e3SAndroid Build Coastguard Worker int dlen = strlen(dir_name);
737*1a3d31e3SAndroid Build Coastguard Worker DIR *dir = opendir(dir_name);
738*1a3d31e3SAndroid Build Coastguard Worker if (!dir)
739*1a3d31e3SAndroid Build Coastguard Worker return NULL;
740*1a3d31e3SAndroid Build Coastguard Worker
741*1a3d31e3SAndroid Build Coastguard Worker while (1) {
742*1a3d31e3SAndroid Build Coastguard Worker int n = 0;
743*1a3d31e3SAndroid Build Coastguard Worker struct tracelist *tl;
744*1a3d31e3SAndroid Build Coastguard Worker struct dirent *d = readdir(dir);
745*1a3d31e3SAndroid Build Coastguard Worker if (!d)
746*1a3d31e3SAndroid Build Coastguard Worker break;
747*1a3d31e3SAndroid Build Coastguard Worker
748*1a3d31e3SAndroid Build Coastguard Worker if (!match_trace(d->d_name, &n))
749*1a3d31e3SAndroid Build Coastguard Worker continue;
750*1a3d31e3SAndroid Build Coastguard Worker
751*1a3d31e3SAndroid Build Coastguard Worker n += dlen + 1; /* dir + '/' + file */
752*1a3d31e3SAndroid Build Coastguard Worker /* Allocate space for tracelist + filename */
753*1a3d31e3SAndroid Build Coastguard Worker tl = calloc(1, sizeof(struct tracelist) + (sizeof(char) * (n + 1)));
754*1a3d31e3SAndroid Build Coastguard Worker if (!tl) {
755*1a3d31e3SAndroid Build Coastguard Worker closedir(dir);
756*1a3d31e3SAndroid Build Coastguard Worker return NULL;
757*1a3d31e3SAndroid Build Coastguard Worker }
758*1a3d31e3SAndroid Build Coastguard Worker tl->next = traces;
759*1a3d31e3SAndroid Build Coastguard Worker tl->name = (char *)(tl + 1);
760*1a3d31e3SAndroid Build Coastguard Worker snprintf(tl->name, n, "%s/%s", dir_name, d->d_name);
761*1a3d31e3SAndroid Build Coastguard Worker traces = tl;
762*1a3d31e3SAndroid Build Coastguard Worker count++;
763*1a3d31e3SAndroid Build Coastguard Worker }
764*1a3d31e3SAndroid Build Coastguard Worker
765*1a3d31e3SAndroid Build Coastguard Worker closedir(dir);
766*1a3d31e3SAndroid Build Coastguard Worker
767*1a3d31e3SAndroid Build Coastguard Worker if (len)
768*1a3d31e3SAndroid Build Coastguard Worker *len = count;
769*1a3d31e3SAndroid Build Coastguard Worker
770*1a3d31e3SAndroid Build Coastguard Worker return traces;
771*1a3d31e3SAndroid Build Coastguard Worker }
772*1a3d31e3SAndroid Build Coastguard Worker
traces_free(struct tracelist * traces)773*1a3d31e3SAndroid Build Coastguard Worker static void traces_free(struct tracelist *traces)
774*1a3d31e3SAndroid Build Coastguard Worker {
775*1a3d31e3SAndroid Build Coastguard Worker while (traces) {
776*1a3d31e3SAndroid Build Coastguard Worker struct tracelist *tl = traces;
777*1a3d31e3SAndroid Build Coastguard Worker traces = traces->next;
778*1a3d31e3SAndroid Build Coastguard Worker free(tl);
779*1a3d31e3SAndroid Build Coastguard Worker }
780*1a3d31e3SAndroid Build Coastguard Worker }
781*1a3d31e3SAndroid Build Coastguard Worker
dump_traces(struct tracelist * traces,int count,char * dumpfile)782*1a3d31e3SAndroid Build Coastguard Worker static int dump_traces(struct tracelist *traces, int count, char *dumpfile)
783*1a3d31e3SAndroid Build Coastguard Worker {
784*1a3d31e3SAndroid Build Coastguard Worker struct tracelist *tl;
785*1a3d31e3SAndroid Build Coastguard Worker char **argv = NULL;
786*1a3d31e3SAndroid Build Coastguard Worker int argc = 0;
787*1a3d31e3SAndroid Build Coastguard Worker int i;
788*1a3d31e3SAndroid Build Coastguard Worker int err = 0;
789*1a3d31e3SAndroid Build Coastguard Worker
790*1a3d31e3SAndroid Build Coastguard Worker argc = count * 2; /* {"-i", trace } */
791*1a3d31e3SAndroid Build Coastguard Worker argc += 4; /* See below */
792*1a3d31e3SAndroid Build Coastguard Worker argv = calloc(argc + 1, sizeof(char *));
793*1a3d31e3SAndroid Build Coastguard Worker if (!argv)
794*1a3d31e3SAndroid Build Coastguard Worker return -errno;
795*1a3d31e3SAndroid Build Coastguard Worker
796*1a3d31e3SAndroid Build Coastguard Worker i = 0;
797*1a3d31e3SAndroid Build Coastguard Worker argv[i++] = "blkparse";
798*1a3d31e3SAndroid Build Coastguard Worker argv[i++] = "-O";
799*1a3d31e3SAndroid Build Coastguard Worker argv[i++] = "-d";
800*1a3d31e3SAndroid Build Coastguard Worker argv[i++] = dumpfile;
801*1a3d31e3SAndroid Build Coastguard Worker for (tl = traces; tl != NULL; tl = tl->next) {
802*1a3d31e3SAndroid Build Coastguard Worker argv[i++] = "-i";
803*1a3d31e3SAndroid Build Coastguard Worker argv[i++] = tl->name;
804*1a3d31e3SAndroid Build Coastguard Worker }
805*1a3d31e3SAndroid Build Coastguard Worker
806*1a3d31e3SAndroid Build Coastguard Worker err = run_program(argc, argv, 1, NULL, NULL);
807*1a3d31e3SAndroid Build Coastguard Worker if (err)
808*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "%s exited with %d, expected 0\n", argv[0], err);
809*1a3d31e3SAndroid Build Coastguard Worker free(argv);
810*1a3d31e3SAndroid Build Coastguard Worker return err;
811*1a3d31e3SAndroid Build Coastguard Worker }
812*1a3d31e3SAndroid Build Coastguard Worker
find_trace_file(char * filename)813*1a3d31e3SAndroid Build Coastguard Worker static char *find_trace_file(char *filename)
814*1a3d31e3SAndroid Build Coastguard Worker {
815*1a3d31e3SAndroid Build Coastguard Worker int ret;
816*1a3d31e3SAndroid Build Coastguard Worker struct stat st;
817*1a3d31e3SAndroid Build Coastguard Worker char *dot;
818*1a3d31e3SAndroid Build Coastguard Worker int found_dir = 0;
819*1a3d31e3SAndroid Build Coastguard Worker char *dumpfile;
820*1a3d31e3SAndroid Build Coastguard Worker int len = strlen(filename);
821*1a3d31e3SAndroid Build Coastguard Worker
822*1a3d31e3SAndroid Build Coastguard Worker /* look for an exact match of whatever they pass in.
823*1a3d31e3SAndroid Build Coastguard Worker * If it is a file, assume it is the dump file.
824*1a3d31e3SAndroid Build Coastguard Worker * If a directory, remember that it existed so we
825*1a3d31e3SAndroid Build Coastguard Worker * can combine traces in that directory later
826*1a3d31e3SAndroid Build Coastguard Worker */
827*1a3d31e3SAndroid Build Coastguard Worker ret = stat(filename, &st);
828*1a3d31e3SAndroid Build Coastguard Worker if (ret == 0) {
829*1a3d31e3SAndroid Build Coastguard Worker if (S_ISREG(st.st_mode))
830*1a3d31e3SAndroid Build Coastguard Worker return strdup(filename);
831*1a3d31e3SAndroid Build Coastguard Worker
832*1a3d31e3SAndroid Build Coastguard Worker if (S_ISDIR(st.st_mode))
833*1a3d31e3SAndroid Build Coastguard Worker found_dir = 1;
834*1a3d31e3SAndroid Build Coastguard Worker }
835*1a3d31e3SAndroid Build Coastguard Worker
836*1a3d31e3SAndroid Build Coastguard Worker if (found_dir) {
837*1a3d31e3SAndroid Build Coastguard Worker int i;
838*1a3d31e3SAndroid Build Coastguard Worker /* Eat up trailing '/'s */
839*1a3d31e3SAndroid Build Coastguard Worker for (i = len - 1; filename[i] == '/'; i--)
840*1a3d31e3SAndroid Build Coastguard Worker filename[i] = '\0';
841*1a3d31e3SAndroid Build Coastguard Worker }
842*1a3d31e3SAndroid Build Coastguard Worker
843*1a3d31e3SAndroid Build Coastguard Worker /*
844*1a3d31e3SAndroid Build Coastguard Worker * try tacking .dump onto the end and see if that already
845*1a3d31e3SAndroid Build Coastguard Worker * has been generated
846*1a3d31e3SAndroid Build Coastguard Worker */
847*1a3d31e3SAndroid Build Coastguard Worker ret = asprintf(&dumpfile, "%s.dump", filename);
848*1a3d31e3SAndroid Build Coastguard Worker if (ret == -1) {
849*1a3d31e3SAndroid Build Coastguard Worker perror("Error building dump file name");
850*1a3d31e3SAndroid Build Coastguard Worker return NULL;
851*1a3d31e3SAndroid Build Coastguard Worker }
852*1a3d31e3SAndroid Build Coastguard Worker ret = stat(dumpfile, &st);
853*1a3d31e3SAndroid Build Coastguard Worker if (ret == 0)
854*1a3d31e3SAndroid Build Coastguard Worker return dumpfile;
855*1a3d31e3SAndroid Build Coastguard Worker
856*1a3d31e3SAndroid Build Coastguard Worker /*
857*1a3d31e3SAndroid Build Coastguard Worker * try to generate the .dump from all the traces in
858*1a3d31e3SAndroid Build Coastguard Worker * a single dir.
859*1a3d31e3SAndroid Build Coastguard Worker */
860*1a3d31e3SAndroid Build Coastguard Worker if (found_dir) {
861*1a3d31e3SAndroid Build Coastguard Worker int count;
862*1a3d31e3SAndroid Build Coastguard Worker struct tracelist *traces = traces_list(filename, &count);
863*1a3d31e3SAndroid Build Coastguard Worker if (traces) {
864*1a3d31e3SAndroid Build Coastguard Worker ret = dump_traces(traces, count, dumpfile);
865*1a3d31e3SAndroid Build Coastguard Worker traces_free(traces);
866*1a3d31e3SAndroid Build Coastguard Worker if (ret == 0)
867*1a3d31e3SAndroid Build Coastguard Worker return dumpfile;
868*1a3d31e3SAndroid Build Coastguard Worker }
869*1a3d31e3SAndroid Build Coastguard Worker }
870*1a3d31e3SAndroid Build Coastguard Worker free(dumpfile);
871*1a3d31e3SAndroid Build Coastguard Worker
872*1a3d31e3SAndroid Build Coastguard Worker /*
873*1a3d31e3SAndroid Build Coastguard Worker * try to generate the .dump from all the blktrace
874*1a3d31e3SAndroid Build Coastguard Worker * files for a named trace
875*1a3d31e3SAndroid Build Coastguard Worker */
876*1a3d31e3SAndroid Build Coastguard Worker dot = strrchr(filename, '.');
877*1a3d31e3SAndroid Build Coastguard Worker if (!dot || strcmp(".dump", dot) != 0) {
878*1a3d31e3SAndroid Build Coastguard Worker struct tracelist trace = {0 ,NULL};
879*1a3d31e3SAndroid Build Coastguard Worker if (dot && dot != filename)
880*1a3d31e3SAndroid Build Coastguard Worker len = dot - filename;
881*1a3d31e3SAndroid Build Coastguard Worker
882*1a3d31e3SAndroid Build Coastguard Worker ret = asprintf(&trace.name, "%*s.blktrace.0", len, filename);
883*1a3d31e3SAndroid Build Coastguard Worker if (ret == -1)
884*1a3d31e3SAndroid Build Coastguard Worker return NULL;
885*1a3d31e3SAndroid Build Coastguard Worker ret = asprintf(&dumpfile, "%*s.dump", len, filename);
886*1a3d31e3SAndroid Build Coastguard Worker if (ret == -1) {
887*1a3d31e3SAndroid Build Coastguard Worker free(trace.name);
888*1a3d31e3SAndroid Build Coastguard Worker return NULL;
889*1a3d31e3SAndroid Build Coastguard Worker }
890*1a3d31e3SAndroid Build Coastguard Worker
891*1a3d31e3SAndroid Build Coastguard Worker ret = dump_traces(&trace, 1, dumpfile);
892*1a3d31e3SAndroid Build Coastguard Worker if (ret == 0) {
893*1a3d31e3SAndroid Build Coastguard Worker free(trace.name);
894*1a3d31e3SAndroid Build Coastguard Worker return dumpfile;
895*1a3d31e3SAndroid Build Coastguard Worker }
896*1a3d31e3SAndroid Build Coastguard Worker free(trace.name);
897*1a3d31e3SAndroid Build Coastguard Worker free(dumpfile);
898*1a3d31e3SAndroid Build Coastguard Worker }
899*1a3d31e3SAndroid Build Coastguard Worker return NULL;
900*1a3d31e3SAndroid Build Coastguard Worker }
open_trace(char * filename)901*1a3d31e3SAndroid Build Coastguard Worker struct trace *open_trace(char *filename)
902*1a3d31e3SAndroid Build Coastguard Worker {
903*1a3d31e3SAndroid Build Coastguard Worker int fd;
904*1a3d31e3SAndroid Build Coastguard Worker char *p;
905*1a3d31e3SAndroid Build Coastguard Worker struct stat st;
906*1a3d31e3SAndroid Build Coastguard Worker int ret;
907*1a3d31e3SAndroid Build Coastguard Worker struct trace *trace;
908*1a3d31e3SAndroid Build Coastguard Worker char *found_filename;
909*1a3d31e3SAndroid Build Coastguard Worker
910*1a3d31e3SAndroid Build Coastguard Worker trace = calloc(1, sizeof(*trace));
911*1a3d31e3SAndroid Build Coastguard Worker if (!trace) {
912*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "unable to allocate memory for trace\n");
913*1a3d31e3SAndroid Build Coastguard Worker return NULL;
914*1a3d31e3SAndroid Build Coastguard Worker }
915*1a3d31e3SAndroid Build Coastguard Worker
916*1a3d31e3SAndroid Build Coastguard Worker found_filename = find_trace_file(filename);
917*1a3d31e3SAndroid Build Coastguard Worker if (!found_filename) {
918*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "Unable to find trace file %s\n", filename);
919*1a3d31e3SAndroid Build Coastguard Worker goto fail;
920*1a3d31e3SAndroid Build Coastguard Worker }
921*1a3d31e3SAndroid Build Coastguard Worker filename = found_filename;
922*1a3d31e3SAndroid Build Coastguard Worker
923*1a3d31e3SAndroid Build Coastguard Worker fd = open(filename, O_RDONLY);
924*1a3d31e3SAndroid Build Coastguard Worker if (fd < 0) {
925*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "Unable to open trace file %s err %s\n", filename, strerror(errno));
926*1a3d31e3SAndroid Build Coastguard Worker goto fail;
927*1a3d31e3SAndroid Build Coastguard Worker }
928*1a3d31e3SAndroid Build Coastguard Worker ret = fstat(fd, &st);
929*1a3d31e3SAndroid Build Coastguard Worker if (ret < 0) {
930*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "stat failed on %s err %s\n", filename, strerror(errno));
931*1a3d31e3SAndroid Build Coastguard Worker goto fail_fd;
932*1a3d31e3SAndroid Build Coastguard Worker }
933*1a3d31e3SAndroid Build Coastguard Worker p = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
934*1a3d31e3SAndroid Build Coastguard Worker if (p == MAP_FAILED) {
935*1a3d31e3SAndroid Build Coastguard Worker fprintf(stderr, "Unable to mmap trace file %s, err %s\n", filename, strerror(errno));
936*1a3d31e3SAndroid Build Coastguard Worker goto fail_fd;
937*1a3d31e3SAndroid Build Coastguard Worker }
938*1a3d31e3SAndroid Build Coastguard Worker trace->fd = fd;
939*1a3d31e3SAndroid Build Coastguard Worker trace->len = st.st_size;
940*1a3d31e3SAndroid Build Coastguard Worker trace->start = p;
941*1a3d31e3SAndroid Build Coastguard Worker trace->cur = p;
942*1a3d31e3SAndroid Build Coastguard Worker trace->io = (struct blk_io_trace *)p;
943*1a3d31e3SAndroid Build Coastguard Worker return trace;
944*1a3d31e3SAndroid Build Coastguard Worker
945*1a3d31e3SAndroid Build Coastguard Worker fail_fd:
946*1a3d31e3SAndroid Build Coastguard Worker close(fd);
947*1a3d31e3SAndroid Build Coastguard Worker fail:
948*1a3d31e3SAndroid Build Coastguard Worker free(trace);
949*1a3d31e3SAndroid Build Coastguard Worker return NULL;
950*1a3d31e3SAndroid Build Coastguard Worker }
tput_event(struct trace * trace)951*1a3d31e3SAndroid Build Coastguard Worker static inline int tput_event(struct trace *trace)
952*1a3d31e3SAndroid Build Coastguard Worker {
953*1a3d31e3SAndroid Build Coastguard Worker if (trace->found_completion)
954*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_COMPLETE;
955*1a3d31e3SAndroid Build Coastguard Worker if (trace->found_issue)
956*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_ISSUE;
957*1a3d31e3SAndroid Build Coastguard Worker if (trace->found_queue)
958*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_QUEUE;
959*1a3d31e3SAndroid Build Coastguard Worker
960*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_COMPLETE;
961*1a3d31e3SAndroid Build Coastguard Worker }
962*1a3d31e3SAndroid Build Coastguard Worker
action_char_to_num(char action)963*1a3d31e3SAndroid Build Coastguard Worker int action_char_to_num(char action)
964*1a3d31e3SAndroid Build Coastguard Worker {
965*1a3d31e3SAndroid Build Coastguard Worker switch (action) {
966*1a3d31e3SAndroid Build Coastguard Worker case 'Q':
967*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_QUEUE;
968*1a3d31e3SAndroid Build Coastguard Worker case 'D':
969*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_ISSUE;
970*1a3d31e3SAndroid Build Coastguard Worker case 'C':
971*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_COMPLETE;
972*1a3d31e3SAndroid Build Coastguard Worker }
973*1a3d31e3SAndroid Build Coastguard Worker return -1;
974*1a3d31e3SAndroid Build Coastguard Worker }
975*1a3d31e3SAndroid Build Coastguard Worker
io_event(struct trace * trace)976*1a3d31e3SAndroid Build Coastguard Worker static inline int io_event(struct trace *trace)
977*1a3d31e3SAndroid Build Coastguard Worker {
978*1a3d31e3SAndroid Build Coastguard Worker if (plot_io_action)
979*1a3d31e3SAndroid Build Coastguard Worker return plot_io_action;
980*1a3d31e3SAndroid Build Coastguard Worker if (trace->found_queue)
981*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_QUEUE;
982*1a3d31e3SAndroid Build Coastguard Worker if (trace->found_issue)
983*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_ISSUE;
984*1a3d31e3SAndroid Build Coastguard Worker if (trace->found_completion)
985*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_COMPLETE;
986*1a3d31e3SAndroid Build Coastguard Worker
987*1a3d31e3SAndroid Build Coastguard Worker return __BLK_TA_COMPLETE;
988*1a3d31e3SAndroid Build Coastguard Worker }
989*1a3d31e3SAndroid Build Coastguard Worker
add_tput(struct trace * trace,struct graph_line_data * writes_gld,struct graph_line_data * reads_gld)990*1a3d31e3SAndroid Build Coastguard Worker void add_tput(struct trace *trace, struct graph_line_data *writes_gld,
991*1a3d31e3SAndroid Build Coastguard Worker struct graph_line_data *reads_gld)
992*1a3d31e3SAndroid Build Coastguard Worker {
993*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *io = trace->io;
994*1a3d31e3SAndroid Build Coastguard Worker struct graph_line_data *gld;
995*1a3d31e3SAndroid Build Coastguard Worker int action = io->action & BLK_TA_MASK;
996*1a3d31e3SAndroid Build Coastguard Worker int seconds;
997*1a3d31e3SAndroid Build Coastguard Worker
998*1a3d31e3SAndroid Build Coastguard Worker if (io->action & BLK_TC_ACT(BLK_TC_NOTIFY))
999*1a3d31e3SAndroid Build Coastguard Worker return;
1000*1a3d31e3SAndroid Build Coastguard Worker
1001*1a3d31e3SAndroid Build Coastguard Worker if (action != tput_event(trace))
1002*1a3d31e3SAndroid Build Coastguard Worker return;
1003*1a3d31e3SAndroid Build Coastguard Worker
1004*1a3d31e3SAndroid Build Coastguard Worker if (BLK_DATADIR(io->action) & BLK_TC_READ)
1005*1a3d31e3SAndroid Build Coastguard Worker gld = reads_gld;
1006*1a3d31e3SAndroid Build Coastguard Worker else
1007*1a3d31e3SAndroid Build Coastguard Worker gld = writes_gld;
1008*1a3d31e3SAndroid Build Coastguard Worker
1009*1a3d31e3SAndroid Build Coastguard Worker seconds = SECONDS(io->time);
1010*1a3d31e3SAndroid Build Coastguard Worker gld->data[seconds].sum += io->bytes;
1011*1a3d31e3SAndroid Build Coastguard Worker
1012*1a3d31e3SAndroid Build Coastguard Worker gld->data[seconds].count = 1;
1013*1a3d31e3SAndroid Build Coastguard Worker if (gld->data[seconds].sum > gld->max)
1014*1a3d31e3SAndroid Build Coastguard Worker gld->max = gld->data[seconds].sum;
1015*1a3d31e3SAndroid Build Coastguard Worker }
1016*1a3d31e3SAndroid Build Coastguard Worker
1017*1a3d31e3SAndroid Build Coastguard Worker #define GDD_PTR_ALLOC_STEP 16
1018*1a3d31e3SAndroid Build Coastguard Worker
get_pid_map(struct trace_file * tf,u32 pid)1019*1a3d31e3SAndroid Build Coastguard Worker static struct pid_map *get_pid_map(struct trace_file *tf, u32 pid)
1020*1a3d31e3SAndroid Build Coastguard Worker {
1021*1a3d31e3SAndroid Build Coastguard Worker struct pid_map *pm;
1022*1a3d31e3SAndroid Build Coastguard Worker
1023*1a3d31e3SAndroid Build Coastguard Worker if (!io_per_process) {
1024*1a3d31e3SAndroid Build Coastguard Worker if (!tf->io_plots)
1025*1a3d31e3SAndroid Build Coastguard Worker tf->io_plots = 1;
1026*1a3d31e3SAndroid Build Coastguard Worker return NULL;
1027*1a3d31e3SAndroid Build Coastguard Worker }
1028*1a3d31e3SAndroid Build Coastguard Worker
1029*1a3d31e3SAndroid Build Coastguard Worker pm = process_hash_insert(pid, NULL);
1030*1a3d31e3SAndroid Build Coastguard Worker /* New entry? */
1031*1a3d31e3SAndroid Build Coastguard Worker if (!pm->index) {
1032*1a3d31e3SAndroid Build Coastguard Worker if (tf->io_plots == tf->io_plots_allocated) {
1033*1a3d31e3SAndroid Build Coastguard Worker tf->io_plots_allocated += GDD_PTR_ALLOC_STEP;
1034*1a3d31e3SAndroid Build Coastguard Worker tf->gdd_reads = realloc(tf->gdd_reads, tf->io_plots_allocated * sizeof(struct graph_dot_data *));
1035*1a3d31e3SAndroid Build Coastguard Worker if (!tf->gdd_reads)
1036*1a3d31e3SAndroid Build Coastguard Worker abort();
1037*1a3d31e3SAndroid Build Coastguard Worker tf->gdd_writes = realloc(tf->gdd_writes, tf->io_plots_allocated * sizeof(struct graph_dot_data *));
1038*1a3d31e3SAndroid Build Coastguard Worker if (!tf->gdd_writes)
1039*1a3d31e3SAndroid Build Coastguard Worker abort();
1040*1a3d31e3SAndroid Build Coastguard Worker memset(tf->gdd_reads + tf->io_plots_allocated - GDD_PTR_ALLOC_STEP,
1041*1a3d31e3SAndroid Build Coastguard Worker 0, GDD_PTR_ALLOC_STEP * sizeof(struct graph_dot_data *));
1042*1a3d31e3SAndroid Build Coastguard Worker memset(tf->gdd_writes + tf->io_plots_allocated - GDD_PTR_ALLOC_STEP,
1043*1a3d31e3SAndroid Build Coastguard Worker 0, GDD_PTR_ALLOC_STEP * sizeof(struct graph_dot_data *));
1044*1a3d31e3SAndroid Build Coastguard Worker }
1045*1a3d31e3SAndroid Build Coastguard Worker pm->index = tf->io_plots++;
1046*1a3d31e3SAndroid Build Coastguard Worker
1047*1a3d31e3SAndroid Build Coastguard Worker return pm;
1048*1a3d31e3SAndroid Build Coastguard Worker }
1049*1a3d31e3SAndroid Build Coastguard Worker return pm;
1050*1a3d31e3SAndroid Build Coastguard Worker }
1051*1a3d31e3SAndroid Build Coastguard Worker
add_io(struct trace * trace,struct trace_file * tf)1052*1a3d31e3SAndroid Build Coastguard Worker void add_io(struct trace *trace, struct trace_file *tf)
1053*1a3d31e3SAndroid Build Coastguard Worker {
1054*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *io = trace->io;
1055*1a3d31e3SAndroid Build Coastguard Worker int action = io->action & BLK_TA_MASK;
1056*1a3d31e3SAndroid Build Coastguard Worker u64 offset;
1057*1a3d31e3SAndroid Build Coastguard Worker int index;
1058*1a3d31e3SAndroid Build Coastguard Worker char *label;
1059*1a3d31e3SAndroid Build Coastguard Worker struct pid_map *pm;
1060*1a3d31e3SAndroid Build Coastguard Worker
1061*1a3d31e3SAndroid Build Coastguard Worker if (io->action & BLK_TC_ACT(BLK_TC_NOTIFY))
1062*1a3d31e3SAndroid Build Coastguard Worker return;
1063*1a3d31e3SAndroid Build Coastguard Worker
1064*1a3d31e3SAndroid Build Coastguard Worker if (action != io_event(trace))
1065*1a3d31e3SAndroid Build Coastguard Worker return;
1066*1a3d31e3SAndroid Build Coastguard Worker
1067*1a3d31e3SAndroid Build Coastguard Worker offset = map_io(trace, io);
1068*1a3d31e3SAndroid Build Coastguard Worker
1069*1a3d31e3SAndroid Build Coastguard Worker pm = get_pid_map(tf, io->pid);
1070*1a3d31e3SAndroid Build Coastguard Worker if (!pm) {
1071*1a3d31e3SAndroid Build Coastguard Worker index = 0;
1072*1a3d31e3SAndroid Build Coastguard Worker label = "";
1073*1a3d31e3SAndroid Build Coastguard Worker } else {
1074*1a3d31e3SAndroid Build Coastguard Worker index = pm->index;
1075*1a3d31e3SAndroid Build Coastguard Worker label = pm->name;
1076*1a3d31e3SAndroid Build Coastguard Worker }
1077*1a3d31e3SAndroid Build Coastguard Worker if (BLK_DATADIR(io->action) & BLK_TC_READ) {
1078*1a3d31e3SAndroid Build Coastguard Worker if (!tf->gdd_reads[index])
1079*1a3d31e3SAndroid Build Coastguard Worker tf->gdd_reads[index] = alloc_dot_data(tf->min_seconds, tf->max_seconds, tf->min_offset, tf->max_offset, tf->stop_seconds, pick_color(), strdup(label));
1080*1a3d31e3SAndroid Build Coastguard Worker set_gdd_bit(tf->gdd_reads[index], offset, io->bytes, io->time);
1081*1a3d31e3SAndroid Build Coastguard Worker } else if (BLK_DATADIR(io->action) & BLK_TC_WRITE) {
1082*1a3d31e3SAndroid Build Coastguard Worker if (!tf->gdd_writes[index])
1083*1a3d31e3SAndroid Build Coastguard Worker tf->gdd_writes[index] = alloc_dot_data(tf->min_seconds, tf->max_seconds, tf->min_offset, tf->max_offset, tf->stop_seconds, pick_color(), strdup(label));
1084*1a3d31e3SAndroid Build Coastguard Worker set_gdd_bit(tf->gdd_writes[index], offset, io->bytes, io->time);
1085*1a3d31e3SAndroid Build Coastguard Worker }
1086*1a3d31e3SAndroid Build Coastguard Worker }
1087*1a3d31e3SAndroid Build Coastguard Worker
add_pending_io(struct trace * trace,struct graph_line_data * gld)1088*1a3d31e3SAndroid Build Coastguard Worker void add_pending_io(struct trace *trace, struct graph_line_data *gld)
1089*1a3d31e3SAndroid Build Coastguard Worker {
1090*1a3d31e3SAndroid Build Coastguard Worker unsigned int seconds;
1091*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *io = trace->io;
1092*1a3d31e3SAndroid Build Coastguard Worker int action = io->action & BLK_TA_MASK;
1093*1a3d31e3SAndroid Build Coastguard Worker double avg;
1094*1a3d31e3SAndroid Build Coastguard Worker struct pending_io *pio;
1095*1a3d31e3SAndroid Build Coastguard Worker
1096*1a3d31e3SAndroid Build Coastguard Worker if (io->action & BLK_TC_ACT(BLK_TC_NOTIFY))
1097*1a3d31e3SAndroid Build Coastguard Worker return;
1098*1a3d31e3SAndroid Build Coastguard Worker
1099*1a3d31e3SAndroid Build Coastguard Worker if (action == __BLK_TA_QUEUE) {
1100*1a3d31e3SAndroid Build Coastguard Worker if (io->sector == 0)
1101*1a3d31e3SAndroid Build Coastguard Worker return;
1102*1a3d31e3SAndroid Build Coastguard Worker if (trace->found_issue || trace->found_completion) {
1103*1a3d31e3SAndroid Build Coastguard Worker pio = hash_queued_io(trace->io);
1104*1a3d31e3SAndroid Build Coastguard Worker /*
1105*1a3d31e3SAndroid Build Coastguard Worker * When there are no ISSUE events count depth and
1106*1a3d31e3SAndroid Build Coastguard Worker * latency at least from queue events
1107*1a3d31e3SAndroid Build Coastguard Worker */
1108*1a3d31e3SAndroid Build Coastguard Worker if (pio && !trace->found_issue) {
1109*1a3d31e3SAndroid Build Coastguard Worker pio->dispatch_time = io->time;
1110*1a3d31e3SAndroid Build Coastguard Worker goto account_io;
1111*1a3d31e3SAndroid Build Coastguard Worker }
1112*1a3d31e3SAndroid Build Coastguard Worker }
1113*1a3d31e3SAndroid Build Coastguard Worker return;
1114*1a3d31e3SAndroid Build Coastguard Worker }
1115*1a3d31e3SAndroid Build Coastguard Worker if (action == __BLK_TA_REQUEUE) {
1116*1a3d31e3SAndroid Build Coastguard Worker if (ios_in_flight > 0)
1117*1a3d31e3SAndroid Build Coastguard Worker ios_in_flight--;
1118*1a3d31e3SAndroid Build Coastguard Worker return;
1119*1a3d31e3SAndroid Build Coastguard Worker }
1120*1a3d31e3SAndroid Build Coastguard Worker if (action != __BLK_TA_ISSUE)
1121*1a3d31e3SAndroid Build Coastguard Worker return;
1122*1a3d31e3SAndroid Build Coastguard Worker
1123*1a3d31e3SAndroid Build Coastguard Worker pio = hash_dispatched_io(trace->io);
1124*1a3d31e3SAndroid Build Coastguard Worker if (!pio)
1125*1a3d31e3SAndroid Build Coastguard Worker return;
1126*1a3d31e3SAndroid Build Coastguard Worker
1127*1a3d31e3SAndroid Build Coastguard Worker if (!trace->found_completion) {
1128*1a3d31e3SAndroid Build Coastguard Worker list_del(&pio->hash_list);
1129*1a3d31e3SAndroid Build Coastguard Worker free(pio);
1130*1a3d31e3SAndroid Build Coastguard Worker }
1131*1a3d31e3SAndroid Build Coastguard Worker
1132*1a3d31e3SAndroid Build Coastguard Worker account_io:
1133*1a3d31e3SAndroid Build Coastguard Worker ios_in_flight++;
1134*1a3d31e3SAndroid Build Coastguard Worker
1135*1a3d31e3SAndroid Build Coastguard Worker seconds = SECONDS(io->time);
1136*1a3d31e3SAndroid Build Coastguard Worker gld->data[seconds].sum += ios_in_flight;
1137*1a3d31e3SAndroid Build Coastguard Worker gld->data[seconds].count++;
1138*1a3d31e3SAndroid Build Coastguard Worker
1139*1a3d31e3SAndroid Build Coastguard Worker avg = (double)gld->data[seconds].sum / gld->data[seconds].count;
1140*1a3d31e3SAndroid Build Coastguard Worker if (gld->max < (u64)avg) {
1141*1a3d31e3SAndroid Build Coastguard Worker gld->max = avg;
1142*1a3d31e3SAndroid Build Coastguard Worker }
1143*1a3d31e3SAndroid Build Coastguard Worker }
1144*1a3d31e3SAndroid Build Coastguard Worker
add_completed_io(struct trace * trace,struct graph_line_data * latency_gld)1145*1a3d31e3SAndroid Build Coastguard Worker void add_completed_io(struct trace *trace,
1146*1a3d31e3SAndroid Build Coastguard Worker struct graph_line_data *latency_gld)
1147*1a3d31e3SAndroid Build Coastguard Worker {
1148*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *io = trace->io;
1149*1a3d31e3SAndroid Build Coastguard Worker int seconds;
1150*1a3d31e3SAndroid Build Coastguard Worker int action = io->action & BLK_TA_MASK;
1151*1a3d31e3SAndroid Build Coastguard Worker struct pending_io *pio;
1152*1a3d31e3SAndroid Build Coastguard Worker double avg;
1153*1a3d31e3SAndroid Build Coastguard Worker u64 latency;
1154*1a3d31e3SAndroid Build Coastguard Worker
1155*1a3d31e3SAndroid Build Coastguard Worker if (io->action & BLK_TC_ACT(BLK_TC_NOTIFY))
1156*1a3d31e3SAndroid Build Coastguard Worker return;
1157*1a3d31e3SAndroid Build Coastguard Worker
1158*1a3d31e3SAndroid Build Coastguard Worker if (action != __BLK_TA_COMPLETE)
1159*1a3d31e3SAndroid Build Coastguard Worker return;
1160*1a3d31e3SAndroid Build Coastguard Worker
1161*1a3d31e3SAndroid Build Coastguard Worker seconds = SECONDS(io->time);
1162*1a3d31e3SAndroid Build Coastguard Worker
1163*1a3d31e3SAndroid Build Coastguard Worker pio = hash_completed_io(trace->io);
1164*1a3d31e3SAndroid Build Coastguard Worker if (!pio)
1165*1a3d31e3SAndroid Build Coastguard Worker return;
1166*1a3d31e3SAndroid Build Coastguard Worker
1167*1a3d31e3SAndroid Build Coastguard Worker if (ios_in_flight > 0)
1168*1a3d31e3SAndroid Build Coastguard Worker ios_in_flight--;
1169*1a3d31e3SAndroid Build Coastguard Worker if (io->time >= pio->dispatch_time) {
1170*1a3d31e3SAndroid Build Coastguard Worker latency = io->time - pio->dispatch_time;
1171*1a3d31e3SAndroid Build Coastguard Worker latency_gld->data[seconds].sum += latency;
1172*1a3d31e3SAndroid Build Coastguard Worker latency_gld->data[seconds].count++;
1173*1a3d31e3SAndroid Build Coastguard Worker }
1174*1a3d31e3SAndroid Build Coastguard Worker
1175*1a3d31e3SAndroid Build Coastguard Worker list_del(&pio->hash_list);
1176*1a3d31e3SAndroid Build Coastguard Worker free(pio);
1177*1a3d31e3SAndroid Build Coastguard Worker
1178*1a3d31e3SAndroid Build Coastguard Worker avg = (double)latency_gld->data[seconds].sum /
1179*1a3d31e3SAndroid Build Coastguard Worker latency_gld->data[seconds].count;
1180*1a3d31e3SAndroid Build Coastguard Worker if (latency_gld->max < (u64)avg) {
1181*1a3d31e3SAndroid Build Coastguard Worker latency_gld->max = avg;
1182*1a3d31e3SAndroid Build Coastguard Worker }
1183*1a3d31e3SAndroid Build Coastguard Worker }
1184*1a3d31e3SAndroid Build Coastguard Worker
add_iop(struct trace * trace,struct graph_line_data * gld)1185*1a3d31e3SAndroid Build Coastguard Worker void add_iop(struct trace *trace, struct graph_line_data *gld)
1186*1a3d31e3SAndroid Build Coastguard Worker {
1187*1a3d31e3SAndroid Build Coastguard Worker struct blk_io_trace *io = trace->io;
1188*1a3d31e3SAndroid Build Coastguard Worker int action = io->action & BLK_TA_MASK;
1189*1a3d31e3SAndroid Build Coastguard Worker int seconds;
1190*1a3d31e3SAndroid Build Coastguard Worker
1191*1a3d31e3SAndroid Build Coastguard Worker if (io->action & BLK_TC_ACT(BLK_TC_NOTIFY))
1192*1a3d31e3SAndroid Build Coastguard Worker return;
1193*1a3d31e3SAndroid Build Coastguard Worker
1194*1a3d31e3SAndroid Build Coastguard Worker /* iops and tput use the same events */
1195*1a3d31e3SAndroid Build Coastguard Worker if (action != tput_event(trace))
1196*1a3d31e3SAndroid Build Coastguard Worker return;
1197*1a3d31e3SAndroid Build Coastguard Worker
1198*1a3d31e3SAndroid Build Coastguard Worker seconds = SECONDS(io->time);
1199*1a3d31e3SAndroid Build Coastguard Worker gld->data[seconds].sum += 1;
1200*1a3d31e3SAndroid Build Coastguard Worker gld->data[seconds].count = 1;
1201*1a3d31e3SAndroid Build Coastguard Worker if (gld->data[seconds].sum > gld->max)
1202*1a3d31e3SAndroid Build Coastguard Worker gld->max = gld->data[seconds].sum;
1203*1a3d31e3SAndroid Build Coastguard Worker }
1204*1a3d31e3SAndroid Build Coastguard Worker
check_record(struct trace * trace)1205*1a3d31e3SAndroid Build Coastguard Worker void check_record(struct trace *trace)
1206*1a3d31e3SAndroid Build Coastguard Worker {
1207*1a3d31e3SAndroid Build Coastguard Worker handle_notify(trace);
1208*1a3d31e3SAndroid Build Coastguard Worker }
1209