Merge branch 'master' of ssh://git.kernel.dk/data/git/blktrace
[blktrace.git] / btt / trace_complete.c
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 "globals.h"
22
23 LIST_HEAD(pending_cs);
24
25 static inline void __run_complete(struct io *c_iop)
26 {
27         LIST_HEAD(rmhd);
28
29         if (remapper_dev(c_iop->t.device))
30                 bilink_for_each_down(run_remap, c_iop, &rmhd, 1);
31         else
32                 bilink_for_each_down(run_issue, c_iop, &rmhd, 1);
33
34         dump_iop(c_iop, 1);
35
36         LIST_DEL(&c_iop->c_pending);
37         del_retry(c_iop);
38
39         list_add_tail(&c_iop->f_head, &rmhd);
40         release_iops(&rmhd);
41 }
42
43 static int ready_complete_remapper(struct io *c_iop)
44 {
45         LIST_HEAD(head);
46         struct list_head *p, *q;
47         struct io *l_iop, *a_iop;
48
49         dip_foreach_list(c_iop, IOP_L, &head);
50         list_for_each_safe(p, q, &head) {
51                 l_iop = list_entry(p, struct io, f_head);
52                 LIST_DEL(&l_iop->f_head);
53
54                 ASSERT(!list_empty(&l_iop->up_list));
55                 a_iop = bilink_first_up(l_iop, NULL);
56                 if (ready_remap(a_iop, c_iop)) {
57                         dip_rem(l_iop);
58                         bilink(a_iop, c_iop);
59                         c_iop->bytes_left -= a_iop->t.bytes;
60                 }
61         }
62
63         return c_iop->bytes_left == 0;
64 }
65
66 int ready_complete(struct io *c_iop)
67 {
68         __u64 d2c;
69         struct io *d_iop;
70
71         if (c_iop->bytes_left == 0)
72                 return 1;
73
74         if (remapper_dev(c_iop->t.device))
75                 return ready_complete_remapper(c_iop);
76
77         if (!list_empty(&c_iop->down_list))
78                 return 1;
79
80         d_iop = dip_find_sec(c_iop->dip, IOP_D, BIT_START(c_iop));
81         if (!d_iop)
82                 return -1;
83
84         if (c_iop->t.bytes != d_iop->t.bytes) {
85                 fprintf(stderr, 
86                         "\nFATAL: Probable time anomaly detected\n");
87                 fprintf(stderr, 
88                         "D @ %15.9lf missing C, later C @ %15.9lf\n", 
89                         BIT_TIME(d_iop->t.time), 
90                         BIT_TIME(c_iop->t.time));
91                 exit(1);
92         }
93
94         if (!ready_issue(d_iop, c_iop))
95                 return 0;
96
97         c_iop->bytes_left = 0;
98
99         d2c = tdelta(d_iop, c_iop);
100         update_d2c(d_iop, d_iop->down_len, d2c);
101         latency_d2c(d_iop->dip, c_iop->t.time, d2c);
102         iostat_complete(d_iop, c_iop);
103
104         bilink(d_iop, c_iop);
105         dip_rem(d_iop);
106         return 1;
107 }
108
109 void trace_complete(struct io *c_iop)
110 {
111         if (io_setup(c_iop, IOP_C)) {
112                 update_blks(c_iop);
113                 update_cregion(&all_regions, c_iop->t.time);
114                 update_cregion(&c_iop->dip->regions, c_iop->t.time);
115                 if (c_iop->pip)
116                         update_cregion(&c_iop->pip->regions, c_iop->t.time);
117
118                 list_add_tail(&c_iop->c_pending, &pending_cs);
119                 switch (ready_complete(c_iop)) {
120                 case  1: 
121                         __run_complete(c_iop); 
122                         break;
123                 case  0: 
124                         add_retry(c_iop); 
125                         break;
126                 case -1: 
127                         LIST_DEL(&c_iop->c_pending);
128                         del_retry(c_iop);
129                         io_release(c_iop);
130                         break;
131                 }
132         }
133         else 
134                 io_release(c_iop);
135 }
136
137 void retry_complete(struct io *c_iop, __u64 now)
138 {
139         double tc = BIT_TIME(c_iop->t.time);
140
141         switch (ready_complete(c_iop)) {
142         case  1: 
143 #if defined(DEBUG)
144                 fprintf(stderr, "Retried %15.9lf success!\n", tc);
145 #endif
146                 __run_complete(c_iop); 
147                 break;
148         case  0:
149                 if (now == 0 || ((BIT_TIME(now) - tc) < 1.0))
150                         break;
151                 if (!list_empty(&c_iop->down_list))
152                         break;
153                 /*FALLTHROUGH*/
154         case -1: 
155                 LIST_DEL(&c_iop->c_pending);
156                 del_retry(c_iop);
157                 io_release(c_iop);
158                 break;
159         }
160 }