Fix remap handling (again).
[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                 struct bilink *blp;
31                 struct io *iop = bilink_first_down(c_iop, &blp);
32
33                 if (iop->type == IOP_Q) {
34                         run_queue(iop, c_iop, &rmhd);
35                         biunlink(blp);
36                 }
37                 else
38                         bilink_for_each_down(run_remap, c_iop, &rmhd, 1);
39         }
40         else
41                 bilink_for_each_down(run_issue, c_iop, &rmhd, 1);
42
43         dump_iop(c_iop, 1);
44
45         LIST_DEL(&c_iop->c_pending);
46         del_retry(c_iop);
47
48         list_add_tail(&c_iop->f_head, &rmhd);
49         release_iops(&rmhd);
50 }
51
52 static int ready_complete_remapper(struct io *c_iop)
53 {
54         LIST_HEAD(head);
55         struct list_head *p, *q;
56
57         dip_foreach_list(c_iop, IOP_L, &head);
58         if (list_empty(&head)) {
59                 struct io *q_iop;
60
61                 dip_foreach_list(c_iop, IOP_Q, &head);
62                 list_for_each_safe(p, q, &head) {
63                         q_iop = list_entry(p, struct io, f_head);
64                         LIST_DEL(&q_iop->f_head);
65
66                         ASSERT(list_empty(&q_iop->up_list));
67                         ASSERT(list_empty(&q_iop->down_list));
68                         ASSERT(q_iop->t.bytes == c_iop->t.bytes);
69                         if (ready_queue(q_iop, c_iop)) {
70                                 dip_rem(q_iop);
71                                 bilink(q_iop, c_iop);
72                                 c_iop->bytes_left -= q_iop->t.bytes;
73                         }
74                 }
75         }
76         else {
77                 struct io *l_iop, *a_iop;
78
79                 list_for_each_safe(p, q, &head) {
80                         l_iop = list_entry(p, struct io, f_head);
81                         LIST_DEL(&l_iop->f_head);
82
83                         ASSERT(!list_empty(&l_iop->up_list));
84                         a_iop = bilink_first_up(l_iop, NULL);
85                         if (ready_remap(a_iop, c_iop)) {
86                                 dip_rem(l_iop);
87                                 bilink(a_iop, c_iop);
88                                 c_iop->bytes_left -= a_iop->t.bytes;
89                         }
90                 }
91         }
92
93         return c_iop->bytes_left == 0;
94 }
95
96 int ready_complete(struct io *c_iop)
97 {
98         __u64 d2c;
99         struct io *d_iop;
100
101         if (c_iop->bytes_left == 0)
102                 return 1;
103
104         if (remapper_dev(c_iop->t.device))
105                 return ready_complete_remapper(c_iop);
106
107         if (!list_empty(&c_iop->down_list))
108                 return 1;
109
110         d_iop = dip_find_sec(c_iop->dip, IOP_D, BIT_START(c_iop));
111         if (!d_iop)
112                 return -1;
113
114         if (c_iop->t.bytes != d_iop->t.bytes) {
115                 fprintf(stderr, 
116                         "\nFATAL: Probable time anomaly detected\n");
117                 fprintf(stderr, 
118                         "D @ %15.9lf missing C, later C @ %15.9lf\n", 
119                         BIT_TIME(d_iop->t.time), 
120                         BIT_TIME(c_iop->t.time));
121                 exit(1);
122         }
123
124         if (!ready_issue(d_iop, c_iop))
125                 return 0;
126
127         c_iop->bytes_left = 0;
128
129         d2c = tdelta(d_iop, c_iop);
130         update_d2c(d_iop, d_iop->down_len, d2c);
131         latency_d2c(d_iop->dip, c_iop->t.time, d2c);
132         iostat_complete(d_iop, c_iop);
133
134         bilink(d_iop, c_iop);
135         dip_rem(d_iop);
136         return 1;
137 }
138
139 void trace_complete(struct io *c_iop)
140 {
141         if (io_setup(c_iop, IOP_C)) {
142                 update_blks(c_iop);
143                 update_cregion(&all_regions, c_iop->t.time);
144                 update_cregion(&c_iop->dip->regions, c_iop->t.time);
145                 if (c_iop->pip)
146                         update_cregion(&c_iop->pip->regions, c_iop->t.time);
147
148                 list_add_tail(&c_iop->c_pending, &pending_cs);
149                 switch (ready_complete(c_iop)) {
150                 case  1: 
151                         __run_complete(c_iop); 
152                         break;
153                 case  0: 
154                         add_retry(c_iop); 
155                         break;
156                 case -1: 
157                         LIST_DEL(&c_iop->c_pending);
158                         del_retry(c_iop);
159                         io_release(c_iop);
160                         break;
161                 }
162         }
163         else 
164                 io_release(c_iop);
165 }
166
167 void retry_complete(struct io *c_iop, __u64 now)
168 {
169         double tc = BIT_TIME(c_iop->t.time);
170
171         switch (ready_complete(c_iop)) {
172         case  1: 
173 #if defined(DEBUG)
174                 fprintf(stderr, "Retried %15.9lf success!\n", tc);
175 #endif
176                 __run_complete(c_iop); 
177                 break;
178         case  0:
179                 if (now == 0 || ((BIT_TIME(now) - tc) < 1.0))
180                         break;
181                 if (!list_empty(&c_iop->down_list))
182                         break;
183                 /*FALLTHROUGH*/
184         case -1: 
185                 LIST_DEL(&c_iop->c_pending);
186                 del_retry(c_iop);
187                 io_release(c_iop);
188                 break;
189         }
190 }