@@ -94,6 +94,94 @@ void block_acct_start(BlockAcctStats *stats, BlockAcctCookie *cookie,
94
94
cookie -> type = type ;
95
95
}
96
96
97
+ /* block_latency_histogram_compare_func:
98
+ * Compare @key with interval [@it[0], @it[1]).
99
+ * Return: -1 if @key < @it[0]
100
+ * 0 if @key in [@it[0], @it[1])
101
+ * +1 if @key >= @it[1]
102
+ */
103
+ static int block_latency_histogram_compare_func (const void * key , const void * it )
104
+ {
105
+ uint64_t k = * (uint64_t * )key ;
106
+ uint64_t a = ((uint64_t * )it )[0 ];
107
+ uint64_t b = ((uint64_t * )it )[1 ];
108
+
109
+ return k < a ? -1 : (k < b ? 0 : 1 );
110
+ }
111
+
112
+ static void block_latency_histogram_account (BlockLatencyHistogram * hist ,
113
+ int64_t latency_ns )
114
+ {
115
+ uint64_t * pos ;
116
+
117
+ if (hist -> bins == NULL ) {
118
+ /* histogram disabled */
119
+ return ;
120
+ }
121
+
122
+
123
+ if (latency_ns < hist -> boundaries [0 ]) {
124
+ hist -> bins [0 ]++ ;
125
+ return ;
126
+ }
127
+
128
+ if (latency_ns >= hist -> boundaries [hist -> nbins - 2 ]) {
129
+ hist -> bins [hist -> nbins - 1 ]++ ;
130
+ return ;
131
+ }
132
+
133
+ pos = bsearch (& latency_ns , hist -> boundaries , hist -> nbins - 2 ,
134
+ sizeof (hist -> boundaries [0 ]),
135
+ block_latency_histogram_compare_func );
136
+ assert (pos != NULL );
137
+
138
+ hist -> bins [pos - hist -> boundaries + 1 ]++ ;
139
+ }
140
+
141
+ int block_latency_histogram_set (BlockAcctStats * stats , enum BlockAcctType type ,
142
+ uint64List * boundaries )
143
+ {
144
+ BlockLatencyHistogram * hist = & stats -> latency_histogram [type ];
145
+ uint64List * entry ;
146
+ uint64_t * ptr ;
147
+ uint64_t prev = 0 ;
148
+ int new_nbins = 1 ;
149
+
150
+ for (entry = boundaries ; entry ; entry = entry -> next ) {
151
+ if (entry -> value <= prev ) {
152
+ return - EINVAL ;
153
+ }
154
+ new_nbins ++ ;
155
+ prev = entry -> value ;
156
+ }
157
+
158
+ hist -> nbins = new_nbins ;
159
+ g_free (hist -> boundaries );
160
+ hist -> boundaries = g_new (uint64_t , hist -> nbins - 1 );
161
+ for (entry = boundaries , ptr = hist -> boundaries ; entry ;
162
+ entry = entry -> next , ptr ++ )
163
+ {
164
+ * ptr = entry -> value ;
165
+ }
166
+
167
+ g_free (hist -> bins );
168
+ hist -> bins = g_new0 (uint64_t , hist -> nbins );
169
+
170
+ return 0 ;
171
+ }
172
+
173
+ void block_latency_histograms_clear (BlockAcctStats * stats )
174
+ {
175
+ int i ;
176
+
177
+ for (i = 0 ; i < BLOCK_MAX_IOTYPE ; i ++ ) {
178
+ BlockLatencyHistogram * hist = & stats -> latency_histogram [i ];
179
+ g_free (hist -> bins );
180
+ g_free (hist -> boundaries );
181
+ memset (hist , 0 , sizeof (* hist ));
182
+ }
183
+ }
184
+
97
185
static void block_account_one_io (BlockAcctStats * stats , BlockAcctCookie * cookie ,
98
186
bool failed )
99
187
{
@@ -116,6 +204,9 @@ static void block_account_one_io(BlockAcctStats *stats, BlockAcctCookie *cookie,
116
204
stats -> nr_ops [cookie -> type ]++ ;
117
205
}
118
206
207
+ block_latency_histogram_account (& stats -> latency_histogram [cookie -> type ],
208
+ latency_ns );
209
+
119
210
if (!failed || stats -> account_failed ) {
120
211
stats -> total_time_ns [cookie -> type ] += latency_ns ;
121
212
stats -> last_access_time_ns = time_ns ;
0 commit comments