[PATCH] BTT patch: (1/3) 'iostat' totals
[blktrace.git] / btt / devs.c
CommitLineData
63eba147
JA
1/*
2 * blktrace output analysis: generate a timeline & gather statistics
3 *
4 * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21#include <stdio.h>
63eba147
JA
22#include "globals.h"
23
24#define N_DEV_HASH 128
25#define DEV_HASH(dev) ((MAJOR(dev) ^ MINOR(dev)) & (N_DEV_HASH - 1))
6eb42155 26struct list_head dev_heads[N_DEV_HASH];
63eba147 27
6eb42155 28void init_dev_heads(void)
63eba147
JA
29{
30 int i;
63eba147
JA
31 for (i = 0; i < N_DEV_HASH; i++)
32 INIT_LIST_HEAD(&dev_heads[i]);
33}
34
35struct d_info *__dip_find(__u32 device)
36{
37 struct list_head *p;
38 struct d_info *dip;
39
63eba147
JA
40 __list_for_each(p, &dev_heads[DEV_HASH(device)]) {
41 dip = list_entry(p, struct d_info, hash_head);
42 if (device == dip->device)
43 return dip;
44 }
45
46 return NULL;
47}
48
6eb42155 49struct d_info *dip_add(__u32 device, struct io *iop, int link)
63eba147
JA
50{
51 struct d_info *dip = __dip_find(device);
52
53 if (dip == NULL) {
6eb42155
ADB
54 dip = malloc(sizeof(struct d_info));
55 dip->heads = dip_rb_mkhds();
56 init_region(&dip->regions);
63eba147
JA
57 dip->device = device;
58 dip->last_q = (__u64)-1;
63eba147 59 dip->map = dev_map_find(device);
5225e788 60 dip->seek_handle = seeki_init(device);
b2ecdd0f 61 latency_init(dip);
21e47d90
ADB
62 memset(&dip->stats, 0, sizeof(dip->stats));
63 memset(&dip->all_stats, 0, sizeof(dip->all_stats));
63eba147 64 list_add_tail(&dip->hash_head, &dev_heads[DEV_HASH(device)]);
6eb42155 65 list_add_tail(&dip->all_head, &all_devs);
63eba147
JA
66 n_devs++;
67 }
68
6eb42155
ADB
69 if (link)
70 dip_rb_ins(dip, iop);
63eba147
JA
71
72 return dip;
73}
6eb42155
ADB
74
75void dip_rem(struct io *iop)
76{
77 dip_rb_rem(iop);
78}
79
80void dip_foreach(struct io *iop, enum iop_type type,
81 void (*fnc)(struct io *iop, struct io *this), int rm_after)
82{
83 if (rm_after) {
84 LIST_HEAD(head);
85 struct io *this;
86 struct list_head *p, *q;
87
88 dip_rb_fe(iop->dip, type, iop, fnc, &head);
89 list_for_each_safe(p, q, &head) {
90 this = list_entry(p, struct io, f_head);
91 LIST_DEL(&this->f_head);
92 io_release(this);
93 }
94 }
95 else
96 dip_rb_fe(iop->dip, type, iop, fnc, NULL);
97}
98
99struct io *dip_find_sec(struct d_info *dip, enum iop_type type, __u64 sec)
100{
101 return dip_rb_find_sec(dip, type, sec);
102}
103
104void dip_foreach_out(void (*func)(struct d_info *, void *), void *arg)
105{
106 if (devices == NULL) {
107 struct list_head *p;
108 __list_for_each(p, &all_devs)
109 func(list_entry(p, struct d_info, all_head), arg);
110 }
111 else {
112 int i;
113 struct d_info *dip;
114 unsigned int mjr, mnr;
115 char *p = devices;
116
117 while (p && ((i = sscanf(p, "%u,%u", &mjr, &mnr)) == 2)) {
118 dip = __dip_find((__u32)((mjr << MINORBITS) | mnr));
119 ASSERT(dip);
120
121 func(dip, arg);
122
123 p = strchr(p, ';');
124 if (p) p++;
125 }
126 }
127}