Commit | Line | Data |
---|---|---|
095181f2 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 "globals.h" | |
22 | ||
23 | LIST_HEAD(pending_cs); | |
24 | ||
d76c5b81 | 25 | static inline void __run_complete(struct io *c_iop) |
095181f2 | 26 | { |
d76c5b81 | 27 | LIST_HEAD(rmhd); |
095181f2 | 28 | |
d76c5b81 AB |
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); | |
095181f2 | 33 | |
d76c5b81 | 34 | dump_iop(c_iop, 1); |
001b2633 | 35 | |
095181f2 | 36 | LIST_DEL(&c_iop->c_pending); |
001b2633 | 37 | del_retry(c_iop); |
d76c5b81 AB |
38 | |
39 | list_add_tail(&c_iop->f_head, &rmhd); | |
40 | release_iops(&rmhd); | |
095181f2 JA |
41 | } |
42 | ||
d76c5b81 | 43 | static int ready_complete_remapper(struct io *c_iop) |
095181f2 JA |
44 | { |
45 | LIST_HEAD(head); | |
095181f2 | 46 | struct list_head *p, *q; |
d76c5b81 | 47 | struct io *l_iop, *a_iop; |
095181f2 | 48 | |
d76c5b81 | 49 | dip_foreach_list(c_iop, IOP_L, &head); |
095181f2 | 50 | list_for_each_safe(p, q, &head) { |
d76c5b81 AB |
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 | } | |
095181f2 JA |
61 | } |
62 | ||
d76c5b81 | 63 | return c_iop->bytes_left == 0; |
095181f2 JA |
64 | } |
65 | ||
d76c5b81 | 66 | int ready_complete(struct io *c_iop) |
095181f2 | 67 | { |
d76c5b81 AB |
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); | |
095181f2 JA |
92 | } |
93 | ||
d76c5b81 | 94 | if (!ready_issue(d_iop, c_iop)) |
095181f2 JA |
95 | return 0; |
96 | ||
d76c5b81 AB |
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); | |
095181f2 JA |
106 | return 1; |
107 | } | |
108 | ||
d76c5b81 | 109 | void trace_complete(struct io *c_iop) |
095181f2 | 110 | { |
d76c5b81 AB |
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 | } | |
095181f2 JA |
132 | } |
133 | else | |
d76c5b81 | 134 | io_release(c_iop); |
095181f2 JA |
135 | } |
136 | ||
d76c5b81 | 137 | void retry_complete(struct io *c_iop, __u64 now) |
095181f2 | 138 | { |
d76c5b81 AB |
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 | } | |
095181f2 | 160 | } |